home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / com / utils / elm / sources / returnad.c < prev    next >
C/C++ Source or Header  |  1992-05-23  |  13KB  |  466 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: returnadd.c,v 4.1.1.3 90/12/11 15:35:56 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.3 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    returnadd.c,v $
  17.  * Revision 4.1.1.3  90/12/11  15:35:56  syd
  18.  * Add back missing  strlen line, fixes segv problem
  19.  * From: Syd
  20.  *
  21.  * Revision 4.1.1.2  90/12/05  22:33:58  syd
  22.  * Fix missing close brace due to indention error
  23.  * From: Syd
  24.  *
  25.  * Revision 4.1.1.1  90/12/05  21:59:41  syd
  26.  * Fix where header could be going past end on return due to line
  27.  * combination on header continuation.
  28.  * From: Syd via report from Tom Davis
  29.  *
  30.  * Revision 4.1  90/04/28  22:43:54  syd
  31.  * checkin of Elm 2.3 as of Release PL0
  32.  *
  33.  *
  34.  ******************************************************************************/
  35.  
  36. /** This set of routines is used to generate real return addresses
  37.     and also return addresses suitable for inclusion in a users
  38.     alias files (ie optimized based on the pathalias database).
  39.  
  40. **/
  41.  
  42. #include "headers.h"
  43.  
  44. #include <errno.h>
  45.  
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48.  
  49. char *shift_lower();
  50.  
  51. #ifndef OS2
  52. extern int errno;
  53. #endif
  54.  
  55. char *error_name(), *strcat(), *strcpy();
  56.  
  57. #ifdef OPTIMIZE_RETURN
  58.  
  59. optimize_return(address)
  60. char *address;
  61. {
  62.     /** This routine tries to create an optimized address, that is,
  63.         an address that has the minimal information needed to
  64.         route a message to this person given the current path
  65.         database...
  66.     **/
  67.  
  68. #ifndef INTERNET
  69.     char    bogus_internet[SLEN];
  70.  
  71.     sprintf(bogus_internet, "@%s", hostfullname);
  72.  
  73.     /** first off, let's see if we need to strip off the localhost
  74.         address crap... **/
  75.  
  76.     /** if we have a uucp part (e.g.a!b) AND the bogus address...**/
  77.  
  78.     if (chloc(address,'!') != -1 && in_string(address, bogus_internet))
  79.       address[strlen(address)-strlen(bogus_internet)] = '\0';
  80. #endif
  81.  
  82.     /** next step is to figure out what sort of address we have... **/
  83.  
  84.     if (chloc(address, '%') != -1)
  85.       optimize_cmplx_arpa(address);
  86.     else if (chloc(address, '@') != -1)
  87.       optimize_arpa(address);
  88.     else
  89.       optimize_usenet(address);
  90. }
  91.  
  92. optimize_cmplx_arpa(address)
  93. char *address;
  94. {
  95.     /** Try to optimize a complex ARPA address.  A Complex address is one
  96.         that contains '%' (deferred '@').  For example:
  97.         veeger!hpcnof!hplabs!joe%sytech@syte
  98.         is a complex address (no kidding, right?).  The algorithm for
  99.         trying to resolve it is to move all the way to the right, then
  100.         back up left until the first '!' then from there to the SECOND
  101.         metacharacter on the right is the name@host address...(in this
  102.             example, it would be "joe%sytech").  Check this in the routing
  103.         table.  If not present, keep backing out to the right until we
  104.         find a host that is present, or we hit the '@' sign.  Once we
  105.         have a 'normal' ARPA address, hand it to optimize_arpa().
  106.     **/
  107.  
  108.     char name[NLEN], buffer[SLEN], junk[SLEN];
  109.     char host[NLEN], old_host[NLEN];
  110.     register int i, loc, nloc = 0, hloc = 0, passes = 1;
  111.  
  112.     /** first off, get the name%host... **/
  113.  
  114.     for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--)
  115.        ;
  116.  
  117.     while (address[loc] != '\0') {
  118.  
  119.       if (passes == 1) {
  120.         loc++;
  121.  
  122.         while (address[loc] != '%' && address[loc] != '@')
  123.           name[nloc++] = address[loc++];
  124.       }
  125.       else {
  126.         for (i=0; old_host[i] != '\0'; i++)
  127.           name[nloc++] = old_host[i];
  128.       }
  129.  
  130.       loc++;
  131.  
  132.       while (address[loc] != '%' && address[loc] != '@')
  133.         host[hloc++] = address[loc++];
  134.  
  135.       host[hloc] = name[nloc] = '\0';
  136.  
  137.       strcpy(old_host, host);
  138.  
  139.       sprintf(buffer, "%s@%s", name, shift_lower(host));
  140.  
  141.       if (expand_site(buffer, junk) == 0) {
  142.         strcpy(address, buffer);
  143.         return;
  144.       }
  145.       else if (address[loc] == '@') {
  146.         optimize_arpa(address);
  147.         return;
  148.       }
  149.       else
  150.         name[nloc++] = '%';    /* for next pass through */
  151.  
  152.     }
  153. }
  154.  
  155. optimize_arpa(address)
  156. char *address;
  157. {
  158.     /** Get an arpa address and simplify it to the minimal
  159.         route needed to get mail to this person... **/
  160.  
  161.     char name[NLEN], buffer[SLEN], junk[SLEN];
  162.     char host[NLEN];
  163.     register int loc, nloc = 0, hloc = 0, at_sign = 0;
  164.  
  165.     for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--) {
  166.       if (address[loc] == '@')
  167.          at_sign++;    /* remember this spot! */
  168.       else if (at_sign)
  169.         name[nloc++] = address[loc];
  170.       else
  171.         host[hloc++] = address[loc];
  172.     }
  173.  
  174.     name[nloc] = host[hloc] = '\0';
  175.  
  176.     reverse(name);
  177.     reverse(host);
  178.  
  179.     sprintf(buffer,"%s@%s", name, shift_lower(host));
  180.  
  181.     if (expand_site(buffer, junk) == 0) {
  182.       strcpy(address, buffer);
  183.       return;
  184.     }
  185.  
  186.     optimize_usenet(address);    /* that didn't work... */
  187. }
  188.  
  189. optimize_usenet(address)
  190. char *address;
  191. {
  192.     /** optimize the return address IFF it's a standard usenet
  193.         address...
  194.     **/
  195.  
  196.     char name[NLEN],  new_address[SLEN], buffer[SLEN], junk[SLEN];
  197.     register int loc, nloc = 0, aloc = 0, passes = 1;
  198.  
  199.     for (loc = strlen(address)-1; address[loc] != '!' && loc > -1; loc--)
  200.       name[nloc++] = address[loc];
  201.     name[nloc] = '\0';
  202.  
  203.     reverse(name);
  204.  
  205.     new_address[0] = '\0';
  206.  
  207.     /* got name, now get machine until we can get outta here */
  208.  
  209.     while (loc > -1) {
  210.  
  211.       new_address[aloc++] = address[loc--];    /* the '!' char */
  212.  
  213.       while (address[loc] != '!' && loc > -1)
  214.         new_address[aloc++] = address[loc--];
  215.  
  216.       new_address[aloc] = '\0';
  217.  
  218.       strcpy(buffer, new_address);
  219.       reverse(buffer);
  220.  
  221.       if (expand_site(buffer, junk) == 0) {
  222.         if (passes == 1 && chloc(name, '@') == -1) {
  223.           buffer[strlen(buffer) - 1] = '\0';    /* remove '!' */
  224.           sprintf(address, "%s@%s", name, buffer);
  225.         }
  226.         else
  227.           sprintf(address, "%s%s", buffer, name);
  228.         return;        /* success! */
  229.       }
  230.       passes++;
  231.     }
  232.  
  233.     return;        /* nothing to do! */
  234. }
  235.  
  236. #endif    /* OPTIMIZE_RETURN */
  237.  
  238. int
  239. get_return(buffer, msgnum)
  240. char *buffer;
  241. int msgnum;
  242. {
  243.     /** reads msgnum message again, building up the full return
  244.         address including all machines that might have forwarded
  245.         the message.  Returns whether it is using the To line **/
  246.  
  247.     char buf[SLEN], name1[SLEN], name2[SLEN], lastname[SLEN];
  248.     char hold_return[SLEN], alt_name2[SLEN], buf2[SLEN];
  249.     int ok = 1, lines, len_buf, len_buf2;
  250.     int using_to = FALSE, in_header = FALSE;
  251.  
  252.     /* now initialize all the char buffers [thanks Keith!] */
  253.  
  254.     buf[0] = name1[0] = name2[0] = lastname[0] = '\0';
  255.     hold_return[0] = alt_name2[0] = buf2[0] = '\0';
  256.  
  257.     /** get to the first line of the message desired **/
  258.  
  259.     if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  260.       dprint(1, (debugfile,
  261.         "Error: %d not a valid message number message_count = %d (%s)",
  262.         msgnum, message_count, "get_return"));
  263.       error1("%d not a valid message number!");
  264.       return(using_to);
  265.     }
  266.  
  267.     if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  268.       dprint(1, (debugfile,
  269.         "Error: seek %ld bytes into file hit errno %s (%s)",
  270.         headers[msgnum]->offset, error_name(errno),
  271.             "get_return"));
  272.       error2("Couldn't seek %d bytes into file (%s).",
  273.            headers[msgnum]->offset, error_name(errno));
  274.       return(using_to);
  275.     }
  276.  
  277.     /** okay!  Now we're there!  **/
  278.  
  279.     lines = headers[msgnum]->lines;
  280.     in_header = TRUE;
  281.  
  282.     buffer[0] = '\0';
  283.  
  284.     ok = (int) (fgets(buf2, SLEN, mailfile) != NULL);
  285.     if (ok) {
  286.       fixline(buf2);
  287.       len_buf2 = strlen(buf2);
  288.       if(buf2[len_buf2-1] == '\n') lines--; /* got a full line */
  289.     }
  290.  
  291.     while (ok && lines) {
  292.       buf[0] = '\0';
  293.       strncat(buf, buf2, SLEN);
  294.       len_buf = strlen(buf);
  295.       ok = (int) (fgets(buf2, SLEN, mailfile) != NULL);
  296.       if (ok) {
  297.         fixline(buf2);
  298.         len_buf2 = strlen(buf2);
  299.         if(buf2[len_buf2-1] == '\n') lines--; /* got a full line */
  300.       }
  301.       while (ok && lines && whitespace(buf2[0]) && len_buf >= 2) {
  302.         if (buf[len_buf-1] == '\n') {
  303.           len_buf--;
  304.           buf[len_buf] = '\0';
  305.         }
  306.         strncat(buf, buf2, (SLEN-len_buf-1));
  307.         len_buf = strlen(buf);
  308.         ok = (int) (fgets(buf2, SLEN, mailfile) != NULL);
  309.         if (ok) {
  310.           len_buf2 = strlen(buf2);
  311.           if(buf2[len_buf2-1] == '\n') lines--; /* got a full line */
  312.         }
  313.       }
  314.  
  315. /* At this point, "buf" contains the unfolded header line, while "buf2" contains
  316.    the next single line of text from the mail file */
  317.  
  318.       if (in_header) {
  319.         if (len_buf == 1) /* \n only */
  320.           in_header = FALSE;
  321.       }
  322.       else {
  323.         if (first_word(buf, "Forwarded "))
  324.           in_header = TRUE;
  325.       }
  326.  
  327.       if (!in_header)
  328.         continue;
  329.  
  330.       if (first_word(buf, "From "))
  331.         sscanf(buf, "%*s %s", hold_return);
  332.       else if (first_word(buf, ">From")) {
  333.         sscanf(buf,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s %s",
  334.                name1, name2, alt_name2);
  335.         if (strcmp(name2, "from") == 0)        /* remote from xyz  */
  336.           strcpy(name2, alt_name2);
  337.         else if (strcmp(name2, "by") == 0)    /* forwarded by xyz */
  338.           strcpy(name2, alt_name2);
  339.         add_site(buffer, name2, lastname);
  340.       }
  341.  
  342. #ifdef USE_EMBEDDED_ADDRESSES
  343.  
  344.       else if (first_word(buf, "From:")) {
  345.         get_address_from("From:", buf, hold_return);
  346.         buffer[0] = '\0';
  347.           }
  348.           else if (first_word(buf, "Reply-To:")) {
  349.         get_address_from("Reply-To:", buf, buffer);
  350.         return(using_to);
  351.           }
  352.  
  353. #endif
  354.  
  355.       else if (len_buf < 2)    /* done with header */
  356.             lines = 0; /* let's get outta here!  We're done!!! */
  357.     }
  358.  
  359.     if (buffer[0] == '\0')
  360.       strcpy(buffer, hold_return); /* default address! */
  361.     else
  362.       add_site(buffer, name1, lastname);    /* get the user name too! */
  363.  
  364.     if (first_word(buffer, "To:")) {    /* for backward compatibility */
  365.       get_existing_address(buffer,msgnum);
  366.       using_to = TRUE;
  367.     }
  368.     else {
  369.       /*
  370.        * KLUDGE ALERT - DANGER WILL ROBINSON
  371.        * We can't just leave a bare login name as the return address,
  372.        * or it will be alias-expanded.
  373.        * So we qualify it with the current host name (and, maybe, domain).
  374.        * Sigh.
  375.        */
  376.  
  377.       if (chloc(buffer, '@') < 0
  378.        && chloc(buffer, '%') < 0
  379.        && chloc(buffer, '!') < 0)
  380.       {
  381. #ifdef INTERNET
  382.         sprintf(buffer + strlen(buffer), "@%s", hostfullname);
  383. #else
  384.         strcpy(buf, buffer);
  385.         sprintf(buffer, "%s!%s", hostname, buf);
  386. #endif
  387.       }
  388.  
  389.       /*
  390.        * If we have a space character,
  391.        * or we DON'T have '!' or '@' chars,
  392.        * append the user-readable name.
  393.        */
  394.       if (chloc(headers[msgnum]->from, ' ') >= 0 ||
  395.           (chloc(headers[msgnum]->from, '!') < 0 &&
  396.            chloc(headers[msgnum]->from, '@') < 0)) {
  397.            sprintf(buffer + strlen(buffer),
  398.                " (%s)", headers[msgnum]->from);
  399.           }
  400.     }
  401.  
  402.     return(using_to);
  403. }
  404.  
  405. get_existing_address(buffer, msgnum)
  406. char *buffer;
  407. int msgnum;
  408. {
  409.     /** This routine is called when the message being responded to has
  410.         "To:xyz" as the return address, signifying that this message is
  411.         an automatically saved copy of a message previously sent.  The
  412.         correct to address can be obtained fairly simply by reading the
  413.         To: header from the message itself and (blindly) copying it to
  414.         the given buffer.  Note that this header can be either a normal
  415.         "To:" line (Elm) or "Originally-To:" (previous versions e.g.Msg)
  416.     **/
  417.  
  418.     char mybuf[LONG_STRING];
  419.     register char ok = 1, in_to = 0;
  420.  
  421.     buffer[0] = '\0';
  422.  
  423.     /** first off, let's get to the beginning of the message... **/
  424.  
  425.     if(msgnum < 0 || msgnum >= message_count || message_count < 1) {
  426.       dprint(1, (debugfile,
  427.         "Error: %d not a valid message number message_count = %d (%s)",
  428.         msgnum, message_count, "get_existing_address"));
  429.       error1("%d not a valid message number!");
  430.       return;
  431.     }
  432.         if (fseek(mailfile, headers[msgnum]->offset, 0) == -1) {
  433.         dprint(1, (debugfile,
  434.             "Error: seek %ld bytes into file hit errno %s (%s)",
  435.             headers[msgnum]->offset, error_name(errno),
  436.             "get_existing_address"));
  437.         error2("Couldn't seek %d bytes into the file (%s).",
  438.                headers[msgnum]->offset, error_name(errno));
  439.         return;
  440.         }
  441.  
  442.         /** okay!  Now we're there!  **/
  443.  
  444.         while (ok) {
  445.           ok = (int) (fgets(mybuf, LONG_STRING, mailfile) != NULL);
  446.       no_ret(mybuf);    /* remove return character */
  447.  
  448.           if (first_word(mybuf, "To: ")) {
  449.         in_to = TRUE;
  450.         strcpy(buffer, (char *) mybuf + strlen("To: "));
  451.           }
  452.       else if (first_word(mybuf, "Original-To:")) {
  453.         in_to = TRUE;
  454.         strcpy(buffer, (char *) mybuf + strlen("Original-To:"));
  455.       }
  456.       else if (in_to && whitespace(mybuf[0])) {
  457.         strcat(buffer, " ");        /* tag a space in   */
  458.         strcat(buffer, (char *) mybuf + 1);    /* skip 1 whitespace */
  459.       }
  460.       else if (strlen(mybuf) < 2)
  461.         return;                /* we're done for!  */
  462.       else
  463.         in_to = 0;
  464.       }
  465. }
  466.