cmd3.c revision 77274
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3574769Smikeh#if 0 361590Srgrimesstatic char sccsid[] = "@(#)cmd3.c 8.1 (Berkeley) 6/6/93"; 3774769Smikeh#endif 3874769Smikehstatic const char rcsid[] = 3974769Smikeh "$FreeBSD: head/usr.bin/mail/cmd3.c 77274 2001-05-27 20:26:22Z mikeh $"; 401590Srgrimes#endif /* not lint */ 411590Srgrimes 421590Srgrimes#include "rcv.h" 431590Srgrimes#include "extern.h" 441590Srgrimes 451590Srgrimes/* 461590Srgrimes * Mail -- a mail program 471590Srgrimes * 481590Srgrimes * Still more user commands. 491590Srgrimes */ 501590Srgrimes 511590Srgrimes/* 521590Srgrimes * Process a shell escape by saving signals, ignoring signals, 531590Srgrimes * and forking a sh -c 541590Srgrimes */ 551590Srgrimesint 561590Srgrimesshell(str) 571590Srgrimes char *str; 581590Srgrimes{ 591590Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 6077274Smikeh char *sh; 611590Srgrimes char cmd[BUFSIZ]; 621590Srgrimes 6374769Smikeh if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd)) 6477274Smikeh return (1); 6574769Smikeh if (bangexp(cmd, sizeof(cmd)) < 0) 6677274Smikeh return (1); 6777274Smikeh if ((sh = value("SHELL")) == NULL) 6877274Smikeh sh = _PATH_CSHELL; 6977274Smikeh (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL); 7077274Smikeh (void)signal(SIGINT, sigint); 711590Srgrimes printf("!\n"); 7277274Smikeh return (0); 731590Srgrimes} 741590Srgrimes 751590Srgrimes/* 761590Srgrimes * Fork an interactive shell. 771590Srgrimes */ 781590Srgrimes/*ARGSUSED*/ 791590Srgrimesint 801590Srgrimesdosh(str) 811590Srgrimes char *str; 821590Srgrimes{ 831590Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 8477274Smikeh char *sh; 851590Srgrimes 8677274Smikeh if ((sh = value("SHELL")) == NULL) 8777274Smikeh sh = _PATH_CSHELL; 8877274Smikeh (void)run_command(sh, 0, -1, -1, NULL, NULL, NULL); 8977274Smikeh (void)signal(SIGINT, sigint); 9077274Smikeh printf("\n"); 9177274Smikeh return (0); 921590Srgrimes} 931590Srgrimes 941590Srgrimes/* 951590Srgrimes * Expand the shell escape by expanding unescaped !'s into the 961590Srgrimes * last issued command where possible. 971590Srgrimes */ 981590Srgrimesint 9974769Smikehbangexp(str, strsize) 1001590Srgrimes char *str; 10174769Smikeh size_t strsize; 1021590Srgrimes{ 1031590Srgrimes char bangbuf[BUFSIZ]; 10474769Smikeh static char lastbang[BUFSIZ]; 10577274Smikeh char *cp, *cp2; 10677274Smikeh int n, changed = 0; 1071590Srgrimes 1081590Srgrimes cp = str; 1091590Srgrimes cp2 = bangbuf; 11074769Smikeh n = sizeof(bangbuf); 11177274Smikeh while (*cp != '\0') { 1121590Srgrimes if (*cp == '!') { 1131590Srgrimes if (n < strlen(lastbang)) { 1141590Srgrimesoverf: 1151590Srgrimes printf("Command buffer overflow\n"); 11677274Smikeh return (-1); 1171590Srgrimes } 1181590Srgrimes changed++; 11974769Smikeh if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf)) 12074769Smikeh >= sizeof(bangbuf) - (cp2 - bangbuf)) 12174769Smikeh goto overf; 1221590Srgrimes cp2 += strlen(lastbang); 1231590Srgrimes n -= strlen(lastbang); 1241590Srgrimes cp++; 1251590Srgrimes continue; 1261590Srgrimes } 1271590Srgrimes if (*cp == '\\' && cp[1] == '!') { 1281590Srgrimes if (--n <= 1) 1291590Srgrimes goto overf; 1301590Srgrimes *cp2++ = '!'; 1311590Srgrimes cp += 2; 1321590Srgrimes changed++; 1331590Srgrimes } 1341590Srgrimes if (--n <= 1) 1351590Srgrimes goto overf; 1361590Srgrimes *cp2++ = *cp++; 1371590Srgrimes } 1381590Srgrimes *cp2 = 0; 1391590Srgrimes if (changed) { 1401590Srgrimes printf("!%s\n", bangbuf); 14177274Smikeh (void)fflush(stdout); 1421590Srgrimes } 14374769Smikeh if (strlcpy(str, bangbuf, strsize) >= strsize) 14474769Smikeh goto overf; 14574769Smikeh if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang)) 14674769Smikeh goto overf; 14777274Smikeh return (0); 1481590Srgrimes} 1491590Srgrimes 1501590Srgrimes/* 1511590Srgrimes * Print out a nice help message from some file or another. 1521590Srgrimes */ 1531590Srgrimes 1541590Srgrimesint 1551590Srgrimeshelp() 1561590Srgrimes{ 15777274Smikeh int c; 15877274Smikeh FILE *f; 1591590Srgrimes 1601590Srgrimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 16174769Smikeh warn("%s", _PATH_HELP); 16277274Smikeh return (1); 1631590Srgrimes } 1641590Srgrimes while ((c = getc(f)) != EOF) 1651590Srgrimes putchar(c); 16677274Smikeh (void)Fclose(f); 16777274Smikeh return (0); 1681590Srgrimes} 1691590Srgrimes 1701590Srgrimes/* 1711590Srgrimes * Change user's working directory. 1721590Srgrimes */ 1731590Srgrimesint 1741590Srgrimesschdir(arglist) 1751590Srgrimes char **arglist; 1761590Srgrimes{ 1771590Srgrimes char *cp; 1781590Srgrimes 17977274Smikeh if (*arglist == NULL) { 18077274Smikeh if (homedir == NULL) 18177274Smikeh return (1); 1821590Srgrimes cp = homedir; 18374769Smikeh } else 18477274Smikeh if ((cp = expand(*arglist)) == NULL) 18577274Smikeh return (1); 1861590Srgrimes if (chdir(cp) < 0) { 18774769Smikeh warn("%s", cp); 18877274Smikeh return (1); 1891590Srgrimes } 19077274Smikeh return (0); 1911590Srgrimes} 1921590Srgrimes 1931590Srgrimesint 1941590Srgrimesrespond(msgvec) 1951590Srgrimes int *msgvec; 1961590Srgrimes{ 19777274Smikeh if (value("Replyall") == NULL) 19832189Sjoerg return (dorespond(msgvec)); 1991590Srgrimes else 20032189Sjoerg return (doRespond(msgvec)); 2011590Srgrimes} 2021590Srgrimes 2031590Srgrimes/* 2041590Srgrimes * Reply to a list of messages. Extract each name from the 2051590Srgrimes * message header and send them off to mail1() 2061590Srgrimes */ 2071590Srgrimesint 20832189Sjoergdorespond(msgvec) 2091590Srgrimes int *msgvec; 2101590Srgrimes{ 2111590Srgrimes struct message *mp; 2121590Srgrimes char *cp, *rcv, *replyto; 2131590Srgrimes char **ap; 2141590Srgrimes struct name *np; 2151590Srgrimes struct header head; 2161590Srgrimes 2171590Srgrimes if (msgvec[1] != 0) { 2181590Srgrimes printf("Sorry, can't reply to multiple messages at once\n"); 21977274Smikeh return (1); 2201590Srgrimes } 2211590Srgrimes mp = &message[msgvec[0] - 1]; 2221590Srgrimes touch(mp); 2231590Srgrimes dot = mp; 22477274Smikeh if ((rcv = skin(hfield("from", mp))) == NULL) 2251590Srgrimes rcv = skin(nameof(mp, 1)); 22677274Smikeh if ((replyto = skin(hfield("reply-to", mp))) != NULL) 2271590Srgrimes np = extract(replyto, GTO); 22877274Smikeh else if ((cp = skin(hfield("to", mp))) != NULL) 2291590Srgrimes np = extract(cp, GTO); 2301590Srgrimes else 23177274Smikeh np = NULL; 2321590Srgrimes np = elide(np); 2331590Srgrimes /* 2341590Srgrimes * Delete my name from the reply list, 2351590Srgrimes * and with it, all my alternate names. 2361590Srgrimes */ 2371590Srgrimes np = delname(np, myname); 2381590Srgrimes if (altnames) 23977274Smikeh for (ap = altnames; *ap != NULL; ap++) 2401590Srgrimes np = delname(np, *ap); 24177274Smikeh if (np != NULL && replyto == NULL) 2421590Srgrimes np = cat(np, extract(rcv, GTO)); 24377274Smikeh else if (np == NULL) { 24477274Smikeh if (replyto != NULL) 2451590Srgrimes printf("Empty reply-to field -- replying to author\n"); 2461590Srgrimes np = extract(rcv, GTO); 2471590Srgrimes } 2481590Srgrimes head.h_to = np; 24977274Smikeh if ((head.h_subject = hfield("subject", mp)) == NULL) 2501590Srgrimes head.h_subject = hfield("subj", mp); 2511590Srgrimes head.h_subject = reedit(head.h_subject); 25277274Smikeh if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) { 2531590Srgrimes np = elide(extract(cp, GCC)); 2541590Srgrimes np = delname(np, myname); 2551590Srgrimes if (altnames != 0) 25677274Smikeh for (ap = altnames; *ap != NULL; ap++) 2571590Srgrimes np = delname(np, *ap); 2581590Srgrimes head.h_cc = np; 2591590Srgrimes } else 26077274Smikeh head.h_cc = NULL; 26177274Smikeh head.h_bcc = NULL; 26277274Smikeh head.h_smopts = NULL; 26332189Sjoerg if ((head.h_replyto = getenv("REPLYTO")) == NULL) 26477274Smikeh head.h_replyto = NULL; 26532189Sjoerg head.h_inreplyto = skin(hfield("message-id", mp)); 2661590Srgrimes mail1(&head, 1); 26777274Smikeh return (0); 2681590Srgrimes} 2691590Srgrimes 2701590Srgrimes/* 2711590Srgrimes * Modify the subject we are replying to to begin with Re: if 2721590Srgrimes * it does not already. 2731590Srgrimes */ 2741590Srgrimeschar * 2751590Srgrimesreedit(subj) 27677274Smikeh char *subj; 2771590Srgrimes{ 2781590Srgrimes char *newsubj; 2791590Srgrimes 28077274Smikeh if (subj == NULL) 28177274Smikeh return (NULL); 2821590Srgrimes if ((subj[0] == 'r' || subj[0] == 'R') && 2831590Srgrimes (subj[1] == 'e' || subj[1] == 'E') && 2841590Srgrimes subj[2] == ':') 28577274Smikeh return (subj); 2861590Srgrimes newsubj = salloc(strlen(subj) + 5); 28774769Smikeh sprintf(newsubj, "Re: %s", subj); 28877274Smikeh return (newsubj); 2891590Srgrimes} 2901590Srgrimes 2911590Srgrimes/* 2921590Srgrimes * Preserve the named messages, so that they will be sent 2931590Srgrimes * back to the system mailbox. 2941590Srgrimes */ 2951590Srgrimesint 2961590Srgrimespreserve(msgvec) 2971590Srgrimes int *msgvec; 2981590Srgrimes{ 29977274Smikeh int *ip, mesg; 30077274Smikeh struct message *mp; 3011590Srgrimes 3021590Srgrimes if (edit) { 3031590Srgrimes printf("Cannot \"preserve\" in edit mode\n"); 30477274Smikeh return (1); 3051590Srgrimes } 30629574Sphk for (ip = msgvec; *ip != 0; ip++) { 3071590Srgrimes mesg = *ip; 3081590Srgrimes mp = &message[mesg-1]; 3091590Srgrimes mp->m_flag |= MPRESERVE; 3101590Srgrimes mp->m_flag &= ~MBOX; 3111590Srgrimes dot = mp; 3121590Srgrimes } 31377274Smikeh return (0); 3141590Srgrimes} 3151590Srgrimes 3161590Srgrimes/* 3171590Srgrimes * Mark all given messages as unread. 3181590Srgrimes */ 3191590Srgrimesint 3201590Srgrimesunread(msgvec) 3211590Srgrimes int msgvec[]; 3221590Srgrimes{ 32377274Smikeh int *ip; 3241590Srgrimes 32529574Sphk for (ip = msgvec; *ip != 0; ip++) { 3261590Srgrimes dot = &message[*ip-1]; 3271590Srgrimes dot->m_flag &= ~(MREAD|MTOUCH); 3281590Srgrimes dot->m_flag |= MSTATUS; 3291590Srgrimes } 33077274Smikeh return (0); 3311590Srgrimes} 3321590Srgrimes 3331590Srgrimes/* 3341590Srgrimes * Print the size of each message. 3351590Srgrimes */ 3361590Srgrimesint 3371590Srgrimesmessize(msgvec) 3381590Srgrimes int *msgvec; 3391590Srgrimes{ 34077274Smikeh struct message *mp; 34177274Smikeh int *ip, mesg; 3421590Srgrimes 34329574Sphk for (ip = msgvec; *ip != 0; ip++) { 3441590Srgrimes mesg = *ip; 3451590Srgrimes mp = &message[mesg-1]; 34637453Sbde printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3471590Srgrimes } 34877274Smikeh return (0); 3491590Srgrimes} 3501590Srgrimes 3511590Srgrimes/* 3521590Srgrimes * Quit quickly. If we are sourcing, just pop the input level 3531590Srgrimes * by returning an error. 3541590Srgrimes */ 3551590Srgrimesint 3561590Srgrimesrexit(e) 3571590Srgrimes int e; 3581590Srgrimes{ 3591590Srgrimes if (sourcing) 36077274Smikeh return (1); 3611590Srgrimes exit(e); 3621590Srgrimes /*NOTREACHED*/ 3631590Srgrimes} 3641590Srgrimes 3651590Srgrimes/* 3661590Srgrimes * Set or display a variable value. Syntax is similar to that 3671590Srgrimes * of csh. 3681590Srgrimes */ 3691590Srgrimesint 3701590Srgrimesset(arglist) 3711590Srgrimes char **arglist; 3721590Srgrimes{ 37377274Smikeh struct var *vp; 37477274Smikeh char *cp, *cp2; 3751590Srgrimes char varbuf[BUFSIZ], **ap, **p; 3761590Srgrimes int errs, h, s; 3771590Srgrimes 37877274Smikeh if (*arglist == NULL) { 3791590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 38077274Smikeh for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3811590Srgrimes s++; 38277274Smikeh ap = (char **)salloc(s * sizeof(*ap)); 3831590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 38477274Smikeh for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3851590Srgrimes *p++ = vp->v_name; 38677274Smikeh *p = NULL; 3871590Srgrimes sort(ap); 38877274Smikeh for (p = ap; *p != NULL; p++) 3891590Srgrimes printf("%s\t%s\n", *p, value(*p)); 39077274Smikeh return (0); 3911590Srgrimes } 3921590Srgrimes errs = 0; 39377274Smikeh for (ap = arglist; *ap != NULL; ap++) { 3941590Srgrimes cp = *ap; 3951590Srgrimes cp2 = varbuf; 39674769Smikeh while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3971590Srgrimes *cp2++ = *cp++; 3981590Srgrimes *cp2 = '\0'; 3991590Srgrimes if (*cp == '\0') 4001590Srgrimes cp = ""; 4011590Srgrimes else 4021590Srgrimes cp++; 4031590Srgrimes if (equal(varbuf, "")) { 4041590Srgrimes printf("Non-null variable name required\n"); 4051590Srgrimes errs++; 4061590Srgrimes continue; 4071590Srgrimes } 4081590Srgrimes assign(varbuf, cp); 4091590Srgrimes } 41077274Smikeh return (errs); 4111590Srgrimes} 4121590Srgrimes 4131590Srgrimes/* 4141590Srgrimes * Unset a bunch of variable values. 4151590Srgrimes */ 4161590Srgrimesint 4171590Srgrimesunset(arglist) 4181590Srgrimes char **arglist; 4191590Srgrimes{ 42077274Smikeh struct var *vp, *vp2; 4211590Srgrimes int errs, h; 4221590Srgrimes char **ap; 4231590Srgrimes 4241590Srgrimes errs = 0; 42577274Smikeh for (ap = arglist; *ap != NULL; ap++) { 42677274Smikeh if ((vp2 = lookup(*ap)) == NULL) { 4271590Srgrimes if (!sourcing) { 4281590Srgrimes printf("\"%s\": undefined variable\n", *ap); 4291590Srgrimes errs++; 4301590Srgrimes } 4311590Srgrimes continue; 4321590Srgrimes } 4331590Srgrimes h = hash(*ap); 4341590Srgrimes if (vp2 == variables[h]) { 4351590Srgrimes variables[h] = variables[h]->v_link; 4361590Srgrimes vfree(vp2->v_name); 4371590Srgrimes vfree(vp2->v_value); 43877274Smikeh (void)free(vp2); 4391590Srgrimes continue; 4401590Srgrimes } 4411590Srgrimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4421590Srgrimes ; 4431590Srgrimes vp->v_link = vp2->v_link; 4441590Srgrimes vfree(vp2->v_name); 4451590Srgrimes vfree(vp2->v_value); 44677274Smikeh (void)free(vp2); 4471590Srgrimes } 44877274Smikeh return (errs); 4491590Srgrimes} 4501590Srgrimes 4511590Srgrimes/* 4521590Srgrimes * Put add users to a group. 4531590Srgrimes */ 4541590Srgrimesint 4551590Srgrimesgroup(argv) 4561590Srgrimes char **argv; 4571590Srgrimes{ 45877274Smikeh struct grouphead *gh; 45977274Smikeh struct group *gp; 4601590Srgrimes char **ap, *gname, **p; 46177274Smikeh int h, s; 4621590Srgrimes 46377274Smikeh if (*argv == NULL) { 4641590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 46577274Smikeh for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4661590Srgrimes s++; 46777274Smikeh ap = (char **)salloc(s * sizeof(*ap)); 4681590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 46977274Smikeh for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4701590Srgrimes *p++ = gh->g_name; 47177274Smikeh *p = NULL; 4721590Srgrimes sort(ap); 47377274Smikeh for (p = ap; *p != NULL; p++) 4741590Srgrimes printgroup(*p); 47577274Smikeh return (0); 4761590Srgrimes } 47777274Smikeh if (argv[1] == NULL) { 4781590Srgrimes printgroup(*argv); 47977274Smikeh return (0); 4801590Srgrimes } 4811590Srgrimes gname = *argv; 4821590Srgrimes h = hash(gname); 48377274Smikeh if ((gh = findgroup(gname)) == NULL) { 48477274Smikeh gh = calloc(sizeof(*gh), 1); 4851590Srgrimes gh->g_name = vcopy(gname); 48677274Smikeh gh->g_list = NULL; 4871590Srgrimes gh->g_link = groups[h]; 4881590Srgrimes groups[h] = gh; 4891590Srgrimes } 4901590Srgrimes 4911590Srgrimes /* 4921590Srgrimes * Insert names from the command list into the group. 4931590Srgrimes * Who cares if there are duplicates? They get tossed 4941590Srgrimes * later anyway. 4951590Srgrimes */ 4961590Srgrimes 49777274Smikeh for (ap = argv+1; *ap != NULL; ap++) { 49877274Smikeh gp = calloc(sizeof(*gp), 1); 4991590Srgrimes gp->ge_name = vcopy(*ap); 5001590Srgrimes gp->ge_link = gh->g_list; 5011590Srgrimes gh->g_list = gp; 5021590Srgrimes } 50377274Smikeh return (0); 5041590Srgrimes} 5051590Srgrimes 5061590Srgrimes/* 5071590Srgrimes * Sort the passed string vecotor into ascending dictionary 5081590Srgrimes * order. 5091590Srgrimes */ 5101590Srgrimesvoid 5111590Srgrimessort(list) 5121590Srgrimes char **list; 5131590Srgrimes{ 51477274Smikeh char **ap; 5151590Srgrimes 51677274Smikeh for (ap = list; *ap != NULL; ap++) 5171590Srgrimes ; 5181590Srgrimes if (ap-list < 2) 5191590Srgrimes return; 5201590Srgrimes qsort(list, ap-list, sizeof(*list), diction); 5211590Srgrimes} 5221590Srgrimes 5231590Srgrimes/* 5241590Srgrimes * Do a dictionary order comparison of the arguments from 5251590Srgrimes * qsort. 5261590Srgrimes */ 5271590Srgrimesint 5281590Srgrimesdiction(a, b) 5291590Srgrimes const void *a, *b; 5301590Srgrimes{ 53177274Smikeh return (strcmp(*(const char **)a, *(const char **)b)); 5321590Srgrimes} 5331590Srgrimes 5341590Srgrimes/* 5351590Srgrimes * The do nothing command for comments. 5361590Srgrimes */ 5371590Srgrimes 5381590Srgrimes/*ARGSUSED*/ 5391590Srgrimesint 5401590Srgrimesnull(e) 5411590Srgrimes int e; 5421590Srgrimes{ 54377274Smikeh return (0); 5441590Srgrimes} 5451590Srgrimes 5461590Srgrimes/* 5471590Srgrimes * Change to another file. With no argument, print information about 5481590Srgrimes * the current file. 5491590Srgrimes */ 5501590Srgrimesint 5511590Srgrimesfile(argv) 55277274Smikeh char **argv; 5531590Srgrimes{ 5541590Srgrimes 55577274Smikeh if (argv[0] == NULL) { 5561590Srgrimes newfileinfo(); 55777274Smikeh return (0); 5581590Srgrimes } 5591590Srgrimes if (setfile(*argv) < 0) 56077274Smikeh return (1); 5611590Srgrimes announce(); 56277274Smikeh return (0); 5631590Srgrimes} 5641590Srgrimes 5651590Srgrimes/* 5661590Srgrimes * Expand file names like echo 5671590Srgrimes */ 5681590Srgrimesint 5691590Srgrimesecho(argv) 5701590Srgrimes char **argv; 5711590Srgrimes{ 57277274Smikeh char **ap, *cp; 5731590Srgrimes 57477274Smikeh for (ap = argv; *ap != NULL; ap++) { 5751590Srgrimes cp = *ap; 57677274Smikeh if ((cp = expand(cp)) != NULL) { 5771590Srgrimes if (ap != argv) 57877274Smikeh printf(" "); 5791590Srgrimes printf("%s", cp); 5801590Srgrimes } 5811590Srgrimes } 58277274Smikeh printf("\n"); 58377274Smikeh return (0); 5841590Srgrimes} 5851590Srgrimes 5861590Srgrimesint 5871590SrgrimesRespond(msgvec) 5881590Srgrimes int *msgvec; 5891590Srgrimes{ 59077274Smikeh if (value("Replyall") == NULL) 59132189Sjoerg return (doRespond(msgvec)); 5921590Srgrimes else 59332189Sjoerg return (dorespond(msgvec)); 5941590Srgrimes} 5951590Srgrimes 5961590Srgrimes/* 5971590Srgrimes * Reply to a series of messages by simply mailing to the senders 5981590Srgrimes * and not messing around with the To: and Cc: lists as in normal 5991590Srgrimes * reply. 6001590Srgrimes */ 6011590Srgrimesint 60232189SjoergdoRespond(msgvec) 6031590Srgrimes int msgvec[]; 6041590Srgrimes{ 6051590Srgrimes struct header head; 6061590Srgrimes struct message *mp; 60777274Smikeh int *ap; 60877274Smikeh char *cp, *mid; 6091590Srgrimes 61077274Smikeh head.h_to = NULL; 6111590Srgrimes for (ap = msgvec; *ap != 0; ap++) { 6121590Srgrimes mp = &message[*ap - 1]; 6131590Srgrimes touch(mp); 6141590Srgrimes dot = mp; 61577274Smikeh if ((cp = skin(hfield("from", mp))) == NULL) 6161590Srgrimes cp = skin(nameof(mp, 2)); 6171590Srgrimes head.h_to = cat(head.h_to, extract(cp, GTO)); 61832189Sjoerg mid = skin(hfield("message-id", mp)); 6191590Srgrimes } 62077274Smikeh if (head.h_to == NULL) 62177274Smikeh return (0); 6221590Srgrimes mp = &message[msgvec[0] - 1]; 62377274Smikeh if ((head.h_subject = hfield("subject", mp)) == NULL) 6241590Srgrimes head.h_subject = hfield("subj", mp); 6251590Srgrimes head.h_subject = reedit(head.h_subject); 62677274Smikeh head.h_cc = NULL; 62777274Smikeh head.h_bcc = NULL; 62877274Smikeh head.h_smopts = NULL; 62932189Sjoerg if ((head.h_replyto = getenv("REPLYTO")) == NULL) 63077274Smikeh head.h_replyto = NULL; 63132189Sjoerg head.h_inreplyto = mid; 6321590Srgrimes mail1(&head, 1); 63377274Smikeh return (0); 6341590Srgrimes} 6351590Srgrimes 6361590Srgrimes/* 6371590Srgrimes * Conditional commands. These allow one to parameterize one's 6381590Srgrimes * .mailrc and do some things if sending, others if receiving. 6391590Srgrimes */ 6401590Srgrimesint 6411590Srgrimesifcmd(argv) 6421590Srgrimes char **argv; 6431590Srgrimes{ 64477274Smikeh char *cp; 6451590Srgrimes 6461590Srgrimes if (cond != CANY) { 6471590Srgrimes printf("Illegal nested \"if\"\n"); 64877274Smikeh return (1); 6491590Srgrimes } 6501590Srgrimes cond = CANY; 6511590Srgrimes cp = argv[0]; 6521590Srgrimes switch (*cp) { 6531590Srgrimes case 'r': case 'R': 6541590Srgrimes cond = CRCV; 6551590Srgrimes break; 6561590Srgrimes 6571590Srgrimes case 's': case 'S': 6581590Srgrimes cond = CSEND; 6591590Srgrimes break; 6601590Srgrimes 6611590Srgrimes default: 6621590Srgrimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 66377274Smikeh return (1); 6641590Srgrimes } 66577274Smikeh return (0); 6661590Srgrimes} 6671590Srgrimes 6681590Srgrimes/* 6691590Srgrimes * Implement 'else'. This is pretty simple -- we just 6701590Srgrimes * flip over the conditional flag. 6711590Srgrimes */ 6721590Srgrimesint 6731590Srgrimeselsecmd() 6741590Srgrimes{ 6751590Srgrimes 6761590Srgrimes switch (cond) { 6771590Srgrimes case CANY: 6781590Srgrimes printf("\"Else\" without matching \"if\"\n"); 67977274Smikeh return (1); 6801590Srgrimes 6811590Srgrimes case CSEND: 6821590Srgrimes cond = CRCV; 6831590Srgrimes break; 6841590Srgrimes 6851590Srgrimes case CRCV: 6861590Srgrimes cond = CSEND; 6871590Srgrimes break; 6881590Srgrimes 6891590Srgrimes default: 6901590Srgrimes printf("Mail's idea of conditions is screwed up\n"); 6911590Srgrimes cond = CANY; 6921590Srgrimes break; 6931590Srgrimes } 69477274Smikeh return (0); 6951590Srgrimes} 6961590Srgrimes 6971590Srgrimes/* 6981590Srgrimes * End of if statement. Just set cond back to anything. 6991590Srgrimes */ 7001590Srgrimesint 7011590Srgrimesendifcmd() 7021590Srgrimes{ 7031590Srgrimes 7041590Srgrimes if (cond == CANY) { 7051590Srgrimes printf("\"Endif\" without matching \"if\"\n"); 70677274Smikeh return (1); 7071590Srgrimes } 7081590Srgrimes cond = CANY; 70977274Smikeh return (0); 7101590Srgrimes} 7111590Srgrimes 7121590Srgrimes/* 7131590Srgrimes * Set the list of alternate names. 7141590Srgrimes */ 7151590Srgrimesint 7161590Srgrimesalternates(namelist) 7171590Srgrimes char **namelist; 7181590Srgrimes{ 71977274Smikeh int c; 72077274Smikeh char **ap, **ap2, *cp; 7211590Srgrimes 7221590Srgrimes c = argcount(namelist) + 1; 7231590Srgrimes if (c == 1) { 7241590Srgrimes if (altnames == 0) 72577274Smikeh return (0); 72677274Smikeh for (ap = altnames; *ap != NULL; ap++) 7271590Srgrimes printf("%s ", *ap); 7281590Srgrimes printf("\n"); 72977274Smikeh return (0); 7301590Srgrimes } 7311590Srgrimes if (altnames != 0) 73277274Smikeh (void)free(altnames); 73377274Smikeh altnames = calloc((unsigned)c, sizeof(char *)); 73477274Smikeh for (ap = namelist, ap2 = altnames; *ap != NULL; ap++, ap2++) { 73577274Smikeh cp = calloc((unsigned)strlen(*ap) + 1, sizeof(char)); 7361590Srgrimes strcpy(cp, *ap); 7371590Srgrimes *ap2 = cp; 7381590Srgrimes } 7391590Srgrimes *ap2 = 0; 74077274Smikeh return (0); 7411590Srgrimes} 742