cmd3.c revision 267654
18871Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 4. Neither the name of the University nor the names of its contributors 141558Srgrimes * may be used to endorse or promote products derived from this software 151558Srgrimes * without specific prior written permission. 161558Srgrimes * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes */ 291558Srgrimes 301558Srgrimes#ifndef lint 311558Srgrimes#if 0 321558Srgrimesstatic char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95"; 331558Srgrimes#endif 341558Srgrimes#endif /* not lint */ 3541477Sjulian#include <sys/cdefs.h> 3623675Speter__FBSDID("$FreeBSD: releng/9.3/usr.bin/mail/cmd3.c 216564 2010-12-19 16:25:23Z charnier $"); 3741477Sjulian 3841477Sjulian#include "rcv.h" 3950476Speter#include "extern.h" 401558Srgrimes 411558Srgrimes/* 421558Srgrimes * Mail -- a mail program 4362668Smckusick * 4423675Speter * Still more user commands. 451558Srgrimes */ 461558Srgrimes 471558Srgrimes/* 4823675Speter * Process a shell escape by saving signals, ignoring signals, 4923675Speter * and forking a sh -c 501558Srgrimes */ 5123675Speterint 521558Srgrimesshell(char *str) 531558Srgrimes{ 5423675Speter sig_t sigint = signal(SIGINT, SIG_IGN); 5523675Speter char *sh; 5641474Sjulian char cmd[BUFSIZ]; 571558Srgrimes 5823675Speter if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd)) 597585Sbde return (1); 607585Sbde if (bangexp(cmd, sizeof(cmd)) < 0) 611558Srgrimes return (1); 621558Srgrimes if ((sh = value("SHELL")) == NULL) 6341474Sjulian sh = _PATH_CSHELL; 641558Srgrimes (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL); 6541474Sjulian (void)signal(SIGINT, sigint); 6641474Sjulian printf("!\n"); 671558Srgrimes return (0); 681558Srgrimes} 691558Srgrimes 701558Srgrimes/* 711558Srgrimes * Fork an interactive shell. 721558Srgrimes */ 731558Srgrimes/*ARGSUSED*/ 741558Srgrimesint 751558Srgrimesdosh(char *str __unused) 761558Srgrimes{ 771558Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 781558Srgrimes char *sh; 791558Srgrimes 801558Srgrimes if ((sh = value("SHELL")) == NULL) 811558Srgrimes sh = _PATH_CSHELL; 821558Srgrimes (void)run_command(sh, 0, -1, -1, NULL, NULL, NULL); 831558Srgrimes (void)signal(SIGINT, sigint); 841558Srgrimes printf("\n"); 8523675Speter return (0); 861558Srgrimes} 871558Srgrimes 881558Srgrimes/* 8941474Sjulian * Expand the shell escape by expanding unescaped !'s into the 9041474Sjulian * last issued command where possible. 9141474Sjulian */ 9241474Sjulianint 9341474Sjulianbangexp(char *str, size_t strsize) 9441474Sjulian{ 9541474Sjulian char bangbuf[BUFSIZ]; 9641474Sjulian static char lastbang[BUFSIZ]; 9741474Sjulian char *cp, *cp2; 9841474Sjulian int n, changed = 0; 9941474Sjulian 10041474Sjulian cp = str; 10141474Sjulian cp2 = bangbuf; 10241474Sjulian n = sizeof(bangbuf); 10341474Sjulian while (*cp != '\0') { 10441474Sjulian if (*cp == '!') { 10541474Sjulian if (n < strlen(lastbang)) { 10641474Sjulianoverf: 10741474Sjulian printf("Command buffer overflow\n"); 10841474Sjulian return (-1); 10941474Sjulian } 11041474Sjulian changed++; 11141474Sjulian if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf)) 11241474Sjulian >= sizeof(bangbuf) - (cp2 - bangbuf)) 11341474Sjulian goto overf; 11441474Sjulian cp2 += strlen(lastbang); 11541474Sjulian n -= strlen(lastbang); 11641474Sjulian cp++; 11741474Sjulian continue; 11841474Sjulian } 11941474Sjulian if (*cp == '\\' && cp[1] == '!') { 12041474Sjulian if (--n <= 1) 12141474Sjulian goto overf; 12241474Sjulian *cp2++ = '!'; 12341474Sjulian cp += 2; 12441474Sjulian changed++; 12541474Sjulian } 12641474Sjulian if (--n <= 1) 12741474Sjulian goto overf; 12841474Sjulian *cp2++ = *cp++; 12941474Sjulian } 13041474Sjulian *cp2 = 0; 13141474Sjulian if (changed) { 13241474Sjulian printf("!%s\n", bangbuf); 13341474Sjulian (void)fflush(stdout); 13441474Sjulian } 13541474Sjulian if (strlcpy(str, bangbuf, strsize) >= strsize) 1361558Srgrimes goto overf; 13741474Sjulian if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang)) 1381558Srgrimes goto overf; 1391558Srgrimes return (0); 14041474Sjulian} 14141474Sjulian 14241474Sjulian/* 14341474Sjulian * Print out a nice help message from some file or another. 14441474Sjulian */ 14541474Sjulian 14641474Sjulianint 14741474Sjulianhelp(void) 14841474Sjulian{ 14941474Sjulian int c; 15041474Sjulian FILE *f; 15141474Sjulian 15241474Sjulian if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 15341474Sjulian warn("%s", _PATH_HELP); 15441474Sjulian return (1); 15541474Sjulian } 15641474Sjulian while ((c = getc(f)) != EOF) 15741474Sjulian putchar(c); 15841474Sjulian (void)Fclose(f); 15941474Sjulian return (0); 16041474Sjulian} 16141474Sjulian 16241474Sjulian/* 16341474Sjulian * Change user's working directory. 16441474Sjulian */ 1651558Srgrimesint 1661558Srgrimesschdir(char **arglist) 1671558Srgrimes{ 1681558Srgrimes char *cp; 16923675Speter 1701558Srgrimes if (*arglist == NULL) { 1711558Srgrimes if (homedir == NULL) 1721558Srgrimes return (1); 1731558Srgrimes cp = homedir; 1741558Srgrimes } else 1751558Srgrimes if ((cp = expand(*arglist)) == NULL) 1761558Srgrimes return (1); 1771558Srgrimes if (chdir(cp) < 0) { 1782603Sdg warn("%s", cp); 1791558Srgrimes return (1); 1801558Srgrimes } 1811558Srgrimes return (0); 1821558Srgrimes} 18323675Speter 18423675Speterint 18523675Speterrespond(int *msgvec) 18623675Speter{ 1871558Srgrimes if (value("Replyall") == NULL && value("flipr") == NULL) 1881558Srgrimes return (dorespond(msgvec)); 1891558Srgrimes else 1901558Srgrimes return (doRespond(msgvec)); 1911558Srgrimes} 1921558Srgrimes 1931558Srgrimes/* 1941558Srgrimes * Reply to a list of messages. Extract each name from the 19541474Sjulian * message header and send them off to mail1() 1961558Srgrimes */ 1971558Srgrimesint 1981558Srgrimesdorespond(int *msgvec) 1991558Srgrimes{ 20023999Speter struct message *mp; 20123999Speter char *cp, *rcv, *replyto; 2021558Srgrimes char **ap; 2031558Srgrimes struct name *np; 2041558Srgrimes struct header head; 2051558Srgrimes 2061558Srgrimes if (msgvec[1] != 0) { 2071558Srgrimes printf("Sorry, can't reply to multiple messages at once\n"); 2081558Srgrimes return (1); 2091558Srgrimes } 2101558Srgrimes mp = &message[msgvec[0] - 1]; 2111558Srgrimes touch(mp); 2121558Srgrimes dot = mp; 2131558Srgrimes if ((rcv = skin(hfield("from", mp))) == NULL) 2141558Srgrimes rcv = skin(nameof(mp, 1)); 2151558Srgrimes if ((replyto = skin(hfield("reply-to", mp))) != NULL) 2161558Srgrimes np = extract(replyto, GTO); 2171558Srgrimes else if ((cp = skin(hfield("to", mp))) != NULL) 2181558Srgrimes np = extract(cp, GTO); 2191558Srgrimes else 2201558Srgrimes np = NULL; 2211558Srgrimes np = elide(np); 2221558Srgrimes /* 2231558Srgrimes * Delete my name from the reply list, 2241558Srgrimes * and with it, all my alternate names. 2252603Sdg */ 2261558Srgrimes np = delname(np, myname); 2271558Srgrimes if (altnames) 2282603Sdg for (ap = altnames; *ap != NULL; ap++) 22923675Speter np = delname(np, *ap); 2301558Srgrimes if (np != NULL && replyto == NULL) 2311558Srgrimes np = cat(np, extract(rcv, GTO)); 23237236Sbde else if (np == NULL) { 23341474Sjulian if (replyto != NULL) 2341558Srgrimes printf("Empty reply-to field -- replying to author\n"); 2351558Srgrimes np = extract(rcv, GTO); 23623675Speter } 2371558Srgrimes head.h_to = np; 2381558Srgrimes if ((head.h_subject = hfield("subject", mp)) == NULL) 2391558Srgrimes head.h_subject = hfield("subj", mp); 2401558Srgrimes head.h_subject = reedit(head.h_subject); 2411558Srgrimes if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) { 2421558Srgrimes np = elide(extract(cp, GCC)); 2431558Srgrimes np = delname(np, myname); 24441474Sjulian if (altnames != 0) 24523675Speter for (ap = altnames; *ap != NULL; ap++) 2461558Srgrimes np = delname(np, *ap); 2471558Srgrimes head.h_cc = np; 2481558Srgrimes } else 2491558Srgrimes head.h_cc = NULL; 2501558Srgrimes head.h_bcc = NULL; 2511558Srgrimes head.h_smopts = NULL; 2521558Srgrimes head.h_replyto = value("REPLYTO"); 2531558Srgrimes head.h_inreplyto = skin(hfield("message-id", mp)); 2541558Srgrimes mail1(&head, 1); 2551558Srgrimes return (0); 2561558Srgrimes} 25737236Sbde 25837236Sbde/* 2591558Srgrimes * Modify the subject we are replying to to begin with Re: if 2601558Srgrimes * it does not already. 2611558Srgrimes */ 2621558Srgrimeschar * 2631558Srgrimesreedit(char *subj) 2641558Srgrimes{ 2651558Srgrimes char *newsubj; 2661558Srgrimes 26737236Sbde if (subj == NULL) 2681558Srgrimes return (NULL); 2691558Srgrimes if ((subj[0] == 'r' || subj[0] == 'R') && 2701558Srgrimes (subj[1] == 'e' || subj[1] == 'E') && 2711558Srgrimes subj[2] == ':') 2721558Srgrimes return (subj); 27341474Sjulian newsubj = salloc(strlen(subj) + 5); 2741558Srgrimes sprintf(newsubj, "Re: %s", subj); 2751558Srgrimes return (newsubj); 2761558Srgrimes} 2771558Srgrimes 27834266Sjulian/* 27934266Sjulian * Preserve the named messages, so that they will be sent 28023675Speter * back to the system mailbox. 28134266Sjulian */ 2821558Srgrimesint 2831558Srgrimespreserve(int *msgvec) 2841558Srgrimes{ 2851558Srgrimes int *ip, mesg; 2861558Srgrimes struct message *mp; 2871558Srgrimes 2881558Srgrimes if (edit) { 2891558Srgrimes printf("Cannot \"preserve\" in edit mode\n"); 29041474Sjulian return (1); 2911558Srgrimes } 29241474Sjulian for (ip = msgvec; *ip != 0; ip++) { 2931558Srgrimes mesg = *ip; 29441474Sjulian mp = &message[mesg-1]; 2951558Srgrimes mp->m_flag |= MPRESERVE; 29641474Sjulian mp->m_flag &= ~MBOX; 29741474Sjulian dot = mp; 2981558Srgrimes } 2991558Srgrimes return (0); 3001558Srgrimes} 3011558Srgrimes 3021558Srgrimes/* 3031558Srgrimes * Mark all given messages as unread. 3041558Srgrimes */ 3051558Srgrimesint 3061558Srgrimesunread(int msgvec[]) 3071558Srgrimes{ 3081558Srgrimes int *ip; 30962668Smckusick 31062668Smckusick for (ip = msgvec; *ip != 0; ip++) { 31162668Smckusick dot = &message[*ip-1]; 31262668Smckusick dot->m_flag &= ~(MREAD|MTOUCH); 3131558Srgrimes dot->m_flag |= MSTATUS; 3141558Srgrimes } 3151558Srgrimes return (0); 3161558Srgrimes} 3171558Srgrimes 3181558Srgrimes/* 3191558Srgrimes * Print the size of each message. 3201558Srgrimes */ 3211558Srgrimesint 3221558Srgrimesmessize(int *msgvec) 3231558Srgrimes{ 3241558Srgrimes struct message *mp; 3251558Srgrimes int *ip, mesg; 3261558Srgrimes 3271558Srgrimes for (ip = msgvec; *ip != 0; ip++) { 3281558Srgrimes mesg = *ip; 32941474Sjulian mp = &message[mesg-1]; 3301558Srgrimes printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 33141474Sjulian } 3321558Srgrimes return (0); 3331558Srgrimes} 3341558Srgrimes 3351558Srgrimes/* 3361558Srgrimes * Quit quickly. If we are sourcing, just pop the input level 3371558Srgrimes * by returning an error. 3387585Sbde */ 3391558Srgrimesint 3401558Srgrimesrexit(int e __unused) 3411558Srgrimes{ 3421558Srgrimes if (sourcing) 3431558Srgrimes return (1); 34423675Speter exit(0); 3451558Srgrimes /*NOTREACHED*/ 3461558Srgrimes} 3471558Srgrimes 34862668Smckusick/* 34962668Smckusick * Set or display a variable value. Syntax is similar to that 35062668Smckusick * of csh. 35162668Smckusick */ 35262668Smckusickint 35362668Smckusickset(char **arglist) 35462668Smckusick{ 35562668Smckusick struct var *vp; 35662668Smckusick char *cp, *cp2; 35762668Smckusick char varbuf[BUFSIZ], **ap, **p; 35862668Smckusick int errs, h, s; 35962668Smckusick 36062668Smckusick if (*arglist == NULL) { 36162668Smckusick for (h = 0, s = 1; h < HSHSIZE; h++) 36262668Smckusick for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3631558Srgrimes s++; 3641558Srgrimes ap = (char **)salloc(s * sizeof(*ap)); 3651558Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 3661558Srgrimes for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3671558Srgrimes *p++ = vp->v_name; 3681558Srgrimes *p = NULL; 3691558Srgrimes sort(ap); 37034266Sjulian for (p = ap; *p != NULL; p++) 37134266Sjulian printf("%s\t%s\n", *p, value(*p)); 37223675Speter return (0); 37334266Sjulian } 3741558Srgrimes errs = 0; 3751558Srgrimes for (ap = arglist; *ap != NULL; ap++) { 3761558Srgrimes cp = *ap; 3771558Srgrimes cp2 = varbuf; 3781558Srgrimes while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3791558Srgrimes *cp2++ = *cp++; 3801558Srgrimes *cp2 = '\0'; 3811558Srgrimes if (*cp == '\0') 3821558Srgrimes cp = ""; 3831558Srgrimes else 3841558Srgrimes cp++; 3851558Srgrimes if (equal(varbuf, "")) { 3861558Srgrimes printf("Non-null variable name required\n"); 3871558Srgrimes errs++; 3881558Srgrimes continue; 3891558Srgrimes } 39034266Sjulian assign(varbuf, cp); 39134266Sjulian } 39223675Speter return (errs); 39334266Sjulian} 3941558Srgrimes 3951558Srgrimes/* 3961558Srgrimes * Unset a bunch of variable values. 3971558Srgrimes */ 3981558Srgrimesint 39934266Sjulianunset(char **arglist) 40034266Sjulian{ 40123675Speter struct var *vp, *vp2; 40234266Sjulian int errs, h; 4031558Srgrimes char **ap; 4041558Srgrimes 4051558Srgrimes errs = 0; 4061558Srgrimes for (ap = arglist; *ap != NULL; ap++) { 4071558Srgrimes if ((vp2 = lookup(*ap)) == NULL) { 4081558Srgrimes if (getenv(*ap)) 4091558Srgrimes unsetenv(*ap); 4101558Srgrimes else if (!sourcing) { 4111558Srgrimes printf("\"%s\": undefined variable\n", *ap); 4121558Srgrimes errs++; 4131558Srgrimes } 4141558Srgrimes continue; 4151558Srgrimes } 4161558Srgrimes h = hash(*ap); 4171558Srgrimes if (vp2 == variables[h]) { 4181558Srgrimes variables[h] = variables[h]->v_link; 4191558Srgrimes vfree(vp2->v_name); 4201558Srgrimes vfree(vp2->v_value); 4211558Srgrimes (void)free(vp2); 4221558Srgrimes continue; 4231558Srgrimes } 4241558Srgrimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4251558Srgrimes ; 426 vp->v_link = vp2->v_link; 427 vfree(vp2->v_name); 428 vfree(vp2->v_value); 429 (void)free(vp2); 430 } 431 return (errs); 432} 433 434/* 435 * Put add users to a group. 436 */ 437int 438group(char **argv) 439{ 440 struct grouphead *gh; 441 struct group *gp; 442 char **ap, *gname, **p; 443 int h, s; 444 445 if (*argv == NULL) { 446 for (h = 0, s = 1; h < HSHSIZE; h++) 447 for (gh = groups[h]; gh != NULL; gh = gh->g_link) 448 s++; 449 ap = (char **)salloc(s * sizeof(*ap)); 450 for (h = 0, p = ap; h < HSHSIZE; h++) 451 for (gh = groups[h]; gh != NULL; gh = gh->g_link) 452 *p++ = gh->g_name; 453 *p = NULL; 454 sort(ap); 455 for (p = ap; *p != NULL; p++) 456 printgroup(*p); 457 return (0); 458 } 459 if (argv[1] == NULL) { 460 printgroup(*argv); 461 return (0); 462 } 463 gname = *argv; 464 h = hash(gname); 465 if ((gh = findgroup(gname)) == NULL) { 466 gh = calloc(sizeof(*gh), 1); 467 gh->g_name = vcopy(gname); 468 gh->g_list = NULL; 469 gh->g_link = groups[h]; 470 groups[h] = gh; 471 } 472 473 /* 474 * Insert names from the command list into the group. 475 * Who cares if there are duplicates? They get tossed 476 * later anyway. 477 */ 478 479 for (ap = argv+1; *ap != NULL; ap++) { 480 gp = calloc(sizeof(*gp), 1); 481 gp->ge_name = vcopy(*ap); 482 gp->ge_link = gh->g_list; 483 gh->g_list = gp; 484 } 485 return (0); 486} 487 488/* 489 * Sort the passed string vecotor into ascending dictionary 490 * order. 491 */ 492void 493sort(char **list) 494{ 495 char **ap; 496 497 for (ap = list; *ap != NULL; ap++) 498 ; 499 if (ap-list < 2) 500 return; 501 qsort(list, ap-list, sizeof(*list), diction); 502} 503 504/* 505 * Do a dictionary order comparison of the arguments from 506 * qsort. 507 */ 508int 509diction(const void *a, const void *b) 510{ 511 return (strcmp(*(const char **)a, *(const char **)b)); 512} 513 514/* 515 * The do nothing command for comments. 516 */ 517 518/*ARGSUSED*/ 519int 520null(int e __unused) 521{ 522 return (0); 523} 524 525/* 526 * Change to another file. With no argument, print information about 527 * the current file. 528 */ 529int 530file(char **argv) 531{ 532 533 if (argv[0] == NULL) { 534 newfileinfo(0); 535 return (0); 536 } 537 if (setfile(*argv) < 0) 538 return (1); 539 announce(); 540 return (0); 541} 542 543/* 544 * Expand file names like echo 545 */ 546int 547echo(char **argv) 548{ 549 char **ap, *cp; 550 551 for (ap = argv; *ap != NULL; ap++) { 552 cp = *ap; 553 if ((cp = expand(cp)) != NULL) { 554 if (ap != argv) 555 printf(" "); 556 printf("%s", cp); 557 } 558 } 559 printf("\n"); 560 return (0); 561} 562 563int 564Respond(int *msgvec) 565{ 566 if (value("Replyall") == NULL && value("flipr") == NULL) 567 return (doRespond(msgvec)); 568 else 569 return (dorespond(msgvec)); 570} 571 572/* 573 * Reply to a series of messages by simply mailing to the senders 574 * and not messing around with the To: and Cc: lists as in normal 575 * reply. 576 */ 577int 578doRespond(int msgvec[]) 579{ 580 struct header head; 581 struct message *mp; 582 int *ap; 583 char *cp, *mid; 584 585 head.h_to = NULL; 586 for (ap = msgvec; *ap != 0; ap++) { 587 mp = &message[*ap - 1]; 588 touch(mp); 589 dot = mp; 590 if ((cp = skin(hfield("from", mp))) == NULL) 591 cp = skin(nameof(mp, 2)); 592 head.h_to = cat(head.h_to, extract(cp, GTO)); 593 mid = skin(hfield("message-id", mp)); 594 } 595 if (head.h_to == NULL) 596 return (0); 597 mp = &message[msgvec[0] - 1]; 598 if ((head.h_subject = hfield("subject", mp)) == NULL) 599 head.h_subject = hfield("subj", mp); 600 head.h_subject = reedit(head.h_subject); 601 head.h_cc = NULL; 602 head.h_bcc = NULL; 603 head.h_smopts = NULL; 604 head.h_replyto = value("REPLYTO"); 605 head.h_inreplyto = mid; 606 mail1(&head, 1); 607 return (0); 608} 609 610/* 611 * Conditional commands. These allow one to parameterize one's 612 * .mailrc and do some things if sending, others if receiving. 613 */ 614int 615ifcmd(char **argv) 616{ 617 char *cp; 618 619 if (cond != CANY) { 620 printf("Illegal nested \"if\"\n"); 621 return (1); 622 } 623 cond = CANY; 624 cp = argv[0]; 625 switch (*cp) { 626 case 'r': case 'R': 627 cond = CRCV; 628 break; 629 630 case 's': case 'S': 631 cond = CSEND; 632 break; 633 634 default: 635 printf("Unrecognized if-keyword: \"%s\"\n", cp); 636 return (1); 637 } 638 return (0); 639} 640 641/* 642 * Implement 'else'. This is pretty simple -- we just 643 * flip over the conditional flag. 644 */ 645int 646elsecmd(void) 647{ 648 649 switch (cond) { 650 case CANY: 651 printf("\"Else\" without matching \"if\"\n"); 652 return (1); 653 654 case CSEND: 655 cond = CRCV; 656 break; 657 658 case CRCV: 659 cond = CSEND; 660 break; 661 662 default: 663 printf("Mail's idea of conditions is screwed up\n"); 664 cond = CANY; 665 break; 666 } 667 return (0); 668} 669 670/* 671 * End of if statement. Just set cond back to anything. 672 */ 673int 674endifcmd(void) 675{ 676 677 if (cond == CANY) { 678 printf("\"Endif\" without matching \"if\"\n"); 679 return (1); 680 } 681 cond = CANY; 682 return (0); 683} 684 685/* 686 * Set the list of alternate names. 687 */ 688int 689alternates(char **namelist) 690{ 691 int c; 692 char **ap, **ap2, *cp; 693 694 c = argcount(namelist) + 1; 695 if (c == 1) { 696 if (altnames == 0) 697 return (0); 698 for (ap = altnames; *ap != NULL; ap++) 699 printf("%s ", *ap); 700 printf("\n"); 701 return (0); 702 } 703 if (altnames != 0) 704 (void)free(altnames); 705 altnames = calloc((unsigned)c, sizeof(char *)); 706 for (ap = namelist, ap2 = altnames; *ap != NULL; ap++, ap2++) { 707 cp = calloc((unsigned)strlen(*ap) + 1, sizeof(char)); 708 strcpy(cp, *ap); 709 *ap2 = cp; 710 } 711 *ap2 = 0; 712 return (0); 713} 714