11392Seric # include <stdio.h> 21392Seric # include <ctype.h> 31439Seric # include <errno.h> 41392Seric # include "dlvrmail.h" 51392Seric 6*1819Seric static char SccsId[] = "@(#)collect.c 2.1.1.1 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 */ 421397Seric 431392Seric char * 441392Seric maketemp() 451392Seric { 461392Seric register FILE *tf; 471392Seric char buf[MAXFIELD+1]; 481392Seric static char fbuf[sizeof buf]; 491392Seric extern char *prescan(); 501392Seric extern char *matchhdr(); 511392Seric register char *p; 521392Seric register bool inheader; 531392Seric bool firstline; 541392Seric char c; 551439Seric extern int errno; 561392Seric 571392Seric /* 581392Seric ** Create the temp file name and create the file. 591392Seric */ 601392Seric 611392Seric mktemp(InFileName); 621392Seric close(creat(InFileName, 0600)); 631392Seric if ((tf = fopen(InFileName, "w")) == NULL) 641392Seric { 651392Seric syserr("Cannot create %s", InFileName); 661392Seric return (NULL); 671392Seric } 681392Seric 691392Seric /* 701392Seric ** Copy stdin to temp file & do message editting. 711392Seric ** From person gets copied into fbuf. At the end of 721392Seric ** this loop, if fbuf[0] == '\0' then there was no 731392Seric ** recognized from person in the message. We also 741392Seric ** save the message id in MsgId. The 751392Seric ** flag 'inheader' keeps track of whether we are 761392Seric ** in the header or in the body of the message. 771392Seric ** The flag 'firstline' is only true on the first 781392Seric ** line of a message. 791392Seric ** To keep certain mailers from getting confused, 801392Seric ** and to keep the output clean, lines that look 811392Seric ** like UNIX "From" lines are deleted in the header, 821392Seric ** and prepended with ">" in the body. 831392Seric */ 841392Seric 851392Seric inheader = TRUE; 861392Seric firstline = TRUE; 871392Seric fbuf[0] = '\0'; 881392Seric while (fgets(buf, sizeof buf, stdin) != NULL) 891392Seric { 901392Seric if (inheader && isalnum(buf[0])) 911392Seric { 921392Seric /* get the rest of this field */ 931392Seric while ((c = getc(stdin)) == ' ' || c == '\t') 941392Seric { 951392Seric p = &buf[strlen(buf)]; 961392Seric *p++ = c; 971392Seric if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 981392Seric break; 991392Seric } 1001587Seric if (c != EOF) 1011587Seric ungetc(c, stdin); 1021392Seric } 1031392Seric 1041392Seric if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 1051392Seric break; 1061392Seric 1071392Seric /* are we still in the header? */ 1081392Seric if ((buf[0] == '\n' || buf[0] == '\0') && inheader) 1091392Seric { 1101392Seric inheader = FALSE; 1111392Seric if (MsgId[0] == '\0') 1121392Seric { 1131392Seric makemsgid(); 1141392Seric if (UseMsgId) 1151392Seric fprintf(tf, "Message-Id: <%s>\n", MsgId); 1161392Seric } 1171392Seric # ifdef DEBUG 1181392Seric if (Debug) 1191392Seric printf("EOH\n"); 1201392Seric # endif DEBUG 1211392Seric } 1221392Seric 1231392Seric /* Hide UNIX-like From lines */ 124*1819Seric if (strncmp(buf, "From ", 5) == 0) 1251392Seric { 1261392Seric if (firstline && !SaveFrom) 127*1819Seric { 128*1819Seric savedate(buf); 1291392Seric continue; 130*1819Seric } 1311392Seric fputs(">", tf); 1321624Seric MsgSize++; 1331392Seric } 1341392Seric 1351392Seric if (inheader && !isspace(buf[0])) 1361392Seric { 1371392Seric /* find out if this is really a header */ 1381392Seric for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++) 1391392Seric continue; 1401392Seric while (*p != ':' && isspace(*p)) 1411392Seric p++; 1421392Seric if (*p != ':') 1431392Seric { 1441392Seric inheader = FALSE; 1451392Seric # ifdef DEBUG 1461392Seric if (Debug) 1471392Seric printf("EOH?\n"); 1481392Seric # endif DEBUG 1491392Seric } 1501392Seric } 1511392Seric 1521392Seric if (inheader) 1531392Seric { 1541392Seric /* find the sender */ 1551392Seric p = matchhdr(buf, "sender"); 1561392Seric if (p == NULL && fbuf[0] == '\0') 1571392Seric p = matchhdr(buf, "from"); 1581392Seric if (p != NULL) 1591392Seric prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0'); 1601392Seric 1611392Seric /* find the message id */ 1621392Seric p = matchhdr(buf, "message-id"); 1631392Seric if (p != NULL && MsgId[0] == '\0') 1641392Seric prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0'); 1651392Seric } 1661624Seric MsgSize += strlen(buf); 1671392Seric fputs(buf, tf); 1681392Seric firstline = FALSE; 1691392Seric if (ferror(tf)) 1701392Seric { 1711439Seric if (errno == ENOSPC) 1721439Seric { 1731439Seric freopen(InFileName, "w", tf); 1741439Seric fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 1751439Seric syserr("Out of disk space for temp file"); 1761439Seric } 1771439Seric else 1781439Seric syserr("Cannot write %s", InFileName); 1791439Seric freopen("/dev/null", "w", tf); 1801392Seric } 1811392Seric } 1821392Seric fclose(tf); 1831392Seric if (MsgId[0] == '\0') 1841392Seric makemsgid(); 1851392Seric if (freopen(InFileName, "r", stdin) == NULL) 1861392Seric syserr("Cannot reopen %s", InFileName); 1871392Seric return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL); 1881392Seric } 1891392Seric /* 1901392Seric ** MAKEMSGID -- Compute a message id for this process. 1911392Seric ** 1921392Seric ** This routine creates a message id for a message if 1931392Seric ** it did not have one already. If the MESSAGEID compile 1941392Seric ** flag is set, the messageid will be added to any message 1951392Seric ** that does not already have one. Currently it is more 1961392Seric ** of an artifact, but I suggest that if you are hacking, 1971392Seric ** you leave it in -- I may want to use it someday if 1981392Seric ** duplicate messages turn out to be a problem. 1991392Seric ** 2001392Seric ** Parameters: 2011392Seric ** none. 2021392Seric ** 2031392Seric ** Returns: 2041392Seric ** none. 2051392Seric ** 2061392Seric ** Side Effects: 2071392Seric ** Stores a message-id into MsgId. 2081392Seric ** 2091392Seric ** Called By: 2101392Seric ** maketemp 2111392Seric */ 2121392Seric 2131392Seric makemsgid() 2141392Seric { 2151392Seric auto long t; 2161392Seric extern char *MyLocName; 2171392Seric extern char *ArpaHost; 2181392Seric 2191392Seric time(&t); 2201392Seric sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost); 2211392Seric } 222*1819Seric /* 223*1819Seric ** SAVEDATE -- find and save date field from a "From" line 224*1819Seric ** 225*1819Seric ** This will be used by putheader when a From line is created. 226*1819Seric ** 227*1819Seric ** Parameters: 228*1819Seric ** buf -- a "From" line. 229*1819Seric ** 230*1819Seric ** Returns: 231*1819Seric ** none. 232*1819Seric ** 233*1819Seric ** Side Effects: 234*1819Seric ** Saves the "date" part (with newline) in SentDate. 235*1819Seric */ 236*1819Seric 237*1819Seric char SentDate[30]; 238*1819Seric 239*1819Seric savedate(buf) 240*1819Seric char *buf; 241*1819Seric { 242*1819Seric register char *p; 243*1819Seric 244*1819Seric for (p = buf; p != '\0'; p++) 245*1819Seric { 246*1819Seric if (*p != ' ') 247*1819Seric continue; 248*1819Seric if (strncmp(p, " Sun ", 5) == 0 || 249*1819Seric strncmp(p, " Mon ", 5) == 0 || 250*1819Seric strncmp(p, " Tue ", 5) == 0 || 251*1819Seric strncmp(p, " Wed ", 5) == 0 || 252*1819Seric strncmp(p, " Thu ", 5) == 0 || 253*1819Seric strncmp(p, " Fri ", 5) == 0 || 254*1819Seric strncmp(p, " Sat ", 5) == 0) 255*1819Seric { 256*1819Seric if (p[4] != ' ' || p[8] != ' ' || p[11] != ' ' || 257*1819Seric p[14] != ':' || p[17] != ':' || p[20] != ' ') 258*1819Seric continue; 259*1819Seric strncpy(SentDate, ++p, 25); 260*1819Seric SentDate[24] = '\n'; 261*1819Seric SentDate[25] = '\0'; 262*1819Seric return; 263*1819Seric } 264*1819Seric } 265*1819Seric } 266