11392Seric # include <stdio.h> 21392Seric # include <ctype.h> 31439Seric # include <errno.h> 41392Seric # include "dlvrmail.h" 51392Seric 6*1824Seric static char SccsId[] = "@(#)collect.c 2.2 11/20/80"; 71392Seric 81392Seric /* 91392Seric ** MAKETEMP -- 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: 241392Seric ** none 251392Seric ** 261392Seric ** Returns: 271392Seric ** 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 char MsgId[MAXNAME]; /* message-id, determined or created */ 411624Seric long MsgSize; /* size of message in bytes */ 42*1824Seric bool GotHdr; /* if set, "From ..." line exists */ 431397Seric 441392Seric char * 451392Seric maketemp() 461392Seric { 471392Seric register FILE *tf; 481392Seric char buf[MAXFIELD+1]; 491392Seric static char fbuf[sizeof buf]; 501392Seric extern char *prescan(); 511392Seric extern char *matchhdr(); 521392Seric register char *p; 531392Seric register bool inheader; 541392Seric bool firstline; 551392Seric char c; 561439Seric extern int errno; 571392Seric 581392Seric /* 591392Seric ** Create the temp file name and create the file. 601392Seric */ 611392Seric 621392Seric mktemp(InFileName); 631392Seric close(creat(InFileName, 0600)); 641392Seric if ((tf = fopen(InFileName, "w")) == NULL) 651392Seric { 661392Seric syserr("Cannot create %s", InFileName); 671392Seric return (NULL); 681392Seric } 691392Seric 701392Seric /* 711392Seric ** Copy stdin to temp file & do message editting. 721392Seric ** From person gets copied into fbuf. At the end of 731392Seric ** this loop, if fbuf[0] == '\0' then there was no 741392Seric ** recognized from person in the message. We also 751392Seric ** save the message id in MsgId. The 761392Seric ** flag 'inheader' keeps track of whether we are 771392Seric ** in the header or in the body of the message. 781392Seric ** The flag 'firstline' is only true on the first 791392Seric ** line of a message. 801392Seric ** To keep certain mailers from getting confused, 811392Seric ** and to keep the output clean, lines that look 821392Seric ** like UNIX "From" lines are deleted in the header, 831392Seric ** and prepended with ">" in the body. 841392Seric */ 851392Seric 861392Seric inheader = TRUE; 871392Seric firstline = TRUE; 881392Seric fbuf[0] = '\0'; 891392Seric while (fgets(buf, sizeof buf, stdin) != NULL) 901392Seric { 911392Seric if (inheader && isalnum(buf[0])) 921392Seric { 931392Seric /* get the rest of this field */ 941392Seric while ((c = getc(stdin)) == ' ' || c == '\t') 951392Seric { 961392Seric p = &buf[strlen(buf)]; 971392Seric *p++ = c; 981392Seric if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 991392Seric break; 1001392Seric } 1011587Seric if (c != EOF) 1021587Seric ungetc(c, stdin); 1031392Seric } 1041392Seric 1051392Seric if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 1061392Seric break; 1071392Seric 1081392Seric /* are we still in the header? */ 1091392Seric if ((buf[0] == '\n' || buf[0] == '\0') && inheader) 1101392Seric { 1111392Seric inheader = FALSE; 1121392Seric if (MsgId[0] == '\0') 1131392Seric { 1141392Seric makemsgid(); 1151392Seric if (UseMsgId) 1161392Seric fprintf(tf, "Message-Id: <%s>\n", MsgId); 1171392Seric } 1181392Seric # ifdef DEBUG 1191392Seric if (Debug) 1201392Seric printf("EOH\n"); 1211392Seric # endif DEBUG 1221392Seric } 1231392Seric 1241392Seric /* Hide UNIX-like From lines */ 1251819Seric if (strncmp(buf, "From ", 5) == 0) 1261392Seric { 127*1824Seric if (!firstline) 1281819Seric { 129*1824Seric fputs(">", tf); 130*1824Seric MsgSize++; 1311819Seric } 132*1824Seric else 133*1824Seric GotHdr++; 1341392Seric } 1351392Seric 1361392Seric if (inheader && !isspace(buf[0])) 1371392Seric { 1381392Seric /* find out if this is really a header */ 1391392Seric for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++) 1401392Seric continue; 1411392Seric while (*p != ':' && isspace(*p)) 1421392Seric p++; 1431392Seric if (*p != ':') 1441392Seric { 1451392Seric inheader = FALSE; 1461392Seric # ifdef DEBUG 1471392Seric if (Debug) 1481392Seric printf("EOH?\n"); 1491392Seric # endif DEBUG 1501392Seric } 1511392Seric } 1521392Seric 1531392Seric if (inheader) 1541392Seric { 1551392Seric /* find the sender */ 1561392Seric p = matchhdr(buf, "sender"); 1571392Seric if (p == NULL && fbuf[0] == '\0') 1581392Seric p = matchhdr(buf, "from"); 1591392Seric if (p != NULL) 1601392Seric prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0'); 1611392Seric 1621392Seric /* find the message id */ 1631392Seric p = matchhdr(buf, "message-id"); 1641392Seric if (p != NULL && MsgId[0] == '\0') 1651392Seric prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0'); 1661392Seric } 1671624Seric MsgSize += strlen(buf); 1681392Seric fputs(buf, tf); 1691392Seric firstline = FALSE; 1701392Seric if (ferror(tf)) 1711392Seric { 1721439Seric if (errno == ENOSPC) 1731439Seric { 1741439Seric freopen(InFileName, "w", tf); 1751439Seric fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 1761439Seric syserr("Out of disk space for temp file"); 1771439Seric } 1781439Seric else 1791439Seric syserr("Cannot write %s", InFileName); 1801439Seric freopen("/dev/null", "w", tf); 1811392Seric } 1821392Seric } 1831392Seric fclose(tf); 1841392Seric if (MsgId[0] == '\0') 1851392Seric makemsgid(); 1861392Seric if (freopen(InFileName, "r", stdin) == NULL) 1871392Seric syserr("Cannot reopen %s", InFileName); 1881392Seric return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL); 1891392Seric } 1901392Seric /* 1911392Seric ** MAKEMSGID -- Compute a message id for this process. 1921392Seric ** 1931392Seric ** This routine creates a message id for a message if 1941392Seric ** it did not have one already. If the MESSAGEID compile 1951392Seric ** flag is set, the messageid will be added to any message 1961392Seric ** that does not already have one. Currently it is more 1971392Seric ** of an artifact, but I suggest that if you are hacking, 1981392Seric ** you leave it in -- I may want to use it someday if 1991392Seric ** duplicate messages turn out to be a problem. 2001392Seric ** 2011392Seric ** Parameters: 2021392Seric ** none. 2031392Seric ** 2041392Seric ** Returns: 2051392Seric ** none. 2061392Seric ** 2071392Seric ** Side Effects: 2081392Seric ** Stores a message-id into MsgId. 2091392Seric ** 2101392Seric ** Called By: 2111392Seric ** maketemp 2121392Seric */ 2131392Seric 2141392Seric makemsgid() 2151392Seric { 2161392Seric auto long t; 2171392Seric extern char *MyLocName; 2181392Seric extern char *ArpaHost; 2191392Seric 2201392Seric time(&t); 2211392Seric sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost); 2221392Seric } 223