|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)fio.c 2.16 (Berkeley) 8/11/83";
3: #endif
4:
5: #include "rcv.h"
6: #include <sys/stat.h>
7: #include <errno.h>
8:
9: /*
10: * Mail -- a mail program
11: *
12: * File I/O.
13: */
14:
15: /*
16: * Set up the input pointers while copying the mail file into
17: * /tmp.
18: */
19:
20: setptr(ibuf)
21: FILE *ibuf;
22: {
23: register int c;
24: register char *cp, *cp2;
25: register int count, l;
26: long s;
27: off_t offset;
28: char linebuf[LINESIZE];
29: char wbuf[LINESIZE];
30: int maybe, mestmp, flag, inhead;
31: struct message this;
32: extern char tempSet[];
33:
34: if ((mestmp = opentemp(tempSet)) < 0)
35: exit(1);
36: msgCount = 0;
37: offset = 0;
38: s = 0L;
39: l = 0;
40: maybe = 1;
41: flag = MUSED|MNEW;
42: for (;;) {
43: cp = linebuf;
44: c = getc(ibuf);
45: while (c != EOF && c != '\n') {
46: if (cp - linebuf >= LINESIZE - 1) {
47: ungetc(c, ibuf);
48: *cp = 0;
49: break;
50: }
51: *cp++ = c;
52: c = getc(ibuf);
53: }
54: *cp = 0;
55: if (cp == linebuf && c == EOF) {
56: this.m_flag = flag;
57: flag = MUSED|MNEW;
58: this.m_offset = offsetof(offset);
59: this.m_block = blockof(offset);
60: this.m_size = s;
61: this.m_lines = l;
62: if (append(&this, mestmp)) {
63: perror(tempSet);
64: exit(1);
65: }
66: fclose(ibuf);
67: makemessage(mestmp);
68: close(mestmp);
69: return;
70: }
71: count = cp - linebuf + 1;
72: for (cp = linebuf; *cp;)
73: putc(*cp++, otf);
74: putc('\n', otf);
75: if (ferror(otf)) {
76: perror("/tmp");
77: exit(1);
78: }
79: if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
80: msgCount++;
81: this.m_flag = flag;
82: flag = MUSED|MNEW;
83: inhead = 1;
84: this.m_block = blockof(offset);
85: this.m_offset = offsetof(offset);
86: this.m_size = s;
87: this.m_lines = l;
88: s = 0L;
89: l = 0;
90: if (append(&this, mestmp)) {
91: perror(tempSet);
92: exit(1);
93: }
94: }
95: if (linebuf[0] == 0)
96: inhead = 0;
97: if (inhead && index(linebuf, ':')) {
98: cp = linebuf;
99: cp2 = wbuf;
100: while (isalpha(*cp))
101: *cp2++ = *cp++;
102: *cp2 = 0;
103: if (icequal(wbuf, "status")) {
104: cp = index(linebuf, ':');
105: if (index(cp, 'R'))
106: flag |= MREAD;
107: if (index(cp, 'O'))
108: flag &= ~MNEW;
109: inhead = 0;
110: }
111: }
112: offset += count;
113: s += (long) count;
114: l++;
115: maybe = 0;
116: if (linebuf[0] == 0)
117: maybe = 1;
118: }
119: }
120:
121: /*
122: * Drop the passed line onto the passed output buffer.
123: * If a write error occurs, return -1, else the count of
124: * characters written, including the newline.
125: */
126:
127: putline(obuf, linebuf)
128: FILE *obuf;
129: char *linebuf;
130: {
131: register int c;
132:
133: c = strlen(linebuf);
134: fputs(linebuf, obuf);
135: putc('\n', obuf);
136: if (ferror(obuf))
137: return(-1);
138: return(c+1);
139: }
140:
141: /*
142: * Quickly read a line from the specified input into the line
143: * buffer; return characters read.
144: */
145:
146: freadline(ibuf, linebuf)
147: register FILE *ibuf;
148: register char *linebuf;
149: {
150: register int c;
151: register char *cp;
152:
153: c = getc(ibuf);
154: cp = linebuf;
155: while (c != '\n' && c != EOF) {
156: if (c == 0) {
157: c = getc(ibuf);
158: continue;
159: }
160: if (cp - linebuf >= BUFSIZ-1) {
161: *cp = 0;
162: return(cp - linebuf + 1);
163: }
164: *cp++ = c;
165: c = getc(ibuf);
166: }
167: if (c == EOF && cp == linebuf)
168: return(0);
169: *cp = 0;
170: return(cp - linebuf + 1);
171: }
172:
173: /*
174: * Read up a line from the specified input into the line
175: * buffer. Return the number of characters read. Do not
176: * include the newline at the end.
177: */
178:
179: readline(ibuf, linebuf)
180: FILE *ibuf;
181: char *linebuf;
182: {
183: register char *cp;
184: register int c;
185:
186: do {
187: clearerr(ibuf);
188: c = getc(ibuf);
189: for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) {
190: if (c == 0)
191: continue;
192: if (cp - linebuf < LINESIZE-2)
193: *cp++ = c;
194: }
195: } while (ferror(ibuf) && ibuf == stdin);
196: *cp = 0;
197: if (c == EOF && cp == linebuf)
198: return(0);
199: return(cp - linebuf + 1);
200: }
201:
202: /*
203: * Return a file buffer all ready to read up the
204: * passed message pointer.
205: */
206:
207: FILE *
208: setinput(mp)
209: register struct message *mp;
210: {
211: off_t off;
212:
213: fflush(otf);
214: off = mp->m_block;
215: off <<= 9;
216: off += mp->m_offset;
217: if (fseek(itf, off, 0) < 0) {
218: perror("fseek");
219: panic("temporary file seek");
220: }
221: return(itf);
222: }
223:
224: /*
225: * Take the data out of the passed ghost file and toss it into
226: * a dynamically allocated message structure.
227: */
228:
229: makemessage(f)
230: {
231: register struct message *m;
232: register char *mp;
233: register count;
234:
235: mp = calloc((unsigned) (msgCount + 1), sizeof *m);
236: if (mp == NOSTR) {
237: printf("Insufficient memory for %d messages\n", msgCount);
238: exit(1);
239: }
240: if (message != (struct message *) 0)
241: cfree((char *) message);
242: message = (struct message *) mp;
243: dot = message;
244: lseek(f, 0L, 0);
245: while (count = read(f, mp, BUFSIZ))
246: mp += count;
247: for (m = &message[0]; m < &message[msgCount]; m++) {
248: m->m_size = (m+1)->m_size;
249: m->m_lines = (m+1)->m_lines;
250: m->m_flag = (m+1)->m_flag;
251: }
252: message[msgCount].m_size = 0L;
253: message[msgCount].m_lines = 0;
254: }
255:
256: /*
257: * Append the passed message descriptor onto the temp file.
258: * If the write fails, return 1, else 0
259: */
260:
261: append(mp, f)
262: struct message *mp;
263: {
264: if (write(f, (char *) mp, sizeof *mp) != sizeof *mp)
265: return(1);
266: return(0);
267: }
268:
269: /*
270: * Delete a file, but only if the file is a plain file.
271: */
272:
273: remove(name)
274: char name[];
275: {
276: struct stat statb;
277: extern int errno;
278:
279: if (stat(name, &statb) < 0)
280: return(-1);
281: if ((statb.st_mode & S_IFMT) != S_IFREG) {
282: errno = EISDIR;
283: return(-1);
284: }
285: return(unlink(name));
286: }
287:
288: /*
289: * Terminate an editing session by attempting to write out the user's
290: * file from the temporary. Save any new stuff appended to the file.
291: */
292: edstop()
293: {
294: register int gotcha, c;
295: register struct message *mp;
296: FILE *obuf, *ibuf, *readstat;
297: struct stat statb;
298: char tempname[30], *id;
299: int (*sigs[3])();
300:
301: if (readonly)
302: return;
303: holdsigs();
304: if (Tflag != NOSTR) {
305: if ((readstat = fopen(Tflag, "w")) == NULL)
306: Tflag = NOSTR;
307: }
308: for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
309: if (mp->m_flag & MNEW) {
310: mp->m_flag &= ~MNEW;
311: mp->m_flag |= MSTATUS;
312: }
313: if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
314: gotcha++;
315: if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
316: if ((id = hfield("article-id", mp)) != NOSTR)
317: fprintf(readstat, "%s\n", id);
318: }
319: }
320: if (Tflag != NOSTR)
321: fclose(readstat);
322: if (!gotcha || Tflag != NOSTR)
323: goto done;
324: ibuf = NULL;
325: if (stat(editfile, &statb) >= 0 && statb.st_size > mailsize) {
326: strcpy(tempname, "/tmp/mboxXXXXXX");
327: mktemp(tempname);
328: if ((obuf = fopen(tempname, "w")) == NULL) {
329: perror(tempname);
330: relsesigs();
331: reset(0);
332: }
333: if ((ibuf = fopen(editfile, "r")) == NULL) {
334: perror(editfile);
335: fclose(obuf);
336: remove(tempname);
337: relsesigs();
338: reset(0);
339: }
340: fseek(ibuf, mailsize, 0);
341: while ((c = getc(ibuf)) != EOF)
342: putc(c, obuf);
343: fclose(ibuf);
344: fclose(obuf);
345: if ((ibuf = fopen(tempname, "r")) == NULL) {
346: perror(tempname);
347: remove(tempname);
348: relsesigs();
349: reset(0);
350: }
351: remove(tempname);
352: }
353: printf("\"%s\" ", editfile);
354: flush();
355: if (close(creat(editfile, 0600)) < 0)
356: perror(editfile);
357: if ((obuf = fopen(editfile, "r+")) == NULL) {
358: perror(editfile);
359: relsesigs();
360: reset(0);
361: }
362: c = 0;
363: for (mp = &message[0]; mp < &message[msgCount]; mp++) {
364: if ((mp->m_flag & MDELETED) != 0)
365: continue;
366: c++;
367: if (send(mp, obuf, 0) < 0) {
368: perror(editfile);
369: relsesigs();
370: reset(0);
371: }
372: }
373: gotcha = (c == 0 && ibuf == NULL);
374: if (ibuf != NULL) {
375: while ((c = getc(ibuf)) != EOF)
376: putc(c, obuf);
377: fclose(ibuf);
378: }
379: fflush(obuf);
380: if (ferror(obuf)) {
381: perror(editfile);
382: relsesigs();
383: reset(0);
384: }
385: fclose(obuf);
386: if (gotcha) {
387: remove(editfile);
388: printf("removed\n");
389: }
390: else
391: printf("complete\n");
392: flush();
393:
394: done:
395: relsesigs();
396: }
397:
398: static int sigdepth = 0; /* depth of holdsigs() */
399: static int sigmask = 0;
400: /*
401: * Hold signals SIGHUP - SIGQUIT.
402: */
403: holdsigs()
404: {
405: register int i;
406:
407: if (sigdepth++ == 0)
408: sigmask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT));
409: }
410:
411: /*
412: * Release signals SIGHUP - SIGQUIT
413: */
414: relsesigs()
415: {
416: register int i;
417:
418: if (--sigdepth == 0)
419: sigsetmask(sigmask);
420: }
421:
422: /*
423: * Empty the output buffer.
424: */
425:
426: clrbuf(buf)
427: register FILE *buf;
428: {
429:
430: buf = stdout;
431: buf->_ptr = buf->_base;
432: buf->_cnt = BUFSIZ;
433: }
434:
435: /*
436: * Open a temp file by creating, closing, unlinking, and
437: * reopening. Return the open file descriptor.
438: */
439:
440: opentemp(file)
441: char file[];
442: {
443: register int f;
444:
445: if ((f = creat(file, 0600)) < 0) {
446: perror(file);
447: return(-1);
448: }
449: close(f);
450: if ((f = open(file, 2)) < 0) {
451: perror(file);
452: remove(file);
453: return(-1);
454: }
455: remove(file);
456: return(f);
457: }
458:
459: /*
460: * Flush the standard output.
461: */
462:
463: flush()
464: {
465: fflush(stdout);
466: fflush(stderr);
467: }
468:
469: /*
470: * Determine the size of the file possessed by
471: * the passed buffer.
472: */
473:
474: off_t
475: fsize(iob)
476: FILE *iob;
477: {
478: register int f;
479: struct stat sbuf;
480:
481: f = fileno(iob);
482: if (fstat(f, &sbuf) < 0)
483: return(0);
484: return(sbuf.st_size);
485: }
486:
487: /*
488: * Take a file name, possibly with shell meta characters
489: * in it and expand it by using "sh -c echo filename"
490: * Return the file name as a dynamic string.
491: */
492:
493: char *
494: expand(name)
495: char name[];
496: {
497: char xname[BUFSIZ];
498: char cmdbuf[BUFSIZ];
499: register int pid, l, rc;
500: register char *cp, *Shell;
501: int s, pivec[2], (*sigint)();
502: struct stat sbuf;
503:
504: if (name[0] == '+' && getfold(cmdbuf) >= 0) {
505: sprintf(xname, "%s/%s", cmdbuf, name + 1);
506: return(expand(savestr(xname)));
507: }
508: if (!anyof(name, "~{[*?$`'\"\\"))
509: return(name);
510: if (pipe(pivec) < 0) {
511: perror("pipe");
512: return(name);
513: }
514: sprintf(cmdbuf, "echo %s", name);
515: if ((pid = vfork()) == 0) {
516: sigchild();
517: Shell = value("SHELL");
518: if (Shell == NOSTR)
519: Shell = SHELL;
520: close(pivec[0]);
521: close(1);
522: dup(pivec[1]);
523: close(pivec[1]);
524: close(2);
525: execl(Shell, Shell, "-c", cmdbuf, 0);
526: _exit(1);
527: }
528: if (pid == -1) {
529: perror("fork");
530: close(pivec[0]);
531: close(pivec[1]);
532: return(NOSTR);
533: }
534: close(pivec[1]);
535: l = read(pivec[0], xname, BUFSIZ);
536: close(pivec[0]);
537: while (wait(&s) != pid);
538: ;
539: s &= 0377;
540: if (s != 0 && s != SIGPIPE) {
541: fprintf(stderr, "\"Echo\" failed\n");
542: goto err;
543: }
544: if (l < 0) {
545: perror("read");
546: goto err;
547: }
548: if (l == 0) {
549: fprintf(stderr, "\"%s\": No match\n", name);
550: goto err;
551: }
552: if (l == BUFSIZ) {
553: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
554: goto err;
555: }
556: xname[l] = 0;
557: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
558: ;
559: *++cp = '\0';
560: if (any(' ', xname) && stat(xname, &sbuf) < 0) {
561: fprintf(stderr, "\"%s\": Ambiguous\n", name);
562: goto err;
563: }
564: return(savestr(xname));
565:
566: err:
567: return(NOSTR);
568: }
569:
570: /*
571: * Determine the current folder directory name.
572: */
573: getfold(name)
574: char *name;
575: {
576: char *folder;
577:
578: if ((folder = value("folder")) == NOSTR)
579: return(-1);
580: if (*folder == '/')
581: strcpy(name, folder);
582: else
583: sprintf(name, "%s/%s", homedir, folder);
584: return(0);
585: }
586:
587: /*
588: * A nicer version of Fdopen, which allows us to fclose
589: * without losing the open file.
590: */
591:
592: FILE *
593: Fdopen(fildes, mode)
594: char *mode;
595: {
596: register int f;
597: FILE *fdopen();
598:
599: f = dup(fildes);
600: if (f < 0) {
601: perror("dup");
602: return(NULL);
603: }
604: return(fdopen(f, mode));
605: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.