home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / mush6.0 / part07 / msgs.c < prev   
Encoding:
C/C++ Source or Header  |  1988-04-12  |  18.7 KB  |  698 lines

  1. /* @(#)msgs.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4. #ifdef SYSV
  5. #ifndef USG
  6. #include <sys/locking.h>
  7. #else /* USG */
  8. #include <unistd.h>
  9. #endif /* USG */
  10. #endif /* SYSV */
  11.  
  12. lock_file(filename, fd)
  13. char *filename;
  14. {
  15. #ifdef SYSV
  16. #ifndef USG
  17.     (void) locking(fd, LK_LOCK, 0); /* xenix */
  18. #else
  19.     /* if unable to lock, tell them */
  20.     if (Access(filename, W_OK) || lockf(fd, F_TLOCK, 0)) /* system-v */
  21.     return -1;
  22. #endif /* USG */
  23. #else
  24. #ifdef BSD
  25.     if (flock(fd, LOCK_SH))  /* if exclusively locked, flock blocks */
  26.     return -1;
  27. #else /* BSD */
  28.     "There is no supported file locking function compiled in this version!";
  29. #endif /* BSD */
  30. #endif /* SYSV */
  31.     return 0;
  32. }
  33.  
  34. close_lock(fp)
  35. FILE *fp;
  36. {
  37. #ifdef SYSV
  38. #ifndef USG
  39.     locking(fileno(fp), LK_UNLCK, 0);
  40. #else
  41.     lockf(fileno(fp), F_ULOCK, 0);
  42. #endif /* USG */
  43. #endif /* SYSV */
  44.     fclose(fp);            /* implicit unlock for BSD */
  45. }
  46.  
  47. void
  48. display_msg(n, flg)
  49. register int n;
  50. long flg;
  51. {
  52.     register FILE *pp;
  53.  
  54.     if (ison(msg[n].m_flags, DELETE)) {
  55.     print("Message %d deleted; ", n+1);
  56. #ifdef SUNTOOL
  57.     if (istool)
  58.         print_more("Select UNDELETE to read."), do_clear();
  59.     else
  60. #endif /* SUNTOOL */
  61.     if (iscurses)
  62.         print_more("Type 'u' to undelete.");
  63.     else
  64.         print("Type 'undelete %d' to undelete\n", n+1);
  65.     return;
  66.     }
  67.     set_isread(n);
  68.     if (ison(flg, TOP)) {
  69.     turnon(flg, NO_HEADER);
  70.     print("Top of "), turnon(glob_flags, CONT_PRNT);
  71.     }
  72.  
  73.     if (!istool && isoff(flg, NO_PAGE) &&
  74.         crt < msg[n].m_lines && isoff(flg, TOP)) {
  75.     char buf[32], *pager = do_set(set_options, "pager");
  76.     if (!pager)
  77.         pager = DEF_PAGER;
  78.     if (!*pager || !strcmp(pager, "internal"))
  79.         pager = NULL; /* default to internal pager if pager set to "" */
  80.     (void) do_pager(pager, TRUE); /* start pager */
  81.     (void) do_pager(sprintf(buf, "Message #%d (%d lines)\n",
  82.              n+1, msg[n].m_lines), FALSE);
  83.     (void) copy_msg(n, NULL_FILE, flg);
  84.     (void) do_pager(NULL, FALSE); /* end pager */
  85.     } else {
  86.     print("Message #%d (%d lines)\n", n+1, msg[n].m_lines);
  87.     (void) copy_msg(n, stdout, flg);
  88.     }
  89. }
  90.  
  91. /*
  92.  * copy message 'n' to file "fp" according to various flag arguments
  93.  * return number of lines copied or -1 if system error on fputs.
  94.  * If "fp" is null, send to internal pager.  This can only happen from
  95.  * display_msg above.
  96.  */
  97. copy_msg(n, fp, flags)
  98. register int n;
  99. long flags;
  100. register FILE *fp;
  101. {
  102.     register int  ignoring = 0, lines = 0;
  103.     register char *indent_str;
  104.     int  on_hdr = 1, top, squeeze = FALSE;
  105.     char       line[BUFSIZ], *show_hdrs = NULL;
  106.  
  107.     still_more = 0;
  108.     if (ison(flags, TOP)) {
  109.     register char *p = do_set(set_options, "toplines");
  110.     top = (p)? atoi(p) : crt;
  111.     }
  112.     /* When updating to a folder, always write all headers! */
  113.     if (ison(flags, UPDATE_STATUS))
  114.     turnon(flags, NO_IGNORE);
  115.     else if (do_set(set_options, "alwaysignore"))
  116.     turnoff(flags, NO_IGNORE);
  117.     if (isoff(flags, NO_IGNORE)) {
  118.     if (do_set(set_options, "squeeze"))
  119.         squeeze = TRUE;
  120.     show_hdrs = do_set(set_options, "show_hdrs");
  121.     }
  122.  
  123. #ifdef SUNTOOL
  124.     if (istool && (!fp || fp == stdout)) {
  125.     register int x = (msg[n].m_lines + 2) * l_height(curfont);
  126.  
  127.     if (x > 32765) { /* to overcome a bug in pixrects that sun won't fix */
  128.         print("message too big to display using this font");
  129.         return 0;
  130.     }
  131.     if (x < msg_rect.r_height) /* make it at least as big as the window */
  132.         x = msg_rect.r_height;
  133.     /* If the window isn't big enough, an inifite loop occurs in Addstr */
  134.     if (x < 2 * l_height(curfont) || msg_rect.r_width < 3*l_width(curfont))
  135.         return 0;
  136.     do_clear();
  137.     lock_cursors();
  138.     /* msg_pix is for Addstr() */
  139.     if (!(msg_pix = mem_create(msg_rect.r_width, x, 1))) {
  140.         error("mem_create");
  141.         return 0;
  142.     }
  143.     pr_rop(msg_pix, 0,0, msg_rect.r_width-1, x-1, PIX_CLR, 0,0,0);
  144.     on_hdr = 1;
  145.     }
  146. #endif /* SUNTOOL */
  147.     if (ison(flags, INDENT)) {
  148.     if ((indent_str = do_set(set_options, "pre_indent_str"))) {
  149.         char *old_fmt = hdr_format;
  150.         hdr_format = indent_str;
  151.         fprintf(fp, "%s\n", compose_hdr(n) + 9); /* magic number 9 !! */
  152.         hdr_format = old_fmt;
  153.     }
  154.     if (!(indent_str = do_set(set_options, "indent_str")))
  155.         indent_str = DEF_INDENT_STR;
  156.     }
  157.     if (fseek(tmpf, msg[n].m_offset, L_SET) == -1) {
  158.     error("Unable to find msg %d", n+1);
  159.     return -1;
  160.     }
  161.     while (still_more < msg[n].m_size && fgets(line, BUFSIZ, tmpf)) {
  162.     still_more += strlen(line);
  163.     /*
  164.      * If squeeze is one, all blanks lines squeeze down to one blank line.
  165.      * If squeeze is two, squeezing is in progress so wait for the next \n.
  166.      */
  167.     if (*line == '\n') {
  168.         if (on_hdr)    /* blank line -- end of header */
  169.         turnoff(flags, NO_HEADER), on_hdr = 0;
  170.         if (squeeze > 1)
  171.         continue;
  172.         else if (squeeze)
  173.         squeeze = 2;
  174.     } else if (squeeze > 1)
  175.         squeeze = 1;
  176.  
  177.     if (ison(flags, UPDATE_STATUS))
  178.         if (!strncmp(line, "Status:", 7))
  179.         continue; /* ignore this and other "Status" lines */
  180.         else if (!on_hdr) {
  181.         /* preserve NEW/UNREAD status on preserved messages */
  182.         register char *p = line;
  183.         p += Strcpy(p, "Status: O");
  184.         if (isoff(msg[n].m_flags, UNREAD) &&
  185.             isoff(msg[n].m_flags, PRESERVE))
  186.             *p++ = 'R';
  187.         if (ison(msg[n].m_flags, REPLIED))
  188.             *p++ = 'r';
  189.         *p++ = '\n', *p = 0;
  190.         fputs(line, fp);
  191.         (void) strcpy(line, "\n");
  192.         turnoff(flags, UPDATE_STATUS);
  193.         }
  194.     if (on_hdr && isoff(flags, NO_IGNORE)) {
  195.         register char *p = any(line, " \t:");
  196.         if (!p)
  197.         ignoring = 0, on_hdr = 0;
  198.         else if (ignoring)
  199.         if (*p != ':') {
  200.             Debug("Ignoring: %s", line);
  201.             continue;
  202.         } else
  203.             ignoring = 0;
  204.         if (p && *p == ':') {
  205.         *p = 0;
  206.         ignoring = 0;
  207.         if (show_hdrs) {
  208.             if (!chk_two_lists(line, show_hdrs, ":, \t"))
  209.             ignoring = 1;
  210.         } else {
  211.             register struct options *opts;
  212.             for (opts = ignore_hdr; opts; opts = opts->next)
  213.             if (!lcase_strcmp(opts->option, line)) {
  214.                 ignoring = 1;
  215.                 break;
  216.             }
  217.         }
  218.         *p = ':';
  219.         if (ignoring) {
  220.             Debug("Ignoring: %s", line);
  221.             continue;
  222.         }
  223.         }
  224.     }
  225.     if (!on_hdr && ison(flags, TOP) && !--top)
  226.         break;
  227.     if (isoff(flags, NO_HEADER)) {
  228.         /* note that function returns the number of lines */
  229.         lines++;
  230. #ifdef SUNTOOL
  231.         if (istool && (!fp || fp == stdout)) {
  232.         Addstr(line);
  233.         continue;
  234.         }
  235. #endif /* SUNTOOL */
  236.         if (ison(flags, INDENT))
  237.         fputs(indent_str, fp);
  238.         if (!fp) {
  239.         if (do_pager(line, FALSE) == EOF)
  240.             return -1;
  241.         } else if (fputs(line, fp) == EOF)
  242.         /* Pipe broken, out of filespace, etc */
  243.         return -1;
  244.     }
  245.     }
  246.     if (ison(flags, INDENT) &&
  247.     (indent_str = do_set(set_options, "post_indent_str")) && *indent_str) {
  248.     char *old_fmt = hdr_format;
  249.     hdr_format = indent_str;
  250.     fprintf(fp, "%s\n", compose_hdr(n)+9); /* magic number 9 !! */
  251.     hdr_format = old_fmt;
  252.     }
  253. #ifdef SUNTOOL
  254.     if (istool && (!fp || fp == stdout)) {
  255.     unlock_cursors();
  256.     txt.y = still_more = msg_rect.r_height;
  257.     scroll_win(0);  /* causes a display */
  258.     }
  259. #endif /* SUNTOOL */
  260.     return lines;
  261. }
  262.  
  263. /* get mail from whatever the mailfile points to. open a tempfile for
  264.  * appending, then close it and reopen it for read-only.  some systems
  265.  * have flakey read/write access.
  266.  */
  267. void
  268. getmail()
  269. {
  270.     register FILE    *mail_fp;
  271.     int     lines = 0, get_status = 1, len;
  272.     long     ftell(), bytes;
  273.     char    line[BUFSIZ];
  274.  
  275. #ifdef SYSV
  276.     /* for SVID systems to lock, the file must be open for read/write */
  277.     if (isoff(glob_flags, READ_ONLY))
  278.     mail_fp = fopen(mailfile, "r+");
  279.     else
  280. #endif /* SYSV */
  281.     mail_fp = fopen(mailfile, "r");
  282.  
  283.     if (!mail_fp) {
  284.     error("Unable to open %s", mailfile);
  285.     return;
  286.     }
  287.     /*
  288.      * since this file is usually open for read-only, close it and then
  289.      * reopen it for appending.  This is done to compensate for errors
  290.      * in XENIX and to play it safe with non-essentially writable files.
  291.      * see more notes below (end of proc).
  292.      */
  293.     if (isoff(glob_flags, READ_ONLY)) {
  294.     int    omask = umask(077);
  295.  
  296.     (void) fclose(tmpf);
  297.     tmpf = fopen(tempfile, "a");
  298.     (void) umask(omask);
  299.     if (!tmpf) {
  300.         error("Unable to open %s for appending", tempfile);
  301.         (void) fclose(mail_fp);
  302.         return;
  303.     }
  304.     } else if (msg_cnt)
  305.     (void) fseek(tmpf, msg[msg_cnt-1].m_offset+msg[msg_cnt-1].m_size,L_SET);
  306.  
  307.     if (isoff(glob_flags, READ_ONLY) && lock_file(mailfile, fileno(mail_fp)))
  308.     error("WARNING: unable to lock %s", mailfile);
  309.  
  310.     (void) fseek(mail_fp, ftell(tmpf), L_SET);
  311.  
  312. #ifdef MSG_SEPARATOR
  313.     len = strlen(MSG_SEPARATOR);
  314. #endif /* MSG_SEPARATOR */
  315.  
  316.     while (fgets(line, BUFSIZ, mail_fp) != NULL) {
  317. #ifndef MSG_SEPARATOR
  318.     if (!strncmp(line, "From ", 5) &&
  319.         !sscanf(line+5, "%*s %*s %*s %*d %*d:%*d"))
  320. #else /* MSG_SEPARATOR */
  321.     if (!strncmp(line, MSG_SEPARATOR, len))
  322. #endif /* MSG_SEPARATOR */
  323.     {
  324.         if (msg_cnt == MAXMSGS-1) {
  325.         print("WARNING: exceeded %d messages.\n", MAXMSGS);
  326.         print("You should split \"%s\" into smaller files.\n",mailfile);
  327.         /* make sure that tempfile isn't removed!! */
  328.         turnon(glob_flags, IGN_SIGS);
  329.         cleanup(0); /* probably a more elegant way to exit, but... */
  330.         }
  331.         bytes = ftell(tmpf);
  332.         /* finish up message structure from previous message.
  333.          * if this is incorporating new mail, check "lines" to
  334.          * see if previous message has already been set!
  335.          */
  336.         if (msg_cnt && lines) {
  337.         msg[msg_cnt-1].m_size = bytes - msg[msg_cnt-1].m_offset;
  338.         msg[msg_cnt-1].m_lines = lines;
  339.         }
  340.         msg[msg_cnt].m_offset = bytes;
  341.         msg[msg_cnt].m_flags = lines = 0;
  342.         turnon(msg[msg_cnt].m_flags, UNREAD); /* initialize */
  343.  
  344.         if (isoff(glob_flags, READ_ONLY)) {
  345.         fputs(line, tmpf);
  346.         if (errno == ENOSPC)
  347.             fs_error();
  348.         }
  349.         /* we've read the "From " line, now read the rest of
  350.          * the message headers till we get to a blank line.
  351.          */
  352.         while (fgets(line, BUFSIZ, mail_fp) && (*line != '\n')) {
  353.         register char *p = line;
  354.         if (get_status && !(get_status = strncmp(p, "Status:", 7))) {
  355.             turnon(msg[msg_cnt].m_flags, OLD);
  356.             for (p += 8 ; *p != '\n'; p++)
  357.             switch(*p) {
  358.                 when 'R': turnoff(msg[msg_cnt].m_flags, UNREAD);
  359.                 when 'P': turnon(msg[msg_cnt].m_flags, UNREAD);
  360.                 when 'r': turnon(msg[msg_cnt].m_flags, REPLIED);
  361.                 otherwise :
  362.                 if (ison(glob_flags, WARNING))
  363.                     print("unknown msg status flag: %c", *p);
  364.             }
  365.         }
  366.         lines++;
  367.         if (isoff(glob_flags, READ_ONLY)) {
  368.             fputs(line, tmpf);
  369.             if (errno == ENOSPC)
  370.             fs_error();
  371.         }
  372.         }
  373.         msg_cnt++, get_status = 1;
  374.     }
  375.     lines++;
  376.     if (isoff(glob_flags, READ_ONLY)) {
  377.         fputs(line, tmpf);
  378.         if (errno == ENOSPC)
  379.         fs_error();
  380.     } else
  381.         (void) fseek(tmpf, ftell(mail_fp), L_SET);
  382.     }
  383.     /* msg_cnt may be 0 if there is an error with the format of mailfile */
  384.     if (msg_cnt) {
  385.     msg[msg_cnt-1].m_size = ftell(tmpf) - msg[msg_cnt-1].m_offset;
  386.     msg[msg_cnt-1].m_lines = lines;
  387.     }
  388.  
  389.     close_lock(mail_fp);
  390.  
  391.     /* I've had problems with sys-v opening a file for read/write. I'd
  392.      * try fgets after a seek to an arbitrary place and get NULL. "w+"
  393.      * could be broken (XENIX), so play it safe anyway.
  394.      */
  395.     if (isoff(glob_flags, READ_ONLY)) {
  396.     fclose(tmpf);
  397.     if (!(tmpf = fopen(tempfile, "r")))
  398.         error("unable to open %s for reading", tempfile);
  399.     }
  400. }
  401.  
  402. fs_error()
  403. {
  404.     error("WARNING: unable to write to \"%s\"", tempfile);
  405.     print("Read the manual on what to do on full file systems.\n");
  406.     cleanup(0);
  407. }
  408.  
  409. /*
  410.  * copy temp or whatever back to mailfile
  411.  * Return 0 if new mail came and user doesn't want to exit.
  412.  */
  413. copyback()
  414. {
  415.     register int    new = 0, i, j=0, k=0;
  416.     register long    flg = 0;
  417.     register FILE    *mbox = NULL_FILE, *mail_fp;
  418.     char        *mbox_file, action = 0;
  419.     int         hold = 0, delete_it = 0, dont_unlink = FALSE;
  420.  
  421. #ifdef SUNTOOL
  422.     if (istool) {
  423.     timerclear(&(mail_timer.it_interval));
  424.     timerclear(&(mail_timer.it_value));
  425.     }
  426. #endif /* SUNTOOL */
  427.     if (ison(glob_flags, READ_ONLY)) {
  428.     print("Unable to update %s: read only\n", mailfile);
  429.     return 1;
  430.     }
  431.     if (check_new_mail()) {
  432.     new = 1;
  433.     if (!istool) {
  434.         char buf[256];
  435.         if (iscurses)
  436.         putchar('\n');
  437.         print("Really quit? ");
  438.         buf[0] = 0;
  439.         if (!Getstr(buf, 256, 0) || lower(*buf) != 'y')
  440.         return 0;
  441.     }
  442.     } else if (!msg_cnt) /* prevent unnecessary overwrite */
  443.     return 0;
  444.     /* open mbox if: "autodelete" AND "hold" are NOT set. */
  445.     if (!strcmp(mailfile, spoolfile)
  446.         && !(delete_it = !!do_set(set_options, "autodelete"))
  447.         && !(hold = !!do_set(set_options, "hold"))) {
  448.     register char *p;
  449.     int x = 1; /* tell getpath to ignore "ENOENT" if file not found */
  450.  
  451.     if (!(p = do_set(set_options, "mbox")))
  452.         p = DEF_MBOX;
  453.     mbox_file = getpath(p, &x);
  454.     if (x) {
  455.         if (x > 0)
  456.         print("%s is a directory.\n", mbox_file);
  457.         else
  458.         print("Unable to open %s: %s\n", p, mbox_file);
  459.         mbox = NULL_FILE;
  460.     } else {
  461.         if (Access(mbox_file, F_OK) == -1) /* does it exist? */
  462.         mbox = fopen(mbox_file, "w");
  463.         else
  464.         mbox = fopen(mbox_file, "a");
  465.         if (!mbox)
  466.         error("Unable to write to %s", mbox_file);
  467.     }
  468.     }
  469.     /* reopen the mailfile; set umask accordingly */
  470.     {
  471.     int omask = umask(077);
  472.     mail_fp = fopen(mailfile, "w+");
  473.     (void) umask(omask);
  474.     if (!mail_fp) {
  475.         error("Unable to rewrite %s", mailfile);
  476.         return 0;
  477.     }
  478.     }
  479.     turnon(glob_flags, IGN_SIGS);
  480.     print("Updating \"%s\"", mailfile);
  481.  
  482.     if (lock_file(mailfile, fileno(mail_fp)))
  483.     error("WARNING: unable to lock %s", mailfile);
  484.  
  485.     turnon(flg, UPDATE_STATUS);
  486.     turnon(flg, NO_IGNORE);
  487.  
  488.     for (i = 0; i < msg_cnt; i++)
  489.     /* check to see if message is marked for deletion or, if read and not
  490.      * preserved, delete it if autodelete is set. Otherwise, save the
  491.      * message in the spool file if hold is set. If all fails, save in mbox.
  492.      */
  493.     if (ison(msg[i].m_flags, DELETE)
  494.         || isoff(msg[i].m_flags, UNREAD) && isoff(msg[i].m_flags, PRESERVE) 
  495.         && delete_it) {
  496.         Debug("%s %d",
  497.         (action!='d')? "\ndeleting message:" : "", i+1), action = 'd';
  498.         continue;
  499.     } else if (ison(msg[i].m_flags, UNREAD) ||
  500.          ison(msg[i].m_flags, PRESERVE) || hold || !mbox) {
  501.         j++;
  502.         Debug("%s %d",
  503.         (action!='s')? "\nsaving in spool:" : "", i+1), action = 's';
  504.         if (copy_msg(i, mail_fp, flg) == -1) {
  505.         error("WARNING: unable to write back to spool");
  506.         print("ALL mail left in %s\n", tempfile);
  507.         print("Spool mailbox may be corrupted.\n");
  508.         if (new)
  509.             print("New mail may be lost. :-(\n");
  510.         dont_unlink = TRUE;
  511.         break;
  512.         }
  513.     } else if (!strcmp(mailfile, spoolfile)) {   /* copy back to mbox */
  514.         k++;
  515.         if (copy_msg(i, mbox, flg) == -1) {
  516.         error("WARNING: unable to write to mbox");
  517.         print("Unresolved mail left in %s\n", tempfile);
  518.         dont_unlink = TRUE;
  519.         break;
  520.         }
  521.         Debug("%s %d",
  522.         (action!='m')? "\nsaving in mbox:" : "", i+1), action = 'm';
  523.     }
  524.     Debug("\n%s", mailfile);
  525.  
  526.     close_lock(mail_fp);
  527.  
  528.     if (mbox)
  529.     fclose(mbox);
  530.     if (j) {
  531.     long times[2];
  532.     times[1] = time(×[0]) - (long)2;
  533.     if (!strcmp(mailfile, spoolfile) && utime(mailfile, times))
  534.         error("utime");
  535.     print_more(": saved %d message%s\n", j, (j==1)? NO_STRING: "s");
  536.     } else if (strcmp(mailfile, spoolfile) && !dont_unlink && !new)
  537.     if (unlink(mailfile))
  538.         turnon(glob_flags, CONT_PRNT), error(": cannot remove");
  539.     else
  540.         print_more(": removed\n");
  541.     else
  542.     print_more(": empty\n");
  543.     if (k)
  544.     print("saved %d message%s in %s\n",k,(k==1)? NO_STRING: "s",mbox_file);
  545.     if (new && !istool)
  546.     print("New mail has arrived.\n");
  547.     turnoff(glob_flags, IGN_SIGS);
  548. #ifdef SUNTOOL
  549.     if (istool) {
  550.     mail_timer.it_value.tv_sec = time_out;
  551.     setitimer(ITIMER_REAL, &mail_timer, NULL);
  552.     }
  553. #endif /* SUNTOOL */
  554.     return 1;
  555. }
  556.  
  557. mail_size()
  558. {
  559.     struct stat buf;
  560.     if (strcmp(mailfile, spoolfile)) {
  561.     char tmp[128];
  562.     if (!stat(sprintf(tmp, "%s/%s", MAILDIR, login), &buf))
  563.         spool_size = buf.st_size;
  564.     }
  565.     if (!*mailfile)
  566.     return 0;
  567.     if (stat(mailfile, &buf)) {
  568.     if (errno != ENOENT)
  569.         error("Unable to stat %s", mailfile);
  570.     return 0;
  571.     }
  572.     if (!strcmp(mailfile, spoolfile))
  573.     spool_size = buf.st_size;
  574.     if (buf.st_size > last_size) {
  575.     last_size = buf.st_size;
  576.     return 1;
  577.     }
  578.     return 0;
  579. }
  580.  
  581. void
  582. mail_status(as_prompt)
  583. {
  584.     static char buf[256];
  585.     register int cnt = 0, new = 0, unread = 0, deleted = 0;
  586.  
  587.     for ( ; cnt < msg_cnt; cnt++) {
  588.     if (ison(msg[cnt].m_flags, UNREAD))
  589.         unread++;
  590.     if (ison(msg[cnt].m_flags, DELETE))
  591.         deleted++;
  592.     if (isoff(msg[cnt].m_flags, OLD))
  593.         new++;
  594.     }
  595.     if (as_prompt) {
  596.     register char *p, *b = buf;
  597.     for (p = prompt; *p; p++)
  598.         if (*p == '\\')
  599.         switch (*++p) {
  600.             case 'n': case 'r': *b++ = '\n';
  601.             when 't': *b++ = '\t';
  602.             otherwise: *b++ = *p;
  603.         }
  604.         else if (*p == '%')
  605.         switch (*++p) {
  606.             case 'm':
  607.             b += strlen(sprintf(b,"%d",(msg_cnt)? current_msg+1:0));
  608.             when 't':
  609.             b += strlen(sprintf(b, "%d", msg_cnt));
  610.             when 'd':
  611.             b += strlen(sprintf(b, "%d", deleted));
  612.             when 'u':
  613.             b += strlen(sprintf(b, "%d", unread));
  614.             when 'n':
  615.             b += strlen(sprintf(b, "%d", new));
  616.             when 'f':
  617.             b += Strcpy(b, mailfile);
  618.             if (ison(glob_flags, READ_ONLY))
  619.                 b += Strcpy(b, " [read only]");
  620.             when 'T': case 'D': case 'Y': case 'M': case 'N':
  621.             b += Strcpy(b, Time(p, (long)0));
  622.             otherwise: *b++ = *p;
  623.         }
  624.         else if (*p == '!')
  625.         b += strlen(sprintf(b, "%d", hist_no+1));
  626.         else
  627.         *b++ = *p;
  628.     *b = 0;
  629.     print("%s", buf); /* buf MIGHT have a % in it... don't pass as fmt */
  630.     return;
  631.     }
  632.     (void) sprintf(buf,"\"%s\"%s: %d message%s, %d new, %d unread",
  633.     mailfile, ison(glob_flags, READ_ONLY)? " [read only]" : "",
  634.     msg_cnt, (msg_cnt != 1)? "s": NO_STRING, new, unread);
  635.     if (istool || iscurses)
  636.     (void) sprintf(buf+strlen(buf), ", %d deleted", deleted);
  637. #ifdef SUNTOOL
  638.     if (istool) {
  639.     static char ic_text[4];
  640.     extern struct pixrect mail_icon_image1, mail_icon_image2;
  641.     (void) sprintf(ic_text, "%3d", msg_cnt);
  642.     tool_set_attributes(tool,
  643.         WIN_LABEL, buf,
  644.         WIN_ICON_LABEL, ic_text,
  645.         WIN_ICON_IMAGE, ison(glob_flags, NEW_MAIL)?
  646.         &mail_icon_image2 : &mail_icon_image1,
  647.         0);
  648.     } else
  649. #endif /* SUNTOOL */
  650. #ifdef CURSES
  651.     if (iscurses)
  652.         mvprintw(0, 0, "%-3d %-.*s",
  653.         ((msg_cnt)? current_msg+1 : 0), COLS-5, buf), clrtoeol();
  654.     else
  655. #endif /* CURSES */
  656.         puts(buf);
  657.     return;
  658. }
  659.  
  660. /* return -1 since function doesn't affect messages */
  661. check_flags(flags)
  662. u_long flags;
  663. {
  664.     print_more(" ");
  665.     if (ison(flags, VERBOSE))
  666.     print_more("VERBOSE ");
  667.     if (ison(flags, INCLUDE))
  668.     print_more("INCLUDE ");
  669.     if (ison(flags, INCLUDE_H))
  670.     print_more("INCLUDE_H ");
  671.     if (ison(flags, EDIT))
  672.     print_more("EDIT ");
  673.     if (ison(flags, SIGN))
  674.     print_more("SIGN ");
  675.     if (ison(flags, DO_FORTUNE))
  676.     print_more("DO_FORTUNE ");
  677.     if (ison(flags, NO_HEADER))
  678.     print_more("NO_HEADER ");
  679.     if (ison(flags, DELETE))
  680.     print_more("DELETE ");
  681.     if (ison(flags, OLD))
  682.     print_more("OLD ");
  683.     if (ison(flags, UNREAD))
  684.     print_more("UNREAD ");
  685.     if (ison(flags, UPDATE_STATUS))
  686.     print_more("UPDATE_STATUS ");
  687.     if (ison(flags, NO_PAGE))
  688.     print_more("NO_PAGE ");
  689.     if (ison(flags, INDENT))
  690.     print_more("INDENT ");
  691.     if (ison(flags, NO_IGNORE))
  692.     print_more("NO_IGNORE ");
  693.     if (ison(flags, PRESERVE))
  694.     print_more("PRESERVE ");
  695.     print_more("\n");
  696.     return -1;
  697. }
  698.