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