home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / comm / mail / smail / src / rcs / headers.c,v < prev    next >
Text File  |  1993-12-21  |  28KB  |  1,397 lines

  1. head    1.14;
  2. access;
  3. symbols
  4.     C_1:1.14;
  5. locks; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.14
  10. date    93.11.13.23.13.02;    author Aussem;    state Exp;
  11. branches;
  12. next    1.13;
  13.  
  14. 1.13
  15. date    93.11.06.16.02.16;    author Aussem;    state Exp;
  16. branches;
  17. next    1.12;
  18.  
  19. 1.12
  20. date    93.11.05.22.51.53;    author Aussem;    state Exp;
  21. branches;
  22. next    1.11;
  23.  
  24. 1.11
  25. date    93.11.05.22.22.13;    author Aussem;    state Exp;
  26. branches;
  27. next    1.10;
  28.  
  29. 1.10
  30. date    93.10.28.23.14.01;    author Aussem;    state Exp;
  31. branches;
  32. next    1.9;
  33.  
  34. 1.9
  35. date    93.10.28.22.05.26;    author Aussem;    state Exp;
  36. branches;
  37. next    1.8;
  38.  
  39. 1.8
  40. date    93.10.22.00.27.53;    author Aussem;    state Exp;
  41. branches;
  42. next    1.7;
  43.  
  44. 1.7
  45. date    93.10.17.18.44.20;    author Aussem;    state Exp;
  46. branches;
  47. next    1.6;
  48.  
  49. 1.6
  50. date    93.10.10.21.05.46;    author Aussem;    state Exp;
  51. branches;
  52. next    1.5;
  53.  
  54. 1.5
  55. date    93.10.10.19.32.34;    author Aussem;    state Exp;
  56. branches;
  57. next    1.4;
  58.  
  59. 1.4
  60. date    93.09.18.20.23.05;    author Aussem;    state Exp;
  61. branches;
  62. next    1.3;
  63.  
  64. 1.3
  65. date    93.09.18.16.47.47;    author Aussem;    state Exp;
  66. branches;
  67. next    1.2;
  68.  
  69. 1.2
  70. date    93.09.11.01.42.43;    author Aussem;    state Exp;
  71. branches;
  72. next    1.1;
  73.  
  74. 1.1
  75. date    93.09.08.16.27.13;    author Aussem;    state Exp;
  76. branches;
  77. next    ;
  78.  
  79.  
  80. desc
  81. @analyse and setup the header
  82. @
  83.  
  84.  
  85. 1.14
  86. log
  87. @MAXLINE inserted
  88. @
  89. text
  90. @/*
  91.  *  headers.c
  92.  *
  93.  *  message spooing, header and address parsing and completion
  94.  *  functions for smail/rmail
  95.  *
  96.  * This program is free software; you can redistribute it and/or
  97.  * modify it under the terms of the GNU General Public License as
  98.  * published by the Free Software Foundation; either version 2 of
  99.  * the License, or (at your option) any later version.
  100.  *
  101.  * This program is distributed in the hope that it will be useful,
  102.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  103.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  104.  * General Public License for more details.
  105.  *
  106.  * You should have received a copy of the GNU General Public License
  107.  * along with this program; if not, write to the Free Software
  108.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  109.  *
  110.  * $Log: headers.c,v $
  111.  * Revision 1.13  1993/11/06  16:02:16  Aussem
  112.  * smail does not look in rmail mode in the mailheader
  113.  *
  114.  * Revision 1.12  1993/11/05  22:51:53  Aussem
  115.  * Return-Receipt-To: recognition now works again
  116.  *
  117.  * Revision 1.11  1993/11/05  22:22:13  Aussem
  118.  * Return-Receipt-To: recognition now works
  119.  *
  120.  * Revision 1.10  1993/10/28  23:14:01  Aussem
  121.  * space on right of return-receipt headers forgotten
  122.  *
  123.  * Revision 1.9  1993/10/28  22:05:26  Aussem
  124.  * comments from return-receipt removed
  125.  *
  126.  * Revision 1.8  1993/10/22  00:27:53  Aussem
  127.  * user%site%site.do.main@@sub.do.main
  128.  * and
  129.  * sub.do.main!site.do.main%site%user
  130.  * addresses are now supported
  131.  *
  132.  * Revision 1.7  1993/10/17  18:44:20  Aussem
  133.  * -f argument is now really used
  134.  * smail does not stop on a single dot on a line anymore
  135.  *
  136.  * Revision 1.6  1993/10/10  21:05:46  Aussem
  137.  * continuation lines and whites spaces are now handled in the
  138.  * right way
  139.  *
  140.  * Revision 1.5  1993/10/10  19:32:34  Aussem
  141.  * Bcc: lines are now supported
  142.  *
  143.  * Revision 1.4  1993/09/18  20:23:05  Aussem
  144.  * the cc line can now be parsed from cmdline and from file
  145.  *
  146.  * Revision 1.3  1993/09/18  16:47:47  Aussem
  147.  * insert GNU license text in the header
  148.  *
  149.  * Revision 1.2  1993/09/11  01:42:43  Aussem
  150.  * To: lines will bei insert from mailbody AND cmdline
  151.  * EnforcerHits while generation the Cc: line removed
  152.  *
  153.  * Revision 1.1  1993/09/08  16:27:13  Aussem
  154.  * Initial revision
  155.  *
  156.  *
  157.  */
  158.  
  159. static char     *rcsid="$Id: headers.c,v 1.13 1993/11/06 16:02:16 Aussem Exp Aussem $";
  160.  
  161. # include    <stdio.h>
  162. # include    <stdlib.h>
  163. # include    <sys/types.h>
  164. # include    <time.h>
  165. # include    <ctype.h>
  166. # include    "defs.h"
  167.  
  168. extern enum edebug debug;    /* how verbose we are         */
  169. extern char hostname[];        /* */
  170. extern char hostdomain[];    /* */
  171. extern char *spoolfile;        /* file name of spooled message */
  172. extern FILE *spoolfp;        /* file ptr  to spooled message */
  173. extern int spoolmaster;        /* set if creator of spoolfile  */
  174. extern time_t now;        /* time                */
  175. extern char nows[], arpanows[];    /* time strings            */
  176. extern struct tm *gmt, *loc;    /* time structs            */
  177. extern char *from_addr;        /* replacement fromaddr with -f */
  178. extern char *subject;     /* replacement subject with -s */
  179. extern char *realname;
  180. extern int cc_index;
  181. extern int bcc_index;
  182. extern int receipt;
  183. extern FILE *mystdin;
  184. extern int asrmail;
  185.  
  186. char  return_receipt[SMLBUF]="";
  187.  
  188. static char toline[SMLBUF];
  189. static char fromline[SMLBUF];
  190. static char dateline[SMLBUF];
  191. static char midline[SMLBUF];
  192. static char subjectline[SMLBUF];
  193. static char ccline[SMLBUF]="";
  194. static char *ieof = "NOTNULL";
  195.  
  196. struct reqheaders {
  197.     char *name;
  198.     char *field;
  199.     char have;
  200. };
  201.  
  202. static struct reqheaders reqtab[] = {
  203.     "Message-Id:"    ,    midline        ,    'N'    ,
  204.     "Date:"        ,    dateline    ,    'N'    ,
  205.     "From:"        ,    fromline    ,    'N'    ,
  206.     "To:"        ,    toline        ,    'N'    ,
  207.     "Cc:"        ,    NULL        ,    'N'    ,
  208.     "Bcc:"        ,    NULL        ,    'N'    ,
  209.     "Subject:"    ,    subjectline        ,    'N'    ,
  210.     NULL         ,    NULL        ,    'N'
  211. };
  212.  
  213.  
  214. /*
  215. **
  216. ** parse(): parse <address> into <domain, user, form>.
  217. **
  218. **     input        form
  219. **    -----        ----
  220. **    user        LOCAL
  221. **    domain!user    DOMAIN
  222. **    user@@domain    DOMAIN
  223. **    @@domain,address    LOCAL    (just for sendmail)
  224. **    host!address    UUCP
  225. **
  226. */
  227.  
  228. enum eform
  229. parse(address, domain, user)
  230. char *address;        /* input address     */
  231. char *domain;        /* output domain     */
  232. char *user;        /* output user         */
  233. {
  234.     int parts;
  235.     char *partv[MAXPATH];                /* to crack address */
  236.  
  237. /*
  238. **  If this is route address form @@domain_a,@@domain_b:user@@domain_c, ...
  239. */
  240.  
  241.     if(*address == '@@')
  242. #ifdef SENDMAIL
  243. /*
  244. **  hand it to sendmail
  245. */
  246.     {
  247.         goto local;
  248.     }
  249. #else
  250. /*
  251. **  no sendmail, convert it into a bang path: domain_a!domain_b!domain_c!user
  252. */
  253.     {
  254.         char buf[SMLBUF], *p;
  255.         char t_dom[SMLBUF], t_user[SMLBUF];
  256.  
  257.         (void) strcpy(buf, address+1);        /* elide leading '@@' */
  258.  
  259.         for(p=buf; *p != '\0' ; p++) {    /* search for ',' or ':' */
  260.             if(*p == ':') {        /* reached end of route */
  261.                 break;
  262.             }
  263.             if(*p == ',') {        /* elide ','s */
  264.                 (void) strcpy(p, p+1);
  265.             }
  266.             if(*p == '@@') {        /* convert '@@' to '!' */
  267.                 *p = '!';
  268.             }
  269.         }
  270.  
  271.         if(*p != ':') {    /* bad syntax - punt */
  272.             goto local;
  273.         }
  274.         *p = '\0';
  275.  
  276.         if(parse(p+1, t_dom, t_user) != LOCAL) {
  277.             (void) strcat(buf, "!");
  278.             (void) strcat(buf, t_dom);
  279.         }
  280.         (void) strcat(buf, "!");
  281.         (void) strcat(buf, t_user);
  282.  
  283.         /* munge the address (yuk)
  284.         ** it's OK to copy into 'address', because the machinations
  285.         ** above don't increase the string length of the address.
  286.         */
  287.  
  288.         (void) strcpy(address, buf);
  289.  
  290.         /* re-parse the address */
  291.         return(parse(address, domain, user));
  292.     }
  293. #endif
  294.  
  295. /*
  296. **    user%site%site.do.main@@sub.do.main
  297. ** -> sub.do.main!site.do.main!site!user
  298. **
  299. **    sub.do.main!site.do.main%site%user
  300. ** -> sub.do.main!site.do.main!site!user
  301. */
  302. if(strchr(address,'%'))
  303.     {
  304.    register int i;
  305.    char *p;
  306.  
  307.       parts = ssplit(address, '@@', partv);
  308.    if(parts>1)
  309.        {
  310.         strcpy(domain, partv[1]);
  311.         strncpy(user, partv[0], partv[1]-partv[0]-1);
  312.         user[partv[1]-partv[0]-1] = '\0';
  313.         strcpy(address,domain);
  314.           parts = ssplit(user, '%', partv);
  315.  
  316.        for(i=0;i<parts;i++)
  317.            {
  318.           p=strchr(partv[parts-i-1],'%');
  319.           if(p)    *p='\0';
  320.             strcat(address,"!");
  321.            strcat(address,partv[parts-i-1]);
  322.            }
  323.        }
  324.    else
  325.        {
  326.       for(p=address;*p!='\0';p++)
  327.           if(*p=='%')*p='!';
  328.        }
  329.     }
  330. /*
  331. **  Try splitting at @@.  If it works, this is user@@domain, form DOMAIN.
  332. **  Prefer the righthand @@ in a@@b@@c.
  333. */
  334.     if ((parts = ssplit(address, '@@', partv)) >= 2) {
  335.         (void) strcpy(domain, partv[parts-1]);
  336.         (void) strncpy(user, partv[0], partv[parts-1]-partv[0]-1);
  337.         user[partv[parts-1]-partv[0]-1] = '\0';
  338.         return (DOMAIN);
  339.     }
  340.  
  341. /*
  342. **  Try splitting at !. If it works, see if the piece before the ! has
  343. **  a . in it (domain!user, form DOMAIN) or not (host!user, form UUCP).
  344. */
  345.     if (ssplit(address, '!', partv) > 1) {
  346.         (void) strcpy(user, partv[1]);
  347.         (void) strncpy(domain, partv[0], partv[1]-partv[0]-1);
  348.         domain[partv[1]-partv[0]-1] = '\0';
  349.  
  350.         if((parts = ssplit(domain, '.', partv)) < 2) {
  351.             return(UUCP);
  352.         }
  353.  
  354.         if(partv[parts-1][0] == '\0') {
  355.             partv[parts-1][-1] = '\0'; /* strip trailing . */
  356.         }
  357.         return (DOMAIN);
  358.     }
  359. /* 
  360. **  Done trying.  This must be just a user name, form LOCAL.
  361. */
  362. local:
  363.     (void) strcpy(user, address);
  364.     (void) strcpy(domain, "");
  365.     return(LOCAL);                /* user */
  366. }
  367.  
  368. build(domain, user, form, result)
  369. char *domain;
  370. char *user;
  371. enum eform form;
  372. char *result;
  373. {
  374.     switch((int) form) {
  375.     case LOCAL:
  376.         (void) sprintf(result, "%s", user); 
  377.         break;
  378.     case UUCP:
  379.         (void) sprintf(result, "%s!%s", domain, user);
  380.         break;
  381.     case DOMAIN:
  382.         (void) sprintf(result, "%s@@%s", user, domain);
  383.         break;
  384.     }
  385. }
  386.  
  387. /*
  388. **  ssplit(): split a line into array pointers.
  389. **
  390. **  Each pointer wordv[i] points to the first character after the i'th 
  391. **  occurence of c in buf.  Note that each wordv[i] includes wordv[i+1].
  392. **
  393. */
  394.  
  395. ssplit(buf, c, ptr)
  396. register char *buf;        /* line to split up         */
  397. char c;                /* character to split on    */
  398. char **ptr;            /* the resultant vector        */
  399. {
  400.         int count = 0;
  401.         int wasword = 0;
  402.  
  403.         for(; *buf; buf++) {
  404.         if (!wasword) {
  405.             count++;
  406.             *ptr++ = buf;
  407.         }
  408.         wasword = (c != *buf);
  409.         }
  410.     if (!wasword) {
  411.         count++;
  412.         *ptr++ = buf;
  413.     }
  414.         *ptr = NULL;
  415.         return(count);
  416. }
  417.  
  418. /*
  419. ** Determine whether an address is a local address
  420. */
  421.  
  422. islocal(addr, domain, user)
  423. char *addr, *domain, *user;
  424. {
  425.         enum eform form;
  426.         extern char hostuucp[];
  427.  
  428.         /*
  429.         ** parse the address
  430.         */
  431.  
  432.         form = parse(addr, domain, user);
  433.  
  434.         if((form == LOCAL)            /* user */
  435.         ||(strcmpic(domain, hostdomain) == 0)    /* user@@hostdomain */
  436.         ||(strcmpic(domain, hostname)   == 0)    /* user@@hostname */
  437. #ifdef DOMGATE
  438.         ||(strcmpic(domain, &MYDOM[0]) == 0)    /* user@@MYDOM w/ dot */
  439.         ||(strcmpic(domain, &MYDOM[1]) == 0)    /* user@@MYDOM no dot */
  440. #endif
  441.         ||(strcmpic(domain, hostuucp)   == 0)) {/* user@@hostuucp */
  442.             return(1);
  443.         }
  444.         return(0);
  445. }
  446.  
  447. /*
  448.  *
  449.  */
  450. void
  451. checkheader(char *buf)
  452. {
  453. const char receipt[]="Return-Receipt-To:";
  454. const size_t receipt_len=strlen(receipt);
  455.  
  456. if(strncmpic(buf,(char *)receipt,receipt_len)==0)
  457.     {
  458.     char *r=buf+receipt_len;
  459.  
  460.    for(;*r==' ';r++);
  461.    strcpy(return_receipt,&r[0]);
  462.    r=strchr(return_receipt,' ');
  463.    if(r)
  464.        *r='\0';
  465.    r=strchr(return_receipt,'\n');
  466.    if(r)
  467.        *r='\0';
  468.    strip_comments(return_receipt);
  469.     }
  470. }
  471.  
  472. /*
  473. ** spool - message spooling module
  474. **
  475. ** (1) get dates for headers, etc.
  476. ** (2) if the message is on the standard input (no '-f')
  477. **     (a) create a temp file for spooling the message.
  478. **     (b) collapse the From_ headers into a path.
  479. **     (c) if the mail originated locally, then
  480. **         (i) establish default headers
  481. **        (ii) scan the message headers for required header fields
  482. **       (iii) add any required message headers that are absent
  483. **     (d) copy rest of the message to the spool file
  484. **     (e) close the spool file
  485. ** (3) open the spool file for reading
  486. */
  487.  
  488. void
  489. spool(argc, argv)
  490. int argc;
  491. char **argv;
  492. {
  493.     static char *tmpf = "T:";    /* temp file name */
  494.     char buf[SMLBUF];
  495.     static char splbuf[SMLBUF];
  496.     char from[SMLBUF], domain[SMLBUF], user[SMLBUF];
  497.    int flag=0;
  498.  
  499.     /*
  500.     ** if the mail has already been spooled by
  501.     ** a previous invocation of smail don't respool.
  502.     ** check the file name to prevent things like
  503.     ** rmail -f /etc/passwd badguy@@dreadfuldomain
  504.     */
  505.  
  506.     if((spoolfile != NULL)
  507.     && (strnicmp(spoolfile, tmpf, strlen(tmpf)) != 0)) {
  508.         error(EX_TEMPFAIL, "spool: bad file name '%s'\n", spoolfile);
  509.     }
  510.  
  511.     /*
  512.     ** set dates in local, arpa, and gmt forms
  513.     */
  514.     setdates();
  515.  
  516.     /*
  517.     ** If necessary, copy mystdin to a temp file.
  518.     */
  519.  
  520.     if(spoolfile == NULL) {
  521.         spoolfile = strcpy(splbuf, tmpnam(NULL));
  522.  
  523.         if((spoolfp = fopen(spoolfile, "w")) == NULL) {
  524.             error(EX_CANTCREAT, "can't create %s.\n", spoolfile);
  525.         }
  526.  
  527.         spoolmaster = 1;
  528.  
  529.         /*
  530.         ** rline reads the standard input,
  531.         ** collapsing the From_ and >From_
  532.         ** lines into a single uucp path.
  533.         ** first non-from_ line is in buf[];
  534.         */
  535.  
  536.         rline(from, buf);
  537.  
  538.         /*
  539.       ** if we are not rmail (or started as rmail)
  540.         ** if the mail originated here, we parse the header
  541.         ** and add any required headers that are missing.
  542.         */
  543.  
  544.         if(!asrmail && (islocal(from, domain, user) || (from_addr != NULL))) {
  545.             /*
  546.             ** initialize default headers
  547.             */
  548.             def_headers(argc, argv, from);
  549.  
  550.          /*
  551.          ** Return-Receipt-To: check is done in scanheaders()
  552.          */
  553.          flag=1;
  554.             /*
  555.             ** buf has first, non-from_  line
  556.             */
  557.             scanheaders(buf);
  558.             /*
  559.             ** buf has first, non-header line,
  560.             */
  561.  
  562.             compheaders();
  563.  
  564.             if(buf[0] != '\n') {
  565.                 (void) fputs("\n", spoolfp);
  566.             }
  567.         }
  568.  
  569.         /*
  570.         ** now, copy the rest of the letter into the spool file
  571.         ** terminate on either EOF or '^.$'
  572.         */
  573.         while(ieof != NULL) {
  574.          /*
  575.          ** !flag while we are in the header part
  576.          */
  577.          if(!flag && buf[0]=='\n')
  578.            flag=1;
  579.          /*
  580.          ** if we are in the header and we
  581.          ** should reply to Return-Receipt-To:
  582.          ** Whether smail really answers the header
  583.          ** is decided in deliver.c
  584.          */
  585.          if(receipt && !flag)
  586.            checkheader(buf);
  587.             (void) fputs(buf, spoolfp);
  588.             if((fgets(buf, SMLBUF, mystdin) == NULL)
  589.         /*
  590.          **   Don't know whether this right
  591.          **    || (buf[0] == '.' && buf[1] == '\n')
  592.        */
  593.             )
  594.             {
  595.                 ieof = NULL;
  596.             }
  597.         }
  598.  
  599.         /*
  600.         ** close the spool file, and the standard input.
  601.         */
  602.  
  603.         (void) fclose(spoolfp);
  604.         (void) fclose(mystdin);    /* you don't see this too often! */
  605.     }
  606.  
  607.     if((spoolfp = fopen(spoolfile, "r")) == NULL) {
  608.         error(EX_TEMPFAIL, "can't open %s.\n", spoolfile);
  609.     }
  610. }
  611.  
  612. /*
  613. **
  614. **  rline(): collapse From_ and >From_ lines.
  615. **
  616. **  Same idea as the old rmail, but also turns user@@domain to domain!user.
  617. **
  618. */
  619.  
  620. void
  621. rline(from, retbuf)
  622. char *from;
  623. char *retbuf;
  624. {
  625.     int parts;            /* for cracking From_ lines ... */
  626.     char *partv[16];        /* ... apart using ssplit()     */
  627.     char user[SMLBUF];        /* for rewriting user@@host    */
  628.     char domain[SMLBUF];        /* "   "         "              */
  629.     char addr[SMLBUF];        /* "   "         "              */
  630.     enum eform form;    /* "   "         "              */
  631.     char *c;
  632.     int nhops, i;
  633.     char buf[SMLBUF], tmp[SMLBUF], *hop[128], *e, *b;
  634.  
  635.     if(spoolmaster == 0) return;
  636.  
  637.     buf[0] = from[0] = addr[0] = '\0';
  638. /*
  639. **  Read each line until we hit EOF or a line not beginning with "From "
  640. **  or ">From " (called From_ lines), accumulating the new path in from
  641. **  and stuffing the actual sending user (the user name on the last From_
  642. **  line) in addr.
  643. */
  644.     for(;;) {
  645.         (void) strcpy(retbuf, buf);
  646.         if(ieof == NULL) {
  647.             break;
  648.         }
  649.         if((fgets(buf, sizeof(buf), mystdin) == NULL)
  650.       /*
  651.       ** Don't stop at a line with only one dot
  652.         **|| (buf[0] == '.' && buf[1] == '\n')
  653.         */
  654.       ) {
  655.             ieof = NULL;
  656.             break;
  657.         }
  658.         if (strncmp("From ", buf, 5)
  659.             && strncmp(">From ", buf, 6)) {
  660.             break;
  661.         }
  662. /*
  663. **  Crack the line apart using ssplit.
  664. */
  665.         if(c = index(buf, '\n')) {
  666.             *c = '\0';
  667.         }
  668.         parts = ssplit(buf, ' ', partv);
  669. /*
  670. **  Tack host! onto the from argument if "remote from host" is present.
  671. */
  672.  
  673.         if((parts > 3)
  674.         && (strncmp("remote from ", partv[parts-3], 12) == 0)) {
  675.             (void) strcat(from, partv[parts-1]);
  676.             (void) strcat(from, "!");
  677.         }
  678. /*
  679. **  Stuff user name into addr, overwriting the user name from previous
  680. **  From_ lines, since only the last one counts.  Then rewrite user@@host
  681. **  into host!user, since @@'s don't belong in the From_ argument.
  682. */
  683.         if(parts < 2) {
  684.             break;
  685.         } else {
  686.             char *x = partv[1];
  687.             char *q = index(x, ' ');
  688.             if(q != NULL) {
  689.                 *q = '\0';
  690.             }
  691.             (void) strcpy(addr, x);
  692.         }
  693.  
  694.         (void) parse(addr, domain, user);
  695.         if(*domain == '\0') {
  696.             form = LOCAL;
  697.         } else {
  698.             form = UUCP;
  699.         }
  700.  
  701.         build(domain, user, form, addr);
  702.     }
  703. /*
  704. **  Now tack the user name onto the from argument.
  705. */
  706.     (void) strcat(from, addr);
  707. /*
  708. **  If we still have no from argument, we have junk headers, but we try
  709. **  to get the user's name using /etc/passwd.
  710. */
  711.  
  712.     if (from[0] == '\0') 
  713.         {
  714.       if(!from_addr)
  715.           {
  716.             char *login;
  717.  
  718.             if ((login = getloginname()) == NULL)
  719.                  strcpy(from, "nobody");    /* bad news */
  720.                 else
  721.                  strcpy(from, login);
  722.             }
  723.       else
  724.             strcpy(from,from_addr);
  725.         }
  726.     /* split the from line on '!'s */
  727.     nhops = ssplit(from, '!', hop);
  728.  
  729.     for(i = 0; i < (nhops - 1); i++) {
  730.         b = hop[i];
  731.         if(*b == '\0') {
  732.             continue;
  733.         }
  734.         e = hop[i+1];
  735.         e-- ;
  736.         *e = '\0';    /* null terminate each path segment */
  737.         e++;
  738.  
  739. #ifdef HIDDENHOSTS
  740. /*
  741. **  Strip hidden hosts:  anything.hostname.MYDOM -> hostname.MYDOM
  742. */
  743.         for(p = b;(p = index(p, '.')) != NULL; p++) {
  744.             if(strcmpic(hostdomain, p+1) == 0) {
  745.                 (void) strcpy(b, hostdomain);
  746.                 break;
  747.             }
  748.         }
  749. #endif
  750.  
  751. /*
  752. **  Strip useless MYDOM: hostname.MYDOM -> hostname
  753. */
  754.         if(strcmpic(hop[i], hostdomain) == 0) {
  755.             (void) strcpy(hop[i], hostname);
  756.         }
  757.     }
  758.  
  759. /*
  760. **  Now strip out any redundant information in the From_ line
  761. **  a!b!c!c!d    => a!b!c!d
  762. */
  763.  
  764.     for(i = 0; i < (nhops - 2); i++) {
  765.         b = hop[i];
  766.         e = hop[i+1];
  767.         if(strcmpic(b, e) == 0) {
  768.             *b = '\0';
  769.         }
  770.     }
  771. /*
  772. **  Reconstruct the From_ line
  773. */
  774.     tmp[0] = '\0';            /* empty the tmp buffer */
  775.  
  776.     for(i = 0; i < (nhops - 1); i++) {
  777.         if((hop[i][0] == '\0')    /* deleted this hop */
  778.          ||((tmp[0] == '\0')    /* first hop == hostname */
  779.           &&(strcmpic(hop[i], hostname) == 0))) {
  780.             continue;
  781.         }
  782.         (void) strcat(tmp, hop[i]);
  783.         (void) strcat(tmp, "!");
  784.     }
  785.     (void) strcat(tmp, hop[i]);
  786.     (void) strcpy(from, tmp);
  787.     (void) strcpy(retbuf, buf);
  788.     (void) fprintf(spoolfp, "%s\n", from);
  789. }
  790.  
  791. /*
  792.  *
  793.  */
  794. void
  795. scanheaders(buf)
  796. char *buf;
  797. {
  798.     int inheader = 0;
  799.  
  800.     while(ieof != NULL) {
  801.         if(buf[0] == '\n') {
  802.             break; /* end of headers */
  803.         }
  804.  
  805.         /*
  806.         ** header lines which begin with whitespace
  807.         ** are continuation lines
  808.         */
  809.         if((inheader == 0)
  810.         || ((buf[0] != ' ' && buf[0] != '\t'))) {
  811.             /* not a continuation line
  812.             ** check for header
  813.             */
  814.             if(isheader(buf) == 0) {
  815.                 /*
  816.                 ** not a header
  817.                 */
  818.                 break;
  819.             }
  820.             inheader = 1;
  821.             haveheaders(buf);
  822.          /*
  823.          ** if we should reply to Return-Receipt-To:
  824.          ** grep the address line
  825.          ** Whether smail answers the header
  826.          ** is decided in deliver.c
  827.          */
  828.          if(receipt) checkheader(buf);
  829.         }
  830.  
  831.         /* 
  832.        ** ignore continuation lines and white spaces
  833.        ** their will be handled in To:,Cc: nad Bcc: lines
  834.        **
  835.        */
  836.         if(buf[0] == ' ' || buf[0] == '\t')
  837.             buf[0]='\0';
  838.  
  839.         (void) fputs(buf, spoolfp);
  840.         if((fgets(buf, SMLBUF, mystdin) == NULL)
  841.       /*
  842.       ** Don't stop at a line with only one dot
  843.         **|| (buf[0] == '.' && buf[1] == '\n')
  844.         */
  845.       ) {
  846.             ieof = NULL;
  847.         }
  848.     }
  849.  
  850.     if(isheader(buf)) {
  851.         buf[0] = '\0';
  852.     }
  853. }
  854.  
  855. /*
  856. ** complete headers - add any required headers that are not in the message
  857. */
  858. void
  859. compheaders()
  860. {
  861.     struct reqheaders *i;
  862.  
  863.     /*
  864.     ** look at the table of required headers and
  865.     ** add those that are missing to the spooled message.
  866.     */
  867.     for(i = reqtab; i->name != NULL; i++) {
  868.    /* for the cc-line and bcc-line the field ptr is NULL */
  869.         if(i->have != 'Y' && i->field) {
  870.             (void) fprintf(spoolfp, "%s\n", i->field);
  871.         }
  872.     }
  873. }
  874.  
  875. /*
  876. ** look at a string and determine
  877. ** whether or not it is a valid header.
  878. */
  879. isheader(s)
  880. char *s;
  881. {
  882.     char *p;
  883.  
  884.     /*
  885.     ** header field names must terminate with a colon
  886.     ** and may not be null.
  887.     */
  888.     if(((p = index(s, ':')) == NULL) || (s == p)) {
  889.         return(0);
  890.  
  891.     }
  892.     /*
  893.     ** header field names must consist entirely of
  894.     ** printable ascii characters.
  895.     */
  896.     while(s != p) {
  897.        if(!isprint(*s))
  898.             return(0);
  899. /* we have ansi! if((*s < '!') || (*s > '~'))    return(0); */
  900.         s++;
  901.     }
  902.     /*
  903.     ** we hit the ':', so the field may be a header
  904.     */
  905.     return(1);
  906. }
  907.  
  908. /*
  909. ** compare the header field to those in the required header table.
  910. ** if it matches, then mark the required header as being present
  911. ** in the message.
  912. */
  913. haveheaders(s)
  914. char *s;
  915. {
  916.     struct reqheaders *i;
  917.  
  918.     for(i = reqtab; i->name != NULL; i++) {
  919.         if(strncmpic(i->name, s, strlen(i->name)) == 0) {
  920.             if((strncmpic("Subject:", s, 8) == 0)
  921.             && (subject != NULL)) {
  922.                 (void) sprintf(s, "Subject: %s\n", subject);
  923.             }
  924.             if((strncmpic("From:", s, 5) == 0)
  925.             && (from_addr != NULL)) {
  926.                 (void) sprintf(s, "From: %s\n", from_addr);
  927.             }
  928.          /* To: Cc: and Bcc: will be handled differently */
  929.             if((strncmpic("To:", s, 3) == 0) ||
  930.             (strncmpic("Bcc:", s, 4) == 0) ||
  931.             (strncmpic("Cc:", s, 3) == 0))
  932.                 *s='\0';
  933.          else
  934.                 i->have = 'Y';
  935.             break;
  936.         }
  937.     }
  938. }
  939.  
  940. /*
  941. ** create default headers for the message.
  942. */
  943. def_headers(argc, argv, from)
  944. int argc;
  945. char **argv;
  946. char *from;
  947. {
  948.     def_to(argc, argv);    /* default To:        */
  949.     def_date();        /* default Date:    */
  950.     def_from(from);        /* default From:     */
  951.     def_mid();        /* default Message-Id:    */
  952.    def_subject();
  953. }
  954.  
  955. /*
  956. ** default Date: in arpa format
  957. */
  958. def_date()
  959. {
  960.     (void) strcpy(dateline, "Date: ");
  961.     (void) strcat(dateline, arpanows);
  962. }
  963.  
  964. /*
  965. ** default Message-Id
  966. **  Message-Id: <yymmddhhmm.AAppppp@@hostdomain>
  967. **
  968. **    yy     year
  969. **    mm     month
  970. **    dd     day
  971. **    hh     hour
  972. **    mm     minute
  973. **    ppppp    process-id
  974. **
  975. ** date and time are set by GMT
  976. */
  977. def_mid()
  978. {
  979.     (void) sprintf(midline, "Message-Id: <%02d%02d%02d%02d%02d.AA%05d@@%s>",
  980.         gmt->tm_year,
  981.         gmt->tm_mon+1,
  982.         gmt->tm_mday,
  983.         gmt->tm_hour,
  984.         gmt->tm_min,
  985.         getpid(),
  986.         hostdomain);
  987. }
  988.  
  989. /*
  990. ** default Subject: from cmd-line
  991. **
  992. */
  993. def_subject()
  994. {
  995.     if (subject != NULL) {
  996.         (void) sprintf(subjectline, "Subject: %s", subject);
  997.         return;
  998.     }
  999. }
  1000. /*
  1001. ** default From:
  1002. **  From: user@@hostdomain (Full Name)
  1003. */
  1004. def_from(from)
  1005. char *from;
  1006. {
  1007.     char name[SMLBUF];
  1008.  
  1009.     name[0] = '\0';
  1010.    if(!realname)
  1011.       realname=getrealname(from_addr?from_addr:from);
  1012.    if(realname)
  1013.        strcpy(name,realname);
  1014.  
  1015.     if (from_addr != NULL) {
  1016.         if(name[0] != '\0') {
  1017.             (void) sprintf(fromline,
  1018.                 "From: %s@@%s (%s)", from_addr, hostdomain, name);
  1019.         } else {
  1020.             (void) sprintf(fromline,
  1021.                 "From: %s@@%s", from_addr, hostdomain);
  1022.         }
  1023.         return;
  1024.     }
  1025.  
  1026.     if(name[0] != '\0') {
  1027.         (void) sprintf(fromline,
  1028.             "From: %s@@%s (%s)", from, hostdomain, name);
  1029.     } else {
  1030.         (void) sprintf(fromline,
  1031.             "From: %s@@%s", from, hostdomain);
  1032.     }
  1033. }
  1034.  
  1035. /*
  1036. ** default To:
  1037. **  To: recip1, recip2, ...
  1038. **
  1039. ** lines longer than MAXLINE chars are continued on another line.
  1040. */
  1041. def_to(argc, argv)
  1042. int argc;
  1043. char **argv;
  1044. {
  1045.     int i, n;
  1046.     char *bol;
  1047.  
  1048.    /* if we have bcc-lines in argv donnot 
  1049.       print them in the outgoing mail  */
  1050.    if(bcc_index!=-1)
  1051.        argc=bcc_index;
  1052.  
  1053.     bol = toline;
  1054.     (void) strcpy(bol, "To: ");
  1055.     for(n = i = 0; i < argc; i++) {
  1056.    /* insert the Cc: line */
  1057.       if(i==cc_index)
  1058.           {
  1059.             bol=rindex(toline,',');
  1060.             *bol = '\n';
  1061.             *(bol+1) = '\0';
  1062.             n = 0;
  1063.           strcat(bol,"Cc: ");
  1064.             }
  1065.         (void) strcat(bol, argv[i]);
  1066.  
  1067.         if((index(argv[i], '!') == NULL)
  1068.         && (index(argv[i], '@@') == NULL)) {
  1069.             (void) strcat(bol, "@@");
  1070.             (void) strcat(bol, hostdomain);
  1071.         }
  1072.         if(i+1 < argc) {
  1073.             n = strlen(bol);
  1074.             /* if the line is greater than MAXLINE columns */
  1075.             if(n > MAXLINE) {
  1076.                 (void) strcat(bol, ",\n\t");
  1077.                 bol = bol + strlen(bol);
  1078.                 *bol = '\0';
  1079.                 n = 8;
  1080.             } else {
  1081.                 (void) strcat(bol, ", ");
  1082.             }
  1083.         }
  1084.     }
  1085. }
  1086. @
  1087.  
  1088.  
  1089. 1.13
  1090. log
  1091. @smail does not look in rmail mode in the mailheader
  1092. @
  1093. text
  1094. @d22 3
  1095. d70 1
  1096. a70 1
  1097. static char     *rcsid="$Id: headers.c,v 1.12 1993/11/05 22:51:53 Aussem Exp Aussem $";
  1098. d950 1
  1099. a950 1
  1100. ** lines longer than 50 chars are continued on another line.
  1101. d985 2
  1102. a986 2
  1103.             /* if the line is greater than 50 columns */
  1104.             if(n > 50) {
  1105. @
  1106.  
  1107.  
  1108. 1.12
  1109. log
  1110. @Return-Receipt-To: recognition now works again
  1111. @
  1112. text
  1113. @d22 3
  1114. d67 1
  1115. a67 1
  1116. static char     *rcsid="$Id: headers.c,v 1.11 1993/11/05 22:22:13 Aussem Exp Aussem $";
  1117. d92 1
  1118. d447 1
  1119. d452 1
  1120. a452 1
  1121.         if(islocal(from, domain, user) || (from_addr != NULL)) {
  1122. d458 4
  1123. d483 1
  1124. a483 1
  1125.          ** flag == 0 while we read the header
  1126. d488 1
  1127. a488 1
  1128.          ** if the header is active and we 
  1129. d490 1
  1130. a490 1
  1131.          ** Whether smail answers the header
  1132. d730 7
  1133. @
  1134.  
  1135.  
  1136. 1.11
  1137. log
  1138. @Return-Receipt-To: recognition now works
  1139. @
  1140. text
  1141. @d22 3
  1142. d64 1
  1143. a64 1
  1144. static char     *rcsid="$Id: headers.c,v 1.10 1993/10/28 23:14:01 Aussem Exp Aussem $";
  1145. d401 1
  1146. d473 13
  1147. a485 1
  1148.          if(receipt) checkheader(buf);
  1149. @
  1150.  
  1151.  
  1152. 1.10
  1153. log
  1154. @space on right of return-receipt headers forgotten
  1155. @
  1156. text
  1157. @d22 3
  1158. d61 1
  1159. a61 1
  1160. static char     *rcsid="$Id: headers.c,v 1.9 1993/10/28 22:05:26 Aussem Exp Aussem $";
  1161. d349 25
  1162. d469 1
  1163. d499 1
  1164. a499 1
  1165. **  Same idea as the old rmail, but also turns user@@domain to domain!user. 
  1166. a677 25
  1167. checkheader(char *buf)
  1168. {
  1169. const char receipt[]="Return-Receipt-To: ";
  1170. const size_t receipt_len=strlen(receipt);
  1171.  
  1172. if(strncmpic(buf,(char *)receipt,receipt_len)==0)
  1173.     {
  1174.     char *r=buf+receipt_len;
  1175.  
  1176.    for(;*r==' ';r++);
  1177.    strcpy(return_receipt,&r[0]);
  1178.    r=strchr(return_receipt,' ');
  1179.    if(r)
  1180.        *r='\0';
  1181.    r=strchr(return_receipt,'\n');
  1182.    if(r)
  1183.        *r='\0';
  1184.    strip_comments(return_receipt);
  1185.     }
  1186. }
  1187.  
  1188. /*
  1189.  *
  1190.  */
  1191. void
  1192. a704 1
  1193.          if(receipt) checkheader(buf);
  1194. @
  1195.  
  1196.  
  1197. 1.9
  1198. log
  1199. @comments from return-receipt removed
  1200. @
  1201. text
  1202. @d22 3
  1203. d58 1
  1204. a58 1
  1205. static char     *rcsid="$Id: headers.c,v 1.8 1993/10/22 00:27:53 Aussem Exp Aussem $";
  1206. d657 2
  1207. d660 3
  1208. @
  1209.  
  1210.  
  1211. 1.8
  1212. log
  1213. @user%site%site.do.main@@sub.do.main
  1214. and
  1215. sub.do.main!site.do.main%site%user
  1216. addresses are now supported
  1217. @
  1218. text
  1219. @d22 6
  1220. d55 1
  1221. a55 1
  1222. static char     *rcsid="$Id: headers.c,v 1.7 1993/10/17 18:44:20 Aussem Exp Aussem $";
  1223. d658 1
  1224. @
  1225.  
  1226.  
  1227. 1.7
  1228. log
  1229. @-f argument is now really used
  1230. smail does not stop on a single dot on a line anymore
  1231. @
  1232. text
  1233. @d22 4
  1234. d49 1
  1235. a49 1
  1236. static char     *rcsid="$Id: headers.c,v 1.6 1993/10/10 21:05:46 Aussem Exp Aussem $";
  1237. d129 1
  1238. d183 36
  1239. d228 2
  1240. a229 1
  1241.     } 
  1242. @
  1243.  
  1244.  
  1245. 1.6
  1246. log
  1247. @continuation lines and whites spaces are now handled in the
  1248. right way
  1249. @
  1250. text
  1251. @d22 4
  1252. d45 1
  1253. a45 1
  1254. static char     *rcsid="$Id: headers.c,v 1.5 1993/10/10 19:32:34 Aussem Exp Aussem $";
  1255. d69 1
  1256. d338 1
  1257. a338 1
  1258.     ** If necessary, copy stdin to a temp file.
  1259. d391 7
  1260. a397 2
  1261.             if((fgets(buf, SMLBUF, stdin) == NULL)
  1262.             || (buf[0] == '.' && buf[1] == '\n')) {
  1263. d407 1
  1264. a407 1
  1265.         (void) fclose(stdin);    /* you don't see this too often! */
  1266. d444 1
  1267. a444 1
  1268. **  and stuffing the actual sending user (the user name on the last From_ 
  1269. d452 6
  1270. a457 2
  1271.         if((fgets(buf, sizeof(buf), stdin) == NULL)
  1272.         || (buf[0] == '.' && buf[1] == '\n')) {
  1273. d461 1
  1274. a461 1
  1275.         if (strncmp("From ", buf, 5) 
  1276. d482 2
  1277. a483 2
  1278. **  Stuff user name into addr, overwriting the user name from previous 
  1279. **  From_ lines, since only the last one counts.  Then rewrite user@@host 
  1280. d515 13
  1281. a527 6
  1282.     if (from[0] == '\0') {
  1283.         char *login;
  1284.         if ((login = getloginname()) == NULL) {
  1285.             (void) strcpy(from, "nobody");    /* bad news */
  1286.         } else {
  1287.             (void) strcpy(from, login);
  1288. a528 2
  1289.     }
  1290.  
  1291. d656 6
  1292. a661 2
  1293.         if((fgets(buf, SMLBUF, stdin) == NULL)
  1294.         || (buf[0] == '.' && buf[1] == '\n')) {
  1295. @
  1296.  
  1297.  
  1298. 1.5
  1299. log
  1300. @Bcc: lines are now supported
  1301. @
  1302. text
  1303. @d22 3
  1304. d41 1
  1305. a41 1
  1306. static char     *rcsid="$Id: headers.c,v 1.4 1993/09/18 20:23:05 Aussem Exp Aussem $";
  1307. d627 9
  1308. @
  1309.  
  1310.  
  1311. 1.4
  1312. log
  1313. @the cc line can now be parsed from cmdline and from file
  1314. @
  1315. text
  1316. @d22 3
  1317. d38 1
  1318. a38 1
  1319. static char     *rcsid="$Id: headers.c,v 1.3 1993/09/18 16:47:47 Aussem Exp Aussem $";
  1320. d60 1
  1321. d85 1
  1322. d649 1
  1323. a649 1
  1324.    /* for the cc-line the field ptr is NULL */
  1325. d678 1
  1326. a678 1
  1327.         if((*s < '!') || (*s > '~')) {
  1328. d680 1
  1329. a680 1
  1330.         }
  1331. d709 1
  1332. a709 1
  1333.          /* To: will be handled differently */
  1334. d711 1
  1335. d828 5
  1336. @
  1337.  
  1338.  
  1339. 1.3
  1340. log
  1341. @insert GNU license text in the header
  1342. @
  1343. text
  1344. @d22 3
  1345. d35 1
  1346. a35 1
  1347. static char     *rcsid="$Id: headers.c,v 1.2 1993/09/11 01:42:43 Aussem Exp Aussem $";
  1348. d66 1
  1349. d80 1
  1350. d644 2
  1351. a645 1
  1352.         if(i->have != 'Y') {
  1353. d705 2
  1354. a706 1
  1355.             if(strncmpic("To:", s, 3) == 0)
  1356. @
  1357.  
  1358.  
  1359. 1.2
  1360. log
  1361. @To: lines will bei insert from mailbody AND cmdline
  1362. EnforcerHits while generation the Cc: line removed
  1363. @
  1364. text
  1365. @d7 14
  1366. d22 4
  1367. d32 1
  1368. a32 1
  1369. static char     *rcsid="$Id: headers.c,v 1.1 1993/09/08 16:27:13 Aussem Exp Aussem $";
  1370. @
  1371.  
  1372.  
  1373. 1.1
  1374. log
  1375. @Initial revision
  1376. @
  1377. text
  1378. @d7 3
  1379. a9 1
  1380.  * $Log$
  1381. d11 1
  1382. d14 1
  1383. a14 1
  1384. static char     *rcsid="$Id$";
  1385. d680 5
  1386. a684 1
  1387.             i->have = 'Y';
  1388. d801 1
  1389. d804 3
  1390. a806 4
  1391.             bol = bol + strlen(bol)-1;
  1392.             bol=rindex(bol,' ');
  1393.             *(bol-1) = '\n';
  1394.             *bol = '\0';
  1395. d819 1
  1396. @
  1397.