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