home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume18 / mush6.4 / part07 / folders.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-12  |  16.4 KB  |  593 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, list[];
  22. {
  23.     int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
  24.     char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  25.     struct stat statbuf;
  26.     extern long last_spool_size;
  27.  
  28.     if (ison(glob_flags, IS_PIPE)) {
  29.     print("You can't pipe to the %s command.\n", *argv);
  30.     return -1;
  31.     } else if (ison(glob_flags, IS_SENDING)) {
  32.     print("You can't use the %s command while sending.\n", *argv);
  33.     return -1;
  34.     }
  35.     while (*++argv && (**argv == '-' || **argv == '!'))
  36.     if (!strcmp(*argv, "-?"))
  37.         return help(0, "folder", cmd_help);
  38.     else if (!strcmp(*argv, "-N"))
  39.         no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  40.     else if (!strcmp(*argv, "-r"))
  41.         do_read_only = 1;
  42.     else if (!strcmp(*argv, "!"))
  43.         turnoff(glob_flags, DO_UPDATE);
  44.  
  45.     if (updating) {
  46.     (void) strcpy(buf, mailfile);
  47.     if (ison(glob_flags, READ_ONLY))
  48.         do_read_only = 1;
  49.     } else {
  50.     if (!*argv) {
  51.         mail_status(0);
  52.         return 0;
  53.     }
  54.     if (!strcmp(*argv, "#"))
  55.         if (!*oldfolder) {
  56.         print("No previous folder\n");
  57.         return -1;
  58.         } else
  59.         newfolder = oldfolder;
  60.     else if (!strcmp(*argv, "&")) {
  61.         if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  62.         newfolder = DEF_MBOX;
  63.     } else
  64.         newfolder = *argv;
  65.     n = 0;
  66.     tmp = getpath(newfolder, &n);
  67.     if (n == -1) {
  68.         print("%s: %s\n", newfolder, tmp);
  69.         return -1;
  70.     } else if (n == 1) {
  71.         print("%s: is a directory\n", tmp);
  72.         return -1;
  73.     }
  74.     /* strcpy so copyback() below (which calls getpath) doesn't change
  75.      * the data that tmp intended to point to.
  76.      */
  77.     (void) strcpy(buf, tmp);
  78.     }
  79.     if (stat(buf, &statbuf) == -1 || !(statbuf.st_mode & 0400)) {
  80.     error("Unable to read %s", buf);
  81.     return -1;
  82.     }
  83.     /* If the file can't be opened for writing, autoset READ_ONLY */
  84.     if (!(statbuf.st_mode & 0200))
  85.     do_read_only = 1;
  86. #ifdef SUNTOOL
  87.     if (istool) lock_cursors();
  88. #endif /* SUNTOOL */
  89.  
  90.     if (!copyback(updating ? "Update folder?" : "Change anyway?")) {
  91. #ifdef SUNTOOL
  92.     if (istool) unlock_cursors();
  93. #endif /* SUNTOOL */
  94.     /* an error occured updating the folder */
  95.     return -1;
  96.     }
  97.     if (strcmp(mailfile, buf)) {
  98.     if (!updating)
  99.         (void) strcpy(oldfolder, mailfile);
  100.     strdup(mailfile, buf);
  101.     }
  102.     do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
  103.     last_size = spool_size = 0L;
  104.     while (msg_cnt--) {
  105.     xfree(msg[msg_cnt].m_date_recv);
  106.     xfree(msg[msg_cnt].m_date_sent);
  107.     msg[msg_cnt].m_date_recv = msg[msg_cnt].m_date_sent = NO_STRING;
  108.     }
  109.     msg_cnt = 0, msg[0].m_offset = 0L;
  110.     turnoff(glob_flags, CONT_PRNT);
  111.  
  112.     turnon(glob_flags, IGN_SIGS);
  113.     /* clear the tempfile */
  114.     if (tmpf)
  115.     (void) fclose(tmpf);
  116.     if (!do_read_only) {
  117.     if (!(tmpf = mask_fopen(tempfile, "w"))) {
  118.         error("error truncating %s", tempfile);
  119.         turnoff(glob_flags, IGN_SIGS);
  120.         return -1;
  121.     }
  122.     }
  123.     (void) load_folder(mailfile, TRUE, NULL);
  124.     if (do_read_only && !(tmpf = fopen(mailfile, "r"))) {
  125.     error(mailfile);
  126.     turnoff(glob_flags, IGN_SIGS);
  127.     return -1;
  128.     }
  129.     last_msg_cnt = msg_cnt;  /* for check_new_mail */
  130.     (void) mail_size();
  131.     last_spool_size = spool_size;    /* prevents bogus "new mail" messages */
  132. #ifdef SUNTOOL
  133.     if (istool) {
  134.     panel_set(next_scr, PANEL_SHOW_ITEM, FALSE, 0);
  135.     panel_set(prev_scr, PANEL_SHOW_ITEM, FALSE, 0);
  136.     pw_rop(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,PIX_CLR,0,0,0);
  137.     if (!msg_cnt) {
  138.         add_folder_to_menu(folder_item, 3);
  139.         add_folder_to_menu(save_item, 1);
  140.     }
  141.     }
  142. #endif /* SUNTOOL */
  143.     current_msg = 0;
  144.     turnoff(glob_flags, IGN_SIGS);
  145.  
  146.     /* now sort messages according a user-defined default */
  147.     if (!updating && msg_cnt > 1 && !strcmp(mailfile, spoolfile) &&
  148.         (tmp = do_set(set_options, "sort"))) {
  149.     (void) sprintf(buf, "sort %s", tmp);
  150.     if (argv = make_command(buf, TRPL_NULL, &argc)) {
  151.         /* msg_list can't be null for do_command and since we're not
  152.          * interested in the result, call sort directly
  153.          */
  154.         (void) sort(argc, argv, NULL);
  155.         free_vec(argv);
  156.     }
  157.     }
  158.     turnoff(glob_flags, DO_UPDATE);
  159.  
  160.     /* go to first NEW message */
  161.     while (current_msg < msg_cnt && ison(msg[current_msg].m_flags, OLD))
  162.     current_msg++;
  163.     if (current_msg == msg_cnt)
  164.     /* no new message found -- try first unread message */
  165.     for (current_msg = 0;
  166.          current_msg < msg_cnt && isoff(msg[current_msg].m_flags, UNREAD);
  167.          current_msg++)
  168.          ;
  169.     if (current_msg == msg_cnt)
  170.     current_msg = 0;
  171.  
  172.     if ((!istool || istool && !msg_cnt) && !iscurses)
  173.     mail_status(0);
  174.     /* be quiet if we're piping */
  175.     if ((istool || !updating) && isoff(glob_flags, DO_PIPE) &&
  176.     (istool || !no_hdrs) && msg_cnt)
  177.     (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  178. #ifdef SUNTOOL
  179.     if (istool) {
  180.     if (!msg_cnt)
  181.         print("No Mail in %s\n", mailfile);
  182.     if (!getting_opts)
  183.         if (msg_cnt && isoff(glob_flags, IS_GETTING))
  184.         display_msg(current_msg, (long)0);
  185.         else
  186.         do_clear();
  187.     unlock_cursors();
  188.     }
  189. #endif /* SUNTOOL */
  190.     if (list) {
  191.     clear_msg_list(list);
  192.     bitput(list, list, msg_cnt, =~) /* macro */
  193.     }
  194.     return 0;
  195. }
  196.  
  197. folders(argc, argv)
  198. register char **argv;
  199. {
  200.     register char *p;
  201.     char buf[128], unused[MAXMSGS_BITS];
  202.  
  203.     if (!(p = do_set(set_options, "folder")) || !*p)
  204.     p = DEF_FOLDER;
  205.     (void) sprintf(buf, "ls %s", p);
  206.     if (argv = make_command(buf, TRPL_NULL, &argc))
  207.     return do_command(argc, argv, unused);
  208.     return -1;
  209. }
  210.  
  211. /* merge_folders filename  -- concatenate the folder specified by filename
  212.  *                            to the current folder.
  213.  *
  214.  * RETURN -1 on error -- else return 0.  A bit in msg_list is set to true
  215.  * for each of the "new" messages read in to the current folder.
  216.  */
  217. merge_folders(n, argv, list)
  218. register char **argv, list[];
  219. {
  220.     int no_hdrs = 0, newest_msg;
  221.     long orig_offset;
  222.     char *tmp, *newfolder = NULL, buf[MAXPATHLEN];
  223.  
  224.     if (ison(glob_flags, IS_PIPE)) {
  225.     print("You can't pipe to the %s command.\n", *argv);
  226.     return -1;
  227.     } else if (ison(glob_flags, IS_SENDING)) {
  228.     print("You can't use the %s command while sending.\n", *argv);
  229.     return -1;
  230.     }
  231.  
  232.     while (*++argv && **argv == '-')
  233.     if (!strcmp(*argv, "-?"))
  234.         return help(0, "merge", cmd_help);
  235.     else if (!strcmp(*argv, "-N"))
  236.         no_hdrs = !(iscurses || ison(glob_flags, PRE_CURSES));
  237.  
  238.     if (!*argv)
  239.     return 0;
  240.  
  241.     if (ison(glob_flags, READ_ONLY)) {
  242.     print("Folder is read-only.\n");
  243.     return -1;
  244.     }
  245.  
  246.     if (!strcmp(*argv, "#"))
  247.     if (!*oldfolder) {
  248.         print("No previous folder\n");
  249.         return -1;
  250.     } else
  251.         newfolder = oldfolder;
  252.     else if (!strcmp(*argv, "&")) {
  253.     if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  254.         newfolder = DEF_MBOX;
  255.     } else
  256.     newfolder = *argv;
  257.     n = 0;
  258.     tmp = getpath(newfolder, &n);
  259.     if (n == -1) {
  260.     print("%s: %s\n", newfolder, tmp);
  261.     return -1;
  262.     } else if (n == 1) {
  263.     print("%s: is a directory\n", tmp);
  264.     return -1;
  265.     }
  266.  
  267.     turnon(glob_flags, IGN_SIGS);
  268.     orig_offset = msg[msg_cnt].m_offset;
  269.     (void) load_folder(tmp, 2, list);
  270.     msg[msg_cnt].m_offset = orig_offset;
  271.     newest_msg = last_msg_cnt;
  272.     Debug("newest_msg = %d\n", newest_msg);
  273.     last_msg_cnt = msg_cnt;  /* for check_new_mail */
  274.     Debug("msg_cnt = %d\n", msg_cnt);
  275.     (void) mail_size();
  276.     turnoff(glob_flags, IGN_SIGS);
  277.  
  278.     if ((!istool || istool && !msg_cnt)
  279.         && !iscurses && !ison(glob_flags, PRE_CURSES))
  280.     mail_status(0);
  281.     /* be quiet if we're piping or if told not to show headers */
  282.     if ((istool || !no_hdrs) && isoff(glob_flags, DO_PIPE)
  283.         && newest_msg < msg_cnt)
  284.     (void) cmd_line(sprintf(buf, "headers %d", newest_msg + 1), NULL);
  285.     return 0;
  286. }
  287.  
  288. /*
  289.  * Undigestify messages.  If a message is in digest-format, there are many
  290.  * messages within this message which are to be extracted.  Kinda like a
  291.  * folder within a folder.  By default, this routine will create a new
  292.  * folder that contains the new messages.  -m option will merge the new
  293.  * messages into the current folder.
  294.  */
  295. do_undigest(n, argv, list)
  296. char *argv[], list[];
  297. {
  298.     int r, articles = 0, merge = 0, appending = 0;
  299.     char buf[MAXPATHLEN], cmdbuf[MAXPATHLEN], newlist[MAXMSGS_BITS], *dir, c;
  300.     FILE *fp;
  301.  
  302.     while (argv && *++argv && **argv == '-') {
  303.     n = 1;
  304.     while (c = argv[0][n++])
  305.         switch(c) {
  306.         case 'm':
  307.             if (ison(glob_flags, READ_ONLY)) {
  308.             print("Folder is read only.\n");
  309.             return -1;
  310.             }
  311.             merge++;
  312.         otherwise: return help(0, "undigest", cmd_help);
  313.         }
  314.     }
  315.  
  316.     if ((n = get_msg_list(argv, list)) == -1)
  317.     return -1;
  318.  
  319.     argv += n;
  320.  
  321.     if (*argv) {
  322.     int isdir = 1; /* Ignore file nonexistance errors */
  323.     (void) strcpy(buf, getpath(*argv, &isdir));
  324.     if (isdir < 0) {
  325.         print("%s: %s\n", *argv, buf);
  326.         return -1;
  327.     } else if (isdir == 1) {
  328.         print("%s: is a directory\n", buf);
  329.         return -1;
  330.     }
  331.     } else {
  332.     register char *p, *p2;
  333.     if (Access(dir = ".", W_OK) &&
  334.         !(dir = do_set(set_options, "folder")) &&
  335.         !(dir = do_set(set_options, "tmpdir")))
  336. alted:
  337.         dir = ALTERNATE_HOME;
  338.     for (n = 0; n < msg_cnt; n++)
  339.         if (msg_bit(list, n))
  340.         break;
  341.  
  342.     if (!(p = header_field(n, "subject")))
  343.         (void) mktemp(sprintf(buf, "%s/digestXXXXX", dir));
  344.     else {
  345.         if (!lcase_strncmp(p, "re: ", 4))
  346.         p += 4;
  347.         for (p2 = p; *p2; p2++)
  348.         if (!isalnum(*p2) && *p2 != '-' && *p2 != '.') {
  349.             *p2 = 0;
  350.             break;
  351.         }
  352.         p2 = buf + Strcpy(buf, dir);
  353.         *p2++ = '/';
  354.         (void) strcpy(p2, p);
  355.     }
  356.     }
  357.  
  358.     if (!Access(buf, W_OK)) {
  359.     fp = mask_fopen(buf, "a");
  360.     appending = (fp > 0);
  361.     } else
  362.     fp = mask_fopen(buf, "w");
  363.     if (!fp) {
  364.     if (!*argv && strcmp(dir, ALTERNATE_HOME))
  365.         goto alted;
  366.     error("can't create %s", buf);
  367.     return -1;
  368.     }
  369.  
  370.     for (n = 0; n < msg_cnt; n++) {
  371.     if (!msg_bit(list, n))
  372.         continue;
  373.  
  374.     print("undigesting message %d\n", n+1);
  375.     /* copy message into file making sure all headers exist. */
  376.     r = undigest(n, fp);
  377.     if (r <= 0)
  378.         break;
  379.     articles += r;
  380.     }
  381.     fclose(fp);
  382.     if (r <= 0) {
  383.     if (!appending)
  384.         unlink(buf);
  385.     return -1;
  386.     }
  387.     if (merge) {
  388.     (void) cmd_line(sprintf(cmdbuf, "\\merge -N %s", buf), newlist);
  389.     (void) unlink(buf);
  390.     print("Merged in %d messages.\n", articles);
  391.     } else
  392.     print("Added %d messages to \"%s\".\n", articles, buf);
  393.     clear_msg_list(list);
  394.     for (n = 0; n < msg_cnt; n++)
  395.     if (msg_bit(newlist, n))
  396.         set_msg_bit(list, n);
  397.     return 0;
  398. }
  399.  
  400. /*
  401.  * split digest-message 'n' to file "fp".
  402.  * return number of articles copied or -1 if system error on fputs.
  403.  * A digest is a folder-in-a-message in a special, semi-standard form.
  404.  */
  405. undigest(n, fp)
  406. register int n;
  407. register FILE *fp;
  408. {
  409.     int  art_cnt = 0, on_hdr = -1; /* on_hdr is -1 if hdr not yet found */
  410.     long get_hdr = 0L;
  411.     char from[HDRSIZ], line[HDRSIZ], last_sep[HDRSIZ];
  412.     char from_hdr[256], afrom[256], adate[64];
  413.     char *fdate = "Xxx Xxx 00 00:00:00 0000"; /* Dummy date in ctime form */
  414.     SIGRET (*oldint)(), (*oldquit)();
  415.  
  416.     if (!msg_get(n, from, sizeof from)) {
  417.     error("Unable to find msg %d", n+1);
  418.     return -1;
  419.     }
  420. #ifndef MSG_SEPARATOR
  421.     else {
  422.     char *p = from + 5;
  423.     skipspaces(0);
  424.     p = index(p, ' ');
  425.     if (p) {
  426.         skipspaces(0);
  427.         fdate = p;
  428.     }
  429.     if (fputs(from, fp) == EOF)
  430.         return -1;
  431.     }
  432. #endif /* !MSG_SEPARATOR */
  433.  
  434.     on_intr();
  435.     *afrom = *adate = *last_sep = '\0';
  436.     while (ftell(tmpf) < msg[n].m_offset + msg[n].m_size &&
  437.        fgets(line, sizeof (line), tmpf)) {
  438.     if (ison(glob_flags, WAS_INTR))
  439.         goto handle_error;
  440.     if (*line == '\n' && on_hdr > 0)    /* blank line -- end of header */
  441.         on_hdr = 0;
  442.  
  443.     /* Check for the beginning of a digest article */
  444.     if (!strncmp(line, "--------", 8)) {
  445.         if (get_hdr) {
  446.         if (do_set(set_options, "warning"))
  447.             wprint("Article with no header? (added to article #%d)\n",
  448.                 art_cnt);
  449.         /* Don't start a new message for whatever this is,
  450.          * just fseek back and keep appending to the last one.
  451.          */
  452.         if (fseek(tmpf, get_hdr, L_SET) < 0 ||
  453.             fputs(last_sep, fp) == EOF) {
  454.             art_cnt = -1;
  455.             goto handle_error;
  456.         }
  457.         get_hdr = 0L;
  458.         on_hdr = 0;
  459.         } else {
  460.         (void) strcpy(last_sep, line);
  461.         get_hdr = ftell(tmpf);
  462.         *afrom = *adate = '\0';
  463.         on_hdr = -1;    /* Haven't found the new header yet */
  464.         }
  465.         continue;
  466.     }
  467.  
  468.     if (get_hdr) {
  469.         char *p = *line == '>' ? line + 1 : line;
  470.         if (*line == '\n') {
  471.         if (*afrom || *adate) {
  472.             (void) fseek(tmpf, get_hdr, L_SET);
  473.             /* Terminate the previous article */
  474.             art_cnt++;
  475. #ifdef MSG_SEPARATOR
  476. #ifdef END_MSG_SEP
  477.             if (fputs(END_MSG_SEP, fp) == EOF) {
  478.             art_cnt = -1;
  479.             goto handle_error;
  480.             }
  481. #endif /* END_MSG_SEP */
  482. #ifdef MMDF
  483.             /* MMDF has a newline in MSG_SEPARATOR */
  484.             if (fputs(MSG_SEPARATOR, fp) == EOF)
  485. #else /* !MMDF */
  486.             /* Other MSG_SEPARATORs need a newline */
  487.             if (fputs(MSG_SEPARATOR, fp) == EOF ||
  488.                 fputc('\n', fp) == EOF)
  489. #endif /* MMDF */
  490. #else /* !MSG_SEPARATOR */
  491.             /* Everybody else needs a From_ line */
  492.             if (fprintf(fp, "From %s  %s", *afrom ? afrom : "unknown",
  493.                 *adate ? date_to_ctime(adate) : fdate) == EOF)
  494. #endif /* MSG_SEPARATOR */
  495.             {
  496.             art_cnt = -1;
  497.             goto handle_error;
  498.             }
  499.             /* Make sure there is a From: without a leading > */
  500.             if (*afrom && *from_hdr && fputs(from_hdr, fp) == EOF) {
  501.             art_cnt = -1;
  502.             goto handle_error;
  503.             }
  504.             get_hdr = 0L;
  505.         } else if (on_hdr < 0)
  506.             /* Skip blanks between "--------" and the hdr */
  507.             get_hdr = ftell(tmpf);
  508.         } else if (on_hdr < 0)
  509.         on_hdr = 1;
  510.         if (on_hdr > 0 && !strncmp(p, "From: ", 6)) {
  511.         (void) get_name_n_addr(p + 6, NULL, afrom);
  512.         (void) no_newln(afrom);
  513.         /* Get the From: minus the leading > */
  514.         if (p != line)
  515.             (void) strcpy(from_hdr, p);
  516.         else /* We don't need From: twice! */
  517.             *from_hdr = '\0';
  518.         } else if (on_hdr > 0 && !strncmp(line, "Date: ", 6)) {
  519.         if (p = parse_date(line+6))
  520.             (void) strcpy(adate, p);
  521.         } else if (on_hdr > 0 && !lcase_strncmp(line, "end", 3)) {
  522.         if (!*afrom && !*adate)
  523.             break;
  524.         }
  525.     } else if (fputs(line, fp) == EOF) {
  526.         /* Pipe broken, out of file space, etc */
  527.         art_cnt = -1;
  528.         goto handle_error;
  529.     }
  530.     }
  531.     ++art_cnt;
  532. #ifdef END_MSG_SEP
  533.     if (art_cnt > 0 && fputs(END_MSG_SEP, fp) == EOF) {
  534.     art_cnt = -1;
  535.     goto handle_error;
  536.     }
  537. #endif /* END_MSG_SEP */
  538.     /* If we're still looking for a header, there is some stuff left
  539.      * at the end of the digest.  Create an extra article for it.
  540.      */
  541.     if (get_hdr) {
  542.     char *p;
  543.     (void) fseek(tmpf, get_hdr, L_SET);
  544.     if (ftell(tmpf) >= msg[n].m_offset + msg[n].m_size)
  545.         goto handle_error;
  546. #ifdef MSG_SEPARATOR
  547. #ifdef MMDF
  548.     if (fputs(MSG_SEPARATOR, fp) == EOF)
  549. #else /* !MMDF */
  550.     if (fputs(MSG_SEPARATOR, fp) == EOF ||
  551.         fputc('\n', fp) == EOF)
  552. #endif /* MMDF */
  553. #else /* !MSG_SEPARATOR */
  554.     if (fputs(from, fp) == EOF)
  555. #endif /* MSG_SEPARATOR */
  556.         art_cnt = -1;
  557.     if (!(p = header_field(n, "from")))
  558.         p = "Mush-Undigest (Real author unknown)";
  559.     if (fprintf(fp, "From: %s\n", p) == EOF)
  560.         art_cnt = -1;
  561.     if (!(p = header_field(n, "date")))
  562.         p = fdate, no_newln(p);
  563.     if (fprintf(fp, "Date: %s\n", p) == EOF)
  564.         art_cnt = -1;
  565.     if (!(p = header_field(n, "subject")))
  566.         p = "Digest";
  567.     if (fprintf(fp, "Subject: Trailing part of %s\n\n", p) == EOF)
  568.         art_cnt = -1;
  569.     /* header_field() moves the pointer, so seek again */
  570.     (void) fseek(tmpf, get_hdr, L_SET);
  571.     while (art_cnt > 0 && ftell(tmpf) < msg[n].m_offset + msg[n].m_size
  572.         && fgets(line, sizeof (line), tmpf)) {
  573.         if (fputs(line, fp) == EOF)
  574.         art_cnt = -1;
  575. #ifdef END_MSG_SEP
  576.         if (!strncmp(line, END_MSG_SEP, strlen(END_MSG_SEP)))
  577.         break;
  578. #endif /* END_MSG_SEP */
  579.     }
  580.     /* The END_MSG_SEP, if any, of the digest will have been output
  581.      * by the while loop above, so we don't need to add one here.
  582.      */
  583.     ++art_cnt;
  584.     }
  585. handle_error:
  586.     if (art_cnt == -1)
  587.     error("cannot completely undigest");
  588.     else if (ison(glob_flags, WAS_INTR))
  589.     art_cnt = -1;
  590.     off_intr();
  591.     return art_cnt;
  592. }
  593.