home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / mush5.7 / part08 / hdrs.c next >
Encoding:
C/C++ Source or Header  |  1987-09-19  |  22.5 KB  |  782 lines

  1. /* hdr_procs.c     (c) copyright 1986 (Dan Heller) */
  2.  
  3. /* hdrs.h -- routines that look at message headers */
  4. #include "mush.h"
  5.  
  6. /*
  7.  * get which message via the offset and search for the headers which
  8.  * match the string "str". there may be more than one of a field (like Cc:)
  9.  * so get them all and "cat" them together into the static buffer
  10.  * "buf" and return its address.
  11.  */
  12. char *
  13. header_field(n, str)
  14. char *str;
  15. {
  16.     static char    buf[BUFSIZ];
  17.     char        tmp[BUFSIZ];
  18.     register char  *p, *p2, *b = buf;
  19.     int contd_hdr;  /* true if next line is a continuation of the hdr we want */
  20.  
  21.     if (fseek(tmpf, msg[n].m_offset, L_SET) != 0) {
  22.     error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
  23.     turnon(glob_flags, READ_ONLY);
  24.     return NULL;
  25.     }
  26.     *b = 0;
  27.     while((p = fgets(tmp, BUFSIZ, tmpf)) && *p != '\n') {
  28.     if (*p != ' ' && *p != '\t') {
  29.         contd_hdr = 0;
  30.         /* strcmp ignoring case */
  31.         for(p2 = str; *p && *p2 && *p2 == lower(*p); ++p, ++p2);
  32.         /* MATCH is true if p2 is at the end of str and *p is ':' */
  33.         if (*p2 || *p++ != ':')
  34.         continue;
  35.         else
  36.         contd_hdr = 1;
  37.     } else if (!contd_hdr)
  38.         continue;
  39.     skipspaces(0);
  40.     p2 = no_newln(p);
  41.     *++p2 = ' ', *++p2 = 0;
  42.     b += Strcpy(b, p);
  43.     }
  44.     if (b > buf) /* now get rid of the trailing blank */
  45.     *--b = 0;
  46.     return (*buf)? buf: NULL;
  47. }
  48.  
  49. do_hdrs(argc, argv, list)
  50. register char **argv, list[];
  51. {
  52.     register int   pageful = 0, fnd;
  53.     int        (*oldint)(), (*oldquit)(), show_deleted;
  54.     static int     cnt;
  55.     register char  *p;
  56.     char        first_char = (argc) ? **argv: 'h';
  57.  
  58.     if (!msg_cnt) {
  59.     if (isoff(glob_flags, DO_PIPE))
  60.         return;
  61. #ifdef CURSES
  62.     if (iscurses)
  63.         clear();
  64. #endif CURSES
  65. #ifdef SUNTOOL
  66.     if (istool)
  67.         mail_status(0);
  68. #endif SUNTOOL
  69.     return 0;
  70.     }
  71.     if (first_char == ':' || (argc > 1 && argv[1][0] == ':')) {
  72.     if (first_char != ':')
  73.         argv++;
  74.     return specl_hdrs(argv, list);
  75.     }
  76.  
  77.     if (argc > 1 && !strcmp(argv[1], "-?"))
  78.     return help(0, "headers", cmd_help);
  79.  
  80.     on_intr();
  81.  
  82.     if (argc && (argv[0][1] == '+' || argc > 1 && !strcmp(argv[1], "+")) ||
  83.         first_char == 'z' && !argv[1])
  84.     if (msg_cnt > screen)
  85.         cnt = min(msg_cnt - screen, n_array[0] + screen);
  86.     else
  87.         cnt = 0;
  88.     else if (argc && (argv[0][1] == '-' || argc > 1 && !strcmp(argv[1], "-")))
  89.     cnt = max((cnt - 2*screen), 0);
  90.     else if (argc && *++argv &&
  91.     (isdigit(**argv) || **argv == '^' || **argv == '$')
  92.      || ison(glob_flags, IS_PIPE)) {
  93.     /* if we're coming from a pipe, start display at the first msg bit
  94.      * set in the msg_list
  95.      */
  96.     if (ison(glob_flags, IS_PIPE)) {
  97.         if (isoff(glob_flags, DO_PIPE))
  98.         for (fnd = 0; fnd < msg_cnt; fnd++)
  99.             if (msg_bit(list, fnd))
  100.             wprint("%s\n", compose_hdr(fnd));
  101.         off_intr();
  102.         return 0;
  103.     }
  104.     /* if a number was given, use it */
  105.     if (!(fnd = chk_msg(*argv))) {
  106.         off_intr();
  107.         return -1;
  108.     }
  109.     for (cnt = fnd - 1; cnt > 0 && cnt + screen > msg_cnt; cnt--);
  110.     } else if (current_msg < n_array[0] || current_msg > n_array[screen-1])
  111.     cnt = current_msg; /* adjust if user reads passed screen bounds */
  112.     else if (cnt >= msg_cnt || !argc || !*argv)
  113.     cnt = max((cnt - screen), 0); /* adjust window to maintian position */
  114.  
  115.     show_deleted = !!do_set(set_options, "show_deleted");
  116.  
  117.     for (;pageful<screen && cnt<msg_cnt && isoff(glob_flags, WAS_INTR); cnt++) {
  118.     if (!iscurses && !show_deleted && first_char == 'h'
  119.         && ison(msg[cnt].m_flags, DELETE))
  120.         continue;
  121.     n_array[pageful++] = cnt;
  122.     /* this message was displayed -- set the bit */
  123.     if (list)
  124.         set_msg_bit(list, cnt);
  125.     /* if do_pipe, don't output anything */
  126.     if (ison(glob_flags, DO_PIPE))
  127.         continue;
  128.     p = compose_hdr(cnt);
  129.     if (!istool && (!iscurses || ison(glob_flags, IS_GETTING)))
  130.         puts(p);
  131. #ifdef SUNTOOL
  132.     else if (istool) {
  133.         if (cnt == current_msg) /* embolden or reverse_video */
  134.         highlight(hdr_win, 0,pageful*l_height(DEFAULT), DEFAULT,p);
  135.         else
  136.         pw_text(hdr_win, 0, pageful * l_height(DEFAULT), PIX_SRC,
  137.                             fonts[DEFAULT], p);
  138.         Clrtoeol(hdr_win, strlen(p)*l_width(DEFAULT),
  139.              pageful*l_height(DEFAULT), DEFAULT);
  140.     }
  141. #endif SUNTOOL
  142. #ifdef CURSES
  143.         else if (iscurses)
  144.         mvprintw(pageful, 0, "%-*s", COLS-2, p);
  145. #endif CURSES
  146.     }
  147.     /* just in case a signal stopped us */
  148.     off_intr();
  149.     pageful++;
  150. #ifdef CURSES
  151.     if (iscurses && pageful < screen)
  152.     move(pageful, 0), clrtobot();
  153. #endif CURSES
  154.     if (cnt == msg_cnt) {
  155.     while (pageful <= screen) {
  156.         n_array[pageful-1] = msg_cnt+1; /* assign out-of-range values */
  157. #ifdef SUNTOOL
  158.         if (istool)
  159.         Clrtoeol(hdr_win, 0, pageful * l_height(DEFAULT), DEFAULT);
  160. #endif SUNTOOL
  161.         ++pageful;
  162.     }
  163.     }
  164. #ifdef SUNTOOL
  165.     if (istool) {
  166.     if (msg_cnt > screen) {
  167.         panel_set(next_scr, PANEL_SHOW_ITEM, TRUE, 0);
  168.         panel_set(prev_scr, PANEL_SHOW_ITEM, TRUE, 0);
  169.     }
  170.     mail_status(0);
  171.     }
  172. #endif SUNTOOL
  173.     return 0;
  174. }
  175.  
  176. #define NEW 1
  177. #define ALL 2
  178.  
  179. specl_hdrs(argv, list)
  180. char **argv, list[];
  181. {
  182.     u_long    special = 0;
  183.     int     n = 0;
  184.  
  185.     while (argv[0][++n])
  186.     switch(argv[0][n]) {
  187.         case 'a': special = ALL;
  188.         when 'n': special = NEW;
  189.         when 'u': special = UNREAD;
  190.         when 'o': special = OLD;
  191.         when 'd': special = DELETE;
  192.         otherwise: print("choose from n,u,o,d, or a"); return -1;
  193.     }
  194.     if (debug)
  195.     (void) check_flags(special);
  196.  
  197.     for (n = 0; n < msg_cnt; n++) {
  198.     /*
  199.      * First, see if we're looking for NEW messages.
  200.      * If so, then check to see if the msg is unread and not old.
  201.      * If special > ALL, then special has a mask of bits describing
  202.      * the state of the message.
  203.      */
  204.     if (ison(glob_flags, IS_PIPE)&& !msg_bit(list, n))
  205.         continue;
  206.     if (special == ALL || special == NEW &&
  207.            (ison(msg[n].m_flags, UNREAD) && isoff(msg[n].m_flags, OLD))) {
  208.         if (isoff(glob_flags, DO_PIPE))
  209.         print("%s\n", compose_hdr(n));
  210.         if (list)
  211.         set_msg_bit(list, n);
  212. #ifndef SYSV
  213.     /*
  214.      * XENIX compiler can't handle "special" in ison() macro.
  215.      * It only works if the second argument is a constant!
  216.      */
  217.     } else if (special > ALL && ison(msg[n].m_flags, special)) {
  218.         if (isoff(glob_flags, DO_PIPE))
  219.         print("%s\n", compose_hdr(n));
  220.         if (list)
  221.         set_msg_bit(list, n);
  222. #endif SYSV
  223.     } else {
  224.         if (list)
  225.         unset_msg_bit(list, n);
  226.         Debug("msg[%d].m_flags: %d", n, msg[n].m_flags),
  227.              (void) check_flags(msg[n].m_flags);
  228.     }
  229.     }
  230.     return 0;
  231. }
  232.  
  233. char *
  234. compose_hdr(cnt)
  235. {
  236.     static char buf[256];
  237.     register char *p, *b, *status;
  238.     char from[256], subject[256], date[17], lines[6], chars[6], line[256];
  239.     char to[512], addr[256], name[256];
  240.  
  241.     /* status of the message */
  242.     if (ison(msg[cnt].m_flags, DELETE))
  243.     status = "*";
  244.     else if (ison(msg[cnt].m_flags, OLD) && ison(msg[cnt].m_flags, UNREAD))
  245.     status = "U";
  246.     else if (ison(msg[cnt].m_flags, PRESERVE))
  247.     status = "P";
  248.     else if (isoff(msg[cnt].m_flags, UNREAD))
  249.     status = " ";
  250.     else
  251.     status = "N";
  252.  
  253.     to[0] = from[0] = subject[0] = date[0] = lines[0] = chars[0] =
  254.     addr[0] = name[0] = line[0] = 0;
  255.  
  256.     /* who's the message to */
  257.     if (p = header_field(cnt, "to"))
  258.     (void) strcpy(to, p);
  259.  
  260.     /* who the messages is from--
  261.     %f        From field
  262.     %a        From address
  263.     %n        From name
  264.  
  265.     where %a is anything in angle brackets, or if no angle brackets,
  266.     anything not in parenthesis, and %n is anything in parenthesis, or if
  267.     nothing in parenthesis, anything not in angle brackets.
  268.      */
  269.     if (!(p = header_field(cnt, "from"))) {
  270.     /* if all else fails, then get the first token in "From" line */
  271.     register char *p2;
  272.     p = ""; /* just in case */
  273.     if (fseek(tmpf, msg[cnt].m_offset, L_SET) == -1 ||
  274.         !(p2 = fgets(line, BUFSIZ, tmpf))) {
  275.         error("fseek in %s (msg %d, folder=%s)", tempfile, cnt+1, mailfile);
  276.         turnon(glob_flags, READ_ONLY);
  277.     } else if (!(p = index(p2, ' ')))
  278.         print("Fudged \"From\" line: %s", p2);
  279.     else if (p2 = any(++p, " \t"))
  280.         *p2 = 0;
  281.     }
  282.     skipspaces(0);
  283.     (void) no_newln(p);
  284.     /* if the "from" line produced the user's login name, then the message is
  285.      * from the user -- attempt to give more useful information by telling
  286.      * to whom the message was sent.  This is not possible if the "to" header
  287.      * failed to get info (which is probably impossible).
  288.      */
  289.     if (!strcmp(p, login) && *to)
  290.     (void) sprintf(from, "TO: %s", to);
  291.     else
  292.     (void) strcpy(from, p);
  293.     /* look for < or (  If <, then whatever is inside goes in addr, and
  294.      * whatever isn't inside goes in name.  If it's a (, then whatever is
  295.      * inside goes in name and whatever isn't, goes in addr.  It the same
  296.      * type of thing, but exclusive of each other.
  297.      */
  298.     if (p = any(from, "<(")) {
  299.     register char *p2, *out, *in;
  300.     if (*p == '<')
  301.         out = name, in = addr;
  302.     else
  303.         out = addr, in = name;
  304.  
  305.     (void) strcpy(in, p+1);
  306.     if (p2 = index(in, (*p == '<')? '>' : ')'))
  307.         *p2 = 0;
  308.     /* whatever isn't in <'s gets put in "name". Put p at end of name */
  309.     if (p - from > 1)
  310.         (void) strncpy(out, from, p - from), p = out+(p-from);
  311.     else
  312.         p = out;
  313.     if (p2) {
  314.         /* p2 will be at >, so there will be at least a blank following */
  315.         while (isspace(*++p2));
  316.         /* copy remainder of line onto p (end of name) */
  317.         (void) strcpy(p, p2);
  318.     }
  319.     }
  320.  
  321.     (void) sprintf(lines, "%d", msg[cnt].m_lines);
  322.     (void) sprintf(chars, "%d", msg[cnt].m_size);
  323.  
  324.     /* the date */
  325.     if (p = msg_date(cnt))
  326.     (void) strcpy(date, date_to_string(p));
  327.  
  328.     /* and the subject */
  329.     if (p = header_field(cnt, "subject"))
  330.     (void) strcpy(subject, p);
  331.  
  332.     /* now, construct a header */
  333.     if (!hdr_format) /* this should NEVER be true, but just in case */
  334.     hdr_format = DEF_HDR_FMT;
  335.  
  336.     (void) sprintf(buf, "%3.d ", cnt+1);
  337.     b = buf+4;
  338.     *b++ = ((cnt == current_msg && !iscurses)? '>': ' ');
  339.     cnt = 5;
  340.     for (p = hdr_format; *p; p++)
  341.     if (*p == '\\')
  342.         switch (*++p) {
  343.         case 't':
  344.             while (cnt % 8)
  345.             cnt++, *b++ = ' ';
  346.         when 'n':
  347.             cnt = 1, *b++ = '\n';
  348.         otherwise: cnt++, *b++ = *p;
  349.         }
  350.     else if (*p == '%') {
  351.         int buffer_space = 0;
  352.         register char *p2;
  353.  
  354.         if (isdigit(*++p))
  355.         p = my_atoi(p, &buffer_space);
  356.         switch (*p) {
  357.         case 'f': p2 = from;
  358.         when 'a':
  359.             if (!*(p2 = addr))
  360.             p2 = from;
  361.         when 'n':
  362.             if (!*(p2 = name))
  363.             p2 = from;
  364.         when '%': p2 = "%";
  365.         when 't': p2 = to;
  366.         when 'd': p2 = date;
  367.         when 's': p2 = subject;
  368.         when 'l': p2 = lines;
  369.         when 'c': p2 = chars;
  370.         when 'S': p2 = status;
  371.         otherwise: continue; /* unknown formatting char */
  372.         }
  373.         if (!buffer_space)
  374.         buffer_space = strlen(p2);
  375.         (void) sprintf(b, "%-*.*s", buffer_space, buffer_space, p2);
  376.         cnt += buffer_space, b += buffer_space;
  377.     } else
  378.         cnt++, *b++ = *p;
  379.     for (*b-- = 0; isspace(*b); --b)
  380.     *b = 0;
  381.     return buf;
  382. }
  383.  
  384. /*
  385.  * Using message "n", build a list of recipients that you would mail to if
  386.  * you were to reply to this message.  If "all" is true, then it will take
  387.  * everyone from the To line in addition to the original sender.
  388.  * fix_address() is caled from mail.c, not from here.  There are too many
  389.  * other uses for reply_to to always require reconstruction of return paths.
  390.  * Note that we do NOT deal with Cc paths here either.
  391.  * Check to make sure that we in fact return a legit address (i.e. not blanks
  392.  * or null). If such a case occurs, return login name.  Always pad blank at end.
  393.  */
  394. char *
  395. reply_to(n, all, buf)
  396. register char *buf;
  397. {
  398.     register char *p = NULL, *p2, *b = buf, *field;
  399.     char line[256];
  400.  
  401.     if (field = do_set(set_options, "reply_to_hdr")) {
  402.     if (!*field)
  403.         goto From; /* special case -- get the colon-less From line */
  404.     field = lcase_strcpy(line, field);
  405.     while (*field) {
  406.         if (p2 = any(field, " \t,:"))
  407.         *p2 = 0;
  408.         if ((p = header_field(n, field)) || !p2)
  409.         break;
  410.         else {
  411.         field = p2+1;
  412.         while (isspace(*field) || *field == ':' || *field == ',')
  413.             field++;
  414.         }
  415.     }
  416.     if (!p)
  417.         print("Warning: message contains no `reply_to_hdr' headers.\n");
  418.     }
  419.     if (p || (!p && ((p = header_field(n, "reply-to")) ||
  420.         (p = header_field(n, "return-path")) ||
  421.         (p = header_field(n, "from"))))) {
  422.     skipspaces(0);
  423.     /* correct reply address is in "<correct-address>" */
  424.     if (p2 = index(p, '<')) {
  425.         if (p = index(p2, '>'))
  426.         *p = 0;
  427.         p = ++p2;
  428.     }
  429.     } else if (!p) {
  430. From:
  431.     /* if all else fails, then get the first token in "From" line */
  432.     if (fseek(tmpf, msg[n].m_offset, L_SET) == -1 ||
  433.         !(p2 = fgets(line, BUFSIZ, tmpf))) {
  434.         error("fseek in %s (msg %d, folder=%s)", tempfile, n+1, mailfile);
  435.         turnon(glob_flags, READ_ONLY);
  436.         return "";
  437.     }
  438.     p = index(p2, ' ') + 1;
  439.     }
  440.     /* find the first space and plug a null */
  441.     if (p2 = any(p, " \t\n"))
  442.     *p2 = 0;
  443.     b += Strcpy(buf, p);
  444.  
  445.     /*
  446.      * if `all' is true, append everyone on the "To:" line.
  447.      * cc_to(), called separately, will catch the cc's
  448.      */
  449.     if (all && (p = header_field(n, "to")) && *p)
  450.     (void) sprintf(b, " %s", p);
  451.     rm_cmts_in_addr(buf);
  452.     for (p = buf; isspace(*p); p++);
  453.     if (!*p)
  454.     (void) strcpy(buf, login);
  455.     return strcat(buf, " ");
  456. }
  457.  
  458. char *
  459. subject_to(n, buf)
  460. register char *buf;
  461. {
  462.     register char *p;
  463.     buf[0] = 0; /* make sure it's already null terminated */
  464.     if (!(p = header_field(n, "subject")))
  465.     return NULL;
  466.     if (strncmp(p, "Re:", 3))
  467.     (void) strcpy(buf, "Re: ");
  468.     return strcat(buf, p);
  469. }
  470.  
  471. char *
  472. cc_to(n, buf)
  473. register char *buf;
  474. {
  475.     register char *p;
  476.     buf[0] = 0; /* make sure it's already null terminated */
  477.     if (!(p = header_field(n, "cc")))
  478.     return NULL;
  479.     rm_cmts_in_addr(p);
  480.     return strcpy(buf, p);
  481. }
  482.  
  483. /*
  484.  * fix addresses according to the sender's address.  If he's on a remote
  485.  * machine, chances are that the addresses of everyone else he mailed to
  486.  * are addresses from his machine.  Reconstruct those addresses to route
  487.  * thru the senders machine first.
  488.  */
  489. fix_addresses(to, cc)
  490. char *to, *cc;
  491. {
  492.     int   to_argc, cc_argc, cnt;
  493.     char  **to_argv, **cc_argv, pre_path[128], *p, c;
  494.     char  **new_to, **new_cc, **calloc(), buf[256];
  495.  
  496.     pre_path[0] = 0;
  497.     if (!(to_argv = mk_argv(to, &to_argc, 0)))
  498.     return;   /* what can we do?  Just return unchanged To and Cc lists */
  499.     cc_argv = mk_argv(cc, &cc_argc, 0);  /* the cc list may be empty */
  500.     if (cc_argc == 0 && to_argc == 1)
  501.     return;   /* there's only one reciepient, nothing to alter */
  502.  
  503.     if (p = any(to_argv[0], "!=")) {
  504.     char *p2;
  505.     while (p2 = any(++p, "!="))
  506.         p = p2;
  507.     c = *p, *p = 0;
  508.     (void) strcpy(pre_path, to_argv[0]);
  509.     *p = c;
  510.     for (cnt = 0; cnt < MAX_HOST_NAMES && ourname[cnt]; cnt++)
  511.         if (!strcmp(pre_path, ourname[cnt])) {
  512.         *pre_path = 0;
  513.         break;
  514.         }
  515.     }
  516.  
  517.     if (!(new_to = calloc((unsigned)(to_argc+1), sizeof (char *))) ||
  518.     !(new_cc = calloc((unsigned)(cc_argc+1), sizeof (char *)))) {
  519.     error("malloc in fix_headers");
  520.     return;
  521.     }
  522.     /* this is the original sender */
  523.     strdup(new_to[0], to_argv[0]);
  524.  
  525.     /* now modify the addresses to be routed thru the sender's adderess */
  526.     for (cnt = 1; cnt < to_argc; cnt++) {
  527.     if (p = index(to_argv[cnt], ','))
  528.         *p = 0;
  529.     Debug("Changing \"%s\" to ", to_argv[cnt]);
  530.     (void) sprintf(buf, "%s%s", pre_path, to_argv[cnt]);
  531.     strdup(new_to[cnt], buf);
  532.     Debug("\"%s\"\n", new_to[cnt]);
  533.     }
  534.     for (cnt = 0; cnt < cc_argc; cnt++) {
  535.     Debug("Changing \"%s\" to ", cc_argv[cnt]);
  536.     if (p = index(cc_argv[cnt], ','))
  537.         *p = 0;
  538.     (void) sprintf(buf, "%s%s", pre_path, cc_argv[cnt]);
  539.     strdup(new_cc[cnt], buf);
  540.     Debug("\"%s\"\n", new_cc[cnt]);
  541.     }
  542.     (void) argv_to_string(to, new_to);
  543.     (void) argv_to_string(cc, new_cc);
  544.     free_vec(to_argv);
  545.     free_vec(cc_argv);
  546.     free_vec(new_to);
  547.     free_vec(new_cc);
  548. }
  549.  
  550. /*
  551.  * pass a string describing header like, "Subject: ", current value, and
  552.  * whether or not to prompt for it or to just post the information.
  553.  * If do_prompt is true, "type in" the current value so user can either
  554.  * modify it, erase it, or add to it.
  555.  */
  556. char *
  557. set_header(str, curstr, do_prompt)
  558. register char *str, *curstr;
  559. {
  560.     static char       buf[BUFSIZ];
  561.     int        offset = 0;
  562.     register char  *p = curstr;
  563.  
  564.     buf[0] = 0;
  565.     wprint(str);
  566.     fflush(stdout);         /* force str curstr */
  567.     if (do_prompt) {
  568.     if (curstr)
  569.         for (p = curstr; *p; p++)
  570. #ifdef SUNTOOL
  571.         if (istool)
  572.             rite(*p); /* mimics typing for the tool */
  573.         else
  574. #endif /* SUNTOOL */
  575.         if (isoff(glob_flags, ECHO_FLAG))
  576.             fputc((buf[offset++] = *p), stdout);
  577.         else
  578. #ifdef TIOCSTI
  579.             if (ioctl(0, TIOCSTI, p) == -1) {
  580.             error("ioctl: TIOCSTI");
  581.             wprint("You must retype the entire line.\n%s", str);
  582.             break;
  583.             }
  584. #else
  585.                 {
  586.             wprint("WARNING: -e flag! Type the line over.\n%s", str);
  587.             break;
  588.         }
  589. #endif TIOCSTI
  590.  
  591.     if (istool)
  592.         return NULL;
  593.     if (Getstr(buf, BUFSIZ, offset) == -1)
  594.         buf[0] = 0;
  595.     } else
  596.     puts(strcpy(buf, curstr));
  597.     if (debug > 1)
  598.     print("returning (%s) from set_header\n", buf);
  599.     return buf;
  600. }
  601.  
  602. /*
  603.  * rm_cmts_in_addr() removes the comment lines in addresses that result from
  604.  * sendmail or other mailers which append the user's "real name" on the
  605.  * from lines.  Comments are in parens.
  606.  * `take_me_off' takes occurences of login out of a list of recipients
  607.  * if the variable "metoo" is set.  Some say that "metoo" is supposed to
  608.  * pass the -m flag along to sendmail, but not everyone runs sendmail :-)
  609.  *
  610.  * First expand a possible alias. Note that same string returns if not aliased.
  611.  * strip off host from login name (considers user@host, host!user and so on)
  612.  * if (user == ourlogin)
  613.  *    match host with _this_ host, or
  614.  *    match host with alternate hosts (alternate hostname, * matches all cases)
  615.  *    if matched, then remove name from list.
  616.  * ignore parenthesized names (those are comments ignored by "correct" mailers)
  617.  */
  618. rm_cmts_in_addr(p)
  619. register char *p;
  620. {
  621.     char buf[BUFSIZ], *start = p, *cmnt;
  622.     register char **argv;
  623.     int cnt, argc, x = 0, take_me_off = !do_set(set_options, "metoo");
  624.     int in_cmnt = FALSE, i;
  625.  
  626.     if (!(argv = mk_argv(p, &argc, 0)))
  627.     return;
  628.     for (cnt = 0; cnt < argc; cnt = x+1) {
  629.     /* comments are in parens, as in: "argv (Dan Heller)" */
  630.     if ((cmnt = any(argv[cnt], "()")) || in_cmnt) {
  631.         x++;
  632.         if (cmnt && *cmnt != ')')
  633.         in_cmnt = TRUE;
  634.         else if (cmnt && *cmnt == ')')
  635.         in_cmnt = FALSE; /* else, unchange cmnt flag */
  636.         /* if the previous argument was deleted, then delete this one
  637.          * example, we are "user" and our host is "host" take off:
  638.          * list ... user@host (firstname lastname) more users...
  639.          * "user@host" "(Firstname" "Last name)"
  640.          */
  641.         xfree(argv[cnt]), argv[cnt] = "";
  642.         continue;
  643.     }
  644.     (void) strcpy(buf, argv[x = cnt]);
  645.     /* example: "Dan Heller <argv>" -- real address is in angle brackets
  646.      * delete the angle brackets.  Potential bug: the name is still in
  647.      * the address.. result might be: "Dan Heller argv"
  648.      */
  649.     if (*buf == '<') {
  650.         while (!(p = index(argv[x], '>')))
  651.         if (++x == argc)
  652.             break;
  653.         else
  654.             (void) strcat(buf, argv[x]);
  655.         if (!p)  /* this one is in error, but parse the rest anyway */
  656.         continue;
  657.         if (p = index(buf, '>'))
  658.         *p = 0; /* play with buf, not argv[]! */
  659.     }
  660.  
  661.     /* if we're removing ourselves from the list, see if we're on it */
  662.     if (!take_me_off || !chk_two_lists(login, buf, "!@%="))
  663.         continue;
  664.  
  665.     /* we must be on the list -- see if the hostnames match alternates
  666.      * first match our current host if a host was even given.
  667.      * Bug: if a login name is a subset (or a complete) hostname, then
  668.      * incorrect results may occur.
  669.      */
  670.     if (any(buf, "!@%=")) {
  671.         for (i = 0; i < MAX_HOST_NAMES && ourname[i]; i++)
  672.         if (chk_two_lists(buf, ourname[i], "!@%="))
  673.             break;
  674.         /* If the hostname in the address is one of our hostnames,
  675.          * remove this address.  Else, see if the alternates hostnames
  676.          * are in the address.
  677.          */
  678.         if ((i == MAX_HOST_NAMES || !ourname[i]) &&
  679.         (!(p = do_set(set_options, "alternates")) || *p != '*' &&
  680.          !chk_two_lists(buf, p, "!@%= \t,")))
  681.             continue;
  682.     }
  683.     /* all's well that ends well -- take us off the list */
  684.     xfree(argv[cnt]), argv[cnt] = "";
  685.     }
  686.     (void) argv_to_string(start, argv);
  687.     free_vec(argv);
  688. }
  689.  
  690. /*
  691.  * improve uucp paths by looking at the name of each host listed in the
  692.  * path given.
  693.  *    sun!island!pixar!island!argv
  694.  * It's a legal address, but redundant. Also, if we know we talk to particular
  695.  * hosts via uucp, then we can just start with that host and disregard the
  696.  * rest of the line.  So, first get the known hosts and save them. Then start
  697.  * at the end of the original path (at the last ! found), and move backwards
  698.  * saving each hostname.  If we get to a host that we know about, stop there
  699.  * and use that address.  If we get to a host we've already seen, then
  700.  * delete it and all the hosts since then until the first occurance of that
  701.  * hostname.  When we get to the beginning, the address will be complete.
  702.  *
  703.  * return all results into the original buffer passed to us.  Since we can
  704.  * at worst not touch the path (shorten it if anything), we know we're not
  705.  * going to overrun the buffer.
  706.  */
  707.  
  708. #define go_back_to_bang() for (--p; p > start && *p != '!'; p--)
  709.  
  710. improve_uucp_paths(original)
  711. register char *original;
  712. {
  713.     char       hostnames[32][64], buf[BUFSIZ], *knowns, *end;
  714.     register char *p, *recipient, *start = original, *b = buf, c;
  715.     int           saved_hosts, i;
  716.  
  717.     if (!original || !*original)
  718.     return;
  719.  
  720.     knowns = do_set(set_options, "known_hosts");
  721.  
  722.     while ((end = any(start, " \t,")) || *start) {
  723.     saved_hosts = 0;
  724.     if (!end)
  725.         p = start + strlen(start);
  726.     else
  727.         p = end; /* set p to the "end" cuz p moves. start will equal end */
  728.     c = *p, *p = 0; /* save the char we're nulling out (separating addrs) */
  729.     go_back_to_bang();
  730.     if (p == start)
  731.         b += Strcpy(b, start), recipient = NULL;
  732.     else {
  733.         recipient = p+1;
  734.         while (p > start) {
  735.         /* null remainder of string to save the hostname */
  736.         *p = 0;
  737.         go_back_to_bang();
  738.         /* if p is not at the start, move it forward past the '!' */
  739.         if (p != start)
  740.             ++p;
  741. #ifndef SYSV
  742.         /* next host on the list is ourselves, ignore preceding names */
  743.         for (i = 0; i < MAX_HOST_NAMES && ourname[i]; i++)
  744.             if (!strcmp(p, ourname[i]))
  745.             saved_hosts = 0;
  746. #endif SYSV
  747.         for (i = 0; i < saved_hosts; i++)
  748.             if (!strcmp(hostnames[i], p))
  749.                saved_hosts = i;
  750.         (void) strcpy(hostnames[saved_hosts++], p);
  751.         if (saved_hosts == 32) {
  752.             print("Too many hosts in uucp path! Address not fixed.\n");
  753.             return; /* original buffer is unchanged */
  754.         }
  755.         /* If we know that we call this host, break */
  756.         if (p == start || knowns && chk_two_lists(p, knowns, " ,\t"))
  757.             break;
  758.         --p; /* move p back onto the '!'; it != start */
  759.         }
  760.     }
  761.     while (saved_hosts-- > 0)
  762.         b += strlen(sprintf(b, "%s!", hostnames[saved_hosts]));
  763.     if (recipient) {
  764.         /* if there were no saved_hosts, add a ! */
  765.         if (*(b-1) != '!')
  766.         *b++ = '!';
  767.         b += Strcpy(b, recipient);
  768.     }
  769.     *b++ = c;
  770.     if (!end)
  771.         break;
  772.     start = end + 1;
  773.     if (isspace(*start)) {
  774.         *b++ = ' ';
  775.         while (isspace(*start))
  776.         start++;
  777.     }
  778.     }
  779.     *b = 0;
  780.     (void) strcpy(original, buf);
  781. }
  782.