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 / misc.c < prev    next >
C/C++ Source or Header  |  1992-10-30  |  23KB  |  804 lines

  1. /* @(#)misc.c    (c) copyright 10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. /* check to see if a string describes a message that is within the range of
  6.  * all messages; if invalid, return 0 and print error. else return msg number
  7.  */
  8. chk_msg(s)
  9. register char *s;
  10. {
  11.     register int n;
  12.  
  13.     if ((n = atoi(s)) > 0 && n <= msg_cnt)
  14.     return n;
  15.     else if (*s == '^' && msg_cnt)
  16.     return 1;
  17.     else if (*s == '$' && msg_cnt)
  18.     return msg_cnt;
  19.     else if (*s == '.' && msg_cnt)
  20.     return current_msg+1;
  21.     print("Invalid message number: %s\n", s);
  22.     return 0;
  23. }
  24.  
  25. /*
  26.  * loop thru all msgs starting with current_msg and find next undeleted and
  27.  * unsaved message.  If the variable "wrap" is set, wrap to the beginning of
  28.  * the message list if we hit the end.  otherwise, stop at the end of the list.
  29.  */
  30. next_msg()
  31. {
  32.     register int n = current_msg;
  33.     register int wrap = !!do_set(set_options, "wrap") ||
  34.     istool && !do_set(set_options, "show_deleted");
  35.  
  36.     if (!msg_cnt)
  37.     return current_msg = 0;
  38.     for (n++; n != current_msg; n++)
  39.     if (n == msg_cnt)     /* hit the end, start back at the beginning */
  40.         if (!wrap)
  41.         return current_msg;
  42.         else
  43.         n = -1; /* increments to 0 in  loop  */
  44.     else if (isoff(msg[n].m_flags, DELETE) &&
  45.          isoff(msg[n].m_flags, SAVED))
  46.         return current_msg = n;
  47.     return current_msg = 0;
  48. }
  49.  
  50. /* since print_help just prints help, always return help() */
  51. print_help(argc, argv)
  52. register char **argv;
  53. {
  54.     int about = (argv && *argv && **argv == 'a');
  55.  
  56.     if (!argc || !*++argv)
  57.     return help(0, about? "about": "general", cmd_help);
  58.     if (argv[0][0] == '-')
  59.     return help(0, about? "about": "help", cmd_help);
  60.     return help(0, *argv, cmd_help);
  61. }
  62.  
  63. /* since this function does not affect messages, return -1 */
  64. /*ARGSUSED*/
  65. help(unused, str, file)
  66. char *str, *file;
  67. {
  68.     register char    *p, **text = (char **)str;
  69.     char        buf[BUFSIZ], help_str[32];
  70.     FILE        *fp;
  71.  
  72.     /* If no file given, take "str" arg as message to print */
  73.     if (!file || !*file) {
  74. #ifdef SUNTOOL
  75. #ifdef SUN_4_0 /* SunOS 4.0+ */
  76.     /* SunOS 3.5 doesn't have enough file descriptors */
  77.     turnon(glob_flags, NEW_FRAME);
  78. #endif /* SUN_4_0 */
  79.     strdup(more_prompt, "help");
  80. #endif /* SUNTOOL */
  81.     /* use the pager on the args to the function */
  82.     (void) do_pager(NULL, TRUE);
  83.     while (*text) {
  84.         (void) do_pager(*text++, FALSE);
  85.         if (do_pager("\n", FALSE) == EOF)
  86.         break;
  87.     }
  88.     (void) do_pager(NULL, FALSE);
  89.     return 0;
  90.     } else {
  91.     int d = 0;
  92.     if ((p = getpath(file, &d)) && d == 0) {
  93.         if (!(fp = fopen(p, "r"))) {
  94.         print("Cannot open help file \"%s\".\n", p);
  95.         return -1;
  96.         }
  97.     } else {
  98.         if (d < 0)
  99.         print("Cannot open help file \"%s\": %s\n", file, p);
  100.         else
  101.         print("Help file \"%s\" is a directory?!?\n", p);
  102.         return -1;
  103.     }
  104.     }
  105.  
  106.     /* look for %str% in helpfile */
  107.     (void) sprintf(help_str, "%%%s%%\n", str);
  108.  
  109.     while (p = fgets(buf, sizeof buf, fp))
  110.     if (*p == '%' && !strcmp(p, help_str))
  111.         break;
  112.     if (!p)
  113.     print("There is no help found for \"%s\".\n", (char *)str);
  114.     else {
  115. #ifdef SUNTOOL
  116. #ifdef SUN_4_0 /* SunOS 4.0+ */
  117.     /* SunOS 3.5 doesn't have enough file descriptors */
  118.     turnon(glob_flags, NEW_FRAME);
  119. #endif /* SUN_4_0 */
  120.     strdup(more_prompt, sprintf(buf, "%s help", (char *)str));
  121. #endif /* SUNTOOL */
  122.     (void) do_pager(NULL, TRUE);
  123.     while ((p = fgets(buf, sizeof buf, fp)) && strcmp(p, "%%\n"))
  124.         if (do_pager(buf, FALSE) == EOF)
  125.         break;
  126.     (void) do_pager(NULL, FALSE);
  127.     }
  128.     (void) fclose(fp);
  129.  
  130.     return 0;
  131. }
  132.  
  133. /* return -1 on error or number of arguments in argv that were parsed */
  134. get_msg_list(argv, list)
  135. register char **argv;
  136. char list[];
  137. {
  138.     register char *p2, *p, *end, ch;
  139.     char buf[BUFSIZ];
  140.     register int n;
  141.  
  142.     if (!msg_cnt) {
  143.     print("No messages.\n");
  144.     return -1;
  145.     }
  146.     if (!argv || !*argv) {
  147.     if (isoff(glob_flags, IS_PIPE))
  148.         set_msg_bit(list, current_msg);
  149.     return 0;
  150.     }
  151.     /* first, stuff argv's args into a single char array buffer */
  152.     (void) argv_to_string(buf, argv);
  153.     p = buf;
  154.  
  155.     Debug("get_msg_list: parsing: (%s): ", p);
  156.     /* find the end of the message list */
  157.     skipmsglist(0);
  158.     end = p;
  159.     while (*end && end != buf && !isspace(*end))
  160.     --end;
  161.     ch = *end, *end = '\0'; /* temporarily plug with nul */
  162.     p = buf; /* reset to the beginning */
  163.     /*
  164.      * if do_range returns NULL, an invalid message was specified
  165.      */
  166.     if (!(p2 = do_range(p, list))) {
  167.     *end = ch; /* just in case */
  168.     return -1;
  169.     }
  170.     /*
  171.      * if p2 == p (and p isn't $ or ^ or .), then no message list was
  172.      * specified.  set the current message in such cases if we're not piping
  173.      */
  174.     if (p2 == p) {
  175.     if (*p == '$')
  176.         set_msg_bit(list, msg_cnt-1);
  177.     else if (*p == '^')
  178.         set_msg_bit(list, 0);
  179.     else if (*p == '.' || isoff(glob_flags, IS_PIPE))
  180.         set_msg_bit(list, current_msg);
  181.     }
  182.     for (n = 0; p2 > p && *argv; n++)
  183.     p2 -= (strlen(*argv++)+1);
  184.     Debug("parsed %d args\n", n);
  185.     *end = ch;
  186.     return n;
  187. }
  188.  
  189. /*
  190.  * execute a command from a string.  f'rinstance: "pick -f foobar"
  191.  * The string is made into an argv and then run.  Errors are printed
  192.  * if the command failed to make.
  193.  * NOTES:
  194.  *   NEVER pass straight text: e.g. "pick -f foobar", ALWAYS strcpy(buf, "...")
  195.  *   no history is expanded (ignore_bang).
  196.  */
  197. cmd_line(buf, list)
  198. char buf[], list[];
  199. {
  200.     register char **argv;
  201.     int argc, ret_val = -1;
  202.     u_long save_do_pipe = ison(glob_flags, DO_PIPE);
  203.     u_long save_is_pipe = ison(glob_flags, IS_PIPE);
  204.     char dummy_list[MAXMSGS_BITS];
  205.  
  206.     turnoff(glob_flags, DO_PIPE);
  207.     turnoff(glob_flags, IS_PIPE);
  208.     if (argv = make_command(buf, TRPL_NULL, &argc))
  209.     ret_val = do_command(argc, argv, list? list : dummy_list);
  210.     if (save_do_pipe)
  211.     turnon(glob_flags, DO_PIPE);
  212.     else
  213.     turnoff(glob_flags, DO_PIPE);
  214.     if (save_is_pipe)
  215.     turnon(glob_flags, IS_PIPE);
  216.     else
  217.     turnoff(glob_flags, IS_PIPE);
  218.     return ret_val;
  219. }
  220.  
  221. glob_test(s)
  222. char *s;
  223. {
  224.     print("%s: glob_flags =", s);
  225.     if (ison(glob_flags, DO_UPDATE))
  226.     print_more(" DO_UPDATE");
  227.     if (ison(glob_flags, REV_VIDEO))
  228.     print_more(" REV_VIDEO");
  229.     if (ison(glob_flags, CONT_PRNT))
  230.     print_more(" CONT_PRNT");
  231.     if (ison(glob_flags, DO_SHELL))
  232.     print_more(" DO_SHELL");
  233.     if (ison(glob_flags, DO_PIPE))
  234.     print_more(" DO_PIPE");
  235.     if (ison(glob_flags, IS_PIPE))
  236.     print_more(" IS_PIPE");
  237.     if (ison(glob_flags, IGN_SIGS))
  238.     print_more(" IGN_SIGS");
  239.     if (ison(glob_flags, IGN_BANG))
  240.     print_more(" IGN_BANG");
  241.     if (ison(glob_flags, ECHO_FLAG))
  242.     print_more(" ECHO_FLAG");
  243.     if (ison(glob_flags, IS_GETTING))
  244.     print_more(" IS_GETTING");
  245.     if (ison(glob_flags, PRE_CURSES))
  246.     print_more(" PRE_CURSES");
  247.     if (ison(glob_flags, READ_ONLY))
  248.     print_more(" READ_ONLY");
  249.     if (ison(glob_flags, REDIRECT))
  250.     print_more(" REDIRECT");
  251.     if (ison(glob_flags, WAS_INTR))
  252.     print_more(" WAS_INTR");
  253.     if (ison(glob_flags, WARNING))
  254.     print_more(" WARNING");
  255.     if (ison(glob_flags, NEW_MAIL))
  256.     print_more(" NEW_MAIL");
  257.     if (ison(glob_flags, CNTD_CMD))
  258.     print_more(" CNTD_CMD");
  259.     if (ison(glob_flags, IS_SENDING))
  260.     print_more(" IS_SENDING");
  261.     if (ison(glob_flags, MIL_TIME))
  262.     print_more(" MIL_TIME");
  263.     if (ison(glob_flags, DATE_RECV))
  264.     print_more(" DATE_RECV");
  265.     if (ison(glob_flags, IN_MACRO))
  266.     print_more(" IN_MACRO");
  267.     if (ison(glob_flags, LINE_MACRO))
  268.     print_more(" LINE_MACRO");
  269.     if (ison(glob_flags, QUOTE_MACRO))
  270.     print_more(" QUOTE_MACRO");
  271.     print_more("\n");
  272. }
  273.  
  274. /*
  275.  * Change the status flags for messages.
  276.  *    flags +r        add the replied-to flag to the current message.
  277.  *    flags -S 4-7    remove the "saved" status on msgs 4-7
  278.  *    flags P *        preserves all messages.
  279.  * The + implies: add this flag to the current message's flag bits
  280.  * The - implies: delete this flag to the current message's flag bits
  281.  * No + or - implies that the msg's flag bits are set explicitly.
  282.  * Marks and priorities are preserved in the m_flags field despite
  283.  * what we're doing here.  Thus, other actions taken by this function
  284.  * do not affect marks and priorities.
  285.  */
  286. msg_flags(c, v, list)
  287. register char **v, *list;
  288. {
  289.     register int    i = 0, modify = 0, had_list = 0;
  290.     register u_long    newflag = 0;
  291.     char        sent[32], recv[32];
  292.  
  293.     while (v && *v && *++v)
  294.     for (c = 0; v && v[0] && v[0][c]; c++)
  295.         switch (lower(v[0][c])) {
  296.         case '?' : return help(0, "msg_flags", cmd_help);
  297.         case 'n' : turnon(newflag, UNREAD), turnoff(newflag, OLD);
  298.         when 'd' : turnon(newflag, DELETE);
  299.         when 'p' :
  300.             if (v[0][c] == 'P')
  301.             turnon(newflag, PRESERVE);
  302.             else
  303.             turnon(newflag, PRINTED);
  304.         when 's' : turnon(newflag, SAVED);
  305.         when 'u' : turnon(newflag, UNREAD); /* fall thru! */
  306.         case 'o' : turnon(newflag, OLD);
  307.         when 'r' :
  308.             if (v[0][c] == 'R')
  309.             turnoff(newflag, UNREAD), turnon(newflag, OLD);
  310.             else
  311.             turnon(newflag, REPLIED);
  312.         when 'f' : turnon(newflag, FORWARD);
  313.         when '+' : modify = 1;
  314.         when '-' : modify = 2;
  315.         when '\\' : ; /* skip to the next flag */
  316.         otherwise:
  317.             if ((i = get_msg_list(v, list)) <= 0) {
  318.             print("Unknown flag: %c.  Use flags -? for help\n",
  319.                 v[0][c]);
  320.             return -1;
  321.             } else {
  322.             /* advance argv passed the msg-list */
  323.             v += i;
  324.             /* c will get ++'ed, so it should be 0 */
  325.             c = -1;
  326.             /* record that we have seen a message list */
  327.             had_list = 1;
  328.             }
  329.         }
  330.  
  331.     /* If we haven't got a msglist, use current_msg */
  332.     if (had_list == 0 && isoff(glob_flags, IS_PIPE))
  333.     set_msg_bit(list, current_msg);
  334.  
  335.     for (i = 0; i < msg_cnt; i++) {
  336.     if (!msg_bit(list, i))
  337.         continue;
  338.     else if (!newflag) {
  339.         wprint("msg %d: offset: %d, lines: %d, bytes: %d, flags:", i+1,
  340.         msg[i].m_offset, msg[i].m_lines, msg[i].m_size);
  341.         if (ison(msg[i].m_flags, UNREAD))
  342.         wprint(" UNREAD");
  343.         if (ison(msg[i].m_flags, OLD))
  344.         wprint(" OLD");
  345.         if (ison(msg[i].m_flags, DELETE))
  346.         wprint(" DELETE");
  347.         if (ison(msg[i].m_flags, PRESERVE))
  348.         wprint(" PRESERVE");
  349.         if (ison(msg[i].m_flags, REPLIED))
  350.         wprint(" REPLIED");
  351.         if (ison(msg[i].m_flags, SAVED))
  352.         wprint(" SAVED");
  353.         if (ison(msg[i].m_flags, PRINTED))
  354.         wprint(" PRINTED");
  355.         if (ison(msg[i].m_flags, FORWARD))
  356.         wprint(" FORWARD");
  357.         if (ison(msg[i].m_flags, UPDATE_STATUS))
  358.         wprint(" UPDATE_STATUS");
  359.         for (modify = MAX_PRIORITY; modify > 0; modify--)
  360.         if (ison(msg[i].m_flags, M_PRIORITY(modify)))
  361.             wprint(" %c", 'A' + modify - 1);
  362.         (void) strcpy(sent, date_to_ctime(msg[i].m_date_sent));
  363.         (void) strcpy(recv, date_to_ctime(msg[i].m_date_recv));
  364.         wprint("\n\tsent: %s\trecv: %s", sent, recv);
  365.     } else {
  366.         u_long save_priority = 0L;
  367.         if (modify == 0) {
  368.         int j;
  369.         for (j = 0; j < MAX_PRIORITY; j++)
  370.             if (ison(msg[i].m_flags, M_PRIORITY(j)))
  371.             turnon(save_priority, M_PRIORITY(j));
  372.         }
  373.         switch (modify) {
  374.         case 0: msg[i].m_flags = newflag;
  375.         when 1: msg[i].m_flags |= newflag;
  376.         when 2: msg[i].m_flags &= ~newflag;
  377.         }
  378.         if (save_priority)
  379.         msg[i].m_flags |= save_priority;
  380.         if (isoff(glob_flags, READ_ONLY)) {
  381.         turnon(glob_flags, DO_UPDATE);
  382.         turnon(msg[i].m_flags, DO_UPDATE);
  383.         }
  384.     }
  385.     }
  386.     return 0;
  387. }
  388.  
  389. /*
  390.  * Internal pager.  Start the internal pager by passing the name of
  391.  * the pager in buf and passing TRUE as start_pager. If the internal
  392.  * pager is desired, pass NULL as buf.  Continue paging by passing
  393.  * FALSE as start_pager and the buf is the stuff to pass thru to the
  394.  * pager.  End paging by passing NULL as buf and FALSE as start_pager.
  395.  * start_pager actually has a ternary value -- for use by pipe_msg.
  396.  * If the pager can't be used, or is null, we're paging ourselves.
  397.  * Windows does nothing but echo buf to the msg window (this will change).
  398.  * The "buf" passed to the pager should be a line at a time so as to
  399.  * count \n's.  If there is more than one newline, the first one is nulled
  400.  * and the next line done by calling do_pager recursively.  WARNING: because
  401.  * "buf" is changed, it is *illegal* for anyone calling this routine to pass
  402.  * _constant_ strings --they should be strcpy'ed or sprintf'ed into a temp
  403.  * buff before passing to this routine!  Otherwise, ANSI-C compilers will
  404.  * core dump.  This is because constant strings are read-only.
  405.  * Return EOF if pager died, user exited pager, or if user types 'q'
  406.  * at the --more-- prompt for the internal pager.
  407.  *
  408.  * For windows, copy all the info into a tmpfile and set the pager_textsw
  409.  * to that file.  When the pager ends, delete the file -- textsw will
  410.  * continue to read it since it does its own buffering.
  411.  */
  412. do_pager(buf, start_pager)
  413. char *buf;
  414. {
  415.     static FILE *pp;
  416.     static SIGRET (*oldchld)();
  417.     static int cnt, len;
  418.     static u_long save_echo_flag;
  419. #ifdef SUNTOOL
  420.     static char file[MAXPATHLEN];
  421.     static Textsw sw;
  422.  
  423.     /* pipe_msg will pass -1 for start_pager to avoid this block */
  424.     if (start_pager > -1 && istool) {
  425.     if (buf && !start_pager) {
  426.         if (istool < 2) /* can't use windows yet -- send to stdout */
  427.         (void) fputs(buf, stdout);
  428.         else {
  429.         if (pp)
  430.             fputs(buf, pp);
  431.         else
  432.             textsw_insert(isoff(glob_flags, NEW_FRAME)?
  433.             pager_textsw : sw, buf, strlen(buf));
  434.         }
  435.     } else if (istool >= 2 && start_pager) {
  436.         Frame text_frame;
  437.         extern char *more_prompt;
  438.         char *p;
  439.  
  440.         timeout_cursors(TRUE);
  441.         if (ison(glob_flags, NEW_FRAME)) {
  442.         char *crt_win = do_set(set_options, "crt_win");
  443.         text_frame = window_create(tool, FRAME,
  444.             FRAME_SHOW_LABEL,    TRUE,
  445.             FRAME_LABEL,    more_prompt,
  446.             WIN_HEIGHT,        l_height()*(crt_win? atoi(crt_win):12),
  447.             NULL);
  448.         sw = window_create(text_frame, TEXTSW,
  449.             TEXTSW_LINE_BREAK_ACTION,    TEXTSW_WRAP_AT_CHAR,
  450.             TEXTSW_CLIENT_DATA,        text_frame,
  451.             NULL);
  452.         notify_interpose_event_func(sw, scroll_textwin, NOTIFY_SAFE);
  453.         } else
  454.         textsw_reset(pager_textsw, 0, 0);
  455.  
  456.         /* find a free tmpfile */
  457.         if (!(p = getdir(do_set(set_options, "tmpdir"))))
  458. alted:
  459.         p = ALTERNATE_HOME;
  460.         {
  461.         int pid = getpid();
  462.         do
  463.             sprintf(file, "%s/..X%d", p, pid++);
  464.         while (!Access(file, F_OK));
  465.         }
  466.         if (!(pp = mask_fopen(file, "w"))) {
  467.         if (strcmp(p, ALTERNATE_HOME))
  468.             goto alted;
  469.         error("Can't create '%s'", tempfile);
  470.         }
  471.         return 0;
  472.     } else if (!buf && !start_pager) { /* pager is done */
  473.         if (pp)
  474.         (void) fclose(pp);
  475.         window_set(isoff(glob_flags, NEW_FRAME)? pager_textsw : sw,
  476.         TEXTSW_FILE,        file,
  477.         TEXTSW_READ_ONLY,    TRUE,
  478.         TEXTSW_UPDATE_SCROLLBAR,
  479.         NULL);
  480.         if (ison(glob_flags, NEW_FRAME)) {
  481.         turnoff(glob_flags, NEW_FRAME);
  482.         window_set(window_get(sw, TEXTSW_CLIENT_DATA),
  483.             WIN_SHOW,        TRUE,
  484.             FRAME_NO_CONFIRM,    TRUE,
  485.             FRAME_DONE_PROC,    window_destroy,
  486.             NULL);
  487.         }
  488.         if (unlink(file) == -1)
  489.         error("Cannot unlink %s", file);
  490.         timeout_cursors(FALSE);
  491.     }
  492.     return 0;
  493.     }
  494. #endif /* SUNTOOL */
  495.  
  496.     if (start_pager) {
  497.     turnon(glob_flags, IGN_SIGS);
  498.     cnt = len = 0;
  499.     if (buf && strcmp(buf, "NONE") == 0) {
  500.         cnt = -1;    /* cnt < 0 disables c_more() */
  501.         buf = NULL;
  502.     }
  503.     if (!buf) {
  504.         /* internal pager */
  505.         save_echo_flag = ison(glob_flags, ECHO_FLAG);
  506.         pp = stdout;
  507.         if (save_echo_flag) {
  508.         turnoff(glob_flags, ECHO_FLAG);
  509.         echo_off();
  510.         }
  511.     } else {
  512.         echo_on();
  513.         if (!(pp = popen(buf, "w")))
  514.         error(buf);
  515.         else /* Don't reap popen()'s child */
  516.         oldchld = signal(SIGCHLD, SIG_DFL);
  517.     }
  518.     } else if (!buf) {
  519.     if (pp && pp != stdout) {
  520.         (void) pclose(pp);
  521.         (void) signal(SIGCHLD, oldchld);
  522.     }
  523.     pp = NULL_FILE;
  524.     if (save_echo_flag) {
  525.         echo_on();
  526.         turnon(glob_flags, ECHO_FLAG);
  527.     } else
  528.         echo_off();
  529.     turnoff(glob_flags, IGN_SIGS);
  530.     } else if (pp != stdout || cnt < 0)
  531.     return fputs(buf, pp); /* returns EOF if user exited pager */
  532.     else {
  533.     register char c = 0, *cr = index(buf, '\n');
  534.     len += strlen(buf);
  535.     if (cr) {
  536.         int maxlen =
  537. #ifdef CURSES
  538.         iscurses ? COLS :
  539. #endif /* CURSES */
  540.         80;
  541.         if (len > maxlen)
  542.         cnt += len / maxlen;
  543.         len = 0;
  544.     }
  545.     if (cr && (c = *++cr) != '\0')
  546.         *cr = 0; /* send one line to stdout and prompt for more */
  547.     (void) fputs(buf, pp);
  548.     if (cr && (++cnt / (crt-1))) {
  549.         int n = c_more(NULL);
  550.         if (n == '\n' || n == '\r')
  551.         cnt--; /* go line by line */
  552.         else if (n == CTRL('D') || lower(n) == 'd' || n < 0) {
  553.         clearerr(stdin);
  554.         cnt = ((crt-1)/2);
  555.         } else if (lower(n) == 'q')
  556.         /* could check if "c" is set, but... see warning above */
  557.         return EOF;
  558.         else
  559.         cnt = 1;
  560.     }
  561.     if (c) {
  562.         *cr = c;
  563.         return do_pager(cr, FALSE);
  564.     }
  565.     }
  566.     return 0;
  567. }
  568.  
  569. /* curses based "more" like option */
  570. c_more(p)
  571. register char *p;
  572. {
  573.     register int c;
  574.  
  575.     if (!p)
  576.     p = "--more--";
  577.     print_more(p);
  578.  
  579.     while ((c = getchar()) >= 0 && c != CTRL('D') && !isspace(c) &&
  580.         c != '\n' && c != '\r' && lower(c) != 'q' && lower(c) != 'd')
  581.     bell();
  582.     if (ison(glob_flags, ECHO_FLAG) && c != '\n' && c != '\r')
  583.     while (getchar() != '\n');
  584.     (void) printf("\r%*c\r", strlen(p), ' '); /* remove the prompt */
  585.     (void) fflush(stdout);
  586.     return c;
  587. }
  588.  
  589. /*
  590.  * Your "signature" is of the type:
  591.  *    file_or_path
  592.  *    $variable
  593.  *    \ literal string preceded by a backslash.
  594.  * The variable will be expanded into its string value.
  595.  * To sign the letter, the list of addresses is passed to this routine
  596.  * (separated by whitespace and/or commas).  No comment fields!
  597.  *
  598.  * If "autosign2" is set, then it must be of the form:
  599.  *    autosign2 = "*user user !host !some!path @dom.ain: ~/.sign2"
  600.  *
  601.  * The colon terminates the user/host lists from the "signature" to the right.
  602.  *
  603.  * Whitespace or commas separate tokens.  If everyone on the list exists in
  604.  * the autosign2 list, the alternate signature is used. In case of syntax
  605.  * error, the alternate signature is used without checks (e.g. if the colon
  606.  * is missing).  The alternate signature == null is the same as not signing
  607.  * the letter. An empty list forces signature2.
  608.  *
  609.  * If autosign2 is not set at all, then autosign is checked and used.
  610.  * autosign = <signature>
  611.  */
  612. void
  613. sign_letter(list, flags, fp)
  614. register char *list; /* list of addresses -- no comment fields */
  615. u_long flags;
  616. FILE *fp;
  617. {
  618.     char buf[MAXPATHLEN], *signature;
  619.     register char *p = NULL;
  620.     FILE     *pp2;
  621.     int     lines = 0, noisy;
  622.  
  623.     if (!list)
  624.     return;
  625.     while (isspace(*list))
  626.     list++;
  627.     if (!*list)
  628.     return;
  629.     if (ison(flags, SIGN)) {
  630.     noisy = !chk_option("quiet", "autosign");
  631.     if (!(p = do_set(set_options, "autosign2")))
  632.         buf[0] = 0;
  633.     else {
  634.         if (!(signature = index(p, ':')))
  635.         (void) strcpy(buf, p); /* No colon; use entire string as sig */
  636.         else {
  637.         int ret_val = 0;
  638.         *signature = 0;
  639.         /* p now points to a list of addresses and p2 points to the
  640.          * signature format to use. Check that each address in the list
  641.          * provided (parameter) matches the "addrs" in autosign2.
  642.          */
  643.         skipspaces(0);
  644.         if (!*p)
  645.             /* autosign2 = " : <signature>"  send to all recipients */
  646.             ret_val = 1;
  647.         else if (p = alias_to_address(p)) {
  648.             rm_cmts_in_addr(p);
  649.             ret_val = compare_addrs(list, p, NULL);
  650.         }
  651.         *signature++ = ':'; /* must reset first! */
  652.         buf[0] = 0;
  653.         if (ret_val) {
  654.             while (isspace(*signature))
  655.             signature++;
  656.             /* Null signatures don't sign anything. */
  657.             if (!*strcpy(buf, signature))
  658.             return;
  659.         }
  660.         }
  661.     }
  662.     if (!buf[0]) {
  663.         if (!(p = do_set(set_options, "autosign")) || !*p) {
  664.         char *home;
  665.         if (!(home = do_set(set_options, "home")) || !*home)
  666.             home = ALTERNATE_HOME;
  667.         (void) sprintf(buf, "%s/%s", home, SIGNATURE);
  668.         } else
  669.         (void) strcpy(buf, p);
  670.         if (noisy)
  671.         wprint("Signing letter... ");
  672.     } else if (noisy)
  673.         wprint("Using alternate signature... ");
  674.     (void) fseek(fp, 0L, 2); /* guarantee position at end of file */
  675.     (void) fputc('\n', fp);
  676.     (void) fflush(fp);
  677.     if (*buf == '$')
  678.         if (!(p = do_set(set_options, buf+1)))
  679.         wprint("(%s isn't set -- letter not signed)\n", buf);
  680.         else {
  681.         putstring(p, fp);
  682.         if (noisy)
  683.             wprint("\n");
  684.         }
  685.     else if (*buf == '\\') {
  686.         putstring(buf, fp);
  687.         if (noisy)
  688.         wprint("\n");
  689.     } else if (*buf == '[') {
  690.         char *rbr = index(buf, ']');
  691.         if (rbr)
  692.         *rbr = 0;
  693.         putstring(buf + 1, fp);
  694.         if (noisy)
  695.         wprint("\n");
  696.     } else if (*buf == '|' || *buf == '!') {
  697.         (void) strcat(buf, " ");
  698.         (void) strcat(buf, list);
  699.         if (!(pp2 = popen(buf+1, "r")))
  700.         error(buf+1);
  701.         else {
  702.         turnon(glob_flags, IGN_SIGS);
  703.         while (fgets(buf, sizeof(buf), pp2)) {
  704.             int len = strlen(buf);
  705.             (void) fputs(buf, fp), lines++;
  706.             if (len < sizeof buf - 1 && buf[len - 1] != '\n')
  707.             (void) fputc('\n', fp);
  708.         }
  709.         (void) pclose(pp2);
  710.         (void) fflush(fp);
  711.         turnoff(glob_flags, IGN_SIGS);
  712.         if (noisy)
  713.             wprint("added %d line%s\n", lines, lines == 1? "" : "s");
  714.         }
  715.     } else {
  716.         /* precede _file_ signatures ONLY with "-- \n" */
  717.         (void) fputs("-- \n", fp);
  718.         (void) fflush(fp);
  719.         (void) file_to_fp(buf, fp, "r");
  720.     }
  721.     }
  722.  
  723.     (void) fflush(stdout); /* for sys-v and older xenix */
  724.  
  725.     /* if fortune is set, check to see if fortunates is set. If so,
  726.      * check to see if all the recipient are on the fortunates list.
  727.      */
  728.     if (ison(flags, DO_FORTUNE)) {
  729.     noisy = !chk_option("quiet", "fortune");
  730.     if (p = do_set(set_options, "fortunates")) {
  731.         if (!(p = alias_to_address(p)))
  732.         return; /* no reason to hang around */
  733.         rm_cmts_in_addr(p);
  734.         if (!compare_addrs(list, p, buf)) {
  735.         if (noisy) {
  736.             wprint("\"fortunates\" does not contain \"%s\".\n", buf);
  737.             wprint("No fortune added.\n");
  738.         }
  739.         return;
  740.         }
  741.     }
  742.     if (noisy)
  743.         wprint("You may be fortunate... ");
  744.     if ((p = do_set(set_options, "fortune")) && *p == '/')
  745.         (void) strcpy(buf, p);
  746.     else
  747.         (void) sprintf(buf, "%s %s", FORTUNE, (p && *p == '-')? p: "-s");
  748.     if (!(pp2 = popen(buf, "r")))
  749.         error(buf);
  750.     else {
  751.         turnon(glob_flags, IGN_SIGS);
  752.         (void) fseek(fp, 0L, 2); /* go to end of file */
  753.         while (fgets(buf, sizeof(buf), pp2))
  754.         (void) fputs(buf, fp), lines++;
  755.         (void) pclose(pp2);
  756.         turnoff(glob_flags, IGN_SIGS);
  757.         (void) fflush(fp);
  758.         if (noisy)
  759.         wprint("added %d line%s\n", lines, lines == 1? "" : "s");
  760.     }
  761.     }
  762.     (void) fflush(stdout); /* for sys-v and older xenix */
  763. }
  764.  
  765.  
  766. /* return -1 since function doesn't affect messages */
  767. check_flags(flags)
  768. u_long flags;
  769. {
  770.     print_more(" ");
  771.     if (ison(flags, VERBOSE))
  772.     print_more("VERBOSE ");
  773.     if (ison(flags, INCLUDE))
  774.     print_more("INCLUDE ");
  775.     if (ison(flags, INCLUDE_H))
  776.     print_more("INCLUDE_H ");
  777.     if (ison(flags, EDIT))
  778.     print_more("EDIT ");
  779.     if (ison(flags, SIGN))
  780.     print_more("SIGN ");
  781.     if (ison(flags, DO_FORTUNE))
  782.     print_more("DO_FORTUNE ");
  783.     if (ison(flags, NO_HEADER))
  784.     print_more("NO_HEADER ");
  785.     if (ison(flags, DELETE))
  786.     print_more("DELETE ");
  787.     if (ison(flags, OLD))
  788.     print_more("OLD ");
  789.     if (ison(flags, UNREAD))
  790.     print_more("UNREAD ");
  791.     if (ison(flags, UPDATE_STATUS))
  792.     print_more("UPDATE_STATUS ");
  793.     if (ison(flags, NO_PAGE))
  794.     print_more("NO_PAGE ");
  795.     if (ison(flags, INDENT))
  796.     print_more("INDENT ");
  797.     if (ison(flags, NO_IGNORE))
  798.     print_more("NO_IGNORE ");
  799.     if (ison(flags, PRESERVE))
  800.     print_more("PRESERVE ");
  801.     print_more("\n");
  802.     return -1;
  803. }
  804.