changed "dp" command to say "At EOF" when executed on last message
[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
fc3f7633 11static char *SccsId = "@(#)cmd1.c 2.2 %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;
25
26 n = msgvec[0];
27 if (n != 0)
28 screen = (n-1)/SCREEN;
29 if (screen < 0)
30 screen = 0;
31 mp = &message[screen * SCREEN];
32 if (mp >= &message[msgCount])
33 mp = &message[msgCount - SCREEN];
34 if (mp < &message[0])
35 mp = &message[0];
36 flag = 0;
37 mesg = mp - &message[0];
f75dd1e5
KS
38 if (dot != &message[n-1])
39 dot = mp;
d702437a
KS
40 for (; mp < &message[msgCount]; mp++) {
41 mesg++;
42 if (mp->m_flag & MDELETED)
43 continue;
44 if (flag++ >= SCREEN)
45 break;
46 printhead(mesg);
47 sreset();
48 }
49 if (flag == 0) {
50 printf("No more mail.\n");
51 return(1);
52 }
53 return(0);
54}
55
56/*
57 * Scroll to the next/previous screen
58 */
59
60scroll(arg)
61 char arg[];
62{
63 register int s;
64 int cur[1];
65
66 cur[0] = 0;
67 s = screen;
68 switch (*arg) {
69 case 0:
70 case '+':
71 s++;
72 if (s*SCREEN > msgCount) {
73 printf("On last screenful of messages\n");
74 return(0);
75 }
76 screen = s;
77 break;
78
79 case '-':
80 if (--s < 0) {
81 printf("On first screenful of messages\n");
82 return(0);
83 }
84 screen = s;
85 break;
86
87 default:
88 printf("Unrecognized scrolling command \"%s\"\n", arg);
89 return(1);
90 }
91 return(headers(cur));
92}
93
94
95/*
96 * Print out the headlines for each message
97 * in the passed message list.
98 */
99
100from(msgvec)
101 int *msgvec;
102{
103 register int *ip;
104
105 for (ip = msgvec; *ip != NULL; ip++) {
106 printhead(*ip);
107 sreset();
108 }
109 if (--ip >= msgvec)
110 dot = &message[*ip - 1];
111 return(0);
112}
113
114/*
115 * Print out the header of a specific message.
116 * This is a slight improvement to the standard one.
117 */
118
119printhead(mesg)
120{
121 struct message *mp;
122 FILE *ibuf;
f75dd1e5 123 char headline[LINESIZE], wcount[10], *subjline, dispc, curind;
d702437a
KS
124 char pbuf[BUFSIZ];
125 int s;
126 struct headline hl;
127 register char *cp;
128
129 mp = &message[mesg-1];
130 ibuf = setinput(mp);
131 readline(ibuf, headline);
132 subjline = hfield("subject", mp);
133 if (subjline == NOSTR)
134 subjline = hfield("subj", mp);
135
136 /*
137 * Bletch!
138 */
139
140 if (subjline != NOSTR && strlen(subjline) > 28)
141 subjline[29] = '\0';
f75dd1e5 142 curind = dot == mp ? '>' : ' ';
d702437a
KS
143 dispc = ' ';
144 if (mp->m_flag & MSAVED)
145 dispc = '*';
146 if (mp->m_flag & MPRESERVE)
147 dispc = 'P';
5bfbbe88 148 if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
f4d36a07 149 dispc = 'N';
5bfbbe88
KS
150 if ((mp->m_flag & (MREAD|MNEW)) == 0)
151 dispc = 'U';
f2230dfd
KS
152 if (mp->m_flag & MBOX)
153 dispc = 'M';
d702437a
KS
154 parse(headline, &hl, pbuf);
155 sprintf(wcount, " %d/%d", mp->m_lines, mp->m_size);
156 s = strlen(wcount);
157 cp = wcount + s;
158 while (s < 7)
159 s++, *cp++ = ' ';
160 *cp = '\0';
161 if (subjline != NOSTR)
f75dd1e5 162 printf("%c%c%3d %-8s %16.16s %s \"%s\"\n", curind, dispc, mesg,
186f16d8 163 nameof(mp, 0), hl.l_date, wcount, subjline);
d702437a 164 else
f75dd1e5 165 printf("%c%c%3d %-8s %16.16s %s\n", curind, dispc, mesg,
186f16d8 166 nameof(mp, 0), hl.l_date, wcount);
d702437a
KS
167}
168
169/*
170 * Print out the value of dot.
171 */
172
173pdot()
174{
175 printf("%d\n", dot - &message[0] + 1);
176 return(0);
177}
178
179/*
180 * Print out all the possible commands.
181 */
182
183pcmdlist()
184{
185 register struct cmd *cp;
186 register int cc;
187 extern struct cmd cmdtab[];
188
189 printf("Commands are:\n");
190 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
191 cc += strlen(cp->c_name) + 2;
192 if (cc > 72) {
193 printf("\n");
194 cc = strlen(cp->c_name) + 2;
195 }
196 if ((cp+1)->c_name != NOSTR)
197 printf("%s, ", cp->c_name);
198 else
199 printf("%s\n", cp->c_name);
200 }
201 return(0);
202}
203
204/*
205 * Type out the messages requested.
206 */
207
740867ff
KS
208jmp_buf pipestop;
209
d702437a
KS
210type(msgvec)
211 int *msgvec;
212{
213 register *ip;
214 register struct message *mp;
215 register int mesg;
740867ff
KS
216 register char *cp;
217 int c, nlines;
218 int brokpipe();
219 FILE *ibuf, *obuf;
220
221 obuf = stdout;
222 if (setjmp(pipestop)) {
223 if (obuf != stdout) {
740867ff 224 pipef = NULL;
fc3f7633 225 pclose(obuf);
740867ff 226 }
fd0ddf32 227 sigset(SIGPIPE, SIG_DFL);
740867ff
KS
228 return(0);
229 }
230 if (intty && outtty && (cp = value("crt")) != NOSTR) {
231 for (ip = msgvec, nlines = 0; *ip && ip-msgvec < msgCount; ip++)
232 nlines += message[*ip - 1].m_lines;
233 if (nlines > atoi(cp)) {
234 obuf = popen(MORE, "w");
235 if (obuf == NULL) {
236 perror(MORE);
237 obuf = stdout;
238 }
239 else {
240 pipef = obuf;
fd0ddf32 241 sigset(SIGPIPE, brokpipe);
740867ff
KS
242 }
243 }
244 }
d702437a
KS
245 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
246 mesg = *ip;
247 touch(mesg);
248 mp = &message[mesg-1];
249 dot = mp;
740867ff
KS
250 print(mp, obuf);
251 }
740867ff 252 if (obuf != stdout) {
740867ff 253 pipef = NULL;
fc3f7633 254 pclose(obuf);
d702437a 255 }
fd0ddf32 256 sigset(SIGPIPE, SIG_DFL);
d702437a
KS
257 return(0);
258}
259
740867ff
KS
260/*
261 * Respond to a broken pipe signal --
262 * probably caused by using quitting more.
263 */
264
265brokpipe()
266{
267
fd0ddf32 268 sigrelse(SIGPIPE);
fc3f7633 269 longjmp(pipestop, 1);
740867ff
KS
270}
271
d702437a
KS
272/*
273 * Print the indicated message on standard output.
274 */
275
740867ff 276print(mp, obuf)
d702437a 277 register struct message *mp;
740867ff 278 FILE *obuf;
d702437a
KS
279{
280
281 if (value("quiet") == NOSTR)
740867ff 282 fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1);
d702437a 283 touch(mp - &message[0] + 1);
740867ff 284 send(mp, obuf);
d702437a
KS
285}
286
287/*
288 * Print the top so many lines of each desired message.
289 * The number of lines is taken from the variable "toplines"
290 * and defaults to 5.
291 */
292
293top(msgvec)
294 int *msgvec;
295{
296 register int *ip;
297 register struct message *mp;
298 register int mesg;
299 int c, topl, lines, lineb;
300 char *valtop, linebuf[LINESIZE];
301 FILE *ibuf;
302
303 topl = 5;
304 valtop = value("toplines");
305 if (valtop != NOSTR) {
306 topl = atoi(valtop);
307 if (topl < 0 || topl > 10000)
308 topl = 5;
309 }
310 lineb = 1;
311 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
312 mesg = *ip;
313 touch(mesg);
314 mp = &message[mesg-1];
315 dot = mp;
316 if (value("quiet") == NOSTR)
317 printf("Message %2d:\n", mesg);
318 ibuf = setinput(mp);
319 c = mp->m_lines;
320 if (!lineb)
321 printf("\n");
322 for (lines = 0; lines < c && lines <= topl; lines++) {
323 if (readline(ibuf, linebuf) <= 0)
324 break;
325 puts(linebuf);
326 lineb = blankline(linebuf);
327 }
328 }
329 return(0);
330}
331
332/*
333 * Touch all the given messages so that they will
334 * get mboxed.
335 */
336
337stouch(msgvec)
338 int msgvec[];
339{
340 register int *ip;
341
342 for (ip = msgvec; *ip != 0; ip++) {
d702437a 343 dot = &message[*ip-1];
5bfbbe88 344 dot->m_flag |= MTOUCH;
d702437a
KS
345 dot->m_flag &= ~MPRESERVE;
346 }
347 return(0);
348}
f2230dfd
KS
349
350/*
351 * Make sure all passed messages get mboxed.
352 */
353
354mboxit(msgvec)
355 int msgvec[];
356{
357 register int *ip;
358
359 for (ip = msgvec; *ip != 0; ip++) {
360 dot = &message[*ip-1];
361 dot->m_flag |= MTOUCH|MBOX;
362 dot->m_flag &= ~MPRESERVE;
363 }
364 return(0);
365}