|
|
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[] = "@(#)cmd1.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: * User commands.
25: */
26:
27: /*
28: * Print the current active headings.
29: * Don't change dot if invoker didn't give an argument.
30: */
31:
32: static int screen;
33:
34: headers(msgvec)
35: int *msgvec;
36: {
37: register int n, mesg, flag;
38: register struct message *mp;
39: int size;
40:
41: size = screensize();
42: n = msgvec[0];
43: if (n != 0)
44: screen = (n-1)/size;
45: if (screen < 0)
46: screen = 0;
47: mp = &message[screen * size];
48: if (mp >= &message[msgCount])
49: mp = &message[msgCount - size];
50: if (mp < &message[0])
51: mp = &message[0];
52: flag = 0;
53: mesg = mp - &message[0];
54: if (dot != &message[n-1])
55: dot = mp;
56: for (; mp < &message[msgCount]; mp++) {
57: mesg++;
58: if (mp->m_flag & MDELETED)
59: continue;
60: if (flag++ >= size)
61: break;
62: printhead(mesg);
63: sreset();
64: }
65: if (flag == 0) {
66: printf("No more mail.\n");
67: return(1);
68: }
69: return(0);
70: }
71:
72: /*
73: * Set the list of alternate names for out host.
74: */
75: local(namelist)
76: char **namelist;
77: {
78: register int c;
79: register char **ap, **ap2, *cp;
80:
81: c = argcount(namelist) + 1;
82: if (c == 1) {
83: if (localnames == 0)
84: return(0);
85: for (ap = localnames; *ap; ap++)
86: printf("%s ", *ap);
87: printf("\n");
88: return(0);
89: }
90: if (localnames != 0)
91: cfree((char *) localnames);
92: localnames = (char **) calloc((unsigned) c, sizeof (char *));
93: for (ap = namelist, ap2 = localnames; *ap; ap++, ap2++) {
94: cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char));
95: strcpy(cp, *ap);
96: *ap2 = cp;
97: }
98: *ap2 = 0;
99: return(0);
100: }
101:
102: /*
103: * Scroll to the next/previous screen
104: */
105:
106: scroll(arg)
107: char arg[];
108: {
109: register int s, size;
110: int cur[1];
111:
112: cur[0] = 0;
113: size = screensize();
114: s = screen;
115: switch (*arg) {
116: case 0:
117: case '+':
118: s++;
119: if (s * size > msgCount) {
120: printf("On last screenful of messages\n");
121: return(0);
122: }
123: screen = s;
124: break;
125:
126: case '-':
127: if (--s < 0) {
128: printf("On first screenful of messages\n");
129: return(0);
130: }
131: screen = s;
132: break;
133:
134: default:
135: printf("Unrecognized scrolling command \"%s\"\n", arg);
136: return(1);
137: }
138: return(headers(cur));
139: }
140:
141: /*
142: * Compute screen size.
143: */
144: screensize()
145: {
146: int s;
147: char *cp;
148:
149: if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0)
150: return s;
151: return screenheight - 4;
152: }
153:
154: /*
155: * Print out the headlines for each message
156: * in the passed message list.
157: */
158:
159: from(msgvec)
160: int *msgvec;
161: {
162: register int *ip;
163:
164: for (ip = msgvec; *ip != NULL; ip++) {
165: printhead(*ip);
166: sreset();
167: }
168: if (--ip >= msgvec)
169: dot = &message[*ip - 1];
170: return(0);
171: }
172:
173: /*
174: * Print out the header of a specific message.
175: * This is a slight improvement to the standard one.
176: */
177:
178: printhead(mesg)
179: {
180: struct message *mp;
181: char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
182: char pbuf[BUFSIZ];
183: struct headline hl;
184: int subjlen;
185:
186: mp = &message[mesg-1];
187: readline(setinput(mp), headline);
188: if ((subjline = hfield("subject", mp)) == NOSTR)
189: subjline = hfield("subj", mp);
190: /*
191: * Bletch!
192: */
193: curind = dot == mp ? '>' : ' ';
194: dispc = ' ';
195: if (mp->m_flag & MSAVED)
196: dispc = '*';
197: if (mp->m_flag & MPRESERVE)
198: dispc = 'P';
199: if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
200: dispc = 'N';
201: if ((mp->m_flag & (MREAD|MNEW)) == 0)
202: dispc = 'U';
203: if (mp->m_flag & MBOX)
204: dispc = 'M';
205: parse(headline, &hl, pbuf);
206: sprintf(wcount, "%3d/%-4ld", mp->m_lines, mp->m_size);
207: subjlen = screenwidth - 50 - strlen(wcount);
208: if (subjline == NOSTR || subjlen < 0) /* pretty pathetic */
209: printf("%c%c%3d %-20.20s %16.16s %s\n",
210: curind, dispc, mesg, nameof(mp, 0), hl.l_date, wcount);
211: else
212: printf("%c%c%3d %-20.20s %16.16s %s \"%.*s\"\n",
213: curind, dispc, mesg, nameof(mp, 0), hl.l_date, wcount,
214: subjlen, subjline);
215: }
216:
217: /*
218: * Print out the value of dot.
219: */
220:
221: pdot()
222: {
223: printf("%d\n", dot - &message[0] + 1);
224: return(0);
225: }
226:
227: /*
228: * Print out all the possible commands.
229: */
230:
231: pcmdlist()
232: {
233: register struct cmd *cp;
234: register int cc;
235: extern struct cmd cmdtab[];
236:
237: printf("Commands are:\n");
238: for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
239: cc += strlen(cp->c_name) + 2;
240: if (cc > 72) {
241: printf("\n");
242: cc = strlen(cp->c_name) + 2;
243: }
244: if ((cp+1)->c_name != NOSTR)
245: printf("%s, ", cp->c_name);
246: else
247: printf("%s\n", cp->c_name);
248: }
249: return(0);
250: }
251:
252: /*
253: * Paginate messages, honor ignored fields.
254: */
255: more(msgvec)
256: int *msgvec;
257: {
258: return (type1(msgvec, 1, 1));
259: }
260:
261: /*
262: * Paginate messages, even printing ignored fields.
263: */
264: More(msgvec)
265: int *msgvec;
266: {
267:
268: return (type1(msgvec, 0, 1));
269: }
270:
271: /*
272: * Type out messages, honor ignored fields.
273: */
274: type(msgvec)
275: int *msgvec;
276: {
277:
278: return(type1(msgvec, 1, 0));
279: }
280:
281: /*
282: * Type out messages, even printing ignored fields.
283: */
284: Type(msgvec)
285: int *msgvec;
286: {
287:
288: return(type1(msgvec, 0, 0));
289: }
290:
291: /*
292: * Type out the messages requested.
293: */
294: jmp_buf pipestop;
295:
296: type1(msgvec, doign, page)
297: int *msgvec;
298: {
299: register *ip;
300: register struct message *mp;
301: register int mesg;
302: register char *cp;
303: int nlines;
304: int brokpipe();
305: FILE *obuf;
306:
307: obuf = stdout;
308: if (setjmp(pipestop)) {
309: if (obuf != stdout) {
310: pipef = NULL;
311: pclose(obuf);
312: }
313: signal(SIGPIPE, SIG_DFL);
314: return(0);
315: }
316: if (intty && outtty && (page || (cp = value("crt")) != NOSTR)) {
317: nlines = 0;
318: if (!page) {
319: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
320: nlines += message[*ip - 1].m_lines;
321: }
322: if (page || nlines > atoi(cp)) {
323: cp = value("PAGER");
324: if (cp == NULL || *cp == '\0')
325: cp = MORE;
326: obuf = popen(cp, "w");
327: if (obuf == NULL) {
328: perror(cp);
329: obuf = stdout;
330: } else {
331: pipef = obuf;
332: signal(SIGPIPE, brokpipe);
333: }
334: }
335: }
336: for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
337: mesg = *ip;
338: touch(mesg);
339: mp = &message[mesg-1];
340: dot = mp;
341: if (value("quiet") == NOSTR)
342: fprintf(obuf, "Message %d:\n", mesg);
343: send(mp, obuf, doign);
344: }
345: if (obuf != stdout) {
346: pipef = NULL;
347: pclose(obuf);
348: }
349: signal(SIGPIPE, SIG_DFL);
350: return(0);
351: }
352:
353: /*
354: * Respond to a broken pipe signal --
355: * probably caused by using quitting more.
356: */
357:
358: brokpipe()
359: {
360: longjmp(pipestop, 1);
361: }
362:
363: /*
364: * Print the top so many lines of each desired message.
365: * The number of lines is taken from the variable "toplines"
366: * and defaults to 5.
367: */
368:
369: top(msgvec)
370: int *msgvec;
371: {
372: register int *ip;
373: register struct message *mp;
374: register int mesg;
375: int c, topl, lines, lineb;
376: char *valtop, linebuf[LINESIZE];
377: FILE *ibuf;
378:
379: topl = 5;
380: valtop = value("toplines");
381: if (valtop != NOSTR) {
382: topl = atoi(valtop);
383: if (topl < 0 || topl > 10000)
384: topl = 5;
385: }
386: lineb = 1;
387: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
388: mesg = *ip;
389: touch(mesg);
390: mp = &message[mesg-1];
391: dot = mp;
392: if (value("quiet") == NOSTR)
393: printf("Message %2d:\n", mesg);
394: ibuf = setinput(mp);
395: c = mp->m_lines;
396: if (!lineb)
397: printf("\n");
398: for (lines = 0; lines < c && lines <= topl; lines++) {
399: if (readline(ibuf, linebuf) < 0)
400: break;
401: puts(linebuf);
402: lineb = blankline(linebuf);
403: }
404: }
405: return(0);
406: }
407:
408: /*
409: * Touch all the given messages so that they will
410: * get mboxed.
411: */
412:
413: stouch(msgvec)
414: int msgvec[];
415: {
416: register int *ip;
417:
418: for (ip = msgvec; *ip != 0; ip++) {
419: dot = &message[*ip-1];
420: dot->m_flag |= MTOUCH;
421: dot->m_flag &= ~MPRESERVE;
422: }
423: return(0);
424: }
425:
426: /*
427: * Make sure all passed messages get mboxed.
428: */
429:
430: mboxit(msgvec)
431: int msgvec[];
432: {
433: register int *ip;
434:
435: for (ip = msgvec; *ip != 0; ip++) {
436: dot = &message[*ip-1];
437: dot->m_flag |= MTOUCH|MBOX;
438: dot->m_flag &= ~MPRESERVE;
439: }
440: return(0);
441: }
442:
443: /*
444: * List the folders the user currently has.
445: */
446: folders()
447: {
448: char dirname[BUFSIZ];
449: int pid, e;
450: union wait s;
451:
452: if (getfold(dirname) < 0) {
453: printf("No value set for \"folder\"\n");
454: return(-1);
455: }
456: switch ((pid = fork())) {
457: case 0:
458: execlp("ls", "ls", dirname, 0);
459: _exit(1);
460:
461: case -1:
462: perror("fork");
463: return(-1);
464:
465: default:
466: while ((e = wait(&s)) != -1 && e != pid)
467: ;
468: }
469: return(0);
470: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.