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