release 2
[unix-history] / usr / src / usr.sbin / sendmail / src / collect.c
CommitLineData
cb590f52
EA
1# include <stdio.h>
2# include <ctype.h>
b8020f57 3# include <errno.h>
cb590f52
EA
4# include "dlvrmail.h"
5
1faf68d2 6static char SccsId[] = "@(#)collect.c 2.1 %G%";
cb590f52
EA
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
afcbcc6e
EA
40char MsgId[MAXNAME]; /* message-id, determined or created */
41long MsgSize; /* size of message in bytes */
628ac6c6 42
cb590f52
EA
43char *
44maketemp()
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;
b8020f57 55 extern int errno;
cb590f52
EA
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 }
0982b655
EA
100 if (c != EOF)
101 ungetc(c, stdin);
cb590f52
EA
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);
afcbcc6e 130 MsgSize++;
cb590f52
EA
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 }
afcbcc6e 164 MsgSize += strlen(buf);
cb590f52
EA
165 fputs(buf, tf);
166 firstline = FALSE;
167 if (ferror(tf))
168 {
b8020f57
EA
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);
cb590f52
EA
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\f/*
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
211makemsgid()
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}