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