cmd1.c revision 1.34 1 1.34 christos /* $NetBSD: cmd1.c,v 1.34 2013/10/18 20:17:59 christos Exp $ */
2 1.5 christos
3 1.1 cgd /*-
4 1.3 deraadt * Copyright (c) 1980, 1993
5 1.3 deraadt * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * Redistribution and use in source and binary forms, with or without
8 1.1 cgd * modification, are permitted provided that the following conditions
9 1.1 cgd * are met:
10 1.1 cgd * 1. Redistributions of source code must retain the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer.
12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer in the
14 1.1 cgd * documentation and/or other materials provided with the distribution.
15 1.21 agc * 3. Neither the name of the University nor the names of its contributors
16 1.1 cgd * may be used to endorse or promote products derived from this software
17 1.1 cgd * without specific prior written permission.
18 1.1 cgd *
19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.1 cgd * SUCH DAMAGE.
30 1.1 cgd */
31 1.1 cgd
32 1.10 lukem #include <sys/cdefs.h>
33 1.1 cgd #ifndef lint
34 1.5 christos #if 0
35 1.6 tls static char sccsid[] = "@(#)cmd1.c 8.2 (Berkeley) 4/20/95";
36 1.5 christos #else
37 1.34 christos __RCSID("$NetBSD: cmd1.c,v 1.34 2013/10/18 20:17:59 christos Exp $");
38 1.5 christos #endif
39 1.1 cgd #endif /* not lint */
40 1.1 cgd
41 1.28 christos #include <assert.h>
42 1.28 christos
43 1.1 cgd #include "rcv.h"
44 1.3 deraadt #include "extern.h"
45 1.27 christos #include "format.h"
46 1.26 christos #ifdef MIME_SUPPORT
47 1.26 christos #include "mime.h"
48 1.26 christos #endif
49 1.30 christos #include "sig.h"
50 1.28 christos #include "thread.h"
51 1.28 christos
52 1.1 cgd
53 1.1 cgd /*
54 1.1 cgd * Mail -- a mail program
55 1.1 cgd *
56 1.1 cgd * User commands.
57 1.1 cgd */
58 1.1 cgd
59 1.28 christos static int screen;
60 1.28 christos
61 1.28 christos /*
62 1.28 christos * Compute screen size.
63 1.28 christos */
64 1.28 christos static int
65 1.28 christos screensize(void)
66 1.28 christos {
67 1.28 christos int s;
68 1.28 christos char *cp;
69 1.28 christos
70 1.28 christos if ((cp = value(ENAME_SCREEN)) != NULL && (s = atoi(cp)) > 0)
71 1.28 christos return s;
72 1.28 christos return screenheight - 4;
73 1.28 christos }
74 1.28 christos
75 1.28 christos /*
76 1.28 christos * Print out the header of a specific message.
77 1.28 christos * This is a slight improvement to the standard one.
78 1.28 christos */
79 1.28 christos PUBLIC void
80 1.28 christos printhead(int mesg)
81 1.28 christos {
82 1.28 christos const char *fmtstr;
83 1.28 christos char *msgline;
84 1.28 christos
85 1.28 christos fmtstr = value(ENAME_HEADER_FORMAT);
86 1.28 christos if (fmtstr == NULL)
87 1.28 christos fmtstr = DEFAULT_HEADER_FORMAT;
88 1.28 christos msgline = smsgprintf(fmtstr, get_message(mesg));
89 1.28 christos if (screenwidth > 0)
90 1.28 christos msgline[screenwidth] = '\0';
91 1.28 christos (void)printf("%s\n", msgline);
92 1.30 christos sig_check();
93 1.28 christos }
94 1.28 christos
95 1.1 cgd /*
96 1.1 cgd * Print the current active headings.
97 1.1 cgd * Don't change dot if invoker didn't give an argument.
98 1.1 cgd */
99 1.28 christos PUBLIC int
100 1.15 wiz headers(void *v)
101 1.1 cgd {
102 1.30 christos int *msgvec;
103 1.30 christos int n;
104 1.30 christos int flag;
105 1.10 lukem struct message *mp;
106 1.1 cgd int size;
107 1.1 cgd
108 1.30 christos msgvec = v;
109 1.1 cgd size = screensize();
110 1.1 cgd n = msgvec[0];
111 1.1 cgd if (n != 0)
112 1.28 christos screen = (n - 1)/size;
113 1.1 cgd if (screen < 0)
114 1.1 cgd screen = 0;
115 1.28 christos
116 1.28 christos if ((mp = get_message(screen * size + 1)) == NULL) {
117 1.28 christos int msgCount;
118 1.28 christos msgCount = get_msgCount();
119 1.28 christos if (screen * size + 1 > msgCount)
120 1.28 christos mp = get_message(msgCount - size + 1);
121 1.28 christos if (mp == NULL)
122 1.28 christos mp = get_message(1);
123 1.28 christos }
124 1.1 cgd flag = 0;
125 1.28 christos if (dot != get_message(n))
126 1.1 cgd dot = mp;
127 1.28 christos for (/*EMPTY*/; mp; mp = next_message(mp)) {
128 1.1 cgd if (mp->m_flag & MDELETED)
129 1.1 cgd continue;
130 1.1 cgd if (flag++ >= size)
131 1.1 cgd break;
132 1.28 christos printhead(get_msgnum(mp));
133 1.1 cgd }
134 1.1 cgd if (flag == 0) {
135 1.23 christos (void)printf("No more mail.\n");
136 1.28 christos return 1;
137 1.1 cgd }
138 1.28 christos return 0;
139 1.1 cgd }
140 1.1 cgd
141 1.1 cgd /*
142 1.1 cgd * Scroll to the next/previous screen
143 1.1 cgd */
144 1.28 christos PUBLIC int
145 1.15 wiz scroll(void *v)
146 1.1 cgd {
147 1.30 christos char *arg;
148 1.30 christos int s;
149 1.30 christos int size;
150 1.1 cgd int cur[1];
151 1.1 cgd
152 1.30 christos arg = v;
153 1.1 cgd cur[0] = 0;
154 1.1 cgd size = screensize();
155 1.1 cgd s = screen;
156 1.1 cgd switch (*arg) {
157 1.1 cgd case 0:
158 1.1 cgd case '+':
159 1.1 cgd s++;
160 1.28 christos if (s * size >= get_msgCount()) {
161 1.23 christos (void)printf("On last screenful of messages\n");
162 1.28 christos return 0;
163 1.1 cgd }
164 1.1 cgd screen = s;
165 1.1 cgd break;
166 1.1 cgd
167 1.1 cgd case '-':
168 1.1 cgd if (--s < 0) {
169 1.23 christos (void)printf("On first screenful of messages\n");
170 1.28 christos return 0;
171 1.1 cgd }
172 1.1 cgd screen = s;
173 1.1 cgd break;
174 1.1 cgd
175 1.1 cgd default:
176 1.23 christos (void)printf("Unrecognized scrolling command \"%s\"\n", arg);
177 1.28 christos return 1;
178 1.1 cgd }
179 1.28 christos return headers(cur);
180 1.1 cgd }
181 1.1 cgd
182 1.1 cgd /*
183 1.1 cgd * Print out the headlines for each message
184 1.1 cgd * in the passed message list.
185 1.1 cgd */
186 1.28 christos PUBLIC int
187 1.15 wiz from(void *v)
188 1.1 cgd {
189 1.30 christos int *msgvec;
190 1.10 lukem int *ip;
191 1.1 cgd
192 1.30 christos msgvec = v;
193 1.8 pk for (ip = msgvec; *ip != 0; ip++)
194 1.1 cgd printhead(*ip);
195 1.1 cgd if (--ip >= msgvec)
196 1.28 christos dot = get_message(*ip);
197 1.28 christos return 0;
198 1.1 cgd }
199 1.1 cgd
200 1.1 cgd /*
201 1.28 christos * Print out the value of dot.
202 1.1 cgd */
203 1.28 christos /*ARGSUSED*/
204 1.28 christos PUBLIC int
205 1.28 christos pdot(void *v)
206 1.1 cgd {
207 1.28 christos int *msgvec;
208 1.26 christos
209 1.28 christos msgvec = v;
210 1.28 christos dot = get_message(msgvec[0]);
211 1.1 cgd
212 1.28 christos (void)printf("%d\n", get_msgnum(dot));
213 1.28 christos return 0;
214 1.1 cgd }
215 1.1 cgd
216 1.1 cgd /*
217 1.1 cgd * Print out all the possible commands.
218 1.1 cgd */
219 1.23 christos /*ARGSUSED*/
220 1.28 christos PUBLIC int
221 1.26 christos pcmdlist(void *v __unused)
222 1.1 cgd {
223 1.10 lukem const struct cmd *cp;
224 1.30 christos size_t cc;
225 1.1 cgd
226 1.23 christos (void)printf("Commands are:\n");
227 1.30 christos cc = 0;
228 1.30 christos for (cp = cmdtab; cp->c_name != NULL; cp++) {
229 1.1 cgd cc += strlen(cp->c_name) + 2;
230 1.1 cgd if (cc > 72) {
231 1.23 christos (void)printf("\n");
232 1.1 cgd cc = strlen(cp->c_name) + 2;
233 1.1 cgd }
234 1.26 christos if ((cp + 1)->c_name != NULL)
235 1.23 christos (void)printf("%s, ", cp->c_name);
236 1.1 cgd else
237 1.23 christos (void)printf("%s\n", cp->c_name);
238 1.30 christos sig_check();
239 1.1 cgd }
240 1.28 christos return 0;
241 1.1 cgd }
242 1.1 cgd
243 1.28 christos
244 1.28 christos PUBLIC char *
245 1.28 christos sget_msgnum(struct message *mp, struct message *parent)
246 1.26 christos {
247 1.28 christos char *p;
248 1.30 christos
249 1.28 christos if (parent == NULL || parent == mp) {
250 1.28 christos (void)sasprintf(&p, "%d", mp->m_index);
251 1.28 christos return p;
252 1.28 christos }
253 1.28 christos p = sget_msgnum(mp->m_plink, parent);
254 1.26 christos
255 1.28 christos (void)sasprintf(&p, "%s.%d", p, mp->m_index);
256 1.28 christos return p;
257 1.26 christos }
258 1.26 christos
259 1.28 christos PUBLIC void
260 1.28 christos show_msgnum(FILE *obuf, struct message *mp, struct message *parent)
261 1.1 cgd {
262 1.30 christos
263 1.28 christos if (value(ENAME_QUIET) == NULL)
264 1.28 christos (void)fprintf(obuf, "Message %s:\n", sget_msgnum(mp, parent));
265 1.1 cgd }
266 1.1 cgd
267 1.28 christos struct type1_core_args_s {
268 1.28 christos FILE *obuf;
269 1.28 christos struct message *parent;
270 1.28 christos struct ignoretab *igtab;
271 1.28 christos struct mime_info **mip;
272 1.28 christos };
273 1.28 christos static int
274 1.28 christos type1_core(struct message *mp, void *v)
275 1.1 cgd {
276 1.28 christos struct type1_core_args_s *args;
277 1.1 cgd
278 1.28 christos args = v;
279 1.28 christos touch(mp);
280 1.28 christos show_msgnum(args->obuf, mp, args->parent);
281 1.26 christos #ifdef MIME_SUPPORT
282 1.28 christos if (args->mip == NULL)
283 1.28 christos (void)mime_sendmessage(mp, args->obuf, args->igtab, NULL, NULL);
284 1.28 christos else {
285 1.28 christos *args->mip = mime_decode_open(mp);
286 1.28 christos (void)mime_sendmessage(mp, args->obuf, args->igtab, NULL, *args->mip);
287 1.28 christos mime_decode_close(*args->mip);
288 1.28 christos }
289 1.26 christos #else
290 1.28 christos (void)sendmessage(mp, args->obuf, args->igtab, NULL, NULL);
291 1.26 christos #endif
292 1.30 christos sig_check();
293 1.28 christos return 0;
294 1.1 cgd }
295 1.1 cgd
296 1.1 cgd /*
297 1.28 christos * Respond to a broken pipe signal --
298 1.28 christos * probably caused by quitting more.
299 1.1 cgd */
300 1.28 christos static jmp_buf pipestop;
301 1.28 christos
302 1.28 christos /*ARGSUSED*/
303 1.31 joerg __dead static void
304 1.30 christos cmd1_brokpipe(int signo __unused)
305 1.1 cgd {
306 1.30 christos
307 1.28 christos longjmp(pipestop, 1);
308 1.1 cgd }
309 1.1 cgd
310 1.1 cgd /*
311 1.28 christos * Type out the messages requested.
312 1.1 cgd */
313 1.28 christos #ifndef MIME_SUPPORT
314 1.28 christos # define type1(a,b,c) legacy_type1(a,b)
315 1.28 christos #endif
316 1.28 christos static int
317 1.28 christos type1(int *msgvec, int doign, int mime_decode)
318 1.1 cgd {
319 1.28 christos int recursive;
320 1.28 christos int *ip;
321 1.28 christos int msgCount;
322 1.28 christos /*
323 1.28 christos * Some volatile variables so longjmp will get the current not
324 1.28 christos * starting values. Note it is the variable that is volatile,
325 1.28 christos * not what it is pointing at!
326 1.28 christos */
327 1.30 christos FILE *volatile obuf; /* avoid longjmp clobbering */
328 1.34 christos int * volatile mvec;
329 1.30 christos sig_t volatile oldsigpipe; /* avoid longjmp clobbering? */
330 1.26 christos #ifdef MIME_SUPPORT
331 1.30 christos struct mime_info *volatile mip; /* avoid longjmp clobbering? */
332 1.30 christos
333 1.30 christos mip = NULL;
334 1.26 christos #endif
335 1.26 christos
336 1.34 christos mvec = msgvec;
337 1.28 christos if ((obuf = last_registered_file(0)) == NULL)
338 1.28 christos obuf = stdout;
339 1.26 christos
340 1.30 christos /*
341 1.30 christos * Even without MIME_SUPPORT, we need to handle SIGPIPE here
342 1.30 christos * or else the handler in execute() will grab things and our
343 1.30 christos * exit code will never be seen.
344 1.30 christos */
345 1.30 christos sig_check();
346 1.30 christos oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
347 1.28 christos if (setjmp(pipestop))
348 1.28 christos goto close_pipe;
349 1.28 christos
350 1.28 christos msgCount = get_msgCount();
351 1.26 christos
352 1.28 christos recursive = do_recursion();
353 1.34 christos for (ip = mvec; *ip && ip - mvec < msgCount; ip++) {
354 1.28 christos struct type1_core_args_s args;
355 1.28 christos struct message *mp;
356 1.26 christos
357 1.28 christos mp = get_message(*ip);
358 1.28 christos dot = mp;
359 1.28 christos args.obuf = obuf;
360 1.28 christos args.parent = recursive ? mp : NULL;
361 1.28 christos args.igtab = doign ? ignore : 0;
362 1.26 christos #ifdef MIME_SUPPORT
363 1.28 christos args.mip = mime_decode ? __UNVOLATILE(&mip) : NULL;
364 1.26 christos #else
365 1.28 christos args.mip = NULL;
366 1.26 christos #endif
367 1.28 christos (void)thread_recursion(mp, type1_core, &args);
368 1.28 christos }
369 1.30 christos close_pipe:
370 1.26 christos #ifdef MIME_SUPPORT
371 1.28 christos if (mip != NULL) {
372 1.30 christos struct sigaction osa;
373 1.30 christos sigset_t oset;
374 1.30 christos
375 1.28 christos /*
376 1.28 christos * Ignore SIGPIPE so it can't cause a duplicate close.
377 1.28 christos */
378 1.30 christos (void)sig_ignore(SIGPIPE, &osa, &oset);
379 1.28 christos mime_decode_close(mip);
380 1.30 christos (void)sig_restore(SIGPIPE, &osa, &oset);
381 1.28 christos }
382 1.26 christos #endif
383 1.30 christos (void)sig_signal(SIGPIPE, oldsigpipe);
384 1.30 christos sig_check();
385 1.28 christos return 0;
386 1.26 christos }
387 1.26 christos
388 1.28 christos #ifdef MIME_SUPPORT
389 1.28 christos static int
390 1.28 christos de_mime(void)
391 1.26 christos {
392 1.30 christos
393 1.28 christos return value(ENAME_MIME_DECODE_MSG) != NULL;
394 1.26 christos }
395 1.26 christos
396 1.26 christos /*
397 1.26 christos * Identical to type(), but with opposite mime behavior.
398 1.26 christos */
399 1.28 christos PUBLIC int
400 1.26 christos view(void *v)
401 1.26 christos {
402 1.30 christos int *msgvec;
403 1.30 christos
404 1.30 christos msgvec = v;
405 1.28 christos return type1(msgvec, 1, !de_mime());
406 1.26 christos }
407 1.26 christos
408 1.26 christos /*
409 1.26 christos * Identical to Type(), but with opposite mime behavior.
410 1.26 christos */
411 1.28 christos PUBLIC int
412 1.26 christos View(void *v)
413 1.26 christos {
414 1.30 christos int *msgvec;
415 1.26 christos
416 1.30 christos msgvec = v;
417 1.28 christos return type1(msgvec, 0, !de_mime());
418 1.1 cgd }
419 1.26 christos #endif /* MIME_SUPPORT */
420 1.1 cgd
421 1.1 cgd /*
422 1.28 christos * Type out messages, honor ignored fields.
423 1.1 cgd */
424 1.28 christos PUBLIC int
425 1.28 christos type(void *v)
426 1.1 cgd {
427 1.30 christos int *msgvec;
428 1.26 christos
429 1.30 christos msgvec = v;
430 1.28 christos return type1(msgvec, 1, de_mime());
431 1.1 cgd }
432 1.1 cgd
433 1.1 cgd /*
434 1.28 christos * Type out messages, even printing ignored fields.
435 1.1 cgd */
436 1.28 christos PUBLIC int
437 1.28 christos Type(void *v)
438 1.1 cgd {
439 1.30 christos int *msgvec;
440 1.28 christos
441 1.30 christos msgvec = v;
442 1.28 christos return type1(msgvec, 0, de_mime());
443 1.1 cgd }
444 1.1 cgd
445 1.1 cgd /*
446 1.24 christos * Pipe the current message buffer to a command.
447 1.24 christos */
448 1.28 christos PUBLIC int
449 1.24 christos pipecmd(void *v)
450 1.24 christos {
451 1.30 christos char *cmd;
452 1.30 christos FILE *volatile obuf; /* void longjmp clobbering */
453 1.33 christos sig_t volatile oldsigpipe = sig_current(SIGPIPE);
454 1.30 christos
455 1.30 christos cmd = v;
456 1.24 christos if (dot == NULL) {
457 1.24 christos warn("pipcmd: no current message");
458 1.24 christos return 1;
459 1.24 christos }
460 1.24 christos
461 1.24 christos obuf = stdout;
462 1.24 christos if (setjmp(pipestop))
463 1.24 christos goto close_pipe;
464 1.24 christos
465 1.30 christos sig_check();
466 1.32 christos obuf = Popen(cmd, "we");
467 1.24 christos if (obuf == NULL) {
468 1.24 christos warn("pipecmd: Popen failed: %s", cmd);
469 1.24 christos return 1;
470 1.30 christos }
471 1.30 christos
472 1.30 christos oldsigpipe = sig_signal(SIGPIPE, cmd1_brokpipe);
473 1.24 christos
474 1.26 christos (void)sendmessage(dot, obuf, ignoreall, NULL, NULL);
475 1.24 christos close_pipe:
476 1.30 christos sig_check();
477 1.24 christos if (obuf != stdout) {
478 1.30 christos struct sigaction osa;
479 1.30 christos sigset_t oset;
480 1.24 christos /*
481 1.24 christos * Ignore SIGPIPE so it can't cause a duplicate close.
482 1.24 christos */
483 1.30 christos (void)sig_ignore(SIGPIPE, &osa, &oset);
484 1.26 christos (void)Pclose(obuf);
485 1.30 christos (void)sig_restore(SIGPIPE, &osa, &oset);
486 1.24 christos }
487 1.30 christos (void)sig_signal(SIGPIPE, oldsigpipe);
488 1.30 christos sig_check();
489 1.24 christos return 0;
490 1.24 christos }
491 1.24 christos
492 1.28 christos struct top_core_args_s {
493 1.28 christos int lineb;
494 1.30 christos size_t topl;
495 1.28 christos struct message *parent;
496 1.28 christos };
497 1.28 christos static int
498 1.28 christos top_core(struct message *mp, void *v)
499 1.28 christos {
500 1.28 christos char buffer[LINESIZE];
501 1.28 christos struct top_core_args_s *args;
502 1.28 christos FILE *ibuf;
503 1.30 christos size_t lines;
504 1.30 christos size_t c;
505 1.28 christos
506 1.28 christos args = v;
507 1.28 christos touch(mp);
508 1.28 christos if (!args->lineb)
509 1.28 christos (void)printf("\n");
510 1.28 christos show_msgnum(stdout, mp, args->parent);
511 1.28 christos ibuf = setinput(mp);
512 1.28 christos c = mp->m_lines;
513 1.28 christos for (lines = 0; lines < c && lines <= args->topl; lines++) {
514 1.30 christos sig_check();
515 1.30 christos if (readline(ibuf, buffer, (int)sizeof(buffer), 0) < 0)
516 1.28 christos break;
517 1.28 christos (void)puts(buffer);
518 1.28 christos args->lineb = blankline(buffer);
519 1.28 christos }
520 1.30 christos sig_check();
521 1.28 christos return 0;
522 1.28 christos }
523 1.28 christos
524 1.24 christos /*
525 1.1 cgd * Print the top so many lines of each desired message.
526 1.1 cgd * The number of lines is taken from the variable "toplines"
527 1.1 cgd * and defaults to 5.
528 1.1 cgd */
529 1.28 christos PUBLIC int
530 1.15 wiz top(void *v)
531 1.1 cgd {
532 1.28 christos struct top_core_args_s args;
533 1.28 christos int recursive;
534 1.28 christos int msgCount;
535 1.30 christos int *msgvec;
536 1.10 lukem int *ip;
537 1.28 christos int topl;
538 1.28 christos char *valtop;
539 1.1 cgd
540 1.30 christos msgvec = v;
541 1.1 cgd topl = 5;
542 1.28 christos valtop = value(ENAME_TOPLINES);
543 1.16 wiz if (valtop != NULL) {
544 1.1 cgd topl = atoi(valtop);
545 1.1 cgd if (topl < 0 || topl > 10000)
546 1.1 cgd topl = 5;
547 1.1 cgd }
548 1.28 christos args.topl = topl;
549 1.28 christos args.lineb = 1;
550 1.28 christos recursive = do_recursion();
551 1.28 christos msgCount = get_msgCount();
552 1.28 christos for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
553 1.28 christos struct message *mp;
554 1.28 christos
555 1.28 christos mp = get_message(*ip);
556 1.1 cgd dot = mp;
557 1.28 christos args.parent = recursive ? mp : NULL;
558 1.28 christos (void)thread_recursion(mp, top_core, &args);
559 1.1 cgd }
560 1.28 christos return 0;
561 1.1 cgd }
562 1.1 cgd
563 1.1 cgd /*
564 1.1 cgd * Touch all the given messages so that they will
565 1.1 cgd * get mboxed.
566 1.1 cgd */
567 1.28 christos PUBLIC int
568 1.15 wiz stouch(void *v)
569 1.1 cgd {
570 1.30 christos int *msgvec;
571 1.10 lukem int *ip;
572 1.1 cgd
573 1.30 christos msgvec = v;
574 1.30 christos for (ip = msgvec; *ip != 0; ip++) {
575 1.30 christos sig_check();
576 1.28 christos dot = set_m_flag(*ip, ~(MPRESERVE | MTOUCH), MTOUCH);
577 1.30 christos }
578 1.28 christos return 0;
579 1.1 cgd }
580 1.1 cgd
581 1.1 cgd /*
582 1.1 cgd * Make sure all passed messages get mboxed.
583 1.1 cgd */
584 1.28 christos PUBLIC int
585 1.15 wiz mboxit(void *v)
586 1.1 cgd {
587 1.30 christos int *msgvec;
588 1.10 lukem int *ip;
589 1.1 cgd
590 1.30 christos msgvec = v;
591 1.30 christos for (ip = msgvec; *ip != 0; ip++) {
592 1.30 christos sig_check();
593 1.28 christos dot = set_m_flag(*ip,
594 1.28 christos ~(MPRESERVE | MTOUCH | MBOX), MTOUCH | MBOX);
595 1.30 christos }
596 1.28 christos return 0;
597 1.1 cgd }
598 1.1 cgd
599 1.1 cgd /*
600 1.1 cgd * List the folders the user currently has.
601 1.1 cgd */
602 1.23 christos /*ARGSUSED*/
603 1.28 christos PUBLIC int
604 1.26 christos folders(void *v __unused)
605 1.1 cgd {
606 1.7 mikel char dirname[PATHSIZE];
607 1.22 christos const char *cmd;
608 1.1 cgd
609 1.28 christos if (getfold(dirname, sizeof(dirname)) < 0) {
610 1.23 christos (void)printf("No value set for \"folder\"\n");
611 1.1 cgd return 1;
612 1.1 cgd }
613 1.28 christos if ((cmd = value(ENAME_LISTER)) == NULL)
614 1.1 cgd cmd = "ls";
615 1.30 christos (void)run_command(cmd, NULL, -1, -1, dirname, NULL);
616 1.6 tls return 0;
617 1.6 tls }
618 1.6 tls
619 1.6 tls /*
620 1.6 tls * Update the mail file with any new messages that have
621 1.6 tls * come in since we started reading mail.
622 1.6 tls */
623 1.23 christos /*ARGSUSED*/
624 1.28 christos PUBLIC int
625 1.26 christos inc(void *v __unused)
626 1.6 tls {
627 1.30 christos int nmsg;
628 1.30 christos int mdot;
629 1.6 tls
630 1.6 tls nmsg = incfile();
631 1.6 tls
632 1.6 tls if (nmsg == 0) {
633 1.28 christos (void)printf("No new mail.\n");
634 1.6 tls } else if (nmsg > 0) {
635 1.28 christos struct message *mp;
636 1.28 christos mdot = newfileinfo(get_abs_msgCount() - nmsg);
637 1.28 christos if ((mp = get_message(mdot)) != NULL)
638 1.28 christos dot = mp;
639 1.6 tls } else {
640 1.28 christos (void)printf("\"inc\" command failed...\n");
641 1.6 tls }
642 1.1 cgd return 0;
643 1.1 cgd }
644