11392Seric # include <stdio.h> 21392Seric # include <ctype.h> 31439Seric # include <errno.h> 43309Seric # include "sendmail.h" 51392Seric 6*4156Seric static char SccsId[] = "@(#)collect.c 3.14 08/18/81"; 71392Seric 81392Seric /* 92969Seric ** COLLECT -- read & parse message header & make temp file. 101392Seric ** 111392Seric ** Creates a temporary file name and copies the standard 121392Seric ** input to that file. While it is doing it, it looks for 131392Seric ** "From:" and "Sender:" fields to use as the from-person 141392Seric ** (but only if the -a flag is specified). It prefers to 151392Seric ** to use the "Sender:" field. 161392Seric ** 171392Seric ** MIT seems to like to produce "Sent-By:" fields instead 181392Seric ** of "Sender:" fields. We used to catch this, but it turns 191392Seric ** out that the "Sent-By:" field doesn't always correspond 201392Seric ** to someone real ("___057", for instance), as required by 211392Seric ** the protocol. So we limp by..... 221392Seric ** 231392Seric ** Parameters: 241875Seric ** none 251392Seric ** 261392Seric ** Returns: 271875Seric ** Name of temp file. 281392Seric ** 291392Seric ** Side Effects: 301392Seric ** Temp file is created and filled. 311392Seric ** 321392Seric ** Called By: 331392Seric ** main 341392Seric ** 351392Seric ** Notes: 361392Seric ** This is broken off from main largely so that the 371392Seric ** temp buffer can be deallocated. 381392Seric */ 391392Seric 401624Seric long MsgSize; /* size of message in bytes */ 411397Seric 421392Seric char * 432969Seric collect() 441392Seric { 451392Seric register FILE *tf; 461392Seric char buf[MAXFIELD+1]; 471392Seric register char *p; 481392Seric char c; 492900Seric extern bool isheader(); 502900Seric char *xfrom; 512900Seric extern char *hvalue(); 524083Seric extern char *mktemp(); 534083Seric extern char *capitalize(); 544083Seric # ifdef DEBUG 553386Seric HDR *h; 564083Seric # endif 571392Seric 581392Seric /* 591392Seric ** Create the temp file name and create the file. 601392Seric */ 611392Seric 624083Seric (void) mktemp(InFileName); 634083Seric (void) close(creat(InFileName, 0600)); 641392Seric if ((tf = fopen(InFileName, "w")) == NULL) 651392Seric { 661392Seric syserr("Cannot create %s", InFileName); 671392Seric return (NULL); 681392Seric } 691392Seric 702900Seric /* try to read a UNIX-style From line */ 712900Seric if (fgets(buf, sizeof buf, stdin) == NULL) 722900Seric return (NULL); 732900Seric if (strncmp(buf, "From ", 5) == 0) 742900Seric { 752900Seric eatfrom(buf); 764083Seric (void) fgets(buf, sizeof buf, stdin); 772900Seric } 782900Seric 791392Seric /* 801392Seric ** Copy stdin to temp file & do message editting. 811392Seric ** To keep certain mailers from getting confused, 821392Seric ** and to keep the output clean, lines that look 831392Seric ** like UNIX "From" lines are deleted in the header, 841392Seric ** and prepended with ">" in the body. 851392Seric */ 861392Seric 872900Seric for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin)) 881392Seric { 892900Seric /* see if the header is over */ 902900Seric if (!isheader(buf)) 912900Seric break; 922900Seric 932900Seric /* get the rest of this field */ 942900Seric while ((c = getc(stdin)) == ' ' || c == '\t') 951392Seric { 962900Seric p = &buf[strlen(buf)]; 972900Seric *p++ = c; 982900Seric if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 992900Seric break; 1001392Seric } 1014083Seric if (!feof(stdin)) 1024083Seric (void) ungetc(c, stdin); 1031392Seric 1042900Seric MsgSize += strlen(buf); 1051392Seric 1062900Seric /* 1072900Seric ** Snarf header away. 1082900Seric */ 1092900Seric 1103391Seric if (bitset(H_EOH, chompheader(buf, FALSE))) 1113058Seric break; 1122900Seric } 1131392Seric 1142900Seric # ifdef DEBUG 1152900Seric if (Debug) 1162900Seric printf("EOH\n"); 1172900Seric # endif DEBUG 1182900Seric 1192900Seric /* throw away a blank line */ 1202900Seric if (buf[0] == '\n') 1214083Seric (void) fgets(buf, sizeof buf, stdin); 1222900Seric 1232900Seric /* 1242900Seric ** Collect the body of the message. 1252900Seric */ 1262900Seric 1272900Seric for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin) != NULL) 1282900Seric { 129*4156Seric register int i; 130*4156Seric 1312900Seric /* check for end-of-message */ 1322900Seric if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 1332900Seric break; 1342900Seric 1352900Seric /* Hide UNIX-like From lines */ 1362900Seric if (strncmp(buf, "From ", 5) == 0) 1371392Seric { 1382900Seric fputs(">", tf); 1392900Seric MsgSize++; 1401392Seric } 141*4156Seric 142*4156Seric /* 143*4156Seric ** Figure message length, output the line to the temp 144*4156Seric ** file, and insert a newline if missing. 145*4156Seric */ 146*4156Seric 147*4156Seric i = strlen(buf); 148*4156Seric MsgSize += i; 1491392Seric fputs(buf, tf); 150*4156Seric if (buf[i - 1] != '\n') 151*4156Seric fputs("\n", tf); 1521392Seric if (ferror(tf)) 1531392Seric { 1541439Seric if (errno == ENOSPC) 1551439Seric { 1564083Seric (void) freopen(InFileName, "w", tf); 1571439Seric fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 1581439Seric syserr("Out of disk space for temp file"); 1591439Seric } 1601439Seric else 1611439Seric syserr("Cannot write %s", InFileName); 1624083Seric (void) freopen("/dev/null", "w", tf); 1631392Seric } 1641392Seric } 1654083Seric (void) fclose(tf); 1662900Seric 1672900Seric /* 1682900Seric ** Find out some information from the headers. 1693386Seric ** Examples are who is the from person & the date. 1702900Seric */ 1712900Seric 1722900Seric /* from person */ 1732900Seric xfrom = hvalue("sender"); 1742900Seric if (xfrom == NULL) 1752900Seric xfrom = hvalue("from"); 1762900Seric 1773390Seric /* full name of from person */ 1783390Seric p = hvalue("full-name"); 1793390Seric if (p != NULL) 1803390Seric define('x', p); 1813390Seric 1822900Seric /* date message originated */ 1834149Seric p = hvalue("posted-date"); 1844149Seric if (p == NULL) 1854149Seric p = hvalue("date"); 1862900Seric if (p != NULL) 1872900Seric { 1883386Seric define('a', p); 1893386Seric /* we don't have a good way to do canonical conversion .... 1903386Seric define('d', newstr(arpatounix(p))); 1913386Seric .... so we will ignore the problem for the time being */ 1922900Seric } 1932900Seric 1941392Seric if (freopen(InFileName, "r", stdin) == NULL) 1951392Seric syserr("Cannot reopen %s", InFileName); 1962900Seric 1972900Seric # ifdef DEBUG 1982900Seric if (Debug) 1992900Seric { 2002900Seric printf("----- collected header -----\n"); 2012900Seric for (h = Header; h != NULL; h = h->h_link) 2022900Seric printf("%s: %s\n", capitalize(h->h_field), h->h_value); 2032900Seric printf("----------------------------\n"); 2042900Seric } 2052900Seric # endif DEBUG 2062900Seric return (ArpaFmt ? xfrom : NULL); 2071392Seric } 2081392Seric /* 2092900Seric ** EATFROM -- chew up a UNIX style from line and process 2102900Seric ** 2112900Seric ** This does indeed make some assumptions about the format 2122900Seric ** of UNIX messages. 2132900Seric ** 2142900Seric ** Parameters: 2152900Seric ** fm -- the from line. 2162900Seric ** 2172900Seric ** Returns: 2182900Seric ** none. 2192900Seric ** 2202900Seric ** Side Effects: 2212900Seric ** extracts what information it can from the header, 2223386Seric ** such as the date. 2232900Seric */ 2242900Seric 2252900Seric char *MonthList[] = 2262900Seric { 2272900Seric "Jan", "Feb", "Mar", "Apr", "May", "Jun", 2282900Seric "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 2292900Seric NULL 2302900Seric }; 2312900Seric 2322900Seric eatfrom(fm) 2332900Seric char *fm; 2342900Seric { 2352900Seric register char *p; 2362900Seric register char **dt; 2372900Seric 2382900Seric /* find the date part */ 2392900Seric p = fm; 2402900Seric while (*p != '\0') 2412900Seric { 2422900Seric /* skip a word */ 2432900Seric while (*p != '\0' && *p != ' ') 2442900Seric *p++; 2452900Seric while (*p == ' ') 2462900Seric *p++; 2472900Seric if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':') 2482900Seric continue; 2492900Seric 2502900Seric /* we have a possible date */ 2512900Seric for (dt = MonthList; *dt != NULL; dt++) 2522900Seric if (strncmp(*dt, p, 3) == 0) 2532900Seric break; 2542900Seric 2552900Seric if (*dt != NULL) 2562900Seric break; 2572900Seric } 2582900Seric 2592900Seric if (*p != NULL) 2602900Seric { 2613386Seric char *q; 2623386Seric 2632900Seric /* we have found a date */ 2643386Seric q = xalloc(25); 2653386Seric strncpy(q, p, 25); 2663386Seric q[24] = '\0'; 2673386Seric define('d', q); 2682900Seric } 2692900Seric } 270