cmd3.c revision 88150
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 3688150Smikehstatic char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95"; 3774769Smikeh#endif 3874769Smikehstatic const char rcsid[] = 3974769Smikeh "$FreeBSD: head/usr.bin/mail/cmd3.c 88150 2001-12-18 20:52:09Z 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; 26378193Smikeh head.h_replyto = value("REPLYTO"); 26432189Sjoerg head.h_inreplyto = skin(hfield("message-id", mp)); 2651590Srgrimes mail1(&head, 1); 26677274Smikeh return (0); 2671590Srgrimes} 2681590Srgrimes 2691590Srgrimes/* 2701590Srgrimes * Modify the subject we are replying to to begin with Re: if 2711590Srgrimes * it does not already. 2721590Srgrimes */ 2731590Srgrimeschar * 2741590Srgrimesreedit(subj) 27577274Smikeh char *subj; 2761590Srgrimes{ 2771590Srgrimes char *newsubj; 2781590Srgrimes 27977274Smikeh if (subj == NULL) 28077274Smikeh return (NULL); 2811590Srgrimes if ((subj[0] == 'r' || subj[0] == 'R') && 2821590Srgrimes (subj[1] == 'e' || subj[1] == 'E') && 2831590Srgrimes subj[2] == ':') 28477274Smikeh return (subj); 2851590Srgrimes newsubj = salloc(strlen(subj) + 5); 28674769Smikeh sprintf(newsubj, "Re: %s", subj); 28777274Smikeh return (newsubj); 2881590Srgrimes} 2891590Srgrimes 2901590Srgrimes/* 2911590Srgrimes * Preserve the named messages, so that they will be sent 2921590Srgrimes * back to the system mailbox. 2931590Srgrimes */ 2941590Srgrimesint 2951590Srgrimespreserve(msgvec) 2961590Srgrimes int *msgvec; 2971590Srgrimes{ 29877274Smikeh int *ip, mesg; 29977274Smikeh struct message *mp; 3001590Srgrimes 3011590Srgrimes if (edit) { 3021590Srgrimes printf("Cannot \"preserve\" in edit mode\n"); 30377274Smikeh return (1); 3041590Srgrimes } 30529574Sphk for (ip = msgvec; *ip != 0; ip++) { 3061590Srgrimes mesg = *ip; 3071590Srgrimes mp = &message[mesg-1]; 3081590Srgrimes mp->m_flag |= MPRESERVE; 3091590Srgrimes mp->m_flag &= ~MBOX; 3101590Srgrimes dot = mp; 3111590Srgrimes } 31277274Smikeh return (0); 3131590Srgrimes} 3141590Srgrimes 3151590Srgrimes/* 3161590Srgrimes * Mark all given messages as unread. 3171590Srgrimes */ 3181590Srgrimesint 3191590Srgrimesunread(msgvec) 3201590Srgrimes int msgvec[]; 3211590Srgrimes{ 32277274Smikeh int *ip; 3231590Srgrimes 32429574Sphk for (ip = msgvec; *ip != 0; ip++) { 3251590Srgrimes dot = &message[*ip-1]; 3261590Srgrimes dot->m_flag &= ~(MREAD|MTOUCH); 3271590Srgrimes dot->m_flag |= MSTATUS; 3281590Srgrimes } 32977274Smikeh return (0); 3301590Srgrimes} 3311590Srgrimes 3321590Srgrimes/* 3331590Srgrimes * Print the size of each message. 3341590Srgrimes */ 3351590Srgrimesint 3361590Srgrimesmessize(msgvec) 3371590Srgrimes int *msgvec; 3381590Srgrimes{ 33977274Smikeh struct message *mp; 34077274Smikeh int *ip, mesg; 3411590Srgrimes 34229574Sphk for (ip = msgvec; *ip != 0; ip++) { 3431590Srgrimes mesg = *ip; 3441590Srgrimes mp = &message[mesg-1]; 34537453Sbde printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3461590Srgrimes } 34777274Smikeh return (0); 3481590Srgrimes} 3491590Srgrimes 3501590Srgrimes/* 3511590Srgrimes * Quit quickly. If we are sourcing, just pop the input level 3521590Srgrimes * by returning an error. 3531590Srgrimes */ 3541590Srgrimesint 3551590Srgrimesrexit(e) 3561590Srgrimes int e; 3571590Srgrimes{ 3581590Srgrimes if (sourcing) 35977274Smikeh return (1); 36088150Smikeh exit(0); 3611590Srgrimes /*NOTREACHED*/ 3621590Srgrimes} 3631590Srgrimes 3641590Srgrimes/* 3651590Srgrimes * Set or display a variable value. Syntax is similar to that 3661590Srgrimes * of csh. 3671590Srgrimes */ 3681590Srgrimesint 3691590Srgrimesset(arglist) 3701590Srgrimes char **arglist; 3711590Srgrimes{ 37277274Smikeh struct var *vp; 37377274Smikeh char *cp, *cp2; 3741590Srgrimes char varbuf[BUFSIZ], **ap, **p; 3751590Srgrimes int errs, h, s; 3761590Srgrimes 37777274Smikeh if (*arglist == NULL) { 3781590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 37977274Smikeh for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3801590Srgrimes s++; 38177274Smikeh ap = (char **)salloc(s * sizeof(*ap)); 3821590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 38377274Smikeh for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3841590Srgrimes *p++ = vp->v_name; 38577274Smikeh *p = NULL; 3861590Srgrimes sort(ap); 38777274Smikeh for (p = ap; *p != NULL; p++) 3881590Srgrimes printf("%s\t%s\n", *p, value(*p)); 38977274Smikeh return (0); 3901590Srgrimes } 3911590Srgrimes errs = 0; 39277274Smikeh for (ap = arglist; *ap != NULL; ap++) { 3931590Srgrimes cp = *ap; 3941590Srgrimes cp2 = varbuf; 39574769Smikeh while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3961590Srgrimes *cp2++ = *cp++; 3971590Srgrimes *cp2 = '\0'; 3981590Srgrimes if (*cp == '\0') 3991590Srgrimes cp = ""; 4001590Srgrimes else 4011590Srgrimes cp++; 4021590Srgrimes if (equal(varbuf, "")) { 4031590Srgrimes printf("Non-null variable name required\n"); 4041590Srgrimes errs++; 4051590Srgrimes continue; 4061590Srgrimes } 4071590Srgrimes assign(varbuf, cp); 4081590Srgrimes } 40977274Smikeh return (errs); 4101590Srgrimes} 4111590Srgrimes 4121590Srgrimes/* 4131590Srgrimes * Unset a bunch of variable values. 4141590Srgrimes */ 4151590Srgrimesint 4161590Srgrimesunset(arglist) 4171590Srgrimes char **arglist; 4181590Srgrimes{ 41977274Smikeh struct var *vp, *vp2; 4201590Srgrimes int errs, h; 4211590Srgrimes char **ap; 4221590Srgrimes 4231590Srgrimes errs = 0; 42477274Smikeh for (ap = arglist; *ap != NULL; ap++) { 42577274Smikeh if ((vp2 = lookup(*ap)) == NULL) { 42688150Smikeh if (getenv(*ap)) 42788150Smikeh unsetenv(*ap); 42888150Smikeh else if (!sourcing) { 4291590Srgrimes printf("\"%s\": undefined variable\n", *ap); 4301590Srgrimes errs++; 4311590Srgrimes } 4321590Srgrimes continue; 4331590Srgrimes } 4341590Srgrimes h = hash(*ap); 4351590Srgrimes if (vp2 == variables[h]) { 4361590Srgrimes variables[h] = variables[h]->v_link; 4371590Srgrimes vfree(vp2->v_name); 4381590Srgrimes vfree(vp2->v_value); 43977274Smikeh (void)free(vp2); 4401590Srgrimes continue; 4411590Srgrimes } 4421590Srgrimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4431590Srgrimes ; 4441590Srgrimes vp->v_link = vp2->v_link; 4451590Srgrimes vfree(vp2->v_name); 4461590Srgrimes vfree(vp2->v_value); 44777274Smikeh (void)free(vp2); 4481590Srgrimes } 44977274Smikeh return (errs); 4501590Srgrimes} 4511590Srgrimes 4521590Srgrimes/* 4531590Srgrimes * Put add users to a group. 4541590Srgrimes */ 4551590Srgrimesint 4561590Srgrimesgroup(argv) 4571590Srgrimes char **argv; 4581590Srgrimes{ 45977274Smikeh struct grouphead *gh; 46077274Smikeh struct group *gp; 4611590Srgrimes char **ap, *gname, **p; 46277274Smikeh int h, s; 4631590Srgrimes 46477274Smikeh if (*argv == NULL) { 4651590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 46677274Smikeh for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4671590Srgrimes s++; 46877274Smikeh ap = (char **)salloc(s * sizeof(*ap)); 4691590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 47077274Smikeh for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4711590Srgrimes *p++ = gh->g_name; 47277274Smikeh *p = NULL; 4731590Srgrimes sort(ap); 47477274Smikeh for (p = ap; *p != NULL; p++) 4751590Srgrimes printgroup(*p); 47677274Smikeh return (0); 4771590Srgrimes } 47877274Smikeh if (argv[1] == NULL) { 4791590Srgrimes printgroup(*argv); 48077274Smikeh return (0); 4811590Srgrimes } 4821590Srgrimes gname = *argv; 4831590Srgrimes h = hash(gname); 48477274Smikeh if ((gh = findgroup(gname)) == NULL) { 48577274Smikeh gh = calloc(sizeof(*gh), 1); 4861590Srgrimes gh->g_name = vcopy(gname); 48777274Smikeh gh->g_list = NULL; 4881590Srgrimes gh->g_link = groups[h]; 4891590Srgrimes groups[h] = gh; 4901590Srgrimes } 4911590Srgrimes 4921590Srgrimes /* 4931590Srgrimes * Insert names from the command list into the group. 4941590Srgrimes * Who cares if there are duplicates? They get tossed 4951590Srgrimes * later anyway. 4961590Srgrimes */ 4971590Srgrimes 49877274Smikeh for (ap = argv+1; *ap != NULL; ap++) { 49977274Smikeh gp = calloc(sizeof(*gp), 1); 5001590Srgrimes gp->ge_name = vcopy(*ap); 5011590Srgrimes gp->ge_link = gh->g_list; 5021590Srgrimes gh->g_list = gp; 5031590Srgrimes } 50477274Smikeh return (0); 5051590Srgrimes} 5061590Srgrimes 5071590Srgrimes/* 5081590Srgrimes * Sort the passed string vecotor into ascending dictionary 5091590Srgrimes * order. 5101590Srgrimes */ 5111590Srgrimesvoid 5121590Srgrimessort(list) 5131590Srgrimes char **list; 5141590Srgrimes{ 51577274Smikeh char **ap; 5161590Srgrimes 51777274Smikeh for (ap = list; *ap != NULL; ap++) 5181590Srgrimes ; 5191590Srgrimes if (ap-list < 2) 5201590Srgrimes return; 5211590Srgrimes qsort(list, ap-list, sizeof(*list), diction); 5221590Srgrimes} 5231590Srgrimes 5241590Srgrimes/* 5251590Srgrimes * Do a dictionary order comparison of the arguments from 5261590Srgrimes * qsort. 5271590Srgrimes */ 5281590Srgrimesint 5291590Srgrimesdiction(a, b) 5301590Srgrimes const void *a, *b; 5311590Srgrimes{ 53277274Smikeh return (strcmp(*(const char **)a, *(const char **)b)); 5331590Srgrimes} 5341590Srgrimes 5351590Srgrimes/* 5361590Srgrimes * The do nothing command for comments. 5371590Srgrimes */ 5381590Srgrimes 5391590Srgrimes/*ARGSUSED*/ 5401590Srgrimesint 5411590Srgrimesnull(e) 5421590Srgrimes int e; 5431590Srgrimes{ 54477274Smikeh return (0); 5451590Srgrimes} 5461590Srgrimes 5471590Srgrimes/* 5481590Srgrimes * Change to another file. With no argument, print information about 5491590Srgrimes * the current file. 5501590Srgrimes */ 5511590Srgrimesint 5521590Srgrimesfile(argv) 55377274Smikeh char **argv; 5541590Srgrimes{ 5551590Srgrimes 55677274Smikeh if (argv[0] == NULL) { 55788150Smikeh newfileinfo(0); 55877274Smikeh return (0); 5591590Srgrimes } 5601590Srgrimes if (setfile(*argv) < 0) 56177274Smikeh return (1); 5621590Srgrimes announce(); 56377274Smikeh return (0); 5641590Srgrimes} 5651590Srgrimes 5661590Srgrimes/* 5671590Srgrimes * Expand file names like echo 5681590Srgrimes */ 5691590Srgrimesint 5701590Srgrimesecho(argv) 5711590Srgrimes char **argv; 5721590Srgrimes{ 57377274Smikeh char **ap, *cp; 5741590Srgrimes 57577274Smikeh for (ap = argv; *ap != NULL; ap++) { 5761590Srgrimes cp = *ap; 57777274Smikeh if ((cp = expand(cp)) != NULL) { 5781590Srgrimes if (ap != argv) 57977274Smikeh printf(" "); 5801590Srgrimes printf("%s", cp); 5811590Srgrimes } 5821590Srgrimes } 58377274Smikeh printf("\n"); 58477274Smikeh return (0); 5851590Srgrimes} 5861590Srgrimes 5871590Srgrimesint 5881590SrgrimesRespond(msgvec) 5891590Srgrimes int *msgvec; 5901590Srgrimes{ 59177274Smikeh if (value("Replyall") == NULL) 59232189Sjoerg return (doRespond(msgvec)); 5931590Srgrimes else 59432189Sjoerg return (dorespond(msgvec)); 5951590Srgrimes} 5961590Srgrimes 5971590Srgrimes/* 5981590Srgrimes * Reply to a series of messages by simply mailing to the senders 5991590Srgrimes * and not messing around with the To: and Cc: lists as in normal 6001590Srgrimes * reply. 6011590Srgrimes */ 6021590Srgrimesint 60332189SjoergdoRespond(msgvec) 6041590Srgrimes int msgvec[]; 6051590Srgrimes{ 6061590Srgrimes struct header head; 6071590Srgrimes struct message *mp; 60877274Smikeh int *ap; 60977274Smikeh char *cp, *mid; 6101590Srgrimes 61177274Smikeh head.h_to = NULL; 6121590Srgrimes for (ap = msgvec; *ap != 0; ap++) { 6131590Srgrimes mp = &message[*ap - 1]; 6141590Srgrimes touch(mp); 6151590Srgrimes dot = mp; 61677274Smikeh if ((cp = skin(hfield("from", mp))) == NULL) 6171590Srgrimes cp = skin(nameof(mp, 2)); 6181590Srgrimes head.h_to = cat(head.h_to, extract(cp, GTO)); 61932189Sjoerg mid = skin(hfield("message-id", mp)); 6201590Srgrimes } 62177274Smikeh if (head.h_to == NULL) 62277274Smikeh return (0); 6231590Srgrimes mp = &message[msgvec[0] - 1]; 62477274Smikeh if ((head.h_subject = hfield("subject", mp)) == NULL) 6251590Srgrimes head.h_subject = hfield("subj", mp); 6261590Srgrimes head.h_subject = reedit(head.h_subject); 62777274Smikeh head.h_cc = NULL; 62877274Smikeh head.h_bcc = NULL; 62977274Smikeh head.h_smopts = NULL; 63078193Smikeh head.h_replyto = value("REPLYTO"); 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