cmd1.c revision 1.1.1.2 1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
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.
20 *
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.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)cmd1.c 8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37
38 #include "rcv.h"
39 #include "extern.h"
40
41 /*
42 * Mail -- a mail program
43 *
44 * User commands.
45 */
46
47 /*
48 * Print the current active headings.
49 * Don't change dot if invoker didn't give an argument.
50 */
51
52 static int screen;
53
54 int
55 headers(msgvec)
56 int *msgvec;
57 {
58 register int n, mesg, flag;
59 register struct message *mp;
60 int size;
61
62 size = screensize();
63 n = msgvec[0];
64 if (n != 0)
65 screen = (n-1)/size;
66 if (screen < 0)
67 screen = 0;
68 mp = &message[screen * size];
69 if (mp >= &message[msgCount])
70 mp = &message[msgCount - size];
71 if (mp < &message[0])
72 mp = &message[0];
73 flag = 0;
74 mesg = mp - &message[0];
75 if (dot != &message[n-1])
76 dot = mp;
77 for (; mp < &message[msgCount]; mp++) {
78 mesg++;
79 if (mp->m_flag & MDELETED)
80 continue;
81 if (flag++ >= size)
82 break;
83 printhead(mesg);
84 }
85 if (flag == 0) {
86 printf("No more mail.\n");
87 return(1);
88 }
89 return(0);
90 }
91
92 /*
93 * Scroll to the next/previous screen
94 */
95 int
96 scroll(arg)
97 char arg[];
98 {
99 register int s, size;
100 int cur[1];
101
102 cur[0] = 0;
103 size = screensize();
104 s = screen;
105 switch (*arg) {
106 case 0:
107 case '+':
108 s++;
109 if (s * size > msgCount) {
110 printf("On last screenful of messages\n");
111 return(0);
112 }
113 screen = s;
114 break;
115
116 case '-':
117 if (--s < 0) {
118 printf("On first screenful of messages\n");
119 return(0);
120 }
121 screen = s;
122 break;
123
124 default:
125 printf("Unrecognized scrolling command \"%s\"\n", arg);
126 return(1);
127 }
128 return(headers(cur));
129 }
130
131 /*
132 * Compute screen size.
133 */
134 int
135 screensize()
136 {
137 int s;
138 char *cp;
139
140 if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0)
141 return s;
142 return screenheight - 4;
143 }
144
145 /*
146 * Print out the headlines for each message
147 * in the passed message list.
148 */
149 int
150 from(msgvec)
151 int *msgvec;
152 {
153 register int *ip;
154
155 for (ip = msgvec; *ip != NULL; ip++)
156 printhead(*ip);
157 if (--ip >= msgvec)
158 dot = &message[*ip - 1];
159 return(0);
160 }
161
162 /*
163 * Print out the header of a specific message.
164 * This is a slight improvement to the standard one.
165 */
166 void
167 printhead(mesg)
168 int mesg;
169 {
170 struct message *mp;
171 char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
172 char pbuf[BUFSIZ];
173 struct headline hl;
174 int subjlen;
175 char *name;
176
177 mp = &message[mesg-1];
178 (void) readline(setinput(mp), headline, LINESIZE);
179 if ((subjline = hfield("subject", mp)) == NOSTR)
180 subjline = hfield("subj", mp);
181 /*
182 * Bletch!
183 */
184 curind = dot == mp ? '>' : ' ';
185 dispc = ' ';
186 if (mp->m_flag & MSAVED)
187 dispc = '*';
188 if (mp->m_flag & MPRESERVE)
189 dispc = 'P';
190 if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
191 dispc = 'N';
192 if ((mp->m_flag & (MREAD|MNEW)) == 0)
193 dispc = 'U';
194 if (mp->m_flag & MBOX)
195 dispc = 'M';
196 parse(headline, &hl, pbuf);
197 sprintf(wcount, "%3d/%-5ld", mp->m_lines, mp->m_size);
198 subjlen = screenwidth - 50 - strlen(wcount);
199 name = value("show-rcpt") != NOSTR ?
200 skin(hfield("to", mp)) : nameof(mp, 0);
201 if (subjline == NOSTR || subjlen < 0) /* pretty pathetic */
202 printf("%c%c%3d %-20.20s %16.16s %s\n",
203 curind, dispc, mesg, name, hl.l_date, wcount);
204 else
205 printf("%c%c%3d %-20.20s %16.16s %s \"%.*s\"\n",
206 curind, dispc, mesg, name, hl.l_date, wcount,
207 subjlen, subjline);
208 }
209
210 /*
211 * Print out the value of dot.
212 */
213 int
214 pdot()
215 {
216 printf("%d\n", dot - &message[0] + 1);
217 return(0);
218 }
219
220 /*
221 * Print out all the possible commands.
222 */
223 int
224 pcmdlist()
225 {
226 register struct cmd *cp;
227 register int cc;
228 extern struct cmd cmdtab[];
229
230 printf("Commands are:\n");
231 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
232 cc += strlen(cp->c_name) + 2;
233 if (cc > 72) {
234 printf("\n");
235 cc = strlen(cp->c_name) + 2;
236 }
237 if ((cp+1)->c_name != NOSTR)
238 printf("%s, ", cp->c_name);
239 else
240 printf("%s\n", cp->c_name);
241 }
242 return(0);
243 }
244
245 /*
246 * Paginate messages, honor ignored fields.
247 */
248 int
249 more(msgvec)
250 int *msgvec;
251 {
252 return (type1(msgvec, 1, 1));
253 }
254
255 /*
256 * Paginate messages, even printing ignored fields.
257 */
258 int
259 More(msgvec)
260 int *msgvec;
261 {
262
263 return (type1(msgvec, 0, 1));
264 }
265
266 /*
267 * Type out messages, honor ignored fields.
268 */
269 int
270 type(msgvec)
271 int *msgvec;
272 {
273
274 return(type1(msgvec, 1, 0));
275 }
276
277 /*
278 * Type out messages, even printing ignored fields.
279 */
280 int
281 Type(msgvec)
282 int *msgvec;
283 {
284
285 return(type1(msgvec, 0, 0));
286 }
287
288 /*
289 * Type out the messages requested.
290 */
291 jmp_buf pipestop;
292 int
293 type1(msgvec, doign, page)
294 int *msgvec;
295 int doign, page;
296 {
297 register *ip;
298 register struct message *mp;
299 register char *cp;
300 int nlines;
301 FILE *obuf;
302
303 obuf = stdout;
304 if (setjmp(pipestop))
305 goto close_pipe;
306 if (value("interactive") != NOSTR &&
307 (page || (cp = value("crt")) != NOSTR)) {
308 nlines = 0;
309 if (!page) {
310 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
311 nlines += message[*ip - 1].m_lines;
312 }
313 if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
314 cp = value("PAGER");
315 if (cp == NULL || *cp == '\0')
316 cp = _PATH_MORE;
317 obuf = Popen(cp, "w");
318 if (obuf == NULL) {
319 perror(cp);
320 obuf = stdout;
321 } else
322 signal(SIGPIPE, brokpipe);
323 }
324 }
325 for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
326 mp = &message[*ip - 1];
327 touch(mp);
328 dot = mp;
329 if (value("quiet") == NOSTR)
330 fprintf(obuf, "Message %d:\n", *ip);
331 (void) send(mp, obuf, doign ? ignore : 0, NOSTR);
332 }
333 close_pipe:
334 if (obuf != stdout) {
335 /*
336 * Ignore SIGPIPE so it can't cause a duplicate close.
337 */
338 signal(SIGPIPE, SIG_IGN);
339 Pclose(obuf);
340 signal(SIGPIPE, SIG_DFL);
341 }
342 return(0);
343 }
344
345 /*
346 * Respond to a broken pipe signal --
347 * probably caused by quitting more.
348 */
349 void
350 brokpipe(signo)
351 int signo;
352 {
353 longjmp(pipestop, 1);
354 }
355
356 /*
357 * Print the top so many lines of each desired message.
358 * The number of lines is taken from the variable "toplines"
359 * and defaults to 5.
360 */
361 int
362 top(msgvec)
363 int *msgvec;
364 {
365 register int *ip;
366 register struct message *mp;
367 int c, topl, lines, lineb;
368 char *valtop, linebuf[LINESIZE];
369 FILE *ibuf;
370
371 topl = 5;
372 valtop = value("toplines");
373 if (valtop != NOSTR) {
374 topl = atoi(valtop);
375 if (topl < 0 || topl > 10000)
376 topl = 5;
377 }
378 lineb = 1;
379 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
380 mp = &message[*ip - 1];
381 touch(mp);
382 dot = mp;
383 if (value("quiet") == NOSTR)
384 printf("Message %d:\n", *ip);
385 ibuf = setinput(mp);
386 c = mp->m_lines;
387 if (!lineb)
388 printf("\n");
389 for (lines = 0; lines < c && lines <= topl; lines++) {
390 if (readline(ibuf, linebuf, LINESIZE) < 0)
391 break;
392 puts(linebuf);
393 lineb = blankline(linebuf);
394 }
395 }
396 return(0);
397 }
398
399 /*
400 * Touch all the given messages so that they will
401 * get mboxed.
402 */
403 int
404 stouch(msgvec)
405 int msgvec[];
406 {
407 register int *ip;
408
409 for (ip = msgvec; *ip != 0; ip++) {
410 dot = &message[*ip-1];
411 dot->m_flag |= MTOUCH;
412 dot->m_flag &= ~MPRESERVE;
413 }
414 return(0);
415 }
416
417 /*
418 * Make sure all passed messages get mboxed.
419 */
420 int
421 mboxit(msgvec)
422 int msgvec[];
423 {
424 register int *ip;
425
426 for (ip = msgvec; *ip != 0; ip++) {
427 dot = &message[*ip-1];
428 dot->m_flag |= MTOUCH|MBOX;
429 dot->m_flag &= ~MPRESERVE;
430 }
431 return(0);
432 }
433
434 /*
435 * List the folders the user currently has.
436 */
437 int
438 folders()
439 {
440 char dirname[BUFSIZ];
441 char *cmd;
442
443 if (getfold(dirname) < 0) {
444 printf("No value set for \"folder\"\n");
445 return 1;
446 }
447 if ((cmd = value("LISTER")) == NOSTR)
448 cmd = "ls";
449 (void) run_command(cmd, 0, -1, -1, dirname, NOSTR, NOSTR);
450 return 0;
451 }
452