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