Annotation of 43BSDTahoe/usr.lib/sendmail/src/collect.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Eric P. Allman
                      3:  * Copyright (c) 1988 Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms are permitted
                      7:  * provided that the above copyright notice and this paragraph are
                      8:  * duplicated in all such forms and that any documentation,
                      9:  * advertising materials, and other materials related to such
                     10:  * distribution and use acknowledge that the software was developed
                     11:  * by the University of California, Berkeley.  The name of the
                     12:  * University may not be used to endorse or promote products derived
                     13:  * from this software without specific prior written permission.
                     14:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     15:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     16:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char sccsid[] = "@(#)collect.c  5.4 (Berkeley) 6/30/88";
                     21: #endif /* not lint */
                     22: 
                     23: # include <errno.h>
                     24: # include "sendmail.h"
                     25: 
                     26: /*
                     27: **  COLLECT -- read & parse message header & make temp file.
                     28: **
                     29: **     Creates a temporary file name and copies the standard
                     30: **     input to that file.  Leading UNIX-style "From" lines are
                     31: **     stripped off (after important information is extracted).
                     32: **
                     33: **     Parameters:
                     34: **             sayok -- if set, give an ARPANET style message
                     35: **                     to say we are ready to collect input.
                     36: **
                     37: **     Returns:
                     38: **             none.
                     39: **
                     40: **     Side Effects:
                     41: **             Temp file is created and filled.
                     42: **             The from person may be set.
                     43: */
                     44: 
                     45: collect(sayok)
                     46:        bool sayok;
                     47: {
                     48:        register FILE *tf;
                     49:        char buf[MAXFIELD+2];
                     50:        register char *p;
                     51:        extern char *hvalue();
                     52: 
                     53:        /*
                     54:        **  Create the temp file name and create the file.
                     55:        */
                     56: 
                     57:        CurEnv->e_df = newstr(queuename(CurEnv, 'd'));
                     58:        if ((tf = dfopen(CurEnv->e_df, "w")) == NULL)
                     59:        {
                     60:                syserr("Cannot create %s", CurEnv->e_df);
                     61:                NoReturn = TRUE;
                     62:                finis();
                     63:        }
                     64:        (void) chmod(CurEnv->e_df, FileMode);
                     65: 
                     66:        /*
                     67:        **  Tell ARPANET to go ahead.
                     68:        */
                     69: 
                     70:        if (sayok)
                     71:                message("354", "Enter mail, end with \".\" on a line by itself");
                     72: 
                     73:        /*
                     74:        **  Try to read a UNIX-style From line
                     75:        */
                     76: 
                     77:        (void) sfgets(buf, sizeof buf, InChannel);
                     78:        fixcrlf(buf, FALSE);
                     79: # ifndef NOTUNIX
                     80:        if (!SaveFrom && strncmp(buf, "From ", 5) == 0)
                     81:        {
                     82:                eatfrom(buf);
                     83:                (void) sfgets(buf, sizeof buf, InChannel);
                     84:                fixcrlf(buf, FALSE);
                     85:        }
                     86: # endif NOTUNIX
                     87: 
                     88:        /*
                     89:        **  Copy InChannel to temp file & do message editing.
                     90:        **      To keep certain mailers from getting confused,
                     91:        **      and to keep the output clean, lines that look
                     92:        **      like UNIX "From" lines are deleted in the header.
                     93:        */
                     94: 
                     95:        do
                     96:        {
                     97:                int c;
                     98:                extern bool isheader();
                     99: 
                    100:                /* drop out on error */
                    101:                if (ferror(InChannel))
                    102:                        break;
                    103: 
                    104:                /* if the line is too long, throw the rest away */
                    105:                if (index(buf, '\n') == NULL)
                    106:                {
                    107:                        while ((c = getc(InChannel)) != '\n' && c != EOF)
                    108:                                continue;
                    109:                        /* give an error? */
                    110:                }
                    111: 
                    112:                fixcrlf(buf, TRUE);
                    113: 
                    114:                /* see if the header is over */
                    115:                if (!isheader(buf))
                    116:                        break;
                    117: 
                    118:                /* get the rest of this field */
                    119:                while ((c = getc(InChannel)) == ' ' || c == '\t')
                    120:                {
                    121:                        p = &buf[strlen(buf)];
                    122:                        *p++ = '\n';
                    123:                        *p++ = c;
                    124:                        if (sfgets(p, MAXFIELD - (p - buf), InChannel) == NULL)
                    125:                                break;
                    126:                        fixcrlf(p, TRUE);
                    127:                }
                    128:                if (!feof(InChannel) && !ferror(InChannel))
                    129:                        (void) ungetc(c, InChannel);
                    130: 
                    131:                CurEnv->e_msgsize += strlen(buf);
                    132: 
                    133:                /*
                    134:                **  Snarf header away.
                    135:                */
                    136: 
                    137:                if (bitset(H_EOH, chompheader(buf, FALSE)))
                    138:                        break;
                    139:        } while (sfgets(buf, MAXFIELD, InChannel) != NULL);
                    140: 
                    141: # ifdef DEBUG
                    142:        if (tTd(30, 1))
                    143:                printf("EOH\n");
                    144: # endif DEBUG
                    145: 
                    146:        /* throw away a blank line */
                    147:        if (buf[0] == '\0')
                    148:                (void) sfgets(buf, MAXFIELD, InChannel);
                    149: 
                    150:        /*
                    151:        **  Collect the body of the message.
                    152:        */
                    153: 
                    154:        do
                    155:        {
                    156:                register char *bp = buf;
                    157: 
                    158:                fixcrlf(buf, TRUE);
                    159: 
                    160:                /* check for end-of-message */
                    161:                if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
                    162:                        break;
                    163: 
                    164:                /* check for transparent dot */
                    165:                if (OpMode == MD_SMTP && !IgnrDot && bp[0] == '.' && bp[1] == '.')
                    166:                        bp++;
                    167: 
                    168:                /*
                    169:                **  Figure message length, output the line to the temp
                    170:                **  file, and insert a newline if missing.
                    171:                */
                    172: 
                    173:                CurEnv->e_msgsize += strlen(bp) + 1;
                    174:                fputs(bp, tf);
                    175:                fputs("\n", tf);
                    176:                if (ferror(tf))
                    177:                        tferror(tf);
                    178:        } while (sfgets(buf, MAXFIELD, InChannel) != NULL);
                    179:        if (fflush(tf) != 0)
                    180:                tferror(tf);
                    181:        (void) fclose(tf);
                    182: 
                    183:        /* An EOF when running SMTP is an error */
                    184:        if ((feof(InChannel) || ferror(InChannel)) && OpMode == MD_SMTP)
                    185:        {
                    186:                syserr("collect: unexpected close, from=%s", CurEnv->e_from.q_paddr);
                    187: 
                    188:                /* don't return an error indication */
                    189:                CurEnv->e_to = NULL;
                    190:                CurEnv->e_flags &= ~EF_FATALERRS;
                    191: 
                    192:                /* and don't try to deliver the partial message either */
                    193:                finis();
                    194:        }
                    195: 
                    196:        /*
                    197:        **  Find out some information from the headers.
                    198:        **      Examples are who is the from person & the date.
                    199:        */
                    200: 
                    201:        eatheader(CurEnv);
                    202: 
                    203:        /*
                    204:        **  Add an Apparently-To: line if we have no recipient lines.
                    205:        */
                    206: 
                    207:        if (hvalue("to") == NULL && hvalue("cc") == NULL &&
                    208:            hvalue("bcc") == NULL && hvalue("apparently-to") == NULL)
                    209:        {
                    210:                register ADDRESS *q;
                    211: 
                    212:                /* create an Apparently-To: field */
                    213:                /*    that or reject the message.... */
                    214:                for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next)
                    215:                {
                    216:                        if (q->q_alias != NULL)
                    217:                                continue;
                    218: # ifdef DEBUG
                    219:                        if (tTd(30, 3))
                    220:                                printf("Adding Apparently-To: %s\n", q->q_paddr);
                    221: # endif DEBUG
                    222:                        addheader("apparently-to", q->q_paddr, CurEnv);
                    223:                }
                    224:        }
                    225: 
                    226:        if ((CurEnv->e_dfp = fopen(CurEnv->e_df, "r")) == NULL)
                    227:                syserr("Cannot reopen %s", CurEnv->e_df);
                    228: }
                    229: /*
                    230: **  TFERROR -- signal error on writing the temporary file.
                    231: **
                    232: **     Parameters:
                    233: **             tf -- the file pointer for the temporary file.
                    234: **
                    235: **     Returns:
                    236: **             none.
                    237: **
                    238: **     Side Effects:
                    239: **             Gives an error message.
                    240: **             Arranges for following output to go elsewhere.
                    241: */
                    242: 
                    243: tferror(tf)
                    244:        FILE *tf;
                    245: {
                    246:        if (errno == ENOSPC)
                    247:        {
                    248:                (void) freopen(CurEnv->e_df, "w", tf);
                    249:                fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
                    250:                usrerr("452 Out of disk space for temp file");
                    251:        }
                    252:        else
                    253:                syserr("collect: Cannot write %s", CurEnv->e_df);
                    254:        (void) freopen("/dev/null", "w", tf);
                    255: }
                    256: /*
                    257: **  EATFROM -- chew up a UNIX style from line and process
                    258: **
                    259: **     This does indeed make some assumptions about the format
                    260: **     of UNIX messages.
                    261: **
                    262: **     Parameters:
                    263: **             fm -- the from line.
                    264: **
                    265: **     Returns:
                    266: **             none.
                    267: **
                    268: **     Side Effects:
                    269: **             extracts what information it can from the header,
                    270: **             such as the date.
                    271: */
                    272: 
                    273: # ifndef NOTUNIX
                    274: 
                    275: char   *DowList[] =
                    276: {
                    277:        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
                    278: };
                    279: 
                    280: char   *MonthList[] =
                    281: {
                    282:        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    283:        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
                    284:        NULL
                    285: };
                    286: 
                    287: eatfrom(fm)
                    288:        char *fm;
                    289: {
                    290:        register char *p;
                    291:        register char **dt;
                    292: 
                    293: # ifdef DEBUG
                    294:        if (tTd(30, 2))
                    295:                printf("eatfrom(%s)\n", fm);
                    296: # endif DEBUG
                    297: 
                    298:        /* find the date part */
                    299:        p = fm;
                    300:        while (*p != '\0')
                    301:        {
                    302:                /* skip a word */
                    303:                while (*p != '\0' && *p != ' ')
                    304:                        p++;
                    305:                while (*p == ' ')
                    306:                        p++;
                    307:                if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':')
                    308:                        continue;
                    309: 
                    310:                /* we have a possible date */
                    311:                for (dt = DowList; *dt != NULL; dt++)
                    312:                        if (strncmp(*dt, p, 3) == 0)
                    313:                                break;
                    314:                if (*dt == NULL)
                    315:                        continue;
                    316: 
                    317:                for (dt = MonthList; *dt != NULL; dt++)
                    318:                        if (strncmp(*dt, &p[4], 3) == 0)
                    319:                                break;
                    320:                if (*dt != NULL)
                    321:                        break;
                    322:        }
                    323: 
                    324:        if (*p != NULL)
                    325:        {
                    326:                char *q;
                    327:                extern char *arpadate();
                    328: 
                    329:                /* we have found a date */
                    330:                q = xalloc(25);
                    331:                (void) strncpy(q, p, 25);
                    332:                q[24] = '\0';
                    333:                define('d', q, CurEnv);
                    334:                q = arpadate(q);
                    335:                define('a', newstr(q), CurEnv);
                    336:        }
                    337: }
                    338: 
                    339: # endif NOTUNIX

unix.superglobalmegacorp.com

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