Annotation of coherent/d/bin/mail/smail/headers.c, revision 1.1.1.1

1.1       root        1: /*
                      2: **  message spooing, header and address parsing and completion
                      3: **  functions for smail/rmail
                      4: */
                      5: 
                      6: #ifndef lint
                      7: static char    *sccsid="@(#)headers.c  2.5 (smail) 9/15/87";
                      8: #endif
                      9: 
                     10: # include      <stdio.h>
                     11: # include      <sys/types.h>
                     12: # include      <time.h>
                     13: # include      <ctype.h>
                     14: # include      <pwd.h>
                     15: # include      "defs.h"
                     16: 
                     17: extern enum edebug debug;      /* how verbose we are           */ 
                     18: extern char hostname[];                /* */
                     19: extern char hostdomain[];      /* */
                     20: extern char *spoolfile;                /* file name of spooled message */
                     21: extern FILE *spoolfp;          /* file ptr  to spooled message */
                     22: extern int spoolmaster;                /* set if creator of spoolfile  */
                     23: extern time_t now;             /* time                         */
                     24: extern char nows[], arpanows[];        /* time strings                 */
                     25: extern struct tm *gmt, *loc;   /* time structs                 */
                     26: extern char *from_addr;                /* replacement fromaddr with -F */
                     27: 
                     28: static char toline[SMLBUF];
                     29: static char fromline[SMLBUF];
                     30: static char dateline[SMLBUF];
                     31: static char midline[SMLBUF];
                     32: static char *ieof = "NOTNULL";
                     33: 
                     34: struct reqheaders {
                     35:        char *name;
                     36:        char *field;
                     37:        char have;
                     38: };
                     39: 
                     40: static struct reqheaders reqtab[] = {
                     41:        "Message-Id:"   ,       midline         ,       'N'     ,
                     42:        "Date:"         ,       dateline        ,       'N'     ,
                     43:        "From:"         ,       fromline        ,       'N'     ,
                     44:        "To:"           ,       toline          ,       'N'     ,
                     45:        NULL            ,       NULL            ,       'N'
                     46: };
                     47: 
                     48: 
                     49: /*
                     50: **
                     51: ** parse(): parse <address> into <domain, user, form>.
                     52: **
                     53: **     input           form
                     54: **     -----           ----
                     55: **     user            LOCAL
                     56: **     domain!user     DOMAIN
                     57: **     user@domain     DOMAIN
                     58: **     @domain,address LOCAL   (just for sendmail)
                     59: **     host!address    UUCP
                     60: **
                     61: */
                     62: 
                     63: enum eform
                     64: parse(address, domain, user)
                     65: char *address;         /* input address        */
                     66: char *domain;          /* output domain        */
                     67: char *user;            /* output user          */
                     68: {
                     69:        int parts;
                     70:        char *partv[MAXPATH];                           /* to crack address */
                     71: 
                     72: /*
                     73: **  If this is route address form @domain_a,@domain_b:user@domain_c, ...
                     74: */
                     75:        if(*address == '@')
                     76: #ifdef SENDMAIL
                     77: /*
                     78: **  hand it to sendmail
                     79: */
                     80:        {
                     81:                goto local;
                     82:        }
                     83: #else
                     84: /*
                     85: **  no sendmail, convert it into a bang path: domain_a!domain_b!domain_c!user
                     86: */
                     87:        {
                     88:                char buf[SMLBUF], *p;
                     89:                char t_dom[SMLBUF], t_user[SMLBUF];
                     90: 
                     91:                (void) strcpy(buf, address+1);          /* elide leading '@' */
                     92: 
                     93:                for(p=buf; *p != '\0' ; p++) {  /* search for ',' or ':' */
                     94:                        if(*p == ':') {         /* reached end of route */
                     95:                                break;
                     96:                        }
                     97:                        if(*p == ',') {         /* elide ','s */
                     98:                                (void) strcpy(p, p+1);
                     99:                        }
                    100:                        if(*p == '@') {         /* convert '@' to '!' */
                    101:                                *p = '!';
                    102:                        }
                    103:                }
                    104: 
                    105:                if(*p != ':') { /* bad syntax - punt */
                    106:                        goto local;
                    107:                }
                    108:                *p = '\0';
                    109: 
                    110:                if(parse(p+1, t_dom, t_user) != LOCAL) {
                    111:                        (void) strcat(buf, "!");
                    112:                        (void) strcat(buf, t_dom);
                    113:                }
                    114:                (void) strcat(buf, "!");
                    115:                (void) strcat(buf, t_user);
                    116: 
                    117:                /* munge the address (yuk)
                    118:                ** it's OK to copy into 'address', because the machinations
                    119:                ** above don't increase the string length of the address.
                    120:                */
                    121: 
                    122:                (void) strcpy(address, buf);
                    123: 
                    124:                /* re-parse the address */
                    125:                return(parse(address, domain, user));
                    126:        }
                    127: #endif
                    128: /*
                    129: **  Try splitting at @.  If it works, this is user@domain, form DOMAIN.
                    130: **  Prefer the righthand @ in a@b@c.
                    131: */
                    132:        if ((parts = ssplit(address, '@', partv)) >= 2) {
                    133:                (void) strcpy(domain, partv[parts-1]);
                    134:                (void) strncpy(user, partv[0], partv[parts-1]-partv[0]-1);
                    135:                user[partv[parts-1]-partv[0]-1] = '\0';
                    136:                return (DOMAIN);
                    137:        } 
                    138: /*
                    139: **  Try splitting at !. If it works, see if the piece before the ! has
                    140: **  a . in it (domain!user, form DOMAIN) or not (host!user, form UUCP).
                    141: */
                    142:        if (ssplit(address, '!', partv) > 1) {
                    143:                (void) strcpy(user, partv[1]);
                    144:                (void) strncpy(domain, partv[0], partv[1]-partv[0]-1);
                    145:                domain[partv[1]-partv[0]-1] = '\0';
                    146: 
                    147:                if((parts = ssplit(domain, '.', partv)) < 2) {
                    148:                        return(UUCP);
                    149:                }
                    150: 
                    151:                if(partv[parts-1][0] == '\0') {
                    152:                        partv[parts-1][-1] = '\0'; /* strip trailing . */
                    153:                }
                    154:                return (DOMAIN);
                    155:        }
                    156: /* 
                    157: **  Done trying.  This must be just a user name, form LOCAL.
                    158: */
                    159: local:
                    160:        (void) strcpy(user, address);
                    161:        (void) strcpy(domain, "");
                    162:        return(LOCAL);                          /* user */
                    163: }
                    164: 
                    165: build(domain, user, form, result)
                    166: char *domain;
                    167: char *user;
                    168: enum eform form;
                    169: char *result;
                    170: {
                    171:        switch((int) form) {
                    172:        case LOCAL:
                    173:                (void) sprintf(result, "%s", user); 
                    174:                break;
                    175:        case UUCP:
                    176:                (void) sprintf(result, "%s!%s", domain, user);
                    177:                break;
                    178:        case DOMAIN:
                    179:                (void) sprintf(result, "%s@%s", user, domain);
                    180:                break;
                    181:        }
                    182: }
                    183: 
                    184: /*
                    185: **  ssplit(): split a line into array pointers.
                    186: **
                    187: **  Each pointer wordv[i] points to the first character after the i'th 
                    188: **  occurence of c in buf.  Note that each wordv[i] includes wordv[i+1].
                    189: **
                    190: */
                    191: 
                    192: ssplit(buf, c, ptr)
                    193: register char *buf;            /* line to split up             */
                    194: char c;                                /* character to split on        */
                    195: char **ptr;                    /* the resultant vector         */
                    196: {
                    197:         int count = 0;
                    198:         int wasword = 0;
                    199: 
                    200:         for(; *buf; buf++) {
                    201:                if (!wasword) {
                    202:                        count++;
                    203:                        *ptr++ = buf;
                    204:                }
                    205:                wasword = (c != *buf);
                    206:         }
                    207:        if (!wasword) {
                    208:                count++;
                    209:                *ptr++ = buf;
                    210:        }
                    211:         *ptr = NULL;
                    212:         return(count);
                    213: }
                    214: 
                    215: /*
                    216: ** Determine whether an address is a local address
                    217: */
                    218: 
                    219: islocal(addr, domain, user)
                    220: char *addr, *domain, *user;
                    221: {
                    222:                enum eform form, parse();
                    223:                extern char hostuucp[];
                    224: 
                    225:                /*
                    226:                ** parse the address
                    227:                */
                    228: 
                    229:                form = parse(addr, domain, user);
                    230: 
                    231:                if((form == LOCAL)                      /* user */
                    232:                ||(strcmpic(domain, hostdomain) == 0)   /* user@hostdomain */
                    233:                ||(strcmpic(domain, hostname)   == 0)   /* user@hostname */
                    234: #ifdef DOMGATE
                    235:                ||(strcmpic(domain, &MYDOM[0]) == 0)    /* user@MYDOM w/ dot */
                    236:                ||(strcmpic(domain, &MYDOM[1]) == 0)    /* user@MYDOM no dot */
                    237: #endif
                    238:                ||(strcmpic(domain, hostuucp)   == 0)) {/* user@hostuucp */
                    239:                        return(1);
                    240:                }
                    241:                return(0);
                    242: }
                    243: 
                    244: /*
                    245: ** spool - message spooling module
                    246: **
                    247: ** (1) get dates for headers, etc.
                    248: ** (2) if the message is on the standard input (no '-f')
                    249: **     (a) create a temp file for spooling the message.
                    250: **     (b) collapse the From_ headers into a path.
                    251: **     (c) if the mail originated locally, then
                    252: **          (i) establish default headers
                    253: **         (ii) scan the message headers for required header fields
                    254: **        (iii) add any required message headers that are absent
                    255: **     (d) copy rest of the message to the spool file
                    256: **     (e) close the spool file
                    257: ** (3) open the spool file for reading
                    258: */
                    259: 
                    260: void
                    261: spool(argc, argv)
                    262: int argc;
                    263: char **argv;
                    264: {
                    265:        static char *tmpf = "/tmp/rmXXXXXX";    /* temp file name */
                    266:        char *mktemp();
                    267:        char buf[SMLBUF];
                    268:        static char splbuf[SMLBUF];
                    269:        char from[SMLBUF], domain[SMLBUF], user[SMLBUF];
                    270:        void rline(), scanheaders(), compheaders();
                    271: 
                    272:        /*
                    273:        ** if the mail has already been spooled by
                    274:        ** a previous invocation of smail don't respool.
                    275:        ** check the file name to prevent things like
                    276:        ** rmail -f /etc/passwd badguy@dreadfuldomain
                    277:        */
                    278: 
                    279:        if((spoolfile != NULL)
                    280:        && (strncmp(spoolfile, tmpf, strlen(tmpf) - 6) != 0)) {
                    281:                error(EX_TEMPFAIL, "spool: bad file name '%s'\n", spoolfile);
                    282:        }
                    283: 
                    284:        /*
                    285:        ** set dates in local, arpa, and gmt forms
                    286:        */
                    287:        setdates();
                    288: 
                    289:        /*
                    290:        ** If necessary, copy stdin to a temp file.
                    291:        */
                    292: 
                    293:        if(spoolfile == NULL) {
                    294:                spoolfile = strcpy(splbuf, tmpf);
                    295:                (void) mktemp(spoolfile);
                    296: 
                    297:                if((spoolfp = fopen(spoolfile, "w")) == NULL) {
                    298:                        error(EX_CANTCREAT, "can't create %s.\n", spoolfile);
                    299:                }
                    300: 
                    301:                spoolmaster = 1;
                    302: 
                    303:                /*
                    304:                ** rline reads the standard input,
                    305:                ** collapsing the From_ and >From_
                    306:                ** lines into a single uucp path.
                    307:                ** first non-from_ line is in buf[];
                    308:                */
                    309: 
                    310:                rline(from, buf);
                    311: 
                    312:                /*
                    313:                ** if the mail originated here, we parse the header
                    314:                ** and add any required headers that are missing.
                    315:                */
                    316: 
                    317:                if(islocal(from, domain, user) || (from_addr != NULL)) {
                    318:                        /*
                    319:                        ** initialize default headers
                    320:                        */
                    321:                        def_headers(argc, argv, from);
                    322: 
                    323:                        /*
                    324:                        ** buf has first, non-from_  line
                    325:                        */
                    326:                        scanheaders(buf);
                    327:                        /*
                    328:                        ** buf has first, non-header line,
                    329:                        */
                    330: 
                    331:                        compheaders();
                    332: 
                    333:                        if(buf[0] != '\n') {
                    334:                                (void) fputs("\n", spoolfp);
                    335:                                fflush(spoolfp);
                    336:                        }
                    337:                }
                    338: 
                    339:                /*
                    340:                ** now, copy the rest of the letter into the spool file
                    341:                ** terminate on either EOF or '^.$'
                    342:                */
                    343: 
                    344:                while(ieof != NULL) {
                    345:                        (void) fputs(buf, spoolfp);
                    346:                        fflush(spoolfp);
                    347:                        if((fgets(buf, SMLBUF, stdin) == NULL)
                    348:                        || (buf[0] == '.' && buf[1] == '\n')) {
                    349:                                ieof = NULL;
                    350:                        }
                    351:                }
                    352: 
                    353:                /*
                    354:                ** close the spool file, and the standard input.
                    355:                */
                    356: 
                    357:                (void) fclose(spoolfp);
                    358:                (void) fclose(stdin);   /* you don't see this too often! */
                    359:        }
                    360: 
                    361:        if((spoolfp = fopen(spoolfile, "r")) == NULL) {
                    362:                error(EX_TEMPFAIL, "can't open %s.\n", spoolfile);
                    363:        }
                    364: }
                    365: 
                    366: /*
                    367: **
                    368: **  rline(): collapse From_ and >From_ lines.
                    369: **
                    370: **  Same idea as the old rmail, but also turns user@domain to domain!user. 
                    371: **
                    372: */
                    373: 
                    374: void
                    375: rline(from, retbuf)
                    376: char *from;
                    377: char *retbuf;
                    378: {
                    379:        int parts;                      /* for cracking From_ lines ... */
                    380:        char *partv[16];                /* ... apart using ssplit()     */
                    381:        char user[SMLBUF];              /* for rewriting user@host      */
                    382:        char domain[SMLBUF];            /* "   "         "              */
                    383:        char addr[SMLBUF];              /* "   "         "              */
                    384:        enum eform form, parse();       /* "   "         "              */
                    385:        extern build();                 /* "   "         "              */
                    386:        char *c;
                    387:        int nhops, i;
                    388:        char buf[SMLBUF], tmp[SMLBUF], *hop[128], *e, *b;
                    389:        char *pwuid();
                    390: 
                    391:        if(spoolmaster == 0) return;
                    392: 
                    393:        buf[0] = from[0] = addr[0] = '\0';
                    394: /*
                    395: **  Read each line until we hit EOF or a line not beginning with "From "
                    396: **  or ">From " (called From_ lines), accumulating the new path in from
                    397: **  and stuffing the actual sending user (the user name on the last From_ 
                    398: **  line) in addr.
                    399: */
                    400:        for(;;) {
                    401:                (void) strcpy(retbuf, buf);
                    402:                if(ieof == NULL) {
                    403:                        break;
                    404:                }
                    405:                if((fgets(buf, sizeof(buf), stdin) == NULL)
                    406:                || (buf[0] == '.' && buf[1] == '\n')) {
                    407:                        ieof = NULL;
                    408:                        break;
                    409:                }
                    410:                if (strncmp("From ", buf, 5) 
                    411:                    && strncmp(">From ", buf, 6)) {
                    412:                        break;
                    413:                }
                    414: /*
                    415: **  Crack the line apart using ssplit.
                    416: */
                    417:                if(c = index(buf, '\n')) {
                    418:                        *c = '\0';
                    419:                }
                    420:                parts = ssplit(buf, ' ', partv);
                    421: /*
                    422: **  Tack host! onto the from argument if "remote from host" is present.
                    423: */
                    424: 
                    425:                if((parts > 3)
                    426:                && (strncmp("remote from ", partv[parts-3], 12) == 0)) {
                    427:                        (void) strcat(from, partv[parts-1]);
                    428:                        (void) strcat(from, "!");
                    429:                }
                    430: /*
                    431: **  Stuff user name into addr, overwriting the user name from previous 
                    432: **  From_ lines, since only the last one counts.  Then rewrite user@host 
                    433: **  into host!user, since @'s don't belong in the From_ argument.
                    434: */
                    435:                if(parts < 2) {
                    436:                        break;
                    437:                } else {
                    438:                        char *x = partv[1];
                    439:                        char *q = index(x, ' ');
                    440:                        if(q != NULL) {
                    441:                                *q = '\0';
                    442:                        }
                    443:                        (void) strcpy(addr, x);
                    444:                }
                    445: 
                    446:                (void) parse(addr, domain, user);
                    447:                if(*domain == '\0') {
                    448:                        form = LOCAL;
                    449:                } else {
                    450:                        form = UUCP;
                    451:                }
                    452: 
                    453:                build(domain, user, form, addr);
                    454:        }
                    455: /*
                    456: **  Now tack the user name onto the from argument.
                    457: */
                    458:        (void) strcat(from, addr);
                    459: /*
                    460: **  If we still have no from argument, we have junk headers, but we try
                    461: **  to get the user's name using /etc/passwd.
                    462: */
                    463: 
                    464:        if (from[0] == '\0') {
                    465:                char *login;
                    466:                if ((login = pwuid(getuid())) == NULL) {
                    467:                        (void) strcpy(from, "nobody");  /* bad news */
                    468:                } else {
                    469:                        (void) strcpy(from, login);
                    470:                }
                    471:        }
                    472: 
                    473:        /* split the from line on '!'s */
                    474:        nhops = ssplit(from, '!', hop);
                    475: 
                    476:        for(i = 0; i < (nhops - 1); i++) {
                    477:                b = hop[i];
                    478:                if(*b == '\0') {
                    479:                        continue;
                    480:                }
                    481:                e = hop[i+1];
                    482:                e-- ;
                    483:                *e = '\0';      /* null terminate each path segment */
                    484:                e++;
                    485: 
                    486: #ifdef HIDDENHOSTS
                    487: /*
                    488: **  Strip hidden hosts:  anything.hostname.MYDOM -> hostname.MYDOM
                    489: */
                    490:                for(p = b;(p = index(p, '.')) != NULL; p++) {
                    491:                        if(strcmpic(hostdomain, p+1) == 0) {
                    492:                                (void) strcpy(b, hostdomain);
                    493:                                break;
                    494:                        }
                    495:                }
                    496: #endif
                    497: 
                    498: /*
                    499: **  Strip useless MYDOM: hostname.MYDOM -> hostname
                    500: */
                    501:                if(strcmpic(hop[i], hostdomain) == 0) {
                    502:                        (void) strcpy(hop[i], hostname);
                    503:                }
                    504:        }
                    505: 
                    506: /*
                    507: **  Now strip out any redundant information in the From_ line
                    508: **  a!b!c!c!d  => a!b!c!d
                    509: */
                    510: 
                    511:        for(i = 0; i < (nhops - 2); i++) {
                    512:                b = hop[i];
                    513:                e = hop[i+1];
                    514:                if(strcmpic(b, e) == 0) {
                    515:                        *b = '\0';
                    516:                }
                    517:        }
                    518: /*
                    519: **  Reconstruct the From_ line
                    520: */
                    521:        tmp[0] = '\0';                  /* empty the tmp buffer */
                    522: 
                    523:        for(i = 0; i < (nhops - 1); i++) {
                    524:                if((hop[i][0] == '\0')  /* deleted this hop */
                    525:                 ||((tmp[0] == '\0')    /* first hop == hostname */
                    526:                  &&(strcmpic(hop[i], hostname) == 0))) {
                    527:                        continue;
                    528:                }
                    529:                (void) strcat(tmp, hop[i]);
                    530:                (void) strcat(tmp, "!");
                    531:        }
                    532:        (void) strcat(tmp, hop[i]);
                    533:        (void) strcpy(from, tmp);
                    534:        (void) strcpy(retbuf, buf);
                    535:        (void) fprintf(spoolfp, "%s\n", from);
                    536: }
                    537: 
                    538: void
                    539: scanheaders(buf)
                    540: char *buf;
                    541: {
                    542:        int inheader = 0;
                    543: 
                    544:        while(ieof != NULL) {
                    545:                if(buf[0] == '\n') {
                    546:                        break; /* end of headers */
                    547:                }
                    548: 
                    549:                /*
                    550:                ** header lines which begin with whitespace
                    551:                ** are continuation lines
                    552:                */
                    553:                if((inheader == 0)
                    554:                || ((buf[0] != ' ' && buf[0] != '\t'))) {
                    555:                        /* not a continuation line
                    556:                        ** check for header
                    557:                        */
                    558:                        if(isheader(buf) == 0) {
                    559:                                /*
                    560:                                ** not a header
                    561:                                */
                    562:                                break;
                    563:                        }
                    564:                        inheader = 1;
                    565:                        haveheaders(buf);
                    566:                }
                    567:                (void) fputs(buf, spoolfp);
                    568:                fflush(spoolfp);
                    569:                if((fgets(buf, SMLBUF, stdin) == NULL)
                    570:                || (buf[0] == '.' && buf[1] == '\n')) {
                    571:                        ieof = NULL;
                    572:                }
                    573:        }
                    574: 
                    575:        if(isheader(buf)) {
                    576:                buf[0] = '\0';
                    577:        }
                    578: }
                    579: 
                    580: /*
                    581: ** complete headers - add any required headers that are not in the message
                    582: */
                    583: void
                    584: compheaders()
                    585: {
                    586:        struct reqheaders *i;
                    587: 
                    588:        /*
                    589:        ** look at the table of required headers and
                    590:        ** add those that are missing to the spooled message.
                    591:        */
                    592:        for(i = reqtab; i->name != NULL; i++) {
                    593:                if(i->have != 'Y') {
                    594:                        (void) fprintf(spoolfp, "%s\n", i->field);
                    595:                }
                    596:        }
                    597: }
                    598: 
                    599: /*
                    600: ** look at a string and determine
                    601: ** whether or not it is a valid header.
                    602: */
                    603: isheader(s)
                    604: char *s;
                    605: {
                    606:        char *p;
                    607: 
                    608:        /*
                    609:        ** header field names must terminate with a colon
                    610:        ** and may not be null.
                    611:        */
                    612:        if(((p = index(s, ':')) == NULL) || (s == p)) {
                    613:                return(0);
                    614: 
                    615:        }
                    616:        /*
                    617:        ** header field names must consist entirely of
                    618:        ** printable ascii characters.
                    619:        */
                    620:        while(s != p) {
                    621:                if((*s < '!') || (*s > '~')) {
                    622:                        return(0);
                    623:                }
                    624:                s++;
                    625:        }
                    626:        /*
                    627:        ** we hit the ':', so the field may be a header
                    628:        */
                    629:        return(1);
                    630: }
                    631: 
                    632: /*
                    633: ** compare the header field to those in the required header table.
                    634: ** if it matches, then mark the required header as being present
                    635: ** in the message.
                    636: */
                    637: haveheaders(s)
                    638: char *s;
                    639: {
                    640:        struct reqheaders *i;
                    641: 
                    642:        for(i = reqtab; i->name != NULL; i++) {
                    643:                if(strncmpic(i->name, s, strlen(i->name)) == 0) {
                    644:                        if((strncmpic("From:", s, 5) == 0)
                    645:                        && (from_addr != NULL)) {
                    646:                                (void) sprintf(s, "From: %s\n", from_addr);
                    647:                        }
                    648:                        i->have = 'Y';
                    649:                        break;
                    650:                }
                    651:        }
                    652: }
                    653: 
                    654: /*
                    655: ** create default headers for the message.
                    656: */
                    657: def_headers(argc, argv, from)
                    658: int argc;
                    659: char **argv;
                    660: char *from;
                    661: {
                    662:        def_to(argc, argv);     /* default To:          */
                    663:        def_date();             /* default Date:        */
                    664:        def_from(from);         /* default From:        */
                    665:        def_mid();              /* default Message-Id:  */
                    666: }
                    667: 
                    668: /*
                    669: ** default Date: in arpa format
                    670: */
                    671: def_date()
                    672: {
                    673:        (void) strcpy(dateline, "Date: ");
                    674:        (void) strcat(dateline, arpanows);
                    675: }
                    676: 
                    677: /*
                    678: ** default Message-Id
                    679: **  Message-Id: <yymmddhhmm.AAppppp@hostdomain>
                    680: **
                    681: **     yy       year
                    682: **     mm       month
                    683: **     dd       day
                    684: **     hh       hour
                    685: **     mm       minute
                    686: **     ppppp   process-id
                    687: **
                    688: ** date and time are set by GMT
                    689: */
                    690: def_mid()
                    691: {
                    692:        (void) sprintf(midline, "Message-Id: <%02d%02d%02d%02d%02d.AA%05d@%s>",
                    693:                gmt->tm_year,
                    694:                gmt->tm_mon+1,
                    695:                gmt->tm_mday,
                    696:                gmt->tm_hour,
                    697:                gmt->tm_min,
                    698:                getpid(),
                    699:                hostdomain);
                    700: }
                    701: 
                    702: /*
                    703: ** default From:
                    704: **  From: user@hostdomain (Full Name)
                    705: */
                    706: def_from(from)
                    707: char *from;
                    708: {
                    709: 
                    710:        char *nameptr;
                    711:        char name[SMLBUF];
                    712:        char *getenv(), *login;
                    713:        char *pwfnam(), *pwuid();
                    714: 
                    715:        if (from_addr != NULL) {
                    716:                (void) sprintf(fromline, "From: %s", from_addr);
                    717:                return;
                    718:        }
                    719: 
                    720:        name[0] = '\0';
                    721:        if((nameptr = getenv("NAME")) != NULL) {
                    722:                (void) strcpy(name, nameptr);
                    723:        } else if((login = pwuid(getuid())) != NULL) {
                    724:                if((nameptr = pwfnam(login)) != NULL) {
                    725:                        (void) strcpy(name, nameptr);
                    726:                }
                    727:        }
                    728:        if(name[0] != '\0') {
                    729:                (void) sprintf(fromline,
                    730:                        "From: %s@%s (%s)", from, hostdomain, name);
                    731:        } else {
                    732:                (void) sprintf(fromline,
                    733:                        "From: %s@%s", from, hostdomain);
                    734:        }
                    735: }
                    736: 
                    737: /*
                    738: ** default To:
                    739: **  To: recip1, recip2, ...
                    740: **
                    741: ** lines longer than 50 chars are continued on another line.
                    742: */
                    743: def_to(argc, argv)
                    744: int argc;
                    745: char **argv;
                    746: {
                    747:        int i, n;
                    748:        char *bol;
                    749: 
                    750:        bol = toline;
                    751:        (void) strcpy(bol, "To: ");
                    752:        for(n = i = 0; i < argc; i++) {
                    753:                (void) strcat(bol, argv[i]);
                    754: 
                    755:                if((index(argv[i], '!') == NULL)
                    756:                && (index(argv[i], '@') == NULL)) {
                    757:                        (void) strcat(bol, "@");
                    758:                        (void) strcat(bol, hostdomain);
                    759:                }
                    760:                if(i+1 < argc) {
                    761:                        n = strlen(bol);
                    762:                        if(n > 50) {
                    763:                                (void) strcat(bol, ",\n\t");
                    764:                                bol = bol + strlen(bol);
                    765:                                *bol = '\0';
                    766:                                n = 8;
                    767:                        } else {
                    768:                                (void) strcat(bol, ", ");
                    769:                        }
                    770:                }
                    771:        }
                    772: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.