BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / mail / cmd1.c
CommitLineData
d3dde041
EW
1/*-
2 * Copyright (c) 1980 The Regents of the University of California.
0c5f72fb
KB
3 * All rights reserved.
4 *
1c15e888
C
5 * Redistribution and use in source and binary forms are permitted provided
6 * that: (1) source distributions retain this entire copyright notice and
7 * comment, and (2) distributions including binaries display the following
8 * acknowledgement: ``This product includes software developed by the
9 * University of California, Berkeley and its contributors'' in the
10 * documentation or other materials provided with the distribution and in
11 * all advertising materials mentioning features or use of this software.
12 * Neither the name of the University nor the names of its contributors may
13 * be used to endorse or promote products derived from this software without
14 * specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
b059c7be
DF
18 */
19
acfc7e9b 20#ifndef lint
1c15e888 21static char sccsid[] = "@(#)cmd1.c 5.21 (Berkeley) 6/25/90";
acfc7e9b 22#endif /* not lint */
2ae9f53f 23
d702437a 24#include "rcv.h"
d702437a
KS
25
26/*
27 * Mail -- a mail program
28 *
29 * User commands.
30 */
31
d702437a
KS
32/*
33 * Print the current active headings.
f75dd1e5 34 * Don't change dot if invoker didn't give an argument.
d702437a
KS
35 */
36
37static int screen;
38
39headers(msgvec)
40 int *msgvec;
41{
42 register int n, mesg, flag;
43 register struct message *mp;
1491ef97 44 int size;
d702437a 45
1491ef97 46 size = screensize();
d702437a
KS
47 n = msgvec[0];
48 if (n != 0)
1491ef97 49 screen = (n-1)/size;
d702437a
KS
50 if (screen < 0)
51 screen = 0;
1491ef97 52 mp = &message[screen * size];
d702437a 53 if (mp >= &message[msgCount])
1491ef97 54 mp = &message[msgCount - size];
d702437a
KS
55 if (mp < &message[0])
56 mp = &message[0];
57 flag = 0;
58 mesg = mp - &message[0];
f75dd1e5
KS
59 if (dot != &message[n-1])
60 dot = mp;
d702437a
KS
61 for (; mp < &message[msgCount]; mp++) {
62 mesg++;
63 if (mp->m_flag & MDELETED)
64 continue;
1491ef97 65 if (flag++ >= size)
d702437a
KS
66 break;
67 printhead(mesg);
d702437a
KS
68 }
69 if (flag == 0) {
70 printf("No more mail.\n");
71 return(1);
72 }
73 return(0);
74}
75
76/*
77 * Scroll to the next/previous screen
78 */
d702437a
KS
79scroll(arg)
80 char arg[];
81{
1491ef97 82 register int s, size;
d702437a
KS
83 int cur[1];
84
85 cur[0] = 0;
1491ef97 86 size = screensize();
d702437a
KS
87 s = screen;
88 switch (*arg) {
89 case 0:
90 case '+':
91 s++;
1491ef97 92 if (s * size > msgCount) {
d702437a
KS
93 printf("On last screenful of messages\n");
94 return(0);
95 }
96 screen = s;
97 break;
98
99 case '-':
100 if (--s < 0) {
101 printf("On first screenful of messages\n");
102 return(0);
103 }
104 screen = s;
105 break;
106
107 default:
108 printf("Unrecognized scrolling command \"%s\"\n", arg);
109 return(1);
110 }
111 return(headers(cur));
112}
113
1491ef97 114/*
828615a1 115 * Compute screen size.
1491ef97
KS
116 */
117screensize()
118{
828615a1
EW
119 int s;
120 char *cp;
121
122 if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0)
123 return s;
124 return screenheight - 4;
1491ef97 125}
d702437a
KS
126
127/*
128 * Print out the headlines for each message
129 * in the passed message list.
130 */
131
132from(msgvec)
133 int *msgvec;
134{
135 register int *ip;
136
f674e088 137 for (ip = msgvec; *ip != NULL; ip++)
d702437a 138 printhead(*ip);
d702437a
KS
139 if (--ip >= msgvec)
140 dot = &message[*ip - 1];
141 return(0);
142}
143
144/*
145 * Print out the header of a specific message.
146 * This is a slight improvement to the standard one.
147 */
148
149printhead(mesg)
150{
151 struct message *mp;
2d7425cf 152 char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
d702437a 153 char pbuf[BUFSIZ];
d702437a 154 struct headline hl;
828615a1 155 int subjlen;
d3dde041 156 char *name;
d702437a
KS
157
158 mp = &message[mesg-1];
38ed7007 159 (void) readline(setinput(mp), headline, LINESIZE);
828615a1 160 if ((subjline = hfield("subject", mp)) == NOSTR)
d702437a 161 subjline = hfield("subj", mp);
d702437a
KS
162 /*
163 * Bletch!
164 */
f75dd1e5 165 curind = dot == mp ? '>' : ' ';
d702437a
KS
166 dispc = ' ';
167 if (mp->m_flag & MSAVED)
168 dispc = '*';
169 if (mp->m_flag & MPRESERVE)
170 dispc = 'P';
5bfbbe88 171 if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
f4d36a07 172 dispc = 'N';
5bfbbe88
KS
173 if ((mp->m_flag & (MREAD|MNEW)) == 0)
174 dispc = 'U';
f2230dfd
KS
175 if (mp->m_flag & MBOX)
176 dispc = 'M';
d702437a 177 parse(headline, &hl, pbuf);
d3dde041 178 sprintf(wcount, "%3d/%-5ld", mp->m_lines, mp->m_size);
828615a1 179 subjlen = screenwidth - 50 - strlen(wcount);
d3dde041
EW
180 name = value("show-rcpt") != NOSTR ?
181 skin(hfield("to", mp)) : nameof(mp, 0);
828615a1
EW
182 if (subjline == NOSTR || subjlen < 0) /* pretty pathetic */
183 printf("%c%c%3d %-20.20s %16.16s %s\n",
d3dde041 184 curind, dispc, mesg, name, hl.l_date, wcount);
d702437a 185 else
828615a1 186 printf("%c%c%3d %-20.20s %16.16s %s \"%.*s\"\n",
d3dde041 187 curind, dispc, mesg, name, hl.l_date, wcount,
828615a1 188 subjlen, subjline);
d702437a
KS
189}
190
191/*
192 * Print out the value of dot.
193 */
194
195pdot()
196{
197 printf("%d\n", dot - &message[0] + 1);
198 return(0);
199}
200
201/*
202 * Print out all the possible commands.
203 */
204
205pcmdlist()
206{
207 register struct cmd *cp;
208 register int cc;
209 extern struct cmd cmdtab[];
210
211 printf("Commands are:\n");
212 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
213 cc += strlen(cp->c_name) + 2;
214 if (cc > 72) {
215 printf("\n");
216 cc = strlen(cp->c_name) + 2;
217 }
218 if ((cp+1)->c_name != NOSTR)
219 printf("%s, ", cp->c_name);
220 else
221 printf("%s\n", cp->c_name);
222 }
223 return(0);
224}
225
b041ccec
S
226/*
227 * Paginate messages, honor ignored fields.
228 */
229more(msgvec)
230 int *msgvec;
231{
232 return (type1(msgvec, 1, 1));
233}
234
235/*
236 * Paginate messages, even printing ignored fields.
237 */
238More(msgvec)
239 int *msgvec;
240{
241
242 return (type1(msgvec, 0, 1));
243}
244
d702437a 245/*
15bff4bb 246 * Type out messages, honor ignored fields.
d702437a 247 */
15bff4bb
KS
248type(msgvec)
249 int *msgvec;
250{
d702437a 251
b041ccec 252 return(type1(msgvec, 1, 0));
15bff4bb
KS
253}
254
255/*
256 * Type out messages, even printing ignored fields.
257 */
258Type(msgvec)
259 int *msgvec;
260{
261
b041ccec 262 return(type1(msgvec, 0, 0));
15bff4bb
KS
263}
264
265/*
266 * Type out the messages requested.
267 */
740867ff
KS
268jmp_buf pipestop;
269
b041ccec 270type1(msgvec, doign, page)
d702437a
KS
271 int *msgvec;
272{
273 register *ip;
274 register struct message *mp;
740867ff 275 register char *cp;
828615a1 276 int nlines;
740867ff 277 int brokpipe();
828615a1 278 FILE *obuf;
740867ff
KS
279
280 obuf = stdout;
07b0d286
EW
281 if (setjmp(pipestop))
282 goto close_pipe;
686f6134
EW
283 if (value("interactive") != NOSTR &&
284 (page || (cp = value("crt")) != NOSTR)) {
2d7425cf 285 nlines = 0;
b041ccec 286 if (!page) {
b041ccec
S
287 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
288 nlines += message[*ip - 1].m_lines;
289 }
d56fd190 290 if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
2d7425cf
S
291 cp = value("PAGER");
292 if (cp == NULL || *cp == '\0')
435e8dff 293 cp = _PATH_MORE;
d96977db 294 obuf = Popen(cp, "w");
740867ff 295 if (obuf == NULL) {
2d7425cf 296 perror(cp);
740867ff 297 obuf = stdout;
07b0d286 298 } else
828615a1 299 signal(SIGPIPE, brokpipe);
740867ff
KS
300 }
301 }
828615a1 302 for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
470c33f3
EW
303 mp = &message[*ip - 1];
304 touch(mp);
d702437a 305 dot = mp;
828615a1 306 if (value("quiet") == NOSTR)
470c33f3 307 fprintf(obuf, "Message %d:\n", *ip);
2de8fc95 308 (void) send(mp, obuf, doign ? ignore : 0, NOSTR);
740867ff 309 }
07b0d286 310close_pipe:
740867ff 311 if (obuf != stdout) {
07b0d286
EW
312 /*
313 * Ignore SIGPIPE so it can't cause a duplicate close.
314 */
315 signal(SIGPIPE, SIG_IGN);
d96977db 316 Pclose(obuf);
07b0d286 317 signal(SIGPIPE, SIG_DFL);
d702437a
KS
318 }
319 return(0);
320}
321
740867ff
KS
322/*
323 * Respond to a broken pipe signal --
07b0d286 324 * probably caused by quitting more.
740867ff
KS
325 */
326
327brokpipe()
328{
fc3f7633 329 longjmp(pipestop, 1);
740867ff
KS
330}
331
d702437a
KS
332/*
333 * Print the top so many lines of each desired message.
334 * The number of lines is taken from the variable "toplines"
335 * and defaults to 5.
336 */
337
338top(msgvec)
339 int *msgvec;
340{
341 register int *ip;
342 register struct message *mp;
d702437a
KS
343 int c, topl, lines, lineb;
344 char *valtop, linebuf[LINESIZE];
345 FILE *ibuf;
346
347 topl = 5;
348 valtop = value("toplines");
349 if (valtop != NOSTR) {
350 topl = atoi(valtop);
351 if (topl < 0 || topl > 10000)
352 topl = 5;
353 }
354 lineb = 1;
355 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
470c33f3
EW
356 mp = &message[*ip - 1];
357 touch(mp);
d702437a
KS
358 dot = mp;
359 if (value("quiet") == NOSTR)
470c33f3 360 printf("Message %d:\n", *ip);
d702437a
KS
361 ibuf = setinput(mp);
362 c = mp->m_lines;
363 if (!lineb)
364 printf("\n");
365 for (lines = 0; lines < c && lines <= topl; lines++) {
38ed7007 366 if (readline(ibuf, linebuf, LINESIZE) < 0)
d702437a
KS
367 break;
368 puts(linebuf);
369 lineb = blankline(linebuf);
370 }
371 }
372 return(0);
373}
374
375/*
376 * Touch all the given messages so that they will
377 * get mboxed.
378 */
d702437a
KS
379stouch(msgvec)
380 int msgvec[];
381{
382 register int *ip;
383
384 for (ip = msgvec; *ip != 0; ip++) {
d702437a 385 dot = &message[*ip-1];
5bfbbe88 386 dot->m_flag |= MTOUCH;
d702437a
KS
387 dot->m_flag &= ~MPRESERVE;
388 }
389 return(0);
390}
f2230dfd
KS
391
392/*
393 * Make sure all passed messages get mboxed.
394 */
395
396mboxit(msgvec)
397 int msgvec[];
398{
399 register int *ip;
400
401 for (ip = msgvec; *ip != 0; ip++) {
402 dot = &message[*ip-1];
403 dot->m_flag |= MTOUCH|MBOX;
404 dot->m_flag &= ~MPRESERVE;
405 }
406 return(0);
407}
2470b1d8
KS
408
409/*
410 * List the folders the user currently has.
411 */
412folders()
413{
828615a1 414 char dirname[BUFSIZ];
d33aa50d 415 char *cmd;
2470b1d8 416
a5bfa0a3
KS
417 if (getfold(dirname) < 0) {
418 printf("No value set for \"folder\"\n");
2ee3bce2 419 return 1;
2470b1d8 420 }
d33aa50d
EW
421 if ((cmd = value("LISTER")) == NOSTR)
422 cmd = "ls";
423 (void) run_command(cmd, 0, -1, -1, dirname, NOSTR);
424 return 0;
2470b1d8 425}