added call to inithost() if GETHOST is defined
[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
15bff4bb 11static char *SccsId = "@(#)cmd1.c 2.8 %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/*
15bff4bb 234 * Type out messages, honor ignored fields.
d702437a 235 */
15bff4bb
KS
236type(msgvec)
237 int *msgvec;
238{
d702437a 239
15bff4bb
KS
240 return(type1(msgvec, 1));
241}
242
243/*
244 * Type out messages, even printing ignored fields.
245 */
246Type(msgvec)
247 int *msgvec;
248{
249
250 return(type1(msgvec, 0));
251}
252
253/*
254 * Type out the messages requested.
255 */
740867ff
KS
256jmp_buf pipestop;
257
15bff4bb 258type1(msgvec, doign)
d702437a
KS
259 int *msgvec;
260{
261 register *ip;
262 register struct message *mp;
263 register int mesg;
740867ff
KS
264 register char *cp;
265 int c, nlines;
266 int brokpipe();
267 FILE *ibuf, *obuf;
268
269 obuf = stdout;
270 if (setjmp(pipestop)) {
271 if (obuf != stdout) {
740867ff 272 pipef = NULL;
fc3f7633 273 pclose(obuf);
740867ff 274 }
fd0ddf32 275 sigset(SIGPIPE, SIG_DFL);
740867ff
KS
276 return(0);
277 }
278 if (intty && outtty && (cp = value("crt")) != NOSTR) {
279 for (ip = msgvec, nlines = 0; *ip && ip-msgvec < msgCount; ip++)
280 nlines += message[*ip - 1].m_lines;
281 if (nlines > atoi(cp)) {
282 obuf = popen(MORE, "w");
283 if (obuf == NULL) {
284 perror(MORE);
285 obuf = stdout;
286 }
287 else {
288 pipef = obuf;
fd0ddf32 289 sigset(SIGPIPE, brokpipe);
740867ff
KS
290 }
291 }
292 }
d702437a
KS
293 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
294 mesg = *ip;
295 touch(mesg);
296 mp = &message[mesg-1];
297 dot = mp;
15bff4bb 298 print(mp, obuf, doign);
740867ff 299 }
740867ff 300 if (obuf != stdout) {
740867ff 301 pipef = NULL;
fc3f7633 302 pclose(obuf);
d702437a 303 }
fd0ddf32 304 sigset(SIGPIPE, SIG_DFL);
d702437a
KS
305 return(0);
306}
307
740867ff
KS
308/*
309 * Respond to a broken pipe signal --
310 * probably caused by using quitting more.
311 */
312
313brokpipe()
314{
ea394d88 315# ifdef VMUNIX
fd0ddf32 316 sigrelse(SIGPIPE);
ea394d88
KS
317# else
318 signal(SIGPIPE, brokpipe);
319# endif
fc3f7633 320 longjmp(pipestop, 1);
740867ff
KS
321}
322
d702437a
KS
323/*
324 * Print the indicated message on standard output.
325 */
326
15bff4bb 327print(mp, obuf, doign)
d702437a 328 register struct message *mp;
740867ff 329 FILE *obuf;
d702437a
KS
330{
331
332 if (value("quiet") == NOSTR)
740867ff 333 fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1);
d702437a 334 touch(mp - &message[0] + 1);
15bff4bb 335 send(mp, obuf, doign);
d702437a
KS
336}
337
338/*
339 * Print the top so many lines of each desired message.
340 * The number of lines is taken from the variable "toplines"
341 * and defaults to 5.
342 */
343
344top(msgvec)
345 int *msgvec;
346{
347 register int *ip;
348 register struct message *mp;
349 register int mesg;
350 int c, topl, lines, lineb;
351 char *valtop, linebuf[LINESIZE];
352 FILE *ibuf;
353
354 topl = 5;
355 valtop = value("toplines");
356 if (valtop != NOSTR) {
357 topl = atoi(valtop);
358 if (topl < 0 || topl > 10000)
359 topl = 5;
360 }
361 lineb = 1;
362 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
363 mesg = *ip;
364 touch(mesg);
365 mp = &message[mesg-1];
366 dot = mp;
367 if (value("quiet") == NOSTR)
368 printf("Message %2d:\n", mesg);
369 ibuf = setinput(mp);
370 c = mp->m_lines;
371 if (!lineb)
372 printf("\n");
373 for (lines = 0; lines < c && lines <= topl; lines++) {
374 if (readline(ibuf, linebuf) <= 0)
375 break;
376 puts(linebuf);
377 lineb = blankline(linebuf);
378 }
379 }
380 return(0);
381}
382
383/*
384 * Touch all the given messages so that they will
385 * get mboxed.
386 */
387
388stouch(msgvec)
389 int msgvec[];
390{
391 register int *ip;
392
393 for (ip = msgvec; *ip != 0; ip++) {
d702437a 394 dot = &message[*ip-1];
5bfbbe88 395 dot->m_flag |= MTOUCH;
d702437a
KS
396 dot->m_flag &= ~MPRESERVE;
397 }
398 return(0);
399}
f2230dfd
KS
400
401/*
402 * Make sure all passed messages get mboxed.
403 */
404
405mboxit(msgvec)
406 int msgvec[];
407{
408 register int *ip;
409
410 for (ip = msgvec; *ip != 0; ip++) {
411 dot = &message[*ip-1];
412 dot->m_flag |= MTOUCH|MBOX;
413 dot->m_flag &= ~MPRESERVE;
414 }
415 return(0);
416}
2470b1d8
KS
417
418/*
419 * List the folders the user currently has.
420 */
421folders()
422{
2470b1d8
KS
423 char dirname[BUFSIZ], cmd[BUFSIZ];
424 int pid, s, e;
425
a5bfa0a3
KS
426 if (getfold(dirname) < 0) {
427 printf("No value set for \"folder\"\n");
2470b1d8
KS
428 return(-1);
429 }
2470b1d8
KS
430 switch ((pid = fork())) {
431 case 0:
64df7743 432 sigchild();
a5bfa0a3 433 execlp("ls", "ls", dirname, 0);
2470b1d8 434 clrbuf(stdout);
2470b1d8
KS
435 exit(1);
436
437 case -1:
438 perror("fork");
439 return(-1);
440
441 default:
442 while ((e = wait(&s)) != -1 && e != pid)
443 ;
444 }
445 return(0);
446}