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