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