new symbols ala %cpu
[unix-history] / usr / src / usr.sbin / sendmail / src / collect.c
CommitLineData
cb590f52
EA
1# include <stdio.h>
2# include <ctype.h>
3# include "dlvrmail.h"
4
5static char SccsId[] = "@(#)collect.c 1.2 %G%";
6
7/*
8** MAKETEMP -- read & parse message header & make temp file.
9**
10** Creates a temporary file name and copies the standard
11** input to that file. While it is doing it, it looks for
12** "From:" and "Sender:" fields to use as the from-person
13** (but only if the -a flag is specified). It prefers to
14** to use the "Sender:" field.
15**
16** MIT seems to like to produce "Sent-By:" fields instead
17** of "Sender:" fields. We used to catch this, but it turns
18** out that the "Sent-By:" field doesn't always correspond
19** to someone real ("___057", for instance), as required by
20** the protocol. So we limp by.....
21**
22** Parameters:
23** none
24**
25** Returns:
26** Name of temp file.
27**
28** Side Effects:
29** Temp file is created and filled.
30**
31** Called By:
32** main
33**
34** Notes:
35** This is broken off from main largely so that the
36** temp buffer can be deallocated.
37*/
38
39char *
40maketemp()
41{
42 register FILE *tf;
43 char buf[MAXFIELD+1];
44 static char fbuf[sizeof buf];
45 extern char *prescan();
46 extern char *matchhdr();
47 register char *p;
48 register bool inheader;
49 bool firstline;
50 char c;
51
52 /*
53 ** Create the temp file name and create the file.
54 */
55
56 mktemp(InFileName);
57 close(creat(InFileName, 0600));
58 if ((tf = fopen(InFileName, "w")) == NULL)
59 {
60 syserr("Cannot create %s", InFileName);
61 return (NULL);
62 }
63
64 /*
65 ** Copy stdin to temp file & do message editting.
66 ** From person gets copied into fbuf. At the end of
67 ** this loop, if fbuf[0] == '\0' then there was no
68 ** recognized from person in the message. We also
69 ** save the message id in MsgId. The
70 ** flag 'inheader' keeps track of whether we are
71 ** in the header or in the body of the message.
72 ** The flag 'firstline' is only true on the first
73 ** line of a message.
74 ** To keep certain mailers from getting confused,
75 ** and to keep the output clean, lines that look
76 ** like UNIX "From" lines are deleted in the header,
77 ** and prepended with ">" in the body.
78 */
79
80 inheader = TRUE;
81 firstline = TRUE;
82 fbuf[0] = '\0';
83 while (fgets(buf, sizeof buf, stdin) != NULL)
84 {
85 if (inheader && isalnum(buf[0]))
86 {
87 /* get the rest of this field */
88 while ((c = getc(stdin)) == ' ' || c == '\t')
89 {
90 p = &buf[strlen(buf)];
91 *p++ = c;
92 if (fgets(p, sizeof buf - (p - buf), stdin) == NULL)
93 break;
94 }
95 ungetc(c, stdin);
96 }
97
98 if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
99 break;
100
101 /* are we still in the header? */
102 if ((buf[0] == '\n' || buf[0] == '\0') && inheader)
103 {
104 inheader = FALSE;
105 if (MsgId[0] == '\0')
106 {
107 makemsgid();
108 if (UseMsgId)
109 fprintf(tf, "Message-Id: <%s>\n", MsgId);
110 }
111# ifdef DEBUG
112 if (Debug)
113 printf("EOH\n");
114# endif DEBUG
115 }
116
117 /* Hide UNIX-like From lines */
118 if (buf[0] == 'F' && buf[1] == 'r' && buf[2] == 'o' &&
119 buf[3] == 'm' && buf[4] == ' ')
120 {
121 if (firstline && !SaveFrom)
122 continue;
123 fputs(">", tf);
124 }
125
126 if (inheader && !isspace(buf[0]))
127 {
128 /* find out if this is really a header */
129 for (p = buf; *p != ':' && *p != '\0' && !isspace(*p); p++)
130 continue;
131 while (*p != ':' && isspace(*p))
132 p++;
133 if (*p != ':')
134 {
135 inheader = FALSE;
136# ifdef DEBUG
137 if (Debug)
138 printf("EOH?\n");
139# endif DEBUG
140 }
141 }
142
143 if (inheader)
144 {
145 /* find the sender */
146 p = matchhdr(buf, "sender");
147 if (p == NULL && fbuf[0] == '\0')
148 p = matchhdr(buf, "from");
149 if (p != NULL)
150 prescan(p, fbuf, &fbuf[sizeof fbuf - 1], '\0');
151
152 /* find the message id */
153 p = matchhdr(buf, "message-id");
154 if (p != NULL && MsgId[0] == '\0')
155 prescan(p, MsgId, &MsgId[sizeof MsgId - 1], '\0');
156 }
157 fputs(buf, tf);
158 firstline = FALSE;
159 if (ferror(tf))
160 {
161 syserr("Cannot write %s", InFileName);
162 clearerr(tf);
163 break;
164 }
165 }
166 fclose(tf);
167 if (MsgId[0] == '\0')
168 makemsgid();
169 if (freopen(InFileName, "r", stdin) == NULL)
170 syserr("Cannot reopen %s", InFileName);
171 return (ArpaFmt && fbuf[0] != '\0' ? fbuf : NULL);
172}
173\f/*
174** MAKEMSGID -- Compute a message id for this process.
175**
176** This routine creates a message id for a message if
177** it did not have one already. If the MESSAGEID compile
178** flag is set, the messageid will be added to any message
179** that does not already have one. Currently it is more
180** of an artifact, but I suggest that if you are hacking,
181** you leave it in -- I may want to use it someday if
182** duplicate messages turn out to be a problem.
183**
184** Parameters:
185** none.
186**
187** Returns:
188** none.
189**
190** Side Effects:
191** Stores a message-id into MsgId.
192**
193** Called By:
194** maketemp
195*/
196
197makemsgid()
198{
199 auto long t;
200 extern char *MyLocName;
201 extern char *ArpaHost;
202
203 time(&t);
204 sprintf(MsgId, "%ld.%d.%s@%s", t, getpid(), MyLocName, ArpaHost);
205}