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