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