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