11439Seric # include <errno.h> 23309Seric # include "sendmail.h" 31392Seric 4*4203Seric static char SccsId[] = "@(#)collect.c 3.17 08/22/81"; 51392Seric 61392Seric /* 72969Seric ** COLLECT -- read & parse message header & make temp file. 81392Seric ** 91392Seric ** Creates a temporary file name and copies the standard 101392Seric ** input to that file. While it is doing it, it looks for 111392Seric ** "From:" and "Sender:" fields to use as the from-person 121392Seric ** (but only if the -a flag is specified). It prefers to 131392Seric ** to use the "Sender:" field. 141392Seric ** 151392Seric ** MIT seems to like to produce "Sent-By:" fields instead 161392Seric ** of "Sender:" fields. We used to catch this, but it turns 171392Seric ** out that the "Sent-By:" field doesn't always correspond 181392Seric ** to someone real ("___057", for instance), as required by 191392Seric ** the protocol. So we limp by..... 201392Seric ** 211392Seric ** Parameters: 221875Seric ** none 231392Seric ** 241392Seric ** Returns: 254162Seric ** none. 261392Seric ** 271392Seric ** Side Effects: 281392Seric ** Temp file is created and filled. 294162Seric ** The from person may be set. 301392Seric */ 311392Seric 321624Seric long MsgSize; /* size of message in bytes */ 334182Seric FILE *TempFile; /* the tempfile (after creation) */ 341397Seric 352969Seric collect() 361392Seric { 371392Seric register FILE *tf; 381392Seric char buf[MAXFIELD+1]; 391392Seric register char *p; 401392Seric char c; 412900Seric extern bool isheader(); 422900Seric char *xfrom; 432900Seric extern char *hvalue(); 444083Seric extern char *mktemp(); 454083Seric extern char *capitalize(); 464083Seric # ifdef DEBUG 473386Seric HDR *h; 484083Seric # endif 491392Seric 501392Seric /* 511392Seric ** Create the temp file name and create the file. 521392Seric */ 531392Seric 544083Seric (void) mktemp(InFileName); 554083Seric (void) close(creat(InFileName, 0600)); 561392Seric if ((tf = fopen(InFileName, "w")) == NULL) 571392Seric { 581392Seric syserr("Cannot create %s", InFileName); 594162Seric return; 601392Seric } 611392Seric 622900Seric /* try to read a UNIX-style From line */ 632900Seric if (fgets(buf, sizeof buf, stdin) == NULL) 644162Seric return; 652900Seric if (strncmp(buf, "From ", 5) == 0) 662900Seric { 672900Seric eatfrom(buf); 684083Seric (void) fgets(buf, sizeof buf, stdin); 692900Seric } 702900Seric 711392Seric /* 721392Seric ** Copy stdin to temp file & do message editting. 731392Seric ** To keep certain mailers from getting confused, 741392Seric ** and to keep the output clean, lines that look 751392Seric ** like UNIX "From" lines are deleted in the header, 761392Seric ** and prepended with ">" in the body. 771392Seric */ 781392Seric 792900Seric for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin)) 801392Seric { 812900Seric /* see if the header is over */ 822900Seric if (!isheader(buf)) 832900Seric break; 842900Seric 852900Seric /* get the rest of this field */ 862900Seric while ((c = getc(stdin)) == ' ' || c == '\t') 871392Seric { 882900Seric p = &buf[strlen(buf)]; 892900Seric *p++ = c; 902900Seric if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 912900Seric break; 921392Seric } 934083Seric if (!feof(stdin)) 944083Seric (void) ungetc(c, stdin); 951392Seric 962900Seric MsgSize += strlen(buf); 971392Seric 982900Seric /* 992900Seric ** Snarf header away. 1002900Seric */ 1012900Seric 1023391Seric if (bitset(H_EOH, chompheader(buf, FALSE))) 1033058Seric break; 1042900Seric } 1051392Seric 1062900Seric # ifdef DEBUG 1072900Seric if (Debug) 1082900Seric printf("EOH\n"); 1092900Seric # endif DEBUG 1102900Seric 1112900Seric /* throw away a blank line */ 1122900Seric if (buf[0] == '\n') 1134083Seric (void) fgets(buf, sizeof buf, stdin); 1142900Seric 1152900Seric /* 1162900Seric ** Collect the body of the message. 1172900Seric */ 1182900Seric 1192900Seric for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin) != NULL) 1202900Seric { 1214156Seric register int i; 1224156Seric 1232900Seric /* check for end-of-message */ 1242900Seric if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 1252900Seric break; 1262900Seric 1272900Seric /* Hide UNIX-like From lines */ 1282900Seric if (strncmp(buf, "From ", 5) == 0) 1291392Seric { 1302900Seric fputs(">", tf); 1312900Seric MsgSize++; 1321392Seric } 1334156Seric 1344156Seric /* 1354156Seric ** Figure message length, output the line to the temp 1364156Seric ** file, and insert a newline if missing. 1374156Seric */ 1384156Seric 1394156Seric i = strlen(buf); 1404156Seric MsgSize += i; 1411392Seric fputs(buf, tf); 1424156Seric if (buf[i - 1] != '\n') 1434156Seric fputs("\n", tf); 1441392Seric if (ferror(tf)) 1451392Seric { 1461439Seric if (errno == ENOSPC) 1471439Seric { 1484083Seric (void) freopen(InFileName, "w", tf); 1491439Seric fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 1501439Seric syserr("Out of disk space for temp file"); 1511439Seric } 1521439Seric else 1531439Seric syserr("Cannot write %s", InFileName); 1544083Seric (void) freopen("/dev/null", "w", tf); 1551392Seric } 1561392Seric } 1574083Seric (void) fclose(tf); 1582900Seric 1592900Seric /* 1602900Seric ** Find out some information from the headers. 1613386Seric ** Examples are who is the from person & the date. 1622900Seric */ 1632900Seric 1642900Seric /* from person */ 1652900Seric xfrom = hvalue("sender"); 1662900Seric if (xfrom == NULL) 1672900Seric xfrom = hvalue("from"); 1684162Seric if (ArpaMode != ARPA_NONE) 1694162Seric setfrom(xfrom, NULL); 1702900Seric 1713390Seric /* full name of from person */ 1723390Seric p = hvalue("full-name"); 1733390Seric if (p != NULL) 1743390Seric define('x', p); 1753390Seric 1762900Seric /* date message originated */ 1774149Seric p = hvalue("posted-date"); 1784149Seric if (p == NULL) 1794149Seric p = hvalue("date"); 1802900Seric if (p != NULL) 1812900Seric { 1823386Seric define('a', p); 1833386Seric /* we don't have a good way to do canonical conversion .... 1843386Seric define('d', newstr(arpatounix(p))); 1853386Seric .... so we will ignore the problem for the time being */ 1862900Seric } 1872900Seric 1884182Seric if ((TempFile = fopen(InFileName, "r")) == NULL) 1891392Seric syserr("Cannot reopen %s", InFileName); 1902900Seric 1912900Seric # ifdef DEBUG 1922900Seric if (Debug) 1932900Seric { 1942900Seric printf("----- collected header -----\n"); 1952900Seric for (h = Header; h != NULL; h = h->h_link) 1962900Seric printf("%s: %s\n", capitalize(h->h_field), h->h_value); 1972900Seric printf("----------------------------\n"); 1982900Seric } 1992900Seric # endif DEBUG 2004162Seric return; 2011392Seric } 2021392Seric /* 2032900Seric ** EATFROM -- chew up a UNIX style from line and process 2042900Seric ** 2052900Seric ** This does indeed make some assumptions about the format 2062900Seric ** of UNIX messages. 2072900Seric ** 2082900Seric ** Parameters: 2092900Seric ** fm -- the from line. 2102900Seric ** 2112900Seric ** Returns: 2122900Seric ** none. 2132900Seric ** 2142900Seric ** Side Effects: 2152900Seric ** extracts what information it can from the header, 2163386Seric ** such as the date. 2172900Seric */ 2182900Seric 219*4203Seric char *DowList[] = 220*4203Seric { 221*4203Seric "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 222*4203Seric }; 223*4203Seric 2242900Seric char *MonthList[] = 2252900Seric { 2262900Seric "Jan", "Feb", "Mar", "Apr", "May", "Jun", 2272900Seric "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 2282900Seric NULL 2292900Seric }; 2302900Seric 2312900Seric eatfrom(fm) 2322900Seric char *fm; 2332900Seric { 2342900Seric register char *p; 2352900Seric register char **dt; 2362900Seric 237*4203Seric # ifdef DEBUG 238*4203Seric if (Debug > 1) 239*4203Seric printf("eatfrom(%s)\n", fm); 240*4203Seric # endif DEBUG 241*4203Seric 2422900Seric /* find the date part */ 2432900Seric p = fm; 2442900Seric while (*p != '\0') 2452900Seric { 2462900Seric /* skip a word */ 2472900Seric while (*p != '\0' && *p != ' ') 2482900Seric *p++; 2492900Seric while (*p == ' ') 2502900Seric *p++; 2512900Seric if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':') 2522900Seric continue; 2532900Seric 2542900Seric /* we have a possible date */ 255*4203Seric for (dt = DowList; *dt != NULL; dt++) 2562900Seric if (strncmp(*dt, p, 3) == 0) 2572900Seric break; 258*4203Seric if (*dt == NULL) 259*4203Seric continue; 2602900Seric 261*4203Seric for (dt = MonthList; *dt != NULL; dt++) 262*4203Seric if (strncmp(*dt, &p[4], 3) == 0) 263*4203Seric break; 2642900Seric if (*dt != NULL) 2652900Seric break; 2662900Seric } 2672900Seric 2682900Seric if (*p != NULL) 2692900Seric { 2703386Seric char *q; 2713386Seric 2722900Seric /* we have found a date */ 2733386Seric q = xalloc(25); 2743386Seric strncpy(q, p, 25); 2753386Seric q[24] = '\0'; 2763386Seric define('d', q); 2772900Seric } 2782900Seric } 279