|
|
1.1 root 1: #include <stdio.h>
2: #include <regexp.h>
3: #include <signal.h>
4: #include <pwd.h>
5: #include "mail.h"
6: #include "string.h"
7: #include "message.h"
8: #include "aux.h"
9:
10: /* imported */
11: extern char *malloc();
12: extern long time();
13: extern char *ctime();
14: extern char *getlog();
15: extern void exit();
16: extern char *thedate();
17:
18: /* global to this file */
19: static regexp *rfprog;
20: static regexp *fprog;
21: static pipe_err=0;
22:
23: #define VMLIMIT (64*1024)
24: #define MSGLIMIT (5*1024*1024)
25:
26: extern void
27: default_from(mp)
28: message *mp;
29: {
30: char *logname;
31: struct passwd *pw;
32: extern char *getenv();
33:
34: /* add in date and sender */
35: if ((logname=getenv("upasname")) == NULL) {
36: if ((logname=getlog()) == NULL)
37: logname = "Liz.Bimmler";
38: }
39: s_append(mp->sender, logname);
40: s_append(mp->date, thedate());
41: }
42:
43: extern message *
44: m_new()
45: {
46: message *mp;
47:
48: mp = (message *)malloc(sizeof(message));
49: if (mp == NULL) {
50: perror("message:");
51: exit(1);
52: }
53: mp->sender = s_new();
54: mp->replyaddr = s_new();
55: mp->date = s_new();
56: mp->body = s_new();
57: mp->size = 0;
58: mp->fd = -1;
59: return mp;
60: }
61:
62: extern int
63: m_free(mp)
64: message *mp;
65: {
66: if(mp->fd >= 0)
67: close(mp->fd);
68: s_free(mp->sender);
69: s_free(mp->date);
70: s_free(mp->body);
71: free((char *)mp);
72: }
73:
74: /* read a message into a temp file , return an open fd to it */
75: static int
76: m_read_to_file(fp, mp)
77: FILE *fp;
78: message *mp;
79: {
80: int cfd, fd;
81: int n;
82: char buf[4*1024];
83:
84: /*
85: * create and unlink temp file
86: */
87: strcpy(buf, MAILROOT);
88: strcat(buf, "mtXXXXXX");
89: mktemp(buf);
90: if((cfd = creat(buf, 0600))<0)
91: return -1;
92: if((fd = open(buf, 2))<0){
93: unlink(buf);
94: close(cfd);
95: return -1;
96: }
97: close(cfd);
98: unlink(buf);
99:
100: /*
101: * read the rest into the temp file
102: */
103: while((n = fread(buf, 1, sizeof buf, fp)) > 0){
104: if(write(fd, buf, n) != n){
105: close(fd);
106: return -1;
107: }
108: mp->size += n;
109: if(mp->size > MSGLIMIT){
110: mp->size = -1;
111: break;
112: }
113: }
114:
115: mp->fd = fd;
116: return 0;
117: }
118:
119: /* read in a message, interpret the 'From' header */
120: extern message *
121: m_read(fp, rmail, onatty)
122: FILE *fp;
123: int rmail; /* true if invoked as /bin/rmail */
124: int onatty; /* true if input from a terminal */
125: {
126: message *mp;
127: regsubexp subexp[10];
128: int first;
129:
130: mp = m_new();
131:
132: /* parse From lines */
133: if (rmail) {
134: /* get remote address */
135: string *sender=s_new();
136:
137: if (rfprog == NULL)
138: rfprog = regcomp(REMFROMRE);
139: first = 1;
140: while(s_read_line(fp, s_restart(mp->body)) != NULL) {
141: if (regexec(rfprog, s_to_c(mp->body), subexp, 10) == 0){
142: if(first == 0)
143: break;
144: if (fprog == NULL)
145: fprog = regcomp(FROMRE);
146: if(regexec(fprog, s_to_c(mp->body), subexp,10) == 0)
147: break;
148: s_restart(mp->body);
149: append_match(subexp, s_restart(sender), SENDERMATCH);
150: append_match(subexp, s_restart(mp->date), DATEMATCH);
151: break;
152: }
153: append_match(subexp, s_restart(sender), REMSENDERMATCH);
154: append_match(subexp, s_restart(mp->date), REMDATEMATCH);
155: if(subexp[REMSYSMATCH].sp!=subexp[REMSYSMATCH].ep){
156: append_match(subexp, mp->sender, REMSYSMATCH);
157: s_append(mp->sender, "!");
158: }
159: first = 0;
160: }
161: s_append(mp->sender, s_to_c(sender));
162: s_free(sender);
163: }
164: if (*s_to_c(mp->sender)=='\0')
165: default_from(mp);
166:
167: /* get body */
168: if(onatty){
169: /* user typing on terminal: terminator == '.' or EOF */
170: for(;;) {
171: char *line;
172:
173: if ((line=s_read_line(fp, mp->body))==NULL)
174: break;
175: if (strcmp(".\n", line)==0) {
176: *line = '\0';
177: mp->body->ptr = line;
178: break;
179: }
180: }
181: mp->size = mp->body->ptr - mp->body->base;
182: } else {
183: /*
184: * read up to VMLIMIT bytes (more or less).
185: * if message is longer use temp file
186: */
187: mp->size = s_read_to_lim(fp, mp->body, VMLIMIT);
188: if(mp->size < 0){
189: mp->size = -mp->size;
190: if(m_read_to_file(fp, mp) < 0){
191: perror("m_read");
192: exit(1);
193: }
194: }
195: }
196:
197: /*
198: * ignore 0 length messages from a terminal
199: */
200: if (!rmail && *s_to_c(mp->body) == '\0')
201: return NULL;
202:
203: return mp;
204: }
205:
206: SIGRETURN
207: sigpipe(s)
208: int s;
209: {
210: signal(SIGPIPE, sigpipe);
211: pipe_err = -1;
212: }
213:
214: /* return a piece of message starting at `offset' */
215: extern int
216: m_get(mp, offset, pp)
217: message *mp;
218: long offset;
219: char **pp;
220: {
221: static char buf[4*1024];
222:
223: /*
224: * are we past eof?
225: */
226: if(offset >= mp->size)
227: return 0;
228:
229: /*
230: * are we in the virtual memory portion?
231: */
232: if(offset < mp->body->ptr - mp->body->base){
233: *pp = mp->body->base + offset;
234: return mp->body->ptr - mp->body->base - offset;
235: }
236:
237: /*
238: * read it from the temp file
239: */
240: offset -= mp->body->ptr - mp->body->base;
241: if(mp->fd < 0)
242: return -1;
243: if(lseek(mp->fd, offset, 0)<0)
244: return -1;
245: *pp = buf;
246: return read(mp->fd, buf, sizeof buf);
247: }
248:
249: /* output the message body without ^From escapes */
250: static int
251: m_noescape(mp, fp)
252: message *mp; /* the message */
253: FILE *fp; /* where to print it */
254: {
255: long offset;
256: int n;
257: char *p;
258:
259: for(offset = 0; offset < mp->size; offset += n){
260: n = m_get(mp, offset, &p);
261: if(n < 0){
262: fflush(fp);
263: return -1;
264: }
265: fwrite(p, n, 1, fp);
266: }
267: fflush(fp);
268: return 0;
269: }
270:
271: /*
272: * output the message body with ^From escapes. The state machine
273: * ensures that any line starting with a 'From ' gets a '>' stuck
274: * in front of it.
275: */
276: static int
277: m_escape(mp, fp)
278: message *mp; /* the message */
279: FILE *fp; /* where to print it */
280: {
281: register char *p;
282: register char *end;
283: register int state;
284: long offset;
285: int n;
286: char *start;
287:
288: state = 1;
289: for(offset = 0; offset < mp->size; offset += n){
290: n = m_get(mp, offset, &start);
291: if(n < 0){
292: fflush(fp);
293: return -1;
294: }
295:
296: p = start;
297: for(end = p+n; p < end; p++){
298: switch(state){
299: case 1:
300: if(*p == 'F'){
301: state = 2;
302: continue;
303: }
304: state = 0;
305: break;
306: case 2:
307: if(*p == 'r'){
308: state = 3;
309: continue;
310: }
311: state = 0;
312: fputc('F', fp);
313: break;
314: case 3:
315: if(*p == 'o'){
316: state = 4;
317: continue;
318: }
319: state = 0;
320: fputc('F', fp);
321: fputc('r', fp);
322: break;
323: case 4:
324: if(*p == 'm'){
325: state = 5;
326: continue;
327: }
328: state = 0;
329: fputc('F', fp);
330: fputc('r', fp);
331: fputc('o', fp);
332: break;
333: case 5:
334: if(*p == ' ')
335: fputc('>', fp);
336: state = 0;
337: fputc('F', fp);
338: fputc('r', fp);
339: fputc('o', fp);
340: fputc('m', fp);
341: break;
342: }
343: fputc(*p, fp);
344: if(*p == '\n')
345: state = 1;
346: }
347: }
348: fflush(fp);
349: return 0;
350: }
351:
352: /* output a message */
353: extern int
354: m_print(mp, fp, remote, mbox)
355: message *mp; /* the message */
356: FILE *fp; /* where to print it */
357: char *remote; /* 'remote from' string */
358: {
359: SIG_TYP oldsig;
360: int err;
361:
362: pipe_err = 0;
363: oldsig = signal(SIGPIPE, sigpipe);
364: if (remote != NULL)
365: print_remote_header(fp,s_to_c(mp->sender),s_to_c(mp->date),remote);
366: else
367: print_header(fp, s_to_c(mp->sender), s_to_c(mp->date));
368:
369: if (!mbox)
370: err = m_noescape(mp, fp);
371: else
372: err = m_escape(mp, fp);
373: signal(SIGPIPE, oldsig);
374: if(ferror(fp))
375: err = -1;
376: return pipe_err|err;
377: }
378:
379: /* print just the message body */
380: extern int
381: m_bprint(mp, fp)
382: message *mp; /* the message */
383: FILE *fp; /* where to print it */
384: {
385: SIG_TYP oldsig;
386: int err;
387:
388: pipe_err = 0;
389: oldsig = signal(SIGPIPE, sigpipe);
390: err = m_noescape(mp, fp);
391: signal(SIGPIPE, oldsig);
392: if(ferror(fp))
393: err = -1;
394: return pipe_err|err;
395: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.