1 # include <stdio.h> 2 # include <ctype.h> 3 # include <errno.h> 4 # include "dlvrmail.h" 5 6 static char SccsId[] = "@(#)collect.c 1.4 10/15/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 ungetc(c, stdin); 100 } 101 102 if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 103 break; 104 105 /* are we still in the header? */ 106 if ((buf[0] == '\n' || buf[0] == '\0') && inheader) 107 { 108 inheader = FALSE; 109 if (MsgId[0] == '\0') 110 { 111 makemsgid(); 112 if (UseMsgId) 113 fprintf(tf, "Message-Id: <%s>\n", MsgId); 114 } 115 # ifdef DEBUG 116 if (Debug) 117 printf("EOH\n"); 118 # endif DEBUG 119 } 120 121 /* Hide UNIX-like From lines */ 122 if (buf[0] == 'F' && buf[1] == 'r' && buf[2] == 'o' && 123 buf[3] == 'm' && buf[4] == ' ') 124 { 125 if (firstline && !SaveFrom) 126 continue; 127 fputs(">", tf); 128 } 129 130 if (inheader && !isspace(buf[0])) 131 { 132 /* find out if this is really a header */ 133 for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++) 134 continue; 135 while (*p != ':' && isspace(*p)) 136 p++; 137 if (*p != ':') 138 { 139 inheader = FALSE; 140 # ifdef DEBUG 141 if (Debug) 142 printf("EOH?\n"); 143 # endif DEBUG 144 } 145 } 146 147 if (inheader) 148 { 149 /* find the sender */ 150 p = matchhdr(buf, "sender"); 151 if (p == NULL && fbuf[0] == '\0') 152 p = matchhdr(buf, "from"); 153 if (p != NULL) 154 prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0'); 155 156 /* find the message id */ 157 p = matchhdr(buf, "message-id"); 158 if (p != NULL && MsgId[0] == '\0') 159 prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0'); 160 } 161 fputs(buf, tf); 162 firstline = FALSE; 163 if (ferror(tf)) 164 { 165 if (errno == ENOSPC) 166 { 167 freopen(InFileName, "w", tf); 168 fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 169 syserr("Out of disk space for temp file"); 170 } 171 else 172 syserr("Cannot write %s", InFileName); 173 freopen("/dev/null", "w", tf); 174 } 175 } 176 fclose(tf); 177 if (MsgId[0] == '\0') 178 makemsgid(); 179 if (freopen(InFileName, "r", stdin) == NULL) 180 syserr("Cannot reopen %s", InFileName); 181 return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL); 182 } 183 /* 184 ** MAKEMSGID -- Compute a message id for this process. 185 ** 186 ** This routine creates a message id for a message if 187 ** it did not have one already. If the MESSAGEID compile 188 ** flag is set, the messageid will be added to any message 189 ** that does not already have one. Currently it is more 190 ** of an artifact, but I suggest that if you are hacking, 191 ** you leave it in -- I may want to use it someday if 192 ** duplicate messages turn out to be a problem. 193 ** 194 ** Parameters: 195 ** none. 196 ** 197 ** Returns: 198 ** none. 199 ** 200 ** Side Effects: 201 ** Stores a message-id into MsgId. 202 ** 203 ** Called By: 204 ** maketemp 205 */ 206 207 makemsgid() 208 { 209 auto long t; 210 extern char *MyLocName; 211 extern char *ArpaHost; 212 213 time(&t); 214 sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost); 215 } 216