avoid hanging on multiplexor problems
[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
0982b655 6static char SccsId[] = "@(#)collect.c 1.5 %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
628ac6c6
EA
40char MsgId[MAXNAME];
41
cb590f52
EA
42char *
43maketemp()
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;
b8020f57 54 extern int errno;
cb590f52
EA
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 }
0982b655
EA
99 if (c != EOF)
100 ungetc(c, stdin);
cb590f52
EA
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 {
b8020f57
EA
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);
cb590f52
EA
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\f/*
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
208makemsgid()
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}