|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)cmd2.c 2.11 (Berkeley) 8/11/83";
3: #endif
4:
5: #include "rcv.h"
6: #include <sys/stat.h>
7:
8: /*
9: * Mail -- a mail program
10: *
11: * More user commands.
12: */
13:
14: /*
15: * If any arguments were given, go to the next applicable argument
16: * following dot, otherwise, go to the next applicable message.
17: * If given as first command with no arguments, print first message.
18: */
19:
20: next(msgvec)
21: int *msgvec;
22: {
23: register struct message *mp;
24: register int *ip, *ip2;
25: int list[2], mdot;
26:
27: if (*msgvec != NULL) {
28:
29: /*
30: * If some messages were supplied, find the
31: * first applicable one following dot using
32: * wrap around.
33: */
34:
35: mdot = dot - &message[0] + 1;
36:
37: /*
38: * Find the first message in the supplied
39: * message list which follows dot.
40: */
41:
42: for (ip = msgvec; *ip != NULL; ip++)
43: if (*ip > mdot)
44: break;
45: if (*ip == NULL)
46: ip = msgvec;
47: ip2 = ip;
48: do {
49: mp = &message[*ip2 - 1];
50: if ((mp->m_flag & MDELETED) == 0) {
51: dot = mp;
52: goto hitit;
53: }
54: if (*ip2 != NULL)
55: ip2++;
56: if (*ip2 == NULL)
57: ip2 = msgvec;
58: } while (ip2 != ip);
59: printf("No messages applicable\n");
60: return(1);
61: }
62:
63: /*
64: * If this is the first command, select message 1.
65: * Note that this must exist for us to get here at all.
66: */
67:
68: if (!sawcom)
69: goto hitit;
70:
71: /*
72: * Just find the next good message after dot, no
73: * wraparound.
74: */
75:
76: for (mp = dot+1; mp < &message[msgCount]; mp++)
77: if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
78: break;
79: if (mp >= &message[msgCount]) {
80: printf("At EOF\n");
81: return(0);
82: }
83: dot = mp;
84: hitit:
85: /*
86: * Print dot.
87: */
88:
89: list[0] = dot - &message[0] + 1;
90: list[1] = NULL;
91: return(type(list));
92: }
93:
94: /*
95: * Save a message in a file. Mark the message as saved
96: * so we can discard when the user quits.
97: */
98: save(str)
99: char str[];
100: {
101:
102: return(save1(str, 1));
103: }
104:
105: /*
106: * Copy a message to a file without affected its saved-ness
107: */
108: copycmd(str)
109: char str[];
110: {
111:
112: return(save1(str, 0));
113: }
114:
115: /*
116: * Save/copy the indicated messages at the end of the passed file name.
117: * If mark is true, mark the message "saved."
118: */
119: save1(str, mark)
120: char str[];
121: {
122: register int *ip, mesg;
123: register struct message *mp;
124: char *file, *disp, *cmd;
125: int f, *msgvec, lc, t;
126: long cc;
127: FILE *obuf;
128: struct stat statb;
129:
130: cmd = mark ? "save" : "copy";
131: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
132: if ((file = snarf(str, &f)) == NOSTR)
133: return(1);
134: if (!f) {
135: *msgvec = first(0, MMNORM);
136: if (*msgvec == NULL) {
137: printf("No messages to %s.\n", cmd);
138: return(1);
139: }
140: msgvec[1] = NULL;
141: }
142: if (f && getmsglist(str, msgvec, 0) < 0)
143: return(1);
144: if ((file = expand(file)) == NOSTR)
145: return(1);
146: printf("\"%s\" ", file);
147: flush();
148: if (stat(file, &statb) >= 0)
149: disp = "[Appended]";
150: else
151: disp = "[New file]";
152: if ((obuf = fopen(file, "a")) == NULL) {
153: perror(NOSTR);
154: return(1);
155: }
156: cc = 0L;
157: lc = 0;
158: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
159: mesg = *ip;
160: touch(mesg);
161: mp = &message[mesg-1];
162: if ((t = send(mp, obuf, 0)) < 0) {
163: perror(file);
164: fclose(obuf);
165: return(1);
166: }
167: lc += t;
168: cc += mp->m_size;
169: if (mark)
170: mp->m_flag |= MSAVED;
171: }
172: fflush(obuf);
173: if (ferror(obuf))
174: perror(file);
175: fclose(obuf);
176: printf("%s %d/%ld\n", disp, lc, cc);
177: return(0);
178: }
179:
180: /*
181: * Write the indicated messages at the end of the passed
182: * file name, minus header and trailing blank line.
183: */
184:
185: swrite(str)
186: char str[];
187: {
188: register int *ip, mesg;
189: register struct message *mp;
190: register char *file, *disp;
191: char linebuf[BUFSIZ];
192: int f, *msgvec, lc, cc, t;
193: FILE *obuf, *mesf;
194: struct stat statb;
195:
196: msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
197: if ((file = snarf(str, &f)) == NOSTR)
198: return(1);
199: if ((file = expand(file)) == NOSTR)
200: return(1);
201: if (!f) {
202: *msgvec = first(0, MMNORM);
203: if (*msgvec == NULL) {
204: printf("No messages to write.\n");
205: return(1);
206: }
207: msgvec[1] = NULL;
208: }
209: if (f && getmsglist(str, msgvec, 0) < 0)
210: return(1);
211: printf("\"%s\" ", file);
212: flush();
213: if (stat(file, &statb) >= 0)
214: disp = "[Appended]";
215: else
216: disp = "[New file]";
217: if ((obuf = fopen(file, "a")) == NULL) {
218: perror(NOSTR);
219: return(1);
220: }
221: cc = lc = 0;
222: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
223: mesg = *ip;
224: touch(mesg);
225: mp = &message[mesg-1];
226: mesf = setinput(mp);
227: t = mp->m_lines - 2;
228: readline(mesf, linebuf);
229: while (t-- > 0) {
230: fgets(linebuf, BUFSIZ, mesf);
231: fputs(linebuf, obuf);
232: cc += strlen(linebuf);
233: }
234: lc += mp->m_lines - 2;
235: mp->m_flag |= MSAVED;
236: }
237: fflush(obuf);
238: if (ferror(obuf))
239: perror(file);
240: fclose(obuf);
241: printf("%s %d/%d\n", disp, lc, cc);
242: return(0);
243: }
244:
245: /*
246: * Snarf the file from the end of the command line and
247: * return a pointer to it. If there is no file attached,
248: * just return NOSTR. Put a null in front of the file
249: * name so that the message list processing won't see it,
250: * unless the file name is the only thing on the line, in
251: * which case, return 0 in the reference flag variable.
252: */
253:
254: char *
255: snarf(linebuf, flag)
256: char linebuf[];
257: int *flag;
258: {
259: register char *cp;
260:
261: *flag = 1;
262: cp = strlen(linebuf) + linebuf - 1;
263:
264: /*
265: * Strip away trailing blanks.
266: */
267:
268: while (*cp == ' ' && cp > linebuf)
269: cp--;
270: *++cp = 0;
271:
272: /*
273: * Now search for the beginning of the file name.
274: */
275:
276: while (cp > linebuf && !any(*cp, "\t "))
277: cp--;
278: if (*cp == '\0') {
279: printf("No file specified.\n");
280: return(NOSTR);
281: }
282: if (any(*cp, " \t"))
283: *cp++ = 0;
284: else
285: *flag = 0;
286: return(cp);
287: }
288:
289: /*
290: * Delete messages.
291: */
292:
293: delete(msgvec)
294: int msgvec[];
295: {
296: return(delm(msgvec));
297: }
298:
299: /*
300: * Delete messages, then type the new dot.
301: */
302:
303: deltype(msgvec)
304: int msgvec[];
305: {
306: int list[2];
307: int lastdot;
308:
309: lastdot = dot - &message[0] + 1;
310: if (delm(msgvec) >= 0) {
311: list[0] = dot - &message[0];
312: list[0]++;
313: if (list[0] > lastdot) {
314: touch(list[0]);
315: list[1] = NULL;
316: return(type(list));
317: }
318: printf("At EOF\n");
319: return(0);
320: }
321: else {
322: printf("No more messages\n");
323: return(0);
324: }
325: }
326:
327: /*
328: * Delete the indicated messages.
329: * Set dot to some nice place afterwards.
330: * Internal interface.
331: */
332:
333: delm(msgvec)
334: int *msgvec;
335: {
336: register struct message *mp;
337: register *ip, mesg;
338: int last;
339:
340: last = NULL;
341: for (ip = msgvec; *ip != NULL; ip++) {
342: mesg = *ip;
343: touch(mesg);
344: mp = &message[mesg-1];
345: mp->m_flag |= MDELETED|MTOUCH;
346: mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
347: last = mesg;
348: }
349: if (last != NULL) {
350: dot = &message[last-1];
351: last = first(0, MDELETED);
352: if (last != NULL) {
353: dot = &message[last-1];
354: return(0);
355: }
356: else {
357: dot = &message[0];
358: return(-1);
359: }
360: }
361:
362: /*
363: * Following can't happen -- it keeps lint happy
364: */
365:
366: return(-1);
367: }
368:
369: /*
370: * Undelete the indicated messages.
371: */
372:
373: undelete(msgvec)
374: int *msgvec;
375: {
376: register struct message *mp;
377: register *ip, mesg;
378:
379: for (ip = msgvec; ip-msgvec < msgCount; ip++) {
380: mesg = *ip;
381: if (mesg == 0)
382: return;
383: touch(mesg);
384: mp = &message[mesg-1];
385: dot = mp;
386: mp->m_flag &= ~MDELETED;
387: }
388: }
389:
390: /*
391: * Interactively dump core on "core"
392: */
393:
394: core()
395: {
396: register int pid;
397: int status;
398:
399: if ((pid = vfork()) == -1) {
400: perror("fork");
401: return(1);
402: }
403: if (pid == 0) {
404: sigchild();
405: abort();
406: _exit(1);
407: }
408: printf("Okie dokie");
409: fflush(stdout);
410: while (wait(&status) != pid)
411: ;
412: if (status & 0200)
413: printf(" -- Core dumped\n");
414: else
415: printf("\n");
416: }
417:
418: /*
419: * Clobber as many bytes of stack as the user requests.
420: */
421: clobber(argv)
422: char **argv;
423: {
424: register int times;
425:
426: if (argv[0] == 0)
427: times = 1;
428: else
429: times = (atoi(argv[0]) + 511) / 512;
430: clob1(times);
431: }
432:
433: /*
434: * Clobber the stack.
435: */
436: clob1(n)
437: {
438: char buf[512];
439: register char *cp;
440:
441: if (n <= 0)
442: return;
443: for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
444: ;
445: clob1(n - 1);
446: }
447:
448: /*
449: * Add the given header fields to the ignored list.
450: * If no arguments, print the current list of ignored fields.
451: */
452: igfield(list)
453: char *list[];
454: {
455: char field[BUFSIZ];
456: register int h;
457: register struct ignore *igp;
458: char **ap;
459:
460: if (argcount(list) == 0)
461: return(igshow());
462: for (ap = list; *ap != 0; ap++) {
463: if (isign(*ap))
464: continue;
465: istrcpy(field, *ap);
466: h = hash(field);
467: igp = (struct ignore *) calloc(1, sizeof (struct ignore));
468: igp->i_field = calloc(strlen(field) + 1, sizeof (char));
469: strcpy(igp->i_field, field);
470: igp->i_link = ignore[h];
471: ignore[h] = igp;
472: }
473: return(0);
474: }
475:
476: /*
477: * Print out all currently ignored fields.
478: */
479: igshow()
480: {
481: register int h, count;
482: struct ignore *igp;
483: char **ap, **ring;
484: int igcomp();
485:
486: count = 0;
487: for (h = 0; h < HSHSIZE; h++)
488: for (igp = ignore[h]; igp != 0; igp = igp->i_link)
489: count++;
490: if (count == 0) {
491: printf("No fields currently being ignored.\n");
492: return(0);
493: }
494: ring = (char **) salloc((count + 1) * sizeof (char *));
495: ap = ring;
496: for (h = 0; h < HSHSIZE; h++)
497: for (igp = ignore[h]; igp != 0; igp = igp->i_link)
498: *ap++ = igp->i_field;
499: *ap = 0;
500: qsort(ring, count, sizeof (char *), igcomp);
501: for (ap = ring; *ap != 0; ap++)
502: printf("%s\n", *ap);
503: return(0);
504: }
505:
506: /*
507: * Compare two names for sorting ignored field list.
508: */
509: igcomp(l, r)
510: char **l, **r;
511: {
512:
513: return(strcmp(*l, *r));
514: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.