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