|
|
1.1 root 1: #include <stdio.h>
2: #include <regexp.h>
3: #include <signal.h>
4: #include "mail.h"
5: #include "string.h"
6: #include "message.h"
7: #include "aux.h"
8: #include <sys/stat.h>
9:
10: /* imported */
11: extern char *malloc();
12: extern long time();
13: extern fseek();
14: FILE *lockopen();
15: FILE *lockreopen();
16:
17: /* definition of UNIX message headers */
18:
19: #define MSGALLOC 32
20:
21: typedef struct {
22: message m[MSGALLOC];
23: int o;
24: } msgalloc;
25: static msgalloc *freep=NULL;
26:
27: /* read in a message, interpret the 'From' header */
28: extern message *
29: m_get(sp)
30: string *sp;
31: {
32: message *mp;
33: register char *cp;
34:
35: if (freep==NULL || freep->o >= MSGALLOC) {
36: freep = (msgalloc *)malloc(sizeof(msgalloc));
37: if (freep==NULL) {
38: perror("allocating message");
39: exit(1);
40: }
41: freep->o = 0;
42: }
43: mp = &(freep->m[freep->o++]);
44: mp->body = NULL;
45: mp->sender = s_new();
46: mp->date = s_new();
47: mp->extent = mp->prev = mp->next = NULL;
48: mp->status = 0;
49: mp->pos = 0;
50:
51: if (sp->ptr >= sp->end) {
52: mzero = mp;
53: return NULL;
54: }
55:
56: /* parse From lines */
57: for(cp=sp->ptr; *cp=='\n'||*cp==' '||*cp=='\t'; cp++);
58: for(sp->ptr=cp; *cp != '\n' && *cp; cp++);
59: *cp = '\0';
60: if (parse_header(sp->ptr, mp->sender, mp->date)<0) {
61: fprintf(stderr, "!mailbox format incorrect\n");
62: mzero = mp;
63: return NULL;
64: }
65: *cp++ = '\n';
66: sp->ptr = cp;
67:
68: /* get body */
69: while (cp < sp->end && !IS_HEADER(cp)) {
70: while (*cp++ != '\n')
71: ;
72: }
73: cp[-1] = '\0';
74:
75: mp->size = cp - sp->ptr;
76: mp->body = s_array(sp->ptr, mp->size);
77: sp->ptr = cp;
78: return mp;
79: }
80:
81: /* output a message, return 0 if ok -1 otherwise */
82: extern int
83: m_print(mp, fp, nl, header)
84: message *mp; /* the message */
85: FILE *fp; /* where to print it */
86: {
87: SIG_TYP pstat;
88: int rv = 0;
89:
90: pstat = signal(SIGPIPE, SIG_IGN);
91: if (header)
92: print_header(fp, s_to_c(mp->sender), s_to_c(mp->date));
93: fflush(fp);
94:
95: /*
96: * the following are writes instead of an fwrites because,
97: * in the case of a broken pipe, fwrite will continuously
98: * generate SIGPIPE's. Enough SIGPIPE's will terminate the
99: * process despite the SIG_IGN (at least on v9).
100: */
101: if (mp->size > 0)
102: if(write(fileno(fp), s_to_c(mp->body), mp->size-1) != mp->size-1)
103: rv = -1;
104: if (rv==0 && nl)
105: if(write(fileno(fp), "\n", 1) != 1)
106: rv = -1;
107:
108: signal(SIGPIPE, pstat);
109: return ferror(fp) ? -1 : rv;
110: }
111:
112: /* lists of mail messages */
113: message *mzero; /* zeroth message */
114: message *mlist; /* first mail message */
115: message *mlast; /* last mail message */
116:
117: long mbsize; /* last size of mail box */
118:
119:
120: /*
121: * read in the mail file. mbsize is the spot to start reading from.
122: * if fpp is non-zero then don't close the locked fmailbox, just
123: * return the file pointer to it.
124: */
125: static FILE *
126: rd_mbox(file, reverse, newmail, fp)
127: char *file;
128: int reverse;
129: FILE *fp;
130: {
131: message *mp;
132: int pos = 0;
133: struct stat sbuf;
134: string *line;
135: char *corefile;
136: int len;
137:
138: if(fp==NULL)
139: fp = lockopen(file, "r", 0, -1, -1);
140: if(fp==NULL)
141: return NULL;
142: if (stat(file, &sbuf) < 0){
143: lockclose(fp);
144: return NULL;
145: }
146: if (sbuf.st_size <= mbsize)
147: return fp;
148: fseek(fp, mbsize, 0);
149: len = sbuf.st_size-mbsize;
150: corefile = malloc(len+1);
151: if (corefile == NULL || fread(corefile, len, 1, fp)!=1) {
152: perror("reading mbox");
153: exit(1);
154: }
155: corefile[len-1] = '\n'; /* ensure last mbox char is \n */
156: corefile[len] = '\0'; /* ensure null termination */
157: line = s_array(corefile, len);
158: if (mbsize==0) {
159: switch(delivery_status(s_restart(line))) {
160: case MF_PIPE:
161: printf("mail: mail is being piped to %s\n", line->ptr);
162: lockclose(fp);
163: return NULL;
164: case MF_FORWARD:
165: printf("mail: mail is being forwarded to %s\n", line->ptr);
166: lockclose(fp);
167: return NULL;
168: }
169: }
170: s_restart(line);
171: while((mp = m_get(line)) != NULL) {
172: if (mlist == NULL)
173: mlist = mlast = mp;
174: else if (reverse) {
175: mlast->next = mp;
176: mp->prev = mlast;
177: mlast = mp;
178: } else {
179: mp->next = mlist;
180: mlist->prev = mp;
181: mlist = mp;
182: }
183: }
184: if (mlist==NULL)
185: return fp;
186: mzero->next = mlist;
187: mzero->prev = mlast;
188: for (mp=mzero; mp!=NULL; mp=mp->next)
189: mp->pos=pos++;
190: mbsize = sbuf.st_size;
191: if (newmail)
192: printf("mail: new message arrived\n");
193: return fp;
194: }
195:
196: /* read the mailbox */
197: extern int
198: read_mbox(file, reverse)
199: char *file;
200: int reverse;
201: {
202: FILE *fp;
203: SIG_TYP fhup, fint, fquit;
204:
205: fhup = signal(SIGHUP, SIG_IGN);
206: fint = signal(SIGINT, SIG_IGN);
207: fquit = signal(SIGQUIT, SIG_IGN);
208: fp = rd_mbox(file, reverse, 0, NULL);
209: if(fp!=NULL)
210: lockclose(fp);
211: signal(SIGHUP, fhup);
212: signal(SIGINT, fint);
213: signal(SIGQUIT, fquit);
214: return fp==NULL ? -1 : 0;
215: }
216:
217: /* read the mailbox looking for new messages */
218: extern int
219: reread_mbox(file, reverse)
220: char *file;
221: int reverse;
222: {
223: FILE *fp;
224: SIG_TYP fhup, fint, fquit;
225:
226: fhup = signal(SIGHUP, SIG_IGN);
227: fint = signal(SIGINT, SIG_IGN);
228: fquit = signal(SIGQUIT, SIG_IGN);
229: fp = rd_mbox(file, reverse, 1, NULL);
230: if(fp!=NULL)
231: lockclose(fp);
232: signal(SIGHUP, fhup);
233: signal(SIGINT, fint);
234: signal(SIGQUIT, fquit);
235: return fp==NULL ? -1 : 0;
236: }
237:
238: /* read any changes from the mailbox and write out the result */
239: rdwr_mbox(file, reverse)
240: char *file;
241: {
242: int rv, err;
243: FILE *fp;
244: message *mp;
245:
246: /*
247: * if nothing has changed, just return
248: */
249: for (mp=mlist; mp!=NULL; mp=mp->next)
250: if (mp->status&DELETED)
251: break;
252: if (mp==NULL)
253: return 0;
254:
255: /*
256: * read mailbox to pick up any changes
257: */
258: fp = NULL;
259: if((fp=rd_mbox(file, reverse, 1, NULL)) == NULL){
260: fprintf(stderr, "mail: can't write mail file %s\n", file);
261: return 1;
262: }
263:
264: /*
265: * now rewrite it. use the fp passed back from read_mbox to
266: * maintain the lock across both operations.
267: */
268: if(fp==NULL)
269: fp = lockopen(file, "w", 0, -1, -1);
270: else
271: fp = lockreopen(file, "w", fp);
272: if (fp == NULL) {
273: fprintf(stderr, "mail: can't write mail file %s\n", file);
274: return 1;
275: } else {
276: rv = 0;
277: mlist->prev = NULL; /* ignore mzero */
278: err = 0;
279: for(mp=reverse?mlist:mlast; mp!=NULL; mp=reverse?mp->next:mp->prev)
280: if ((mp->status&DELETED)==0)
281: err += m_print(mp, fp, 1, 1);
282: if (err < 0) {
283: fprintf(stderr,"mail: error writing mail file %s\n", file);
284: rv = 1;
285: }
286: lockclose(fp);
287: }
288: return rv;
289: }
290:
291: /* write out the mail file */
292: extern int
293: write_mbox(file, reverse)
294: char *file;
295: int reverse;
296: {
297: SIG_TYP fhup, fint, fquit;
298: int rv;
299:
300: fhup = signal(SIGHUP, SIG_IGN);
301: fint = signal(SIGINT, SIG_IGN);
302: fquit = signal(SIGQUIT, SIG_IGN);
303: rv = rdwr_mbox(file, reverse);
304: signal(SIGHUP, fhup);
305: signal(SIGINT, fint);
306: signal(SIGQUIT, fquit);
307: return rv;
308: }
309:
310: /* imported */
311: extern char *getenv();
312: extern int getpid();
313:
314: /* global to semaphores */
315: static char semaphore[128];
316:
317: extern void
318: V()
319: {
320: unlink(semaphore);
321: }
322:
323: /* return name of tty if file is already being read, NULL otherwise */
324: extern int
325: P()
326: {
327: char file[128];
328: struct stat sbuf;
329: FILE *fp;
330: int pid;
331: char *home = getenv("HOME");
332:
333: if (home == NULL)
334: return 0;
335: (void)strcpy(file, home);
336: (void)strcat(file, "/.Maillock");
337: if (stat(file, &sbuf) >= 0) {
338:
339: /* lock file exists */
340: fp = fopen(file, "r");
341: if (fp != NULL) {
342: fscanf(fp, "%d", &pid);
343: fclose(fp);
344: }
345: if (fp == NULL || kill(pid, 0)==0) {
346: fprintf(stderr,"WARNING: You are already reading mail.\n");
347: fprintf(stderr, "\tThis instance of mail is read only.\n");
348: return -1;
349: }
350: }
351:
352: /* create a semaphore file */
353: strcpy(semaphore, file);
354: V();
355: fp = fopen(semaphore, "w");
356: if (fp == NULL)
357: return 0; /* nothing else we can do */
358: fprintf(fp, "%d somewhere", getpid());
359: fclose(fp);
360: return 0;
361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.