Ignore machine-check MSRs
[freebsd-src/fkvm-freebsd.git] / usr.bin / mail / cmd1.c
blobbe1b6f63ce4bd8d0d54cb04627c5c68c2e3121e0
1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #ifndef lint
35 #if 0
36 static char sccsid[] = "@(#)cmd1.c 8.2 (Berkeley) 4/20/95";
37 #endif
38 #endif /* not lint */
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
42 #include "rcv.h"
43 #include "extern.h"
46 * Mail -- a mail program
48 * User commands.
51 extern const struct cmd cmdtab[];
54 * Print the current active headings.
55 * Don't change dot if invoker didn't give an argument.
58 static int screen;
60 int
61 headers(msgvec)
62 int *msgvec;
64 int n, mesg, flag, size;
65 struct message *mp;
67 size = screensize();
68 n = msgvec[0];
69 if (n != 0)
70 screen = (n-1)/size;
71 if (screen < 0)
72 screen = 0;
73 mp = &message[screen * size];
74 if (mp >= &message[msgCount])
75 mp = &message[msgCount - size];
76 if (mp < &message[0])
77 mp = &message[0];
78 flag = 0;
79 mesg = mp - &message[0];
80 if (dot != &message[n-1])
81 dot = mp;
82 for (; mp < &message[msgCount]; mp++) {
83 mesg++;
84 if (mp->m_flag & MDELETED)
85 continue;
86 if (flag++ >= size)
87 break;
88 printhead(mesg);
90 if (flag == 0) {
91 printf("No more mail.\n");
92 return (1);
94 return (0);
98 * Scroll to the next/previous screen
101 scroll(arg)
102 char arg[];
104 int s, size;
105 int cur[1];
107 cur[0] = 0;
108 size = screensize();
109 s = screen;
110 switch (*arg) {
111 case 0:
112 case '+':
113 s++;
114 if (s * size >= msgCount) {
115 printf("On last screenful of messages\n");
116 return (0);
118 screen = s;
119 break;
121 case '-':
122 if (--s < 0) {
123 printf("On first screenful of messages\n");
124 return (0);
126 screen = s;
127 break;
129 default:
130 printf("Unrecognized scrolling command \"%s\"\n", arg);
131 return (1);
133 return (headers(cur));
137 * Compute screen size.
140 screensize()
142 int s;
143 char *cp;
145 if ((cp = value("screen")) != NULL && (s = atoi(cp)) > 0)
146 return (s);
147 return (screenheight - 4);
151 * Print out the headlines for each message
152 * in the passed message list.
155 from(msgvec)
156 int *msgvec;
158 int *ip;
160 for (ip = msgvec; *ip != 0; ip++)
161 printhead(*ip);
162 if (--ip >= msgvec)
163 dot = &message[*ip - 1];
164 return (0);
168 * Print out the header of a specific message.
169 * This is a slight improvement to the standard one.
171 void
172 printhead(mesg)
173 int mesg;
175 struct message *mp;
176 char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
177 char pbuf[BUFSIZ];
178 struct headline hl;
179 int subjlen;
180 char *name;
182 mp = &message[mesg-1];
183 (void)readline(setinput(mp), headline, LINESIZE);
184 if ((subjline = hfield("subject", mp)) == NULL)
185 subjline = hfield("subj", mp);
187 * Bletch!
189 curind = dot == mp ? '>' : ' ';
190 dispc = ' ';
191 if (mp->m_flag & MSAVED)
192 dispc = '*';
193 if (mp->m_flag & MPRESERVE)
194 dispc = 'P';
195 if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
196 dispc = 'N';
197 if ((mp->m_flag & (MREAD|MNEW)) == 0)
198 dispc = 'U';
199 if (mp->m_flag & MBOX)
200 dispc = 'M';
201 parse(headline, &hl, pbuf);
202 sprintf(wcount, "%3ld/%-5ld", mp->m_lines, mp->m_size);
203 subjlen = screenwidth - 50 - strlen(wcount);
204 name = value("show-rcpt") != NULL ?
205 skin(hfield("to", mp)) : nameof(mp, 0);
206 if (subjline == NULL || subjlen < 0) /* pretty pathetic */
207 printf("%c%c%3d %-20.20s %16.16s %s\n",
208 curind, dispc, mesg, name, hl.l_date, wcount);
209 else
210 printf("%c%c%3d %-20.20s %16.16s %s \"%.*s\"\n",
211 curind, dispc, mesg, name, hl.l_date, wcount,
212 subjlen, subjline);
216 * Print out the value of dot.
219 pdot()
221 printf("%d\n", dot - &message[0] + 1);
222 return (0);
226 * Print out all the possible commands.
229 pcmdlist()
231 const struct cmd *cp;
232 int cc;
234 printf("Commands are:\n");
235 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
236 cc += strlen(cp->c_name) + 2;
237 if (cc > 72) {
238 printf("\n");
239 cc = strlen(cp->c_name) + 2;
241 if ((cp+1)->c_name != NULL)
242 printf("%s, ", cp->c_name);
243 else
244 printf("%s\n", cp->c_name);
246 return (0);
250 * Paginate messages, honor ignored fields.
253 more(msgvec)
254 int *msgvec;
257 return (type1(msgvec, 1, 1));
261 * Paginate messages, even printing ignored fields.
264 More(msgvec)
265 int *msgvec;
268 return (type1(msgvec, 0, 1));
272 * Type out messages, honor ignored fields.
275 type(msgvec)
276 int *msgvec;
279 return (type1(msgvec, 1, 0));
283 * Type out messages, even printing ignored fields.
286 Type(msgvec)
287 int *msgvec;
290 return (type1(msgvec, 0, 0));
294 * Type out the messages requested.
296 static jmp_buf pipestop;
298 type1(msgvec, doign, page)
299 int *msgvec;
300 int doign, page;
302 int nlines, *ip;
303 struct message *mp;
304 char *cp;
305 FILE *obuf;
307 obuf = stdout;
308 if (setjmp(pipestop))
309 goto close_pipe;
310 if (value("interactive") != NULL &&
311 (page || (cp = value("crt")) != NULL)) {
312 nlines = 0;
313 if (!page) {
314 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
315 nlines += message[*ip - 1].m_lines;
317 if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
318 cp = value("PAGER");
319 if (cp == NULL || *cp == '\0')
320 cp = _PATH_MORE;
321 obuf = Popen(cp, "w");
322 if (obuf == NULL) {
323 warnx("%s", cp);
324 obuf = stdout;
325 } else
326 (void)signal(SIGPIPE, brokpipe);
331 * Send messages to the output.
334 for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
335 mp = &message[*ip - 1];
336 touch(mp);
337 dot = mp;
338 if (value("quiet") == NULL)
339 fprintf(obuf, "Message %d:\n", *ip);
340 (void)sendmessage(mp, obuf, doign ? ignore : 0, NULL);
343 close_pipe:
344 if (obuf != stdout) {
346 * Ignore SIGPIPE so it can't cause a duplicate close.
348 (void)signal(SIGPIPE, SIG_IGN);
349 (void)Pclose(obuf);
350 (void)signal(SIGPIPE, SIG_DFL);
352 return (0);
356 * Respond to a broken pipe signal --
357 * probably caused by quitting more.
359 /*ARGSUSED*/
360 void
361 brokpipe(signo)
362 int signo;
364 longjmp(pipestop, 1);
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.
373 top(msgvec)
374 int *msgvec;
376 int *ip;
377 struct message *mp;
378 int c, topl, lines, lineb;
379 char *valtop, linebuf[LINESIZE];
380 FILE *ibuf;
382 topl = 5;
383 valtop = value("toplines");
384 if (valtop != NULL) {
385 topl = atoi(valtop);
386 if (topl < 0 || topl > 10000)
387 topl = 5;
389 lineb = 1;
390 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
391 mp = &message[*ip - 1];
392 touch(mp);
393 dot = mp;
394 if (value("quiet") == NULL)
395 printf("Message %d:\n", *ip);
396 ibuf = setinput(mp);
397 c = mp->m_lines;
398 if (!lineb)
399 printf("\n");
400 for (lines = 0; lines < c && lines <= topl; lines++) {
401 if (readline(ibuf, linebuf, sizeof(linebuf)) < 0)
402 break;
403 puts(linebuf);
404 lineb = strspn(linebuf, " \t") == strlen(linebuf);
407 return (0);
411 * Touch all the given messages so that they will
412 * get mboxed.
415 stouch(msgvec)
416 int msgvec[];
418 int *ip;
420 for (ip = msgvec; *ip != 0; ip++) {
421 dot = &message[*ip-1];
422 dot->m_flag |= MTOUCH;
423 dot->m_flag &= ~MPRESERVE;
425 return (0);
429 * Make sure all passed messages get mboxed.
432 mboxit(msgvec)
433 int msgvec[];
435 int *ip;
437 for (ip = msgvec; *ip != 0; ip++) {
438 dot = &message[*ip-1];
439 dot->m_flag |= MTOUCH|MBOX;
440 dot->m_flag &= ~MPRESERVE;
442 return (0);
446 * List the folders the user currently has.
449 folders()
451 char dirname[PATHSIZE];
452 char *cmd;
454 if (getfold(dirname, sizeof(dirname)) < 0) {
455 printf("No value set for \"folder\"\n");
456 return (1);
458 if ((cmd = value("LISTER")) == NULL)
459 cmd = "ls";
460 (void)run_command(cmd, 0, -1, -1, dirname, NULL, NULL);
461 return (0);
465 * Update the mail file with any new messages that have
466 * come in since we started reading mail.
469 inc(v)
470 void *v;
472 int nmsg, mdot;
474 nmsg = incfile();
476 if (nmsg == 0)
477 printf("No new mail.\n");
478 else if (nmsg > 0) {
479 mdot = newfileinfo(msgCount - nmsg);
480 dot = &message[mdot - 1];
481 } else
482 printf("\"inc\" command failed...\n");
484 return (0);