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