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