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