1 # include <stdio.h> 2 # include <ctype.h> 3 # include <errno.h> 4 # include "dlvrmail.h" 5 6 static char SccsId[] = "@(#)collect.c 2.3 12/06/80"; 7 8 /* 9 ** MAKETEMP -- read & parse message header & make temp file. 10 ** 11 ** Creates a temporary file name and copies the standard 12 ** input to that file. While it is doing it, it looks for 13 ** "From:" and "Sender:" fields to use as the from-person 14 ** (but only if the -a flag is specified). It prefers to 15 ** to use the "Sender:" field. 16 ** 17 ** MIT seems to like to produce "Sent-By:" fields instead 18 ** of "Sender:" fields. We used to catch this, but it turns 19 ** out that the "Sent-By:" field doesn't always correspond 20 ** to someone real ("___057", for instance), as required by 21 ** the protocol. So we limp by..... 22 ** 23 ** Parameters: 24 ** none 25 ** 26 ** Returns: 27 ** Name of temp file. 28 ** 29 ** Side Effects: 30 ** Temp file is created and filled. 31 ** 32 ** Called By: 33 ** main 34 ** 35 ** Notes: 36 ** This is broken off from main largely so that the 37 ** temp buffer can be deallocated. 38 */ 39 40 char MsgId[MAXNAME]; /* message-id, determined or created */ 41 long MsgSize; /* size of message in bytes */ 42 bool GotHdr; /* if set, "From ..." line exists */ 43 44 char * 45 maketemp() 46 { 47 register FILE *tf; 48 char buf[MAXFIELD+1]; 49 static char fbuf[sizeof buf]; 50 extern char *prescan(); 51 extern char *matchhdr(); 52 register char *p; 53 register bool inheader; 54 bool firstline; 55 char c; 56 extern int errno; 57 58 /* 59 ** Create the temp file name and create the file. 60 */ 61 62 mktemp(InFileName); 63 close(creat(InFileName, 0600)); 64 if ((tf = fopen(InFileName, "w")) == NULL) 65 { 66 syserr("Cannot create %s", InFileName); 67 return (NULL); 68 } 69 70 /* 71 ** Copy stdin to temp file & do message editting. 72 ** From person gets copied into fbuf. At the end of 73 ** this loop, if fbuf[0] == '\0' then there was no 74 ** recognized from person in the message. We also 75 ** save the message id in MsgId. The 76 ** flag 'inheader' keeps track of whether we are 77 ** in the header or in the body of the message. 78 ** The flag 'firstline' is only true on the first 79 ** line of a message. 80 ** To keep certain mailers from getting confused, 81 ** and to keep the output clean, lines that look 82 ** like UNIX "From" lines are deleted in the header, 83 ** and prepended with ">" in the body. 84 */ 85 86 inheader = TRUE; 87 firstline = TRUE; 88 fbuf[0] = '\0'; 89 while (!feof(stdin) && fgets(buf, sizeof buf, stdin) != NULL) 90 { 91 if (inheader && isalnum(buf[0])) 92 { 93 /* get the rest of this field */ 94 while ((c = getc(stdin)) == ' ' || c == '\t') 95 { 96 p = &buf[strlen(buf)]; 97 *p++ = c; 98 if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 99 break; 100 } 101 if (c != EOF) 102 ungetc(c, stdin); 103 } 104 105 if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 106 break; 107 108 /* are we still in the header? */ 109 if ((buf[0] == '\n' || buf[0] == '\0') && inheader) 110 { 111 inheader = FALSE; 112 if (MsgId[0] == '\0') 113 { 114 makemsgid(); 115 if (UseMsgId) 116 fprintf(tf, "Message-Id: <%s>\n", MsgId); 117 } 118 # ifdef DEBUG 119 if (Debug) 120 printf("EOH\n"); 121 # endif DEBUG 122 } 123 124 /* Hide UNIX-like From lines */ 125 if (strncmp(buf, "From ", 5) == 0) 126 { 127 if (!firstline) 128 { 129 fputs(">", tf); 130 MsgSize++; 131 } 132 else 133 GotHdr++; 134 } 135 136 if (inheader && !isspace(buf[0])) 137 { 138 /* find out if this is really a header */ 139 for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++) 140 continue; 141 while (*p != ':' && isspace(*p)) 142 p++; 143 if (*p != ':') 144 { 145 inheader = FALSE; 146 # ifdef DEBUG 147 if (Debug) 148 printf("EOH?\n"); 149 # endif DEBUG 150 } 151 } 152 153 if (inheader) 154 { 155 /* find the sender */ 156 p = matchhdr(buf, "sender"); 157 if (p == NULL && fbuf[0] == '\0') 158 p = matchhdr(buf, "from"); 159 if (p != NULL) 160 prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0'); 161 162 /* find the message id */ 163 p = matchhdr(buf, "message-id"); 164 if (p != NULL && MsgId[0] == '\0') 165 prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0'); 166 } 167 MsgSize += strlen(buf); 168 fputs(buf, tf); 169 firstline = FALSE; 170 if (ferror(tf)) 171 { 172 if (errno == ENOSPC) 173 { 174 freopen(InFileName, "w", tf); 175 fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 176 syserr("Out of disk space for temp file"); 177 } 178 else 179 syserr("Cannot write %s", InFileName); 180 freopen("/dev/null", "w", tf); 181 } 182 } 183 fclose(tf); 184 if (MsgId[0] == '\0') 185 makemsgid(); 186 if (freopen(InFileName, "r", stdin) == NULL) 187 syserr("Cannot reopen %s", InFileName); 188 return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL); 189 } 190 /* 191 ** MAKEMSGID -- Compute a message id for this process. 192 ** 193 ** This routine creates a message id for a message if 194 ** it did not have one already. If the MESSAGEID compile 195 ** flag is set, the messageid will be added to any message 196 ** that does not already have one. Currently it is more 197 ** of an artifact, but I suggest that if you are hacking, 198 ** you leave it in -- I may want to use it someday if 199 ** duplicate messages turn out to be a problem. 200 ** 201 ** Parameters: 202 ** none. 203 ** 204 ** Returns: 205 ** none. 206 ** 207 ** Side Effects: 208 ** Stores a message-id into MsgId. 209 ** 210 ** Called By: 211 ** maketemp 212 */ 213 214 makemsgid() 215 { 216 auto long t; 217 extern char *MyLocName; 218 extern char *ArpaHost; 219 220 time(&t); 221 sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost); 222 } 223