1*f49cbbddSchristos /* $NetBSD: cmd1.c,v 1.34 2013/10/18 20:17:59 christos Exp $ */
288b833a7Schristos
361f28255Scgd /*-
42cb5542fSderaadt * Copyright (c) 1980, 1993
52cb5542fSderaadt * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
327c81c8f3Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3488b833a7Schristos #if 0
3519d35cbcStls static char sccsid[] = "@(#)cmd1.c 8.2 (Berkeley) 4/20/95";
3688b833a7Schristos #else
37*f49cbbddSchristos __RCSID("$NetBSD: cmd1.c,v 1.34 2013/10/18 20:17:59 christos Exp $");
3888b833a7Schristos #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
41f3098750Schristos #include <assert.h>
42f3098750Schristos
4361f28255Scgd #include "rcv.h"
442cb5542fSderaadt #include "extern.h"
45798fbc60Schristos #include "format.h"
468207b28aSchristos #ifdef MIME_SUPPORT
478207b28aSchristos #include "mime.h"
488207b28aSchristos #endif
49ca13337dSchristos #include "sig.h"
50f3098750Schristos #include "thread.h"
51f3098750Schristos
5261f28255Scgd
5361f28255Scgd /*
5461f28255Scgd * Mail -- a mail program
5561f28255Scgd *
5661f28255Scgd * User commands.
5761f28255Scgd */
5861f28255Scgd
59f3098750Schristos static int screen;
60f3098750Schristos
61f3098750Schristos /*
62f3098750Schristos * Compute screen size.
63f3098750Schristos */
64f3098750Schristos static int
screensize(void)65f3098750Schristos screensize(void)
66f3098750Schristos {
67f3098750Schristos int s;
68f3098750Schristos char *cp;
69f3098750Schristos
70f3098750Schristos if ((cp = value(ENAME_SCREEN)) != NULL && (s = atoi(cp)) > 0)
71f3098750Schristos return s;
72f3098750Schristos return screenheight - 4;
73f3098750Schristos }
74f3098750Schristos
75f3098750Schristos /*
76f3098750Schristos * Print out the header of a specific message.
77f3098750Schristos * This is a slight improvement to the standard one.
78f3098750Schristos */
79f3098750Schristos PUBLIC void
printhead(int mesg)80f3098750Schristos printhead(int mesg)
81f3098750Schristos {
82f3098750Schristos const char *fmtstr;
83f3098750Schristos char *msgline;
84f3098750Schristos
85f3098750Schristos fmtstr = value(ENAME_HEADER_FORMAT);
86f3098750Schristos if (fmtstr == NULL)
87f3098750Schristos fmtstr = DEFAULT_HEADER_FORMAT;
88f3098750Schristos msgline = smsgprintf(fmtstr, get_message(mesg));
89f3098750Schristos if (screenwidth > 0)
90f3098750Schristos msgline[screenwidth] = '\0';
91f3098750Schristos (void)printf("%s\n", msgline);
92ca13337dSchristos sig_check();
93f3098750Schristos }
94f3098750Schristos
9561f28255Scgd /*
9661f28255Scgd * Print the current active headings.
9761f28255Scgd * Don't change dot if invoker didn't give an argument.
9861f28255Scgd */
99f3098750Schristos PUBLIC int
headers(void * v)100b127ccccSwiz headers(void *v)
10161f28255Scgd {
102ca13337dSchristos int *msgvec;
103ca13337dSchristos int n;
104ca13337dSchristos int flag;
1057c81c8f3Slukem struct message *mp;
10661f28255Scgd int size;
10761f28255Scgd
108ca13337dSchristos msgvec = v;
10961f28255Scgd size = screensize();
11061f28255Scgd n = msgvec[0];
11161f28255Scgd if (n != 0)
11261f28255Scgd screen = (n - 1)/size;
11361f28255Scgd if (screen < 0)
11461f28255Scgd screen = 0;
115f3098750Schristos
116f3098750Schristos if ((mp = get_message(screen * size + 1)) == NULL) {
117f3098750Schristos int msgCount;
118f3098750Schristos msgCount = get_msgCount();
119f3098750Schristos if (screen * size + 1 > msgCount)
120f3098750Schristos mp = get_message(msgCount - size + 1);
121f3098750Schristos if (mp == NULL)
122f3098750Schristos mp = get_message(1);
123f3098750Schristos }
12461f28255Scgd flag = 0;
125f3098750Schristos if (dot != get_message(n))
12661f28255Scgd dot = mp;
127f3098750Schristos for (/*EMPTY*/; mp; mp = next_message(mp)) {
12861f28255Scgd if (mp->m_flag & MDELETED)
12961f28255Scgd continue;
13061f28255Scgd if (flag++ >= size)
13161f28255Scgd break;
132f3098750Schristos printhead(get_msgnum(mp));
13361f28255Scgd }
13461f28255Scgd if (flag == 0) {
135ca286310Schristos (void)printf("No more mail.\n");
136f3098750Schristos return 1;
13761f28255Scgd }
138f3098750Schristos return 0;
13961f28255Scgd }
14061f28255Scgd
14161f28255Scgd /*
14261f28255Scgd * Scroll to the next/previous screen
14361f28255Scgd */
144f3098750Schristos PUBLIC int
scroll(void * v)145b127ccccSwiz scroll(void *v)
14661f28255Scgd {
147ca13337dSchristos char *arg;
148ca13337dSchristos int s;
149ca13337dSchristos int size;
15061f28255Scgd int cur[1];
15161f28255Scgd
152ca13337dSchristos arg = v;
15361f28255Scgd cur[0] = 0;
15461f28255Scgd size = screensize();
15561f28255Scgd s = screen;
15661f28255Scgd switch (*arg) {
15761f28255Scgd case 0:
15861f28255Scgd case '+':
15961f28255Scgd s++;
160f3098750Schristos if (s * size >= get_msgCount()) {
161ca286310Schristos (void)printf("On last screenful of messages\n");
162f3098750Schristos return 0;
16361f28255Scgd }
16461f28255Scgd screen = s;
16561f28255Scgd break;
16661f28255Scgd
16761f28255Scgd case '-':
16861f28255Scgd if (--s < 0) {
169ca286310Schristos (void)printf("On first screenful of messages\n");
170f3098750Schristos return 0;
17161f28255Scgd }
17261f28255Scgd screen = s;
17361f28255Scgd break;
17461f28255Scgd
17561f28255Scgd default:
176ca286310Schristos (void)printf("Unrecognized scrolling command \"%s\"\n", arg);
177f3098750Schristos return 1;
17861f28255Scgd }
179f3098750Schristos return headers(cur);
18061f28255Scgd }
18161f28255Scgd
18261f28255Scgd /*
18361f28255Scgd * Print out the headlines for each message
18461f28255Scgd * in the passed message list.
18561f28255Scgd */
186f3098750Schristos PUBLIC int
from(void * v)187b127ccccSwiz from(void *v)
18861f28255Scgd {
189ca13337dSchristos int *msgvec;
1907c81c8f3Slukem int *ip;
19161f28255Scgd
192ca13337dSchristos msgvec = v;
193f890b048Spk for (ip = msgvec; *ip != 0; ip++)
19461f28255Scgd printhead(*ip);
19561f28255Scgd if (--ip >= msgvec)
196f3098750Schristos dot = get_message(*ip);
197f3098750Schristos return 0;
19861f28255Scgd }
19961f28255Scgd
20061f28255Scgd /*
20161f28255Scgd * Print out the value of dot.
20261f28255Scgd */
203ca286310Schristos /*ARGSUSED*/
204f3098750Schristos PUBLIC int
pdot(void * v)205f3098750Schristos pdot(void *v)
20661f28255Scgd {
207f3098750Schristos int *msgvec;
208f3098750Schristos
209f3098750Schristos msgvec = v;
210f3098750Schristos dot = get_message(msgvec[0]);
211f3098750Schristos
212f3098750Schristos (void)printf("%d\n", get_msgnum(dot));
213f3098750Schristos return 0;
21461f28255Scgd }
21561f28255Scgd
21661f28255Scgd /*
21761f28255Scgd * Print out all the possible commands.
21861f28255Scgd */
219ca286310Schristos /*ARGSUSED*/
220f3098750Schristos PUBLIC int
pcmdlist(void * v __unused)2218207b28aSchristos pcmdlist(void *v __unused)
22261f28255Scgd {
2237c81c8f3Slukem const struct cmd *cp;
224ca13337dSchristos size_t cc;
22561f28255Scgd
226ca286310Schristos (void)printf("Commands are:\n");
227ca13337dSchristos cc = 0;
228ca13337dSchristos for (cp = cmdtab; cp->c_name != NULL; cp++) {
22961f28255Scgd cc += strlen(cp->c_name) + 2;
23061f28255Scgd if (cc > 72) {
231ca286310Schristos (void)printf("\n");
23261f28255Scgd cc = strlen(cp->c_name) + 2;
23361f28255Scgd }
234ab850155Swiz if ((cp + 1)->c_name != NULL)
235ca286310Schristos (void)printf("%s, ", cp->c_name);
23661f28255Scgd else
237ca286310Schristos (void)printf("%s\n", cp->c_name);
238ca13337dSchristos sig_check();
23961f28255Scgd }
240f3098750Schristos return 0;
24161f28255Scgd }
24261f28255Scgd
243f3098750Schristos
244f3098750Schristos PUBLIC char *
sget_msgnum(struct message * mp,struct message * parent)245f3098750Schristos sget_msgnum(struct message *mp, struct message *parent)
246f3098750Schristos {
247f3098750Schristos char *p;
248ca13337dSchristos
249f3098750Schristos if (parent == NULL || parent == mp) {
250f3098750Schristos (void)sasprintf(&p, "%d", mp->m_index);
251f3098750Schristos return p;
252f3098750Schristos }
253f3098750Schristos p = sget_msgnum(mp->m_plink, parent);
254f3098750Schristos
255f3098750Schristos (void)sasprintf(&p, "%s.%d", p, mp->m_index);
256f3098750Schristos return p;
257f3098750Schristos }
258f3098750Schristos
259f3098750Schristos PUBLIC void
show_msgnum(FILE * obuf,struct message * mp,struct message * parent)260f3098750Schristos show_msgnum(FILE *obuf, struct message *mp, struct message *parent)
261f3098750Schristos {
262ca13337dSchristos
263f3098750Schristos if (value(ENAME_QUIET) == NULL)
264f3098750Schristos (void)fprintf(obuf, "Message %s:\n", sget_msgnum(mp, parent));
265f3098750Schristos }
266f3098750Schristos
267f3098750Schristos struct type1_core_args_s {
268f3098750Schristos FILE *obuf;
269f3098750Schristos struct message *parent;
270f3098750Schristos struct ignoretab *igtab;
271f3098750Schristos struct mime_info **mip;
272f3098750Schristos };
2738207b28aSchristos static int
type1_core(struct message * mp,void * v)274f3098750Schristos type1_core(struct message *mp, void *v)
2758207b28aSchristos {
276f3098750Schristos struct type1_core_args_s *args;
2778207b28aSchristos
278f3098750Schristos args = v;
27961f28255Scgd touch(mp);
280f3098750Schristos show_msgnum(args->obuf, mp, args->parent);
2818207b28aSchristos #ifdef MIME_SUPPORT
282f3098750Schristos if (args->mip == NULL)
283f3098750Schristos (void)mime_sendmessage(mp, args->obuf, args->igtab, NULL, NULL);
284f3098750Schristos else {
285f3098750Schristos *args->mip = mime_decode_open(mp);
286f3098750Schristos (void)mime_sendmessage(mp, args->obuf, args->igtab, NULL, *args->mip);
287f3098750Schristos mime_decode_close(*args->mip);
2888207b28aSchristos }
2898207b28aSchristos #else
290f3098750Schristos (void)sendmessage(mp, args->obuf, args->igtab, NULL, NULL);
2918207b28aSchristos #endif
292ca13337dSchristos sig_check();
293f3098750Schristos return 0;
29461f28255Scgd }
29561f28255Scgd
29661f28255Scgd /*
29761f28255Scgd * Respond to a broken pipe signal --
29861f28255Scgd * probably caused by quitting more.
29961f28255Scgd */
300f3098750Schristos static jmp_buf pipestop;
301f3098750Schristos
302ca286310Schristos /*ARGSUSED*/
3036818646aSjoerg __dead static void
cmd1_brokpipe(int signo __unused)304ca13337dSchristos cmd1_brokpipe(int signo __unused)
30561f28255Scgd {
306ca13337dSchristos
30761f28255Scgd longjmp(pipestop, 1);
30861f28255Scgd }
30961f28255Scgd
31061f28255Scgd /*
311f3098750Schristos * Type out the messages requested.
312f3098750Schristos */
313f3098750Schristos #ifndef MIME_SUPPORT
314f3098750Schristos # define type1(a,b,c) legacy_type1(a,b)
315f3098750Schristos #endif
316f3098750Schristos static int
type1(int * msgvec,int doign,int mime_decode)317f3098750Schristos type1(int *msgvec, int doign, int mime_decode)
318f3098750Schristos {
319f3098750Schristos int recursive;
320f3098750Schristos int *ip;
321f3098750Schristos int msgCount;
322f3098750Schristos /*
323f3098750Schristos * Some volatile variables so longjmp will get the current not
324f3098750Schristos * starting values. Note it is the variable that is volatile,
325f3098750Schristos * not what it is pointing at!
326f3098750Schristos */
327ca13337dSchristos FILE *volatile obuf; /* avoid longjmp clobbering */
328*f49cbbddSchristos int * volatile mvec;
329ca13337dSchristos sig_t volatile oldsigpipe; /* avoid longjmp clobbering? */
330f3098750Schristos #ifdef MIME_SUPPORT
331ca13337dSchristos struct mime_info *volatile mip; /* avoid longjmp clobbering? */
332ca13337dSchristos
333ca13337dSchristos mip = NULL;
334f3098750Schristos #endif
335f3098750Schristos
336*f49cbbddSchristos mvec = msgvec;
337f3098750Schristos if ((obuf = last_registered_file(0)) == NULL)
338f3098750Schristos obuf = stdout;
339f3098750Schristos
340ca13337dSchristos /*
341ca13337dSchristos * Even without MIME_SUPPORT, we need to handle SIGPIPE here
342ca13337dSchristos * or else the handler in execute() will grab things and our
343ca13337dSchristos * exit code will never be seen.
344ca13337dSchristos */
345ca13337dSchristos sig_check();
346ca13337dSchristos oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
347f3098750Schristos if (setjmp(pipestop))
348f3098750Schristos goto close_pipe;
349f3098750Schristos
350f3098750Schristos msgCount = get_msgCount();
351f3098750Schristos
352f3098750Schristos recursive = do_recursion();
353*f49cbbddSchristos for (ip = mvec; *ip && ip - mvec < msgCount; ip++) {
354f3098750Schristos struct type1_core_args_s args;
355f3098750Schristos struct message *mp;
356f3098750Schristos
357f3098750Schristos mp = get_message(*ip);
358f3098750Schristos dot = mp;
359f3098750Schristos args.obuf = obuf;
360f3098750Schristos args.parent = recursive ? mp : NULL;
361f3098750Schristos args.igtab = doign ? ignore : 0;
362f3098750Schristos #ifdef MIME_SUPPORT
363f3098750Schristos args.mip = mime_decode ? __UNVOLATILE(&mip) : NULL;
364f3098750Schristos #else
365f3098750Schristos args.mip = NULL;
366f3098750Schristos #endif
367f3098750Schristos (void)thread_recursion(mp, type1_core, &args);
368f3098750Schristos }
369f3098750Schristos close_pipe:
370ca13337dSchristos #ifdef MIME_SUPPORT
371f3098750Schristos if (mip != NULL) {
372ca13337dSchristos struct sigaction osa;
373ca13337dSchristos sigset_t oset;
374ca13337dSchristos
375f3098750Schristos /*
376f3098750Schristos * Ignore SIGPIPE so it can't cause a duplicate close.
377f3098750Schristos */
378ca13337dSchristos (void)sig_ignore(SIGPIPE, &osa, &oset);
379f3098750Schristos mime_decode_close(mip);
380ca13337dSchristos (void)sig_restore(SIGPIPE, &osa, &oset);
381f3098750Schristos }
382f3098750Schristos #endif
383ca13337dSchristos (void)sig_signal(SIGPIPE, oldsigpipe);
384ca13337dSchristos sig_check();
385f3098750Schristos return 0;
386f3098750Schristos }
387f3098750Schristos
388f3098750Schristos #ifdef MIME_SUPPORT
389f3098750Schristos static int
de_mime(void)390f3098750Schristos de_mime(void)
391f3098750Schristos {
392ca13337dSchristos
393f3098750Schristos return value(ENAME_MIME_DECODE_MSG) != NULL;
394f3098750Schristos }
395f3098750Schristos
396f3098750Schristos /*
397f3098750Schristos * Identical to type(), but with opposite mime behavior.
398f3098750Schristos */
399f3098750Schristos PUBLIC int
view(void * v)400f3098750Schristos view(void *v)
401f3098750Schristos {
402ca13337dSchristos int *msgvec;
403ca13337dSchristos
404ca13337dSchristos msgvec = v;
405f3098750Schristos return type1(msgvec, 1, !de_mime());
406f3098750Schristos }
407f3098750Schristos
408f3098750Schristos /*
409f3098750Schristos * Identical to Type(), but with opposite mime behavior.
410f3098750Schristos */
411f3098750Schristos PUBLIC int
View(void * v)412f3098750Schristos View(void *v)
413f3098750Schristos {
414ca13337dSchristos int *msgvec;
415f3098750Schristos
416ca13337dSchristos msgvec = v;
417f3098750Schristos return type1(msgvec, 0, !de_mime());
418f3098750Schristos }
419f3098750Schristos #endif /* MIME_SUPPORT */
420f3098750Schristos
421f3098750Schristos /*
422f3098750Schristos * Type out messages, honor ignored fields.
423f3098750Schristos */
424f3098750Schristos PUBLIC int
type(void * v)425f3098750Schristos type(void *v)
426f3098750Schristos {
427ca13337dSchristos int *msgvec;
428f3098750Schristos
429ca13337dSchristos msgvec = v;
430f3098750Schristos return type1(msgvec, 1, de_mime());
431f3098750Schristos }
432f3098750Schristos
433f3098750Schristos /*
434f3098750Schristos * Type out messages, even printing ignored fields.
435f3098750Schristos */
436f3098750Schristos PUBLIC int
Type(void * v)437f3098750Schristos Type(void *v)
438f3098750Schristos {
439ca13337dSchristos int *msgvec;
440f3098750Schristos
441ca13337dSchristos msgvec = v;
442f3098750Schristos return type1(msgvec, 0, de_mime());
443f3098750Schristos }
444f3098750Schristos
445f3098750Schristos /*
44685c81c58Schristos * Pipe the current message buffer to a command.
44785c81c58Schristos */
448f3098750Schristos PUBLIC int
pipecmd(void * v)44985c81c58Schristos pipecmd(void *v)
45085c81c58Schristos {
451ca13337dSchristos char *cmd;
452ca13337dSchristos FILE *volatile obuf; /* void longjmp clobbering */
453a7879b44Schristos sig_t volatile oldsigpipe = sig_current(SIGPIPE);
454ca13337dSchristos
455ca13337dSchristos cmd = v;
45685c81c58Schristos if (dot == NULL) {
45785c81c58Schristos warn("pipcmd: no current message");
45885c81c58Schristos return 1;
45985c81c58Schristos }
46085c81c58Schristos
46185c81c58Schristos obuf = stdout;
46285c81c58Schristos if (setjmp(pipestop))
46385c81c58Schristos goto close_pipe;
46485c81c58Schristos
465ca13337dSchristos sig_check();
4665942983dSchristos obuf = Popen(cmd, "we");
46785c81c58Schristos if (obuf == NULL) {
46885c81c58Schristos warn("pipecmd: Popen failed: %s", cmd);
46985c81c58Schristos return 1;
470ca13337dSchristos }
471ca13337dSchristos
472ca13337dSchristos oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
47385c81c58Schristos
4748207b28aSchristos (void)sendmessage(dot, obuf, ignoreall, NULL, NULL);
47585c81c58Schristos close_pipe:
476ca13337dSchristos sig_check();
47785c81c58Schristos if (obuf != stdout) {
478ca13337dSchristos struct sigaction osa;
479ca13337dSchristos sigset_t oset;
48085c81c58Schristos /*
48185c81c58Schristos * Ignore SIGPIPE so it can't cause a duplicate close.
48285c81c58Schristos */
483ca13337dSchristos (void)sig_ignore(SIGPIPE, &osa, &oset);
4848207b28aSchristos (void)Pclose(obuf);
485ca13337dSchristos (void)sig_restore(SIGPIPE, &osa, &oset);
48685c81c58Schristos }
487ca13337dSchristos (void)sig_signal(SIGPIPE, oldsigpipe);
488ca13337dSchristos sig_check();
48985c81c58Schristos return 0;
49085c81c58Schristos }
49185c81c58Schristos
492f3098750Schristos struct top_core_args_s {
493f3098750Schristos int lineb;
494ca13337dSchristos size_t topl;
495f3098750Schristos struct message *parent;
496f3098750Schristos };
497f3098750Schristos static int
top_core(struct message * mp,void * v)498f3098750Schristos top_core(struct message *mp, void *v)
499f3098750Schristos {
500f3098750Schristos char buffer[LINESIZE];
501f3098750Schristos struct top_core_args_s *args;
502f3098750Schristos FILE *ibuf;
503ca13337dSchristos size_t lines;
504ca13337dSchristos size_t c;
505f3098750Schristos
506f3098750Schristos args = v;
507f3098750Schristos touch(mp);
508f3098750Schristos if (!args->lineb)
509f3098750Schristos (void)printf("\n");
510f3098750Schristos show_msgnum(stdout, mp, args->parent);
511f3098750Schristos ibuf = setinput(mp);
512f3098750Schristos c = mp->m_lines;
513f3098750Schristos for (lines = 0; lines < c && lines <= args->topl; lines++) {
514ca13337dSchristos sig_check();
515ca13337dSchristos if (readline(ibuf, buffer, (int)sizeof(buffer), 0) < 0)
516f3098750Schristos break;
517f3098750Schristos (void)puts(buffer);
518f3098750Schristos args->lineb = blankline(buffer);
519f3098750Schristos }
520ca13337dSchristos sig_check();
521f3098750Schristos return 0;
522f3098750Schristos }
523f3098750Schristos
52485c81c58Schristos /*
52561f28255Scgd * Print the top so many lines of each desired message.
52661f28255Scgd * The number of lines is taken from the variable "toplines"
52761f28255Scgd * and defaults to 5.
52861f28255Scgd */
529f3098750Schristos PUBLIC int
top(void * v)530b127ccccSwiz top(void *v)
53161f28255Scgd {
532f3098750Schristos struct top_core_args_s args;
533f3098750Schristos int recursive;
534f3098750Schristos int msgCount;
535ca13337dSchristos int *msgvec;
5367c81c8f3Slukem int *ip;
537f3098750Schristos int topl;
538f3098750Schristos char *valtop;
53961f28255Scgd
540ca13337dSchristos msgvec = v;
54161f28255Scgd topl = 5;
542f3098750Schristos valtop = value(ENAME_TOPLINES);
543ab850155Swiz if (valtop != NULL) {
54461f28255Scgd topl = atoi(valtop);
54561f28255Scgd if (topl < 0 || topl > 10000)
54661f28255Scgd topl = 5;
54761f28255Scgd }
548f3098750Schristos args.topl = topl;
549f3098750Schristos args.lineb = 1;
550f3098750Schristos recursive = do_recursion();
551f3098750Schristos msgCount = get_msgCount();
55261f28255Scgd for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
553f3098750Schristos struct message *mp;
554f3098750Schristos
555f3098750Schristos mp = get_message(*ip);
55661f28255Scgd dot = mp;
557f3098750Schristos args.parent = recursive ? mp : NULL;
558f3098750Schristos (void)thread_recursion(mp, top_core, &args);
55961f28255Scgd }
560f3098750Schristos return 0;
56161f28255Scgd }
56261f28255Scgd
56361f28255Scgd /*
56461f28255Scgd * Touch all the given messages so that they will
56561f28255Scgd * get mboxed.
56661f28255Scgd */
567f3098750Schristos PUBLIC int
stouch(void * v)568b127ccccSwiz stouch(void *v)
56961f28255Scgd {
570ca13337dSchristos int *msgvec;
5717c81c8f3Slukem int *ip;
57261f28255Scgd
573ca13337dSchristos msgvec = v;
574ca13337dSchristos for (ip = msgvec; *ip != 0; ip++) {
575ca13337dSchristos sig_check();
576f3098750Schristos dot = set_m_flag(*ip, ~(MPRESERVE | MTOUCH), MTOUCH);
577ca13337dSchristos }
578f3098750Schristos return 0;
57961f28255Scgd }
58061f28255Scgd
58161f28255Scgd /*
58261f28255Scgd * Make sure all passed messages get mboxed.
58361f28255Scgd */
584f3098750Schristos PUBLIC int
mboxit(void * v)585b127ccccSwiz mboxit(void *v)
58661f28255Scgd {
587ca13337dSchristos int *msgvec;
5887c81c8f3Slukem int *ip;
58961f28255Scgd
590ca13337dSchristos msgvec = v;
591ca13337dSchristos for (ip = msgvec; *ip != 0; ip++) {
592ca13337dSchristos sig_check();
593f3098750Schristos dot = set_m_flag(*ip,
594f3098750Schristos ~(MPRESERVE | MTOUCH | MBOX), MTOUCH | MBOX);
595ca13337dSchristos }
596f3098750Schristos return 0;
59761f28255Scgd }
59861f28255Scgd
59961f28255Scgd /*
60061f28255Scgd * List the folders the user currently has.
60161f28255Scgd */
602ca286310Schristos /*ARGSUSED*/
603f3098750Schristos PUBLIC int
folders(void * v __unused)6048207b28aSchristos folders(void *v __unused)
60561f28255Scgd {
606254cb6fdSmikel char dirname[PATHSIZE];
607ece0fd5cSchristos const char *cmd;
60861f28255Scgd
609f3098750Schristos if (getfold(dirname, sizeof(dirname)) < 0) {
610ca286310Schristos (void)printf("No value set for \"folder\"\n");
61161f28255Scgd return 1;
61261f28255Scgd }
613f3098750Schristos if ((cmd = value(ENAME_LISTER)) == NULL)
61461f28255Scgd cmd = "ls";
615ca13337dSchristos (void)run_command(cmd, NULL, -1, -1, dirname, NULL);
61661f28255Scgd return 0;
61761f28255Scgd }
61819d35cbcStls
61919d35cbcStls /*
62019d35cbcStls * Update the mail file with any new messages that have
62119d35cbcStls * come in since we started reading mail.
62219d35cbcStls */
623ca286310Schristos /*ARGSUSED*/
624f3098750Schristos PUBLIC int
inc(void * v __unused)6258207b28aSchristos inc(void *v __unused)
62619d35cbcStls {
627ca13337dSchristos int nmsg;
628ca13337dSchristos int mdot;
62919d35cbcStls
63019d35cbcStls nmsg = incfile();
63119d35cbcStls
63219d35cbcStls if (nmsg == 0) {
633ca286310Schristos (void)printf("No new mail.\n");
63419d35cbcStls } else if (nmsg > 0) {
635f3098750Schristos struct message *mp;
636f3098750Schristos mdot = newfileinfo(get_abs_msgCount() - nmsg);
637f3098750Schristos if ((mp = get_message(mdot)) != NULL)
638f3098750Schristos dot = mp;
63919d35cbcStls } else {
640ca286310Schristos (void)printf("\"inc\" command failed...\n");
64119d35cbcStls }
64219d35cbcStls return 0;
64319d35cbcStls }
644