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