|
|
1.1 root 1: #
2:
3: #include "rcv.h"
4: #include <sys/stat.h>
5: #include <errno.h>
6:
7: /*
8: * Mail -- a mail program
9: *
10: * File I/O.
11: */
12:
13: /*
14: * Set up the input pointers while copying the mail file into
15: * /tmp.
16: */
17:
18: setptr(ibuf)
19: FILE *ibuf;
20: {
21: register int count, s, l;
22: off_t offset;
23: char linebuf[LINESIZE];
24: int maybe, mestmp, flag;
25: struct message this;
26: extern char tempSet[];
27:
28: if ((mestmp = opentemp(tempSet)) < 0)
29: exit(1);
30: msgCount = 0;
31: offset = 0;
32: s = 0;
33: l = 0;
34: maybe = 1;
35: flag = MUSED;
36: if (value("hold") != NOSTR)
37: flag = MPRESERVE|MUSED;
38: for (;;) {
39: if ((count = readline(ibuf, linebuf)) == 0) {
40: this.m_flag = flag;
41: this.m_offset = offsetof(offset);
42: this.m_block = blockof(offset);
43: this.m_size = s;
44: this.m_lines = l;
45: if (append(&this, mestmp)) {
46: perror(tempSet);
47: exit(1);
48: }
49: fclose(ibuf);
50: makemessage(mestmp);
51: close(mestmp);
52: return;
53: }
54: if (putline(otf, linebuf) < 0) {
55: perror("/tmp");
56: exit(1);
57: }
58: if (maybe && ishead(linebuf)) {
59: msgCount++;
60: this.m_flag = flag;
61: this.m_block = blockof(offset);
62: this.m_offset = offsetof(offset);
63: this.m_size = s;
64: this.m_lines = l;
65: s = 0;
66: l = 0;
67: if (append(&this, mestmp)) {
68: perror(tempSet);
69: exit(1);
70: }
71: }
72: offset += count;
73: s += count;
74: l++;
75: maybe = 0;
76: if (linebuf[0] == 0)
77: maybe = 1;
78: }
79: }
80:
81: /*
82: * Drop the passed line onto the passed output buffer.
83: * If a write error occurs, return -1, else the count of
84: * characters written, including the newline.
85: */
86:
87: putline(obuf, linebuf)
88: FILE *obuf;
89: char *linebuf;
90: {
91: register int c;
92:
93: c = strlen(linebuf);
94: fputs(linebuf, obuf);
95: putc('\n', obuf);
96: if (ferror(obuf))
97: return(-1);
98: return(c+1);
99: }
100:
101: /*
102: * Read up a line from the specified input into the line
103: * buffer. Return the number of characters read. Do not
104: * include the newline at the end.
105: */
106:
107: readline(ibuf, linebuf)
108: FILE *ibuf;
109: char *linebuf;
110: {
111: register char *cp;
112: register int c;
113:
114: do {
115: clearerr(ibuf);
116: c = getc(ibuf);
117: for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) {
118: if (c == 0)
119: continue;
120: if (cp - linebuf < LINESIZE-2)
121: *cp++ = c;
122: }
123: } while (ferror(ibuf) && ibuf == stdin);
124: *cp = 0;
125: if (c == EOF && cp == linebuf)
126: return(0);
127: return(cp - linebuf + 1);
128: }
129:
130: /*
131: * Return a file buffer all ready to read up the
132: * passed message pointer.
133: */
134:
135: FILE *
136: setinput(mp)
137: register struct message *mp;
138: {
139: off_t off;
140:
141: fflush(otf);
142: off = mp->m_block;
143: off <<= 9;
144: off += mp->m_offset;
145: if (fseek(itf, off, 0) < 0) {
146: perror("fseek");
147: panic("temporary file seek");
148: }
149: return(itf);
150: }
151:
152: /*
153: * Take the data out of the passed ghost file and toss it into
154: * a dynamically allocated message structure.
155: */
156:
157: makemessage(f)
158: {
159: register struct message *m;
160: register char *mp;
161: register count;
162:
163: mp = calloc((unsigned) (msgCount + 1), sizeof *m);
164: if (mp == NOSTR) {
165: printf("Insufficient memory for %d messages\n", msgCount);
166: exit(1);
167: }
168: message = (struct message *) mp;
169: dot = message;
170: lseek(f, 0L, 0);
171: while (count = read(f, mp, BUFSIZ))
172: mp += count;
173: for (m = &message[0]; m < &message[msgCount]; m++) {
174: m->m_size = (m+1)->m_size;
175: m->m_lines = (m+1)->m_lines;
176: }
177: message[msgCount].m_size = 0;
178: message[msgCount].m_lines = 0;
179: }
180:
181: /*
182: * Append the passed message descriptor onto the temp file.
183: * If the write fails, return 1, else 0
184: */
185:
186: append(mp, f)
187: struct message *mp;
188: {
189: if (write(f, (char *) mp, sizeof *mp) != sizeof *mp)
190: return(1);
191: return(0);
192: }
193:
194: /*
195: * Delete a file, but only if the file is a plain file.
196: */
197:
198: remove(name)
199: char name[];
200: {
201: struct stat statb;
202: extern int errno;
203:
204: if (stat(name, &statb) < 0)
205: return(-1);
206: if ((statb.st_mode & S_IFMT) != S_IFREG) {
207: errno = EISDIR;
208: return(-1);
209: }
210: return(unlink(name));
211: }
212:
213: /*
214: * Terminate an editing session by attempting to write out the user's
215: * file from the temporary.
216: */
217:
218: edstop()
219: {
220: register int gotcha, c;
221: register struct message *mp;
222: FILE *obuf;
223:
224: for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++)
225: if (mp->m_flag & (MODIFY|MDELETED)) {
226: gotcha++;
227: break;
228: }
229: if (!gotcha)
230: return;
231: printf("\"%s\" ", editfile);
232: flush();
233: if ((obuf = fopen(editfile, "w")) == NULL) {
234: perror(editfile);
235: reset(0);
236: }
237: c = 0;
238: for (mp = &message[0]; mp < &message[msgCount]; mp++) {
239: if ((mp->m_flag & MDELETED) != 0)
240: continue;
241: c++;
242: if (send(mp, obuf) < 0) {
243: perror(editfile);
244: reset(0);
245: }
246: }
247: fflush(obuf);
248: if (ferror(obuf)) {
249: perror(editfile);
250: reset(0);
251: }
252: if (c == 0) {
253: remove(editfile);
254: printf("removed\n");
255: }
256: else
257: printf("complete\n");
258: flush();
259: }
260:
261: /*
262: * Empty the output buffer.
263: */
264:
265: clrbuf(buf)
266: register FILE *buf;
267: {
268:
269: buf = stdout;
270: buf->_ptr = buf->_base;
271: buf->_cnt = BUFSIZ;
272: }
273:
274: /*
275: * Open a temp file by creating, closing, unlinking, and
276: * reopening. Return the open file descriptor.
277: */
278:
279: opentemp(file)
280: char file[];
281: {
282: register int f;
283:
284: if ((f = creat(file, 0600)) < 0) {
285: perror(file);
286: return(-1);
287: }
288: close(f);
289: if ((f = open(file, 2)) < 0) {
290: perror(file);
291: remove(file);
292: return(-1);
293: }
294: remove(file);
295: return(f);
296: }
297:
298: /*
299: * Flush the standard output.
300: */
301:
302: flush()
303: {
304: fflush(stdout);
305: fflush(stderr);
306: }
307:
308: /*
309: * Determine the size of the file possessed by
310: * the passed buffer.
311: */
312:
313: off_t
314: fsize(iob)
315: FILE *iob;
316: {
317: register int f;
318: struct stat sbuf;
319:
320: f = fileno(iob);
321: if (fstat(f, &sbuf) < 0)
322: return(0);
323: return(sbuf.st_size);
324: }
325:
326: /*
327: * Take a file name, possibly with shell meta characters
328: * in it and expand it by using "sh -c echo filename"
329: * Return the file name as a dynamic string.
330: */
331:
332: char *
333: expand(name)
334: char name[];
335: {
336: char xname[BUFSIZ];
337: char cmdbuf[BUFSIZ];
338: register int pid, l, rc;
339: register char *cp, *Shell;
340: int s, pivec[2], (*sigint)();
341: struct stat sbuf;
342:
343: if (!anyof(name, "~{[*?$`'\"\\"))
344: return(name);
345: /* sigint = signal(SIGINT, SIG_IGN); */
346: if (pipe(pivec) < 0) {
347: perror("pipe");
348: /* signal(SIGINT, sigint) */
349: return(name);
350: }
351: sprintf(cmdbuf, "echo %s", name);
352: if ((pid = vfork()) == 0) {
353: Shell = value("SHELL");
354: if (Shell == NOSTR)
355: Shell = SHELL;
356: close(pivec[0]);
357: close(1);
358: dup(pivec[1]);
359: close(pivec[1]);
360: close(2);
361: execl(Shell, Shell, "-c", cmdbuf, 0);
362: _exit(1);
363: }
364: if (pid == -1) {
365: perror("fork");
366: close(pivec[0]);
367: close(pivec[1]);
368: return(NOSTR);
369: }
370: close(pivec[1]);
371: l = read(pivec[0], xname, BUFSIZ);
372: close(pivec[0]);
373: while (wait(&s) != pid);
374: ;
375: s &= 0377;
376: if (s != 0 && s != SIGPIPE) {
377: fprintf(stderr, "\"Echo\" failed\n");
378: goto err;
379: }
380: if (l < 0) {
381: perror("read");
382: goto err;
383: }
384: if (l == 0) {
385: fprintf(stderr, "\"%s\": No match\n", name);
386: goto err;
387: }
388: if (l == BUFSIZ) {
389: fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
390: goto err;
391: }
392: xname[l] = 0;
393: for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
394: ;
395: *++cp = '\0';
396: if (any(' ', xname) && stat(xname, &sbuf) < 0) {
397: fprintf(stderr, "\"%s\": Ambiguous\n", name);
398: goto err;
399: }
400: /* signal(SIGINT, sigint) */
401: return(savestr(xname));
402:
403: err:
404: /* signal(SIGINT, sigint); */
405: return(NOSTR);
406: }
407:
408: /*
409: * A nicer version of Fdopen, which allows us to fclose
410: * without losing the open file.
411: */
412:
413: FILE *
414: Fdopen(fildes, mode)
415: char *mode;
416: {
417: register int f;
418: FILE *fdopen();
419:
420: f = dup(fildes);
421: if (f < 0) {
422: perror("dup");
423: return(NULL);
424: }
425: return(fdopen(f, mode));
426: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.