home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / folders.c < prev    next >
C/C++ Source or Header  |  1992-03-31  |  20KB  |  716 lines

  1. /* @(#)folders.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. static char oldfolder[MAXPATHLEN];
  6.  
  7. /* folder %[user]  --new mailfile is the spool/mail/login file [user].
  8.  * folder #  --new mailfile is the folder previous to the current folder
  9.  * folder &  --new mailfile is ~/mbox (or whatever "mbox" is set to)
  10.  * folder +file --new mailfile is in the directory "folder"; name is 'file'
  11.  * folder "path" --full path name or the one in current working directory.
  12.  *
  13.  * in all cases, changes are updated unless a '!' is specified after the
  14.  * folder command (e.g. "f!", "folder !" "fo!" .. all permutations)
  15.  * as usual, if new mail has arrived before the file is copied back, then
  16.  * user will be notified beforehand.
  17.  *
  18.  * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
  19.  */
  20. folder(argc, argv, list)
  21. register char **argv;
  22. char list[];
  23. {
  24.     int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
  25.     char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  26.     struct stat statbuf;
  27.     extern long last_spool_size;
  28.  
  29.     if (ison(glob_flags, IS_PIPE)) {
  30.     print("You can't pipe to the %s command.\n", *argv);
  31.     return -1;
  32.     } else if (ison(glob_flags, IS_SENDING)) {
  33.     print("You can't use the %s command when sending.\n", *argv);
  34.     return -1;
  35.     } else if (!tempfile || !*tempfile) {
  36.     print("You can't use the %s command in init files.\n", *argv);
  37.     return -1;
  38.     }
  39.     while (*++argv && (**argv == '-' || **argv == '!'))
  40.     if (!strcmp(*argv, "-N"))
  41.         no_hdrs = !iscurses;
  42.     else if (!updating && !strcmp(*argv, "-n"))
  43.         turnoff(glob_flags, DO_UPDATE);
  44.     else if (!strcmp(*argv, "-r"))
  45.         do_read_only = 1;
  46.     else if (!strcmp(*argv, "!")) {
  47.         if (updating)
  48.         turnon(glob_flags, DO_UPDATE);    /* useful? */
  49.         else
  50.         turnoff(glob_flags, DO_UPDATE);
  51.     } else
  52.         return help(0, "folder", cmd_help);
  53.  
  54.     if (updating) {
  55.     (void) strcpy(buf, mailfile);
  56.     if (ison(glob_flags, READ_ONLY))
  57.         do_read_only = 1;
  58.     } else {
  59.     if (!*argv) {
  60.         mail_status(0);
  61.         return 0;
  62.     }
  63.     if (!strcmp(*argv, "#"))
  64.         if (!*oldfolder) {
  65.         print("No previous folder\n");
  66.         return -1;
  67.         } else
  68.         newfolder = oldfolder;
  69.     else if (!strcmp(*argv, "&")) {
  70.         if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  71.         newfolder = DEF_MBOX;
  72.     } else
  73.         newfolder = *argv;
  74.     n = 0;
  75.     tmp = getpath(newfolder, &n);
  76.     if (n == -1) {
  77.         print("%s: %s\n", newfolder, tmp);
  78.         return -1;
  79.     } else if (n == 1) {
  80.         print("%s: is a directory\n", tmp);
  81.         return -1;
  82.     }
  83.     /* strcpy so copyback() below (which calls getpath) doesn't change
  84.      * the data that tmp intended to point to.  Get the cwd if necessary.
  85.      */
  86.     n = 0;
  87.     if (*tmp != '/') {
  88.         if (!GetCwd(buf, sizeof buf)) {
  89.         error("getcwd: %s",buf);
  90.         return -1;
  91.         }
  92.         n = strlen(buf);
  93.         buf[n++] = '/';
  94.     }
  95.     (void) strcpy(&buf[n], tmp);
  96.     }
  97. #ifdef SUNTOOL
  98.     if (istool > 1)
  99.     timeout_cursors(TRUE);
  100. #endif /* SUNTOOL */
  101.     if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
  102.     error("Unable to read %s", buf);
  103. #ifdef SUNTOOL
  104.     if (istool > 1)
  105.         timeout_cursors(FALSE);
  106. #endif /* SUNTOOL */
  107.     return -1;
  108.     }
  109.     /* If the file can't be opened for writing, autoset READ_ONLY */
  110.     if (!(statbuf.st_mode & 0200))
  111.     do_read_only = 1;
  112.  
  113.     if (!(n=copyback(updating?"Update folder?":"Change anyway?",!updating))) {
  114. #ifdef SUNTOOL
  115.     if (istool > 1)
  116.         timeout_cursors(FALSE);
  117. #endif /* SUNTOOL */
  118.     /* an error occured updating the folder */
  119.     return -1;
  120.     }
  121.     turnoff(glob_flags, CORRUPTED);    /* copyback() was successful */
  122.     /* Assure that both oldfolder and mailfile are full paths */
  123.     if (strcmp(mailfile, buf) || !*oldfolder) {
  124.     n = 1; /* force load of new folder */
  125.     if (!updating)
  126.         (void) strcpy(oldfolder, *oldfolder? mailfile : buf);
  127.     strdup(mailfile, buf);
  128.     }
  129.     do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
  130.     last_size = spool_size = 0L;
  131.     while (msg_cnt--) {
  132.     xfree(msg[msg_cnt].m_date_recv);
  133.     xfree(msg[msg_cnt].m_date_sent);
  134.     msg[msg_cnt].m_date_recv = msg[msg_cnt].m_date_sent = NO_STRING;
  135.     }
  136.     msg_cnt = 0, msg[0].m_offset = 0L;
  137.     turnoff(glob_flags, CONT_PRNT);
  138.  
  139.     turnon(glob_flags, IGN_SIGS);
  140.     /* clear the tempfile */
  141.     if (tmpf)
  142.     (void) fclose(tmpf);
  143.     if (!do_read_only) {
  144.     if (!(tmpf = mask_fopen(tempfile, "w"))) {
  145.         error("error truncating %s", tempfile);
  146.         turnoff(glob_flags, IGN_SIGS);
  147. #ifdef SUNTOOL
  148.         if (istool > 1)
  149.         timeout_cursors(FALSE);
  150. #endif /* SUNTOOL */
  151.         return -1;
  152.     }
  153.     }
  154.     /* Don't reload the folder if it was removed */
  155.     if (n > 0) {
  156.     if (load_folder(mailfile, TRUE, NULL) < 1) {
  157.         last_msg_cnt = 0;
  158.         last_size = statbuf.st_size; /* Disable check_new_mail() */
  159.         turnoff(glob_flags, IGN_SIGS);
  160. #ifdef SUNTOOL
  161.         if (istool > 1)
  162.         timeout_cursors(FALSE);
  163. #endif /* SUNTOOL */
  164.         return -1;
  165.     }
  166.     if (do_read_only && !(tmpf = fopen(mailfile, "r"))) {
  167.         error(mailfile);
  168.         turnoff(glob_flags, IGN_SIGS);
  169. #ifdef SUNTOOL
  170.         if (istool > 1)
  171.         timeout_cursors(FALSE);
  172. #endif /* SUNTOOL */
  173.         return -1;
  174.     }
  175.     }
  176.     last_msg_cnt = msg_cnt;  /* for check_new_mail */
  177.     /* Prevent both bogus "new mail" messages and missed new mail */
  178.     last_size = msg[msg_cnt].m_offset;
  179.     if (!strcmp(mailfile, spoolfile))
  180.     spool_size = last_spool_size = last_size;
  181. #ifdef SUNTOOL
  182.     if (istool) {
  183.     extern Panel_item folder_text_item;
  184.     Rect *rect = (Rect *)window_get(hdr_sw, WIN_RECT);
  185.     (void) pw_rop(hdr_win, 0,0, rect->r_width, rect->r_height, PIX_CLR,
  186.         (struct pixrect *) 0,0,0);
  187.     panel_set_value(folder_text_item, mailfile);
  188.     }
  189. #endif /* SUNTOOL */
  190.  
  191.     if (!updating || current_msg >= msg_cnt)
  192.     current_msg = (msg_cnt? 0 : -1);
  193.     turnoff(glob_flags, IGN_SIGS);
  194.  
  195.     /* now sort messages according a user-defined default */
  196.     if (!updating && msg_cnt > 1 && !strcmp(mailfile, spoolfile) &&
  197.         (tmp = do_set(set_options, "sort"))) {
  198.     (void) sprintf(buf, "sort %s", tmp);
  199.     if ((argv = mk_argv(buf, &argc, TRUE)) && argc > 0) {
  200.         /* msg_list can't be null for do_command and since we're not
  201.          * interested in the result, call sort directly
  202.          */
  203.         (void) sort(argc, argv, NULL);
  204.         free_vec(argv);
  205.         if (!updating)
  206.         current_msg = 0;    /* Sort may move the current message */
  207.     }
  208.     }
  209.     turnoff(glob_flags, DO_UPDATE);
  210.  
  211.     /* go to first NEW message */
  212.     for (n = 0; n < msg_cnt && ison(msg[n].m_flags, OLD); n++)
  213.     ;
  214.     if (n == msg_cnt) {
  215.     turnoff(glob_flags, NEW_MAIL);
  216.     if (!updating) {
  217.         /* no new message found -- try first unread message */
  218.         for (n = 0; n < msg_cnt && isoff(msg[n].m_flags, UNREAD); n++)
  219.         ;
  220.     }
  221.     } else {
  222.     turnon(glob_flags, NEW_MAIL);
  223.     /* default for toolmode is true */
  224.     if (istool && !chk_option("quiet", "tool"))
  225.         bell();
  226.     }
  227.     if (msg_cnt && (!updating || current_msg < 0))
  228.     current_msg = (n == msg_cnt ? 0 : n);
  229.  
  230.     /* be quiet if we're piping */
  231.     if (!istool && !updating && !no_hdrs && msg_cnt
  232.         && isoff(glob_flags, DO_PIPE)) {
  233.     if ((!istool || istool && !msg_cnt) && !iscurses)
  234.         mail_status(0);
  235.     (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  236.     }
  237. #ifdef SUNTOOL
  238.     if (istool > 1) {
  239.     if (!msg_cnt)
  240.         print("No Mail in %s\n", mailfile);
  241.     if (msg_cnt) {
  242.         display_msg(current_msg, (long)0);
  243.         do_hdrs(0, DUBL_NULL, NULL);
  244.         /* Automatic display should not "touch" this message */
  245.         turnoff(msg[current_msg].m_flags, DO_UPDATE);
  246.         /* don't update folder just because a message is displayed */
  247.         turnoff(glob_flags, DO_UPDATE);
  248.     }
  249.     timeout_cursors(FALSE);
  250.     }
  251. #endif /* SUNTOOL */
  252.     if (list) {
  253.     clear_msg_list(list);
  254.     bitput(list, list, msg_cnt, =~); /* macro */
  255.     }
  256.     return 0;
  257. }
  258.  
  259. folders(argc, argv)
  260. register char **argv;
  261. {
  262.     register char *p;
  263.     char buf[128], unused[MAXMSGS_BITS];
  264.  
  265.     if (argv && argv[1] && !strcmp(argv[1], "-?"))
  266.     return help(0, "folders", cmd_help);
  267.  
  268.     if (!(p = do_set(set_options, "folder")) || !*p)
  269.     p = DEF_FOLDER;
  270.     (void) sprintf(buf, "ls -FR %s", p);
  271.     if (argv = make_command(buf, TRPL_NULL, &argc))
  272.     return do_command(argc, argv, unused);
  273.     return -1;
  274. }
  275.  
  276. /*
  277.  * Determine whether a file could be a folder.  If prompt is non-NULL,
  278.  * ask the user whether we should treat the file as a folder anyway.
  279.  */
  280. test_folder(name, prompt)
  281. char *name, *prompt;
  282. {
  283.     char line[BUFSIZ], *p;
  284.     FILE *fp = fopen(name, "r");
  285.     int retval = FALSE;
  286.  
  287.     if (!fp)
  288.     return 0;
  289.     if (fgets(line, sizeof line - 1, fp)) {
  290. #ifndef MSG_SEPARATOR
  291.     if (p = any(line, " \t")) {
  292.         skipspaces(1);
  293.         p = any(p, " \t");
  294.     }
  295.     if (p && !strncmp(line, "From ", 5) && (p = parse_date(p + 1)))
  296. #else /* MSG_SEPARATOR */
  297.     if (!strncmp(line, MSG_SEPARATOR, strlen(MSG_SEPARATOR)))
  298. #endif /* MSG_SEPARATOR */
  299.         retval = TRUE;
  300.     } else
  301.     retval = TRUE;    /* Empty files are legitimate folders */
  302.     (void) fclose(fp);
  303.     if (prompt && !retval) {
  304.     char buf[BUFSIZ];
  305. #ifdef SUNTOOL
  306.     if (istool) {
  307.         (void) sprintf(buf, "\"%s\": %s", name, prompt);
  308.         return ask(buf);
  309.     }
  310. #endif /* SUNTOOL */
  311.     print("\"%s\": %s [n] ", name, prompt);
  312.     buf[0] = 0;
  313.     retval = (Getstr(buf, sizeof (buf), 0) && lower(*buf) == 'y');
  314.     }
  315.     return retval;
  316. }
  317.  
  318. /* merge_folders filename  -- concatenate the folder specified by filename
  319.  *                            to the current folder.
  320.  *
  321.  * RETURN -1 on error -- else return 0.  A bit in msg_list is set to true
  322.  * for each of the "new" messages read in to the current folder.
  323.  */
  324. merge_folders(n, argv, list)
  325. register char **argv, list[];
  326. {
  327.     int no_hdrs = 0, newest_msg;
  328.     long orig_offset;
  329.     char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  330.  
  331.     if (ison(glob_flags, IS_PIPE)) {
  332.     print("You can't pipe to the %s command.\n", *argv);
  333.     return -1;
  334.     } else if (ison(glob_flags, IS_SENDING)) {
  335.     print("You can't use the %s command while sending.\n", *argv);
  336.     return -1;
  337.     }
  338.  
  339.     while (*++argv && **argv == '-')
  340.     if (!strcmp(*argv, "-?"))
  341.         return help(0, "merge", cmd_help);
  342.     else if (!strcmp(*argv, "-N"))
  343.         no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  344.  
  345.     if (!*argv)
  346.     return 0;
  347.  
  348.     if (ison(glob_flags, READ_ONLY)) {
  349.     print("Folder is read-only.\n");
  350.     return -1;
  351.     }
  352.  
  353.     if (!strcmp(*argv, "#"))
  354.     if (!*oldfolder) {
  355.         print("No previous folder\n");
  356.         return -1;
  357.     } else
  358.         newfolder = oldfolder;
  359.     else if (!strcmp(*argv, "&")) {
  360.     if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  361.         newfolder = DEF_MBOX;
  362.     } else
  363.     newfolder = *argv;
  364.     n = 0;
  365.     tmp = getpath(newfolder, &n);
  366.     if (n == -1) {
  367.     print("%s: %s\n", newfolder, tmp);
  368.     return -1;
  369.     } else if (n == 1) {
  370.     print("%s: is a directory\n", tmp);
  371.     return -1;
  372.     }
  373.  
  374.     turnon(glob_flags, IGN_SIGS);
  375.     orig_offset = msg[msg_cnt].m_offset;
  376.     (void) load_folder(tmp, 2, list);
  377.     msg[msg_cnt].m_offset = orig_offset;
  378.     newest_msg = last_msg_cnt;
  379.     Debug("newest_msg = %d\n", newest_msg);
  380.     last_msg_cnt = msg_cnt;  /* for check_new_mail */
  381.     Debug("msg_cnt = %d\n", msg_cnt);
  382.     if (current_msg < 0)
  383.     current_msg = 0;
  384.     (void) mail_size();
  385.     turnoff(glob_flags, IGN_SIGS);
  386.  
  387.     if ((!istool || istool && !msg_cnt)
  388.         && !iscurses && !ison(glob_flags, PRE_CURSES))
  389.     mail_status(0);
  390.     /* be quiet if we're piping or if told not to show headers */
  391.     if ((istool || !no_hdrs) && isoff(glob_flags, DO_PIPE)
  392.         && newest_msg < msg_cnt)
  393.     (void) cmd_line(sprintf(buf, "headers %d", newest_msg + 1), NULL);
  394.     return 0;
  395. }
  396.  
  397. /*
  398.  * Default digest article separator
  399.  */
  400. #define ARTICLE_SEP "--------"
  401.  
  402. /*
  403.  * Undigestify messages.  If a message is in digest-format, there are many
  404.  * messages within this message which are to be extracted.  Kinda like a
  405.  * folder within a folder.  By default, this routine will create a new
  406.  * folder that contains the new messages.  -m option will merge the new
  407.  * messages into the current folder.
  408.  */
  409. do_undigest(n, argv, list)
  410. char *argv[], list[];
  411. {
  412.     int r, articles = 0, merge = 0, appending = 0;
  413.     char buf[MAXPATHLEN], cmdbuf[MAXPATHLEN], newlist[MAXMSGS_BITS], *dir;
  414.     char *art_sep = ARTICLE_SEP, *mktemp();
  415.     FILE *fp;
  416.  
  417.     while (argv && *++argv && **argv == '-') {
  418.     switch(argv[0][1]) {
  419.         case 'm':
  420.         if (ison(glob_flags, READ_ONLY)) {
  421.             print("Folder is read only.\n");
  422.             return -1;
  423.         }
  424.         merge++;
  425.         when 'p':
  426.         if (*++argv)
  427.             art_sep = *argv;
  428.         else {
  429.             print("Specify separator pattern with -p.\n");
  430.             return -1;
  431.         }
  432.         otherwise: return help(0, "undigest", cmd_help);
  433.     }
  434.     }
  435.  
  436.     if ((n = get_msg_list(argv, list)) == -1)
  437.     return -1;
  438.  
  439.     argv += n;
  440.  
  441.     if (*argv) {
  442.     int isdir = 1; /* Ignore file nonexistance errors */
  443.     (void) strcpy(buf, getpath(*argv, &isdir));
  444.     if (isdir < 0) {
  445.         print("%s: %s\n", *argv, buf);
  446.         return -1;
  447.     } else if (isdir == 1) {
  448.         print("%s: is a directory\n", buf);
  449.         return -1;
  450.     }
  451.     } else {
  452.     register char *p, *p2;
  453.     if (Access(dir = ".", W_OK) == 0 ||
  454.         (dir = do_set(set_options, "folder")) ||
  455.         (dir = do_set(set_options, "tmpdir")))
  456.         dir = getdir(dir); /* expand metachars */
  457.     if (!dir)
  458. alted:
  459.         dir = ALTERNATE_HOME;
  460.     for (n = 0; n < msg_cnt; n++)
  461.         if (msg_bit(list, n))
  462.         break;
  463.  
  464.     if (!(p = header_field(n, "subject")))
  465.         (void) mktemp(sprintf(buf, "%s/digestXXXXX", dir));
  466.     else {
  467.         if (!lcase_strncmp(p, "re: ", 4))
  468.         p += 4;
  469.         for (p2 = p; *p2; p2++)
  470.         if (!isalnum(*p2) && *p2 != '-' && *p2 != '.') {
  471.             *p2 = 0;
  472.             break;
  473.         }
  474.         p2 = buf + Strcpy(buf, dir);
  475.         *p2++ = '/';
  476.         (void) strcpy(p2, p);
  477.     }
  478.     }
  479.  
  480.     if (!Access(buf, W_OK))
  481.     appending = ((fp = mask_fopen(buf, "a")) != NULL_FILE);
  482.     else
  483.     fp = mask_fopen(buf, "w");
  484.     if (!fp) {
  485.     if (!*argv && strcmp(dir, ALTERNATE_HOME))
  486.         goto alted;
  487.     error("can't create %s", buf);
  488.     return -1;
  489.     }
  490.  
  491.     for (n = 0; n < msg_cnt; n++) {
  492.     if (!msg_bit(list, n))
  493.         continue;
  494.  
  495.     print("undigesting message %d\n", n+1);
  496.     /* copy message into file making sure all headers exist. */
  497.     r = undigest(n, fp, art_sep);
  498.     if (r <= 0)
  499.         break;
  500.     articles += r;
  501.     }
  502.     (void) fclose(fp);
  503.     if (r <= 0) {
  504.     if (!appending)
  505.         (void) unlink(buf);
  506.     return -1;
  507.     }
  508.     if (merge) {
  509.     (void) cmd_line(sprintf(cmdbuf, "\\merge -N %s", buf), newlist);
  510.     (void) unlink(buf);
  511.     print("Merged in %d messages.\n", articles);
  512.     } else
  513.     print("Added %d messages to \"%s\".\n", articles, buf);
  514.     clear_msg_list(list);
  515.     for (n = 0; n < msg_cnt; n++)
  516.     if (msg_bit(newlist, n))
  517.         set_msg_bit(list, n);
  518.     return 0;
  519. }
  520.  
  521. /*
  522.  * split digest-message 'n' to file "fp" using article separator "sep".
  523.  * return number of articles copied or -1 if system error on fputs.
  524.  * A digest is a folder-in-a-message in a special, semi-standard form.
  525.  */
  526. undigest(n, fp, sep)
  527. int n;
  528. FILE *fp;
  529. char *sep;
  530. {
  531.     int  art_cnt = 0, on_hdr = -1; /* on_hdr is -1 if hdr not yet found */
  532.     int  sep_len = (sep ? strlen(sep) : strlen(sep = ARTICLE_SEP));
  533.     long get_hdr = 0L;
  534.     char from[HDRSIZ], line[HDRSIZ], last_sep[HDRSIZ];
  535.     char from_hdr[256], afrom[256], adate[64];
  536.     char *fdate = "Xxx Xxx 00 00:00:00 0000"; /* Dummy date in ctime form */
  537.     SIGRET (*oldint)(), (*oldquit)();
  538.  
  539.     if (!msg_get(n, from, sizeof from)) {
  540.     error("Unable to find msg %d", n+1);
  541.     return -1;
  542.     }
  543. #ifndef MSG_SEPARATOR
  544.     else {
  545.     char *p = from + 5;
  546.     skipspaces(0);
  547.     p = index(p, ' ');
  548.     if (p) {
  549.         skipspaces(0);
  550.         fdate = p;
  551.     }
  552.     if (fputs(from, fp) == EOF)
  553.         return -1;
  554.     }
  555. #endif /* !MSG_SEPARATOR */
  556.  
  557.     on_intr();
  558.     *afrom = *adate = *last_sep = '\0';
  559.     while (ftell(tmpf) < msg[n].m_offset + msg[n].m_size &&
  560.        fgets(line, sizeof (line), tmpf)) {
  561.     if (ison(glob_flags, WAS_INTR))
  562.         goto handle_error;
  563.     if (*line == '\n' && on_hdr > 0)    /* blank line -- end of header */
  564.         on_hdr = 0;
  565.  
  566.     /* Check for the beginning of a digest article */
  567.     if (!strncmp(line, sep, sep_len)) {
  568.         if (get_hdr) {
  569.         if (do_set(set_options, "warning"))
  570.             print("Article with no header? (added to article #%d)\n",
  571.                 art_cnt);
  572.         /* Don't start a new message for whatever this is,
  573.          * just fseek back and keep appending to the last one.
  574.          */
  575.         if (fseek(tmpf, get_hdr, L_SET) < 0 ||
  576.             fputs(last_sep, fp) == EOF) {
  577.             art_cnt = -1;
  578.             goto handle_error;
  579.         }
  580.         get_hdr = 0L;
  581.         on_hdr = 0;
  582.         } else {
  583.         (void) strcpy(last_sep, line);
  584.         get_hdr = ftell(tmpf);
  585.         *afrom = *adate = '\0';
  586.         on_hdr = -1;    /* Haven't found the new header yet */
  587.         }
  588.         continue;
  589.     }
  590.  
  591.     if (get_hdr) {
  592.         char *p = *line == '>' ? line + 1 : line;
  593.         if (*line == '\n') {
  594.         if (*afrom || *adate) {
  595.             (void) fseek(tmpf, get_hdr, L_SET);
  596.             /* Terminate the previous article */
  597.             art_cnt++;
  598. #ifdef MSG_SEPARATOR
  599. #ifdef END_MSG_SEP
  600.             if (fputs(END_MSG_SEP, fp) == EOF) {
  601.             art_cnt = -1;
  602.             goto handle_error;
  603.             }
  604. #endif /* END_MSG_SEP */
  605. #ifdef MMDF
  606.             /* MMDF has a newline in MSG_SEPARATOR */
  607.             if (fputs(MSG_SEPARATOR, fp) == EOF)
  608. #else /* !MMDF */
  609.             /* Other MSG_SEPARATORs need a newline */
  610.             if (fputs(MSG_SEPARATOR, fp) == EOF ||
  611.                 fputc('\n', fp) == EOF)
  612. #endif /* MMDF */
  613. #else /* !MSG_SEPARATOR */
  614.             /* Everybody else needs a From_ line */
  615.             if (fprintf(fp, "From %s  %s", *afrom ? afrom : "unknown",
  616.                 *adate ? date_to_ctime(adate) : fdate) == EOF)
  617. #endif /* MSG_SEPARATOR */
  618.             {
  619.             art_cnt = -1;
  620.             goto handle_error;
  621.             }
  622.             /* Make sure there is a From: without a leading > */
  623.             if (*afrom && *from_hdr && fputs(from_hdr, fp) == EOF) {
  624.             art_cnt = -1;
  625.             goto handle_error;
  626.             }
  627.             get_hdr = 0L;
  628.         } else if (on_hdr < 0)
  629.             /* Skip blanks between "--------" and the hdr */
  630.             get_hdr = ftell(tmpf);
  631.         } else if (on_hdr < 0)
  632.         on_hdr = 1;
  633.         if (on_hdr > 0 && !strncmp(p, "From: ", 6)) {
  634.         (void) get_name_n_addr(p + 6, NULL, afrom);
  635.         (void) no_newln(afrom);
  636.         /* Get the From: minus the leading > */
  637.         if (p != line)
  638.             (void) strcpy(from_hdr, p);
  639.         else /* We don't need From: twice! */
  640.             *from_hdr = '\0';
  641.         } else if (on_hdr > 0 && !strncmp(line, "Date: ", 6)) {
  642.         if (p = parse_date(line+6))
  643.             (void) strcpy(adate, p);
  644.         } else if (on_hdr > 0 && !lcase_strncmp(line, "end", 3)) {
  645.         if (!*afrom && !*adate)
  646.             break;
  647.         }
  648.     } else if (fputs(line, fp) == EOF) {
  649.         /* Pipe broken, out of file space, etc */
  650.         art_cnt = -1;
  651.         goto handle_error;
  652.     }
  653.     }
  654.     ++art_cnt;
  655. #ifdef END_MSG_SEP
  656.     if (art_cnt > 0 && fputs(END_MSG_SEP, fp) == EOF) {
  657.     art_cnt = -1;
  658.     goto handle_error;
  659.     }
  660. #endif /* END_MSG_SEP */
  661.     /* If we're still looking for a header, there is some stuff left
  662.      * at the end of the digest.  Create an extra article for it.
  663.      */
  664.     if (get_hdr) {
  665.     char *p;
  666.     (void) fseek(tmpf, get_hdr, L_SET);
  667.     if (ftell(tmpf) >= msg[n].m_offset + msg[n].m_size)
  668.         goto handle_error;
  669. #ifdef MSG_SEPARATOR
  670. #ifdef MMDF
  671.     if (fputs(MSG_SEPARATOR, fp) == EOF)
  672. #else /* !MMDF */
  673.     if (fputs(MSG_SEPARATOR, fp) == EOF ||
  674.         fputc('\n', fp) == EOF)
  675. #endif /* MMDF */
  676. #else /* !MSG_SEPARATOR */
  677.     if (fputs(from, fp) == EOF)
  678. #endif /* MSG_SEPARATOR */
  679.         art_cnt = -1;
  680.     if (!(p = header_field(n, "from")))
  681.         p = "Mush-Undigest (Real author unknown)";
  682.     if (fprintf(fp, "From: %s\n", p) == EOF)
  683.         art_cnt = -1;
  684.     if (!(p = header_field(n, "date")))
  685.         p = fdate, (void) no_newln(p);
  686.     if (fprintf(fp, "Date: %s\n", p) == EOF)
  687.         art_cnt = -1;
  688.     if (!(p = header_field(n, "subject")))
  689.         p = "Digest";
  690.     if (fprintf(fp, "Subject: Trailing part of %s\n\n", p) == EOF)
  691.         art_cnt = -1;
  692.     /* header_field() moves the pointer, so seek again */
  693.     (void) fseek(tmpf, get_hdr, L_SET);
  694.     while (art_cnt > 0 && ftell(tmpf) < msg[n].m_offset + msg[n].m_size
  695.         && fgets(line, sizeof (line), tmpf)) {
  696.         if (fputs(line, fp) == EOF)
  697.         art_cnt = -1;
  698. #ifdef END_MSG_SEP
  699.         if (!strncmp(line, END_MSG_SEP, strlen(END_MSG_SEP)))
  700.         break;
  701. #endif /* END_MSG_SEP */
  702.     }
  703.     /* The END_MSG_SEP, if any, of the digest will have been output
  704.      * by the while loop above, so we don't need to add one here.
  705.      */
  706.     ++art_cnt;
  707.     }
  708. handle_error:
  709.     if (art_cnt == -1)
  710.     error("cannot completely undigest");
  711.     else if (ison(glob_flags, WAS_INTR))
  712.     art_cnt = -1;
  713.     off_intr();
  714.     return art_cnt;
  715. }
  716.