|
|
1.1 root 1: #ident "@(#)cmd1.c 1.5 'attmail mail(1) command'"
2: #ident "@(#)mailx:cmd1.c 1.7.1.1"
3: /* Copyright (c) 1984 AT&T */
4: /* All Rights Reserved */
5:
6: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
7: /* The copyright notice above does not evidence any */
8: /* actual or intended publication of such source code. */
9:
10: #ident "@(#)mailx:cmd1.c 1.7"
11:
12: #include "rcv.h"
13:
14: /*
15: * mailx -- a modified version of a University of California at Berkeley
16: * mail program
17: *
18: * User commands.
19: */
20:
21: static void brokpipe();
22: static char *dispname();
23: static void print();
24: static int screensize();
25: static int type1();
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 curscreen = 0, oldscreensize = 0;
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: curscreen = (n-1)/size;
45: if (curscreen < 0)
46: curscreen = 0;
47: mp = &message[curscreen * 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: if (Hflag)
57: mp = message;
58: for (; mp < &message[msgCount]; mp++) {
59: mesg++;
60: if (mp->m_flag & MDELETED)
61: continue;
62: if (flag++ >= size && !Hflag)
63: break;
64: printhead(mesg);
65: sreset();
66: }
67: if (flag == 0) {
68: printf("No more mail.\n");
69: return(1);
70: }
71: return(0);
72: }
73:
74: /*
75: * Scroll to the next/previous screen
76: */
77:
78: scroll(arg)
79: char arg[];
80: {
81: register int s, size;
82: int cur[1];
83:
84: cur[0] = 0;
85: size = screensize();
86: s = curscreen;
87: switch (*arg) {
88: case 0:
89: case '+':
90: s++;
91: if (s * size > msgCount) {
92: printf("On last screenful of messages\n");
93: return(0);
94: }
95: curscreen = s;
96: break;
97:
98: case '-':
99: if (--s < 0) {
100: printf("On first screenful of messages\n");
101: return(0);
102: }
103: curscreen = s;
104: break;
105:
106: default:
107: printf("Unrecognized scrolling command \"%s\"\n", arg);
108: return(1);
109: }
110: return(headers(cur));
111: }
112:
113: /*
114: * Compute what the screen size should be.
115: * We use the following algorithm:
116: * If user specifies with screen option, use that.
117: * If baud rate < 1200, use 5
118: * If baud rate = 1200, use 10
119: * If baud rate > 1200, use 20
120: * the variable 'baud' has screensize encoded into it
121: */
122: static int
123: screensize()
124: {
125: register char *cp;
126: register int newscreensize, tmp;
127:
128: cp = value("screen");
129: newscreensize = ((cp != NOSTR) && ((tmp = atoi(cp)) > 0)) ? tmp : baud;
130: /* renormalize the value of curscreen */
131: if (newscreensize != oldscreensize) {
132: curscreen = curscreen * oldscreensize / newscreensize;
133: oldscreensize = newscreensize;
134: }
135: return(newscreensize);
136: }
137:
138: /*
139: * Print out the headlines for each message
140: * in the passed message list.
141: */
142:
143: from(msgvec)
144: int *msgvec;
145: {
146: register int *ip;
147:
148: for (ip = msgvec; *ip != NULL; ip++) {
149: printhead(*ip);
150: sreset();
151: }
152: if (--ip >= msgvec)
153: dot = &message[*ip - 1];
154: return(0);
155: }
156:
157: /*
158: * Print out the header of a specific message.
159: * This is a slight improvement to the standard one.
160: */
161:
162: void
163: printhead(mesg)
164: {
165: struct message *mp;
166: FILE *ibuf;
167: char headline[LINESIZE], *subjline, dispc, curind;
168: char *fromline;
169: char pbuf[LINESIZE];
170: char name[LINESIZE];
171: struct headline hl;
172: register char *cp;
173: int showto;
174:
175: mp = &message[mesg-1];
176: ibuf = setinput(mp);
177: readline(ibuf, headline);
178: if ((subjline = hfield("subject", mp, addone)) == NOSTR
179: && (subjline = hfield("subj", mp, addone)) == NOSTR
180: && (subjline = hfield("message-status", mp, addone)) == NOSTR)
181: subjline = "";
182:
183: curind = (!Hflag && dot == mp) ? '>' : ' ';
184: dispc = ' ';
185: showto = 0;
186: if ((mp->m_flag & (MREAD|MNEW)) == (MREAD|MNEW))
187: dispc = 'R';
188: if ((mp->m_flag & (MREAD|MNEW)) == MREAD)
189: dispc = 'O';
190: if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
191: dispc = 'N';
192: if ((mp->m_flag & (MREAD|MNEW)) == 0)
193: dispc = 'U';
194: if (mp->m_flag & MSAVED)
195: dispc = 'S';
196: if (mp->m_flag & MPRESERVE)
197: dispc = 'H';
198: if (mp->m_flag & MBOX)
199: dispc = 'M';
200: parse(headline, &hl, pbuf);
201:
202: /*
203: * Netnews interface?
204: */
205:
206: if (newsflg) {
207: if ( (fromline=hfield("newsgroups",mp,addone)) == NOSTR /* A */
208: && (fromline=hfield("article-id",mp,addone)) == NOSTR ) /* B */
209: fromline = "<>";
210: else
211: for(cp=fromline; *cp; cp++) { /* limit length */
212: if( any(*cp, " ,\n")){
213: *cp = '\0';
214: break;
215: }
216: }
217: /*
218: * else regular.
219: */
220:
221: } else {
222: fromline = nameof(mp);
223: if (value("showto") && samebody(myname, skin(fromline))
224: && (cp = hfield("to", mp, addto))) {
225: showto = 1;
226: yankword(cp, fromline = name, docomma(cp));
227: }
228: fromline = dispname(fromline);
229: }
230: printf("%c%c%3d ", curind, dispc, mesg);
231: if (showto)
232: printf("To %-15.15s ", fromline);
233: else
234: printf("%-18.18s ", fromline);
235: if (mp->m_text) {
236: printf("%16.16s %4ld/%-5ld %-.25s\n",
237: hl.l_date, mp->m_lines, mp->m_size, subjline);
238: } else {
239: printf("%16.16s binary/%-5ld %-.25s\n", hl.l_date, mp->m_size, subjline);
240: }
241: }
242:
243: /*
244: * Return the full name from an RFC-822 header line
245: * or the last two (or one) component of the address.
246: */
247:
248: static char *
249: dispname(hdr)
250: char *hdr;
251: {
252: char *cp, *cp2;
253:
254: if (hdr == 0)
255: return 0;
256: if (cp = strchr(hdr, '<')) {
257: /* if name field is of the form
258: Any Name <addr-spec>
259: return Any Name. If it's
260: "Any Name" <addr-spec>
261: return Any Name (strip off quotes).
262: Otherwise, return addr-spec
263: */
264: if (cp == hdr) { /* adb */
265: if (cp = strrchr(hdr, '>')) /* adb */
266: *cp = 0; /* adb */
267: } /* adb */
268: else if (*hdr == '"' && (cp = strrchr(++hdr, '"'))) { /* adb */
269: *cp = 0; /* adb */
270: } /* adb */
271: else *cp = 0; /* adb */
272: return hdr;
273: } else if (cp = strchr(hdr, '(')) {
274: hdr = ++cp;
275: if (cp = strchr(hdr, '+'))
276: *cp = 0;
277: if (cp = strrchr(hdr, ')'))
278: *cp = 0;
279: return hdr;
280: }
281: cp = skin(hdr);
282: if (cp2 = strrchr(cp, '!')) {
283: while (cp2 >= cp && *--cp2 != '!');
284: cp = ++cp2;
285: }
286: return cp;
287: }
288:
289: /*
290: * Print out the value of dot.
291: */
292:
293: pdot()
294: {
295: printf("%d\n", dot - &message[0] + 1);
296: return(0);
297: }
298:
299: /*
300: * Print out all the possible commands.
301: */
302:
303: pcmdlist()
304: {
305: register struct cmd *cp;
306: register int cc;
307:
308: printf("Commands are:\n");
309: for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
310: cc += strlen(cp->c_name) + 2;
311: if (cc > 72) {
312: printf("\n");
313: cc = strlen(cp->c_name) + 2;
314: }
315: if ((cp+1)->c_name != NOSTR)
316: printf("%s, ", cp->c_name);
317: else
318: printf("%s\n", cp->c_name);
319: }
320: return(0);
321: }
322:
323: /*
324: * Type out messages, honor ignored fields.
325: */
326: type(msgvec)
327: int *msgvec;
328: {
329:
330: return(type1(msgvec, 1));
331: }
332:
333: /*
334: * Type out messages, even printing ignored fields.
335: */
336: Type(msgvec)
337: int *msgvec;
338: {
339:
340: return(type1(msgvec, 0));
341: }
342:
343: /*
344: * Type out the messages requested.
345: */
346: static jmp_buf pipestop;
347:
348: static int
349: type1(msgvec, doign)
350: int *msgvec;
351: {
352: register *ip;
353: register struct message *mp;
354: register int mesg;
355: register char *cp;
356: long nlines;
357: FILE *obuf;
358: void (*sigint)(), (*sigpipe)();
359: int setsigs = 0;
360:
361: obuf = stdout;
362: if (setjmp(pipestop)) {
363: if (obuf != stdout) {
364: pipef = NULL;
365: npclose(obuf);
366: }
367: goto ret0;
368: }
369: if (intty && outtty && (cp = value("crt")) != NOSTR) {
370: for (ip = msgvec, nlines = 0; *ip && ip-msgvec < msgCount; ip++)
371: nlines += message[*ip - 1].m_lines;
372: if (nlines > atoi(cp)) {
373: char *pg = PG;
374: pg = (pg && *pg) ? pg : "cat";
375: if ((obuf = npopen(pg, "w")) == NULL) {
376: perror(pg);
377: obuf = stdout;
378: } else {
379: pipef = obuf;
380: sigint = sigset(SIGINT, SIG_IGN);
381: sigpipe = sigset(SIGPIPE, brokpipe);
382: setsigs++;
383: }
384: }
385: }
386: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
387: mesg = *ip;
388: touch(mesg);
389: mp = &message[mesg-1];
390: dot = mp;
391: print(mp, obuf, doign);
392: }
393: if (obuf != stdout) {
394: pipef = NULL;
395: npclose(obuf);
396: }
397: ret0:
398: if (setsigs) {
399: sigset(SIGPIPE, sigpipe);
400: sigset(SIGINT, sigint);
401: }
402: return(0);
403: }
404:
405: /*
406: * Respond to a broken pipe signal --
407: * probably caused by user quitting pg.
408: */
409: static void
410: brokpipe()
411: {
412: sigrelse(SIGPIPE);
413: longjmp(pipestop, 1);
414: }
415:
416: /*
417: * Print the indicated message on standard output.
418: */
419:
420: static void
421: print(mp, obuf, doign)
422: register struct message *mp;
423: FILE *obuf;
424: {
425:
426: if (!doign || !isign("message"))
427: fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1);
428: touch(mp - &message[0] + 1);
429: /*
430: * in Area 10 world, no one has ordinary terminals. Everyone has terminal emulators.
431: * So don't worry about binary files. Print 'em anyway.
432: if (mp->m_text) {
433: send(mp, obuf, doign);
434: } else {
435: fprintf(obuf, "\n%s\n", binmsg);
436: }
437: */
438: send(mp, obuf, doign);
439: }
440:
441: /*
442: * Print the top so many lines of each desired message.
443: * The number of lines is taken from the variable "toplines"
444: * and defaults to 5.
445: */
446:
447: top(msgvec)
448: int *msgvec;
449: {
450: register int *ip;
451: register struct message *mp;
452: register int mesg;
453: int topl, lineb;
454: long c, lines;
455: char *valtop, linebuf[LINESIZE];
456: FILE *ibuf;
457:
458: topl = 5;
459: valtop = value("toplines");
460: if (valtop != NOSTR) {
461: topl = atoi(valtop);
462: if (topl < 0 || topl > 10000)
463: topl = 5;
464: }
465: lineb = 1;
466: for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
467: mesg = *ip;
468: touch(mesg);
469: mp = &message[mesg-1];
470: dot = mp;
471: if (value("quiet") == NOSTR)
472: printf("Message %d:\n", mesg);
473: /*
474: * print even binary messages
475: *
476: if (mp->m_text) {
477: */
478: ibuf = setinput(mp);
479: c = mp->m_lines;
480: if (!lineb)
481: printf("\n");
482: for (lines = 0; lines < c && lines < topl; lines++) {
483: if (readline(ibuf, linebuf) <= 0)
484: break;
485: puts(linebuf);
486: lineb = blankline(linebuf);
487: }
488: /*
489: } else {
490: printf("\n%s\n", binmsg);
491: }
492: */
493: }
494: return(0);
495: }
496:
497: /*
498: * Touch all the given messages so that they will
499: * get mboxed.
500: */
501:
502: stouch(msgvec)
503: int msgvec[];
504: {
505: register int *ip;
506:
507: for (ip = msgvec; *ip != 0; ip++) {
508: dot = &message[*ip-1];
509: dot->m_flag |= MTOUCH;
510: dot->m_flag &= ~MPRESERVE;
511: }
512: return(0);
513: }
514:
515: /*
516: * Make sure all passed messages get mboxed.
517: */
518:
519: mboxit(msgvec)
520: int msgvec[];
521: {
522: register int *ip;
523:
524: for (ip = msgvec; *ip != 0; ip++) {
525: dot = &message[*ip-1];
526: dot->m_flag |= MTOUCH|MBOX;
527: dot->m_flag &= ~MPRESERVE;
528: }
529: return(0);
530: }
531:
532: /*
533: * List the folders the user currently has.
534: */
535: folders()
536: {
537: char dirname[BUFSIZ], cmd[BUFSIZ];
538:
539: if (getfold(dirname) < 0) {
540: printf("No value set for \"folder\"\n");
541: return(-1);
542: }
543: sprintf(cmd, "%s %s", LS, dirname);
544: return(system(cmd));
545: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.