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