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