cmd3.c revision 74769
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 74769 2001-03-25 04:57:05Z 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); 601590Srgrimes char *shell; 611590Srgrimes char cmd[BUFSIZ]; 621590Srgrimes 6374769Smikeh if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd)) 641590Srgrimes return 1; 6574769Smikeh if (bangexp(cmd, sizeof(cmd)) < 0) 6674769Smikeh return 1; 671590Srgrimes if ((shell = value("SHELL")) == NOSTR) 681590Srgrimes shell = _PATH_CSHELL; 691590Srgrimes (void) run_command(shell, 0, -1, -1, "-c", cmd, NOSTR); 701590Srgrimes (void) signal(SIGINT, sigint); 711590Srgrimes printf("!\n"); 721590Srgrimes 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); 841590Srgrimes char *shell; 851590Srgrimes 861590Srgrimes if ((shell = value("SHELL")) == NOSTR) 871590Srgrimes shell = _PATH_CSHELL; 881590Srgrimes (void) run_command(shell, 0, -1, -1, NOSTR, NOSTR, NOSTR); 891590Srgrimes (void) signal(SIGINT, sigint); 901590Srgrimes putchar('\n'); 911590Srgrimes 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]; 1051590Srgrimes register char *cp, *cp2; 1061590Srgrimes register int n; 1071590Srgrimes int changed = 0; 1081590Srgrimes 1091590Srgrimes cp = str; 1101590Srgrimes cp2 = bangbuf; 11174769Smikeh n = sizeof(bangbuf); 1121590Srgrimes while (*cp) { 1131590Srgrimes if (*cp == '!') { 1141590Srgrimes if (n < strlen(lastbang)) { 1151590Srgrimesoverf: 1161590Srgrimes printf("Command buffer overflow\n"); 1171590Srgrimes return(-1); 1181590Srgrimes } 1191590Srgrimes changed++; 12074769Smikeh if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf)) 12174769Smikeh >= sizeof(bangbuf) - (cp2 - bangbuf)) 12274769Smikeh goto overf; 1231590Srgrimes cp2 += strlen(lastbang); 1241590Srgrimes n -= strlen(lastbang); 1251590Srgrimes cp++; 1261590Srgrimes continue; 1271590Srgrimes } 1281590Srgrimes if (*cp == '\\' && cp[1] == '!') { 1291590Srgrimes if (--n <= 1) 1301590Srgrimes goto overf; 1311590Srgrimes *cp2++ = '!'; 1321590Srgrimes cp += 2; 1331590Srgrimes changed++; 1341590Srgrimes } 1351590Srgrimes if (--n <= 1) 1361590Srgrimes goto overf; 1371590Srgrimes *cp2++ = *cp++; 1381590Srgrimes } 1391590Srgrimes *cp2 = 0; 1401590Srgrimes if (changed) { 1411590Srgrimes printf("!%s\n", bangbuf); 1421590Srgrimes fflush(stdout); 1431590Srgrimes } 14474769Smikeh if (strlcpy(str, bangbuf, strsize) >= strsize) 14574769Smikeh goto overf; 14674769Smikeh if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang)) 14774769Smikeh goto overf; 1481590Srgrimes return(0); 1491590Srgrimes} 1501590Srgrimes 1511590Srgrimes/* 1521590Srgrimes * Print out a nice help message from some file or another. 1531590Srgrimes */ 1541590Srgrimes 1551590Srgrimesint 1561590Srgrimeshelp() 1571590Srgrimes{ 1581590Srgrimes register c; 1591590Srgrimes register FILE *f; 1601590Srgrimes 1611590Srgrimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 16274769Smikeh warn("%s", _PATH_HELP); 1631590Srgrimes return(1); 1641590Srgrimes } 1651590Srgrimes while ((c = getc(f)) != EOF) 1661590Srgrimes putchar(c); 1671590Srgrimes Fclose(f); 1681590Srgrimes return(0); 1691590Srgrimes} 1701590Srgrimes 1711590Srgrimes/* 1721590Srgrimes * Change user's working directory. 1731590Srgrimes */ 1741590Srgrimesint 1751590Srgrimesschdir(arglist) 1761590Srgrimes char **arglist; 1771590Srgrimes{ 1781590Srgrimes char *cp; 1791590Srgrimes 18074769Smikeh if (*arglist == NOSTR) { 18174769Smikeh if (homedir == NOSTR) 18274769Smikeh return(1); 1831590Srgrimes cp = homedir; 18474769Smikeh } else 1851590Srgrimes if ((cp = expand(*arglist)) == NOSTR) 1861590Srgrimes return(1); 1871590Srgrimes if (chdir(cp) < 0) { 18874769Smikeh warn("%s", cp); 1891590Srgrimes return(1); 1901590Srgrimes } 1911590Srgrimes return 0; 1921590Srgrimes} 1931590Srgrimes 1941590Srgrimesint 1951590Srgrimesrespond(msgvec) 1961590Srgrimes int *msgvec; 1971590Srgrimes{ 1981590Srgrimes if (value("Replyall") == NOSTR) 19932189Sjoerg return (dorespond(msgvec)); 2001590Srgrimes else 20132189Sjoerg return (doRespond(msgvec)); 2021590Srgrimes} 2031590Srgrimes 2041590Srgrimes/* 2051590Srgrimes * Reply to a list of messages. Extract each name from the 2061590Srgrimes * message header and send them off to mail1() 2071590Srgrimes */ 2081590Srgrimesint 20932189Sjoergdorespond(msgvec) 2101590Srgrimes int *msgvec; 2111590Srgrimes{ 2121590Srgrimes struct message *mp; 2131590Srgrimes char *cp, *rcv, *replyto; 2141590Srgrimes char **ap; 2151590Srgrimes struct name *np; 2161590Srgrimes struct header head; 2171590Srgrimes 2181590Srgrimes if (msgvec[1] != 0) { 2191590Srgrimes printf("Sorry, can't reply to multiple messages at once\n"); 2201590Srgrimes return(1); 2211590Srgrimes } 2221590Srgrimes mp = &message[msgvec[0] - 1]; 2231590Srgrimes touch(mp); 2241590Srgrimes dot = mp; 2251590Srgrimes if ((rcv = skin(hfield("from", mp))) == NOSTR) 2261590Srgrimes rcv = skin(nameof(mp, 1)); 2271590Srgrimes if ((replyto = skin(hfield("reply-to", mp))) != NOSTR) 2281590Srgrimes np = extract(replyto, GTO); 2291590Srgrimes else if ((cp = skin(hfield("to", mp))) != NOSTR) 2301590Srgrimes np = extract(cp, GTO); 2311590Srgrimes else 2321590Srgrimes np = NIL; 2331590Srgrimes np = elide(np); 2341590Srgrimes /* 2351590Srgrimes * Delete my name from the reply list, 2361590Srgrimes * and with it, all my alternate names. 2371590Srgrimes */ 2381590Srgrimes np = delname(np, myname); 2391590Srgrimes if (altnames) 2401590Srgrimes for (ap = altnames; *ap; ap++) 2411590Srgrimes np = delname(np, *ap); 2421590Srgrimes if (np != NIL && replyto == NOSTR) 2431590Srgrimes np = cat(np, extract(rcv, GTO)); 2441590Srgrimes else if (np == NIL) { 2451590Srgrimes if (replyto != NOSTR) 2461590Srgrimes printf("Empty reply-to field -- replying to author\n"); 2471590Srgrimes np = extract(rcv, GTO); 2481590Srgrimes } 2491590Srgrimes head.h_to = np; 2501590Srgrimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 2511590Srgrimes head.h_subject = hfield("subj", mp); 2521590Srgrimes head.h_subject = reedit(head.h_subject); 2531590Srgrimes if (replyto == NOSTR && (cp = skin(hfield("cc", mp))) != NOSTR) { 2541590Srgrimes np = elide(extract(cp, GCC)); 2551590Srgrimes np = delname(np, myname); 2561590Srgrimes if (altnames != 0) 2571590Srgrimes for (ap = altnames; *ap; ap++) 2581590Srgrimes np = delname(np, *ap); 2591590Srgrimes head.h_cc = np; 2601590Srgrimes } else 2611590Srgrimes head.h_cc = NIL; 2621590Srgrimes head.h_bcc = NIL; 2631590Srgrimes head.h_smopts = NIL; 26432189Sjoerg if ((head.h_replyto = getenv("REPLYTO")) == NULL) 26532189Sjoerg head.h_replyto = NOSTR; 26632189Sjoerg head.h_inreplyto = skin(hfield("message-id", mp)); 2671590Srgrimes mail1(&head, 1); 2681590Srgrimes return(0); 2691590Srgrimes} 2701590Srgrimes 2711590Srgrimes/* 2721590Srgrimes * Modify the subject we are replying to to begin with Re: if 2731590Srgrimes * it does not already. 2741590Srgrimes */ 2751590Srgrimeschar * 2761590Srgrimesreedit(subj) 2771590Srgrimes register char *subj; 2781590Srgrimes{ 2791590Srgrimes char *newsubj; 2801590Srgrimes 2811590Srgrimes if (subj == NOSTR) 2821590Srgrimes return NOSTR; 2831590Srgrimes if ((subj[0] == 'r' || subj[0] == 'R') && 2841590Srgrimes (subj[1] == 'e' || subj[1] == 'E') && 2851590Srgrimes subj[2] == ':') 2861590Srgrimes return subj; 2871590Srgrimes newsubj = salloc(strlen(subj) + 5); 28874769Smikeh sprintf(newsubj, "Re: %s", subj); 2891590Srgrimes return newsubj; 2901590Srgrimes} 2911590Srgrimes 2921590Srgrimes/* 2931590Srgrimes * Preserve the named messages, so that they will be sent 2941590Srgrimes * back to the system mailbox. 2951590Srgrimes */ 2961590Srgrimesint 2971590Srgrimespreserve(msgvec) 2981590Srgrimes int *msgvec; 2991590Srgrimes{ 3001590Srgrimes register struct message *mp; 3011590Srgrimes register int *ip, mesg; 3021590Srgrimes 3031590Srgrimes if (edit) { 3041590Srgrimes printf("Cannot \"preserve\" in edit mode\n"); 3051590Srgrimes return(1); 3061590Srgrimes } 30729574Sphk for (ip = msgvec; *ip != 0; ip++) { 3081590Srgrimes mesg = *ip; 3091590Srgrimes mp = &message[mesg-1]; 3101590Srgrimes mp->m_flag |= MPRESERVE; 3111590Srgrimes mp->m_flag &= ~MBOX; 3121590Srgrimes dot = mp; 3131590Srgrimes } 3141590Srgrimes return(0); 3151590Srgrimes} 3161590Srgrimes 3171590Srgrimes/* 3181590Srgrimes * Mark all given messages as unread. 3191590Srgrimes */ 3201590Srgrimesint 3211590Srgrimesunread(msgvec) 3221590Srgrimes int msgvec[]; 3231590Srgrimes{ 3241590Srgrimes register int *ip; 3251590Srgrimes 32629574Sphk for (ip = msgvec; *ip != 0; ip++) { 3271590Srgrimes dot = &message[*ip-1]; 3281590Srgrimes dot->m_flag &= ~(MREAD|MTOUCH); 3291590Srgrimes dot->m_flag |= MSTATUS; 3301590Srgrimes } 3311590Srgrimes return(0); 3321590Srgrimes} 3331590Srgrimes 3341590Srgrimes/* 3351590Srgrimes * Print the size of each message. 3361590Srgrimes */ 3371590Srgrimesint 3381590Srgrimesmessize(msgvec) 3391590Srgrimes int *msgvec; 3401590Srgrimes{ 3411590Srgrimes register struct message *mp; 3421590Srgrimes register int *ip, mesg; 3431590Srgrimes 34429574Sphk for (ip = msgvec; *ip != 0; ip++) { 3451590Srgrimes mesg = *ip; 3461590Srgrimes mp = &message[mesg-1]; 34737453Sbde printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3481590Srgrimes } 3491590Srgrimes return(0); 3501590Srgrimes} 3511590Srgrimes 3521590Srgrimes/* 3531590Srgrimes * Quit quickly. If we are sourcing, just pop the input level 3541590Srgrimes * by returning an error. 3551590Srgrimes */ 3561590Srgrimesint 3571590Srgrimesrexit(e) 3581590Srgrimes int e; 3591590Srgrimes{ 3601590Srgrimes if (sourcing) 3611590Srgrimes return(1); 3621590Srgrimes exit(e); 3631590Srgrimes /*NOTREACHED*/ 3641590Srgrimes} 3651590Srgrimes 3661590Srgrimes/* 3671590Srgrimes * Set or display a variable value. Syntax is similar to that 3681590Srgrimes * of csh. 3691590Srgrimes */ 3701590Srgrimesint 3711590Srgrimesset(arglist) 3721590Srgrimes char **arglist; 3731590Srgrimes{ 3741590Srgrimes register struct var *vp; 3751590Srgrimes register char *cp, *cp2; 3761590Srgrimes char varbuf[BUFSIZ], **ap, **p; 3771590Srgrimes int errs, h, s; 3781590Srgrimes 3791590Srgrimes if (*arglist == NOSTR) { 3801590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 3811590Srgrimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3821590Srgrimes s++; 3831590Srgrimes ap = (char **) salloc(s * sizeof *ap); 3841590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 3851590Srgrimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3861590Srgrimes *p++ = vp->v_name; 3871590Srgrimes *p = NOSTR; 3881590Srgrimes sort(ap); 3891590Srgrimes for (p = ap; *p != NOSTR; p++) 3901590Srgrimes printf("%s\t%s\n", *p, value(*p)); 3911590Srgrimes return(0); 3921590Srgrimes } 3931590Srgrimes errs = 0; 3941590Srgrimes for (ap = arglist; *ap != NOSTR; ap++) { 3951590Srgrimes cp = *ap; 3961590Srgrimes cp2 = varbuf; 39774769Smikeh while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3981590Srgrimes *cp2++ = *cp++; 3991590Srgrimes *cp2 = '\0'; 4001590Srgrimes if (*cp == '\0') 4011590Srgrimes cp = ""; 4021590Srgrimes else 4031590Srgrimes cp++; 4041590Srgrimes if (equal(varbuf, "")) { 4051590Srgrimes printf("Non-null variable name required\n"); 4061590Srgrimes errs++; 4071590Srgrimes continue; 4081590Srgrimes } 4091590Srgrimes assign(varbuf, cp); 4101590Srgrimes } 4111590Srgrimes return(errs); 4121590Srgrimes} 4131590Srgrimes 4141590Srgrimes/* 4151590Srgrimes * Unset a bunch of variable values. 4161590Srgrimes */ 4171590Srgrimesint 4181590Srgrimesunset(arglist) 4191590Srgrimes char **arglist; 4201590Srgrimes{ 4211590Srgrimes register struct var *vp, *vp2; 4221590Srgrimes int errs, h; 4231590Srgrimes char **ap; 4241590Srgrimes 4251590Srgrimes errs = 0; 4261590Srgrimes for (ap = arglist; *ap != NOSTR; ap++) { 4271590Srgrimes if ((vp2 = lookup(*ap)) == NOVAR) { 4281590Srgrimes 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); 4391590Srgrimes free((char *)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); 4471590Srgrimes free((char *) vp2); 4481590Srgrimes } 4491590Srgrimes return(errs); 4501590Srgrimes} 4511590Srgrimes 4521590Srgrimes/* 4531590Srgrimes * Put add users to a group. 4541590Srgrimes */ 4551590Srgrimesint 4561590Srgrimesgroup(argv) 4571590Srgrimes char **argv; 4581590Srgrimes{ 4591590Srgrimes register struct grouphead *gh; 4601590Srgrimes register struct group *gp; 4611590Srgrimes register int h; 4621590Srgrimes int s; 4631590Srgrimes char **ap, *gname, **p; 4641590Srgrimes 4651590Srgrimes if (*argv == NOSTR) { 4661590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 4671590Srgrimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4681590Srgrimes s++; 4691590Srgrimes ap = (char **) salloc(s * sizeof *ap); 4701590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 4711590Srgrimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4721590Srgrimes *p++ = gh->g_name; 4731590Srgrimes *p = NOSTR; 4741590Srgrimes sort(ap); 4751590Srgrimes for (p = ap; *p != NOSTR; p++) 4761590Srgrimes printgroup(*p); 4771590Srgrimes return(0); 4781590Srgrimes } 4791590Srgrimes if (argv[1] == NOSTR) { 4801590Srgrimes printgroup(*argv); 4811590Srgrimes return(0); 4821590Srgrimes } 4831590Srgrimes gname = *argv; 4841590Srgrimes h = hash(gname); 4851590Srgrimes if ((gh = findgroup(gname)) == NOGRP) { 4861590Srgrimes gh = (struct grouphead *) calloc(sizeof *gh, 1); 4871590Srgrimes gh->g_name = vcopy(gname); 4881590Srgrimes gh->g_list = NOGE; 4891590Srgrimes gh->g_link = groups[h]; 4901590Srgrimes groups[h] = gh; 4911590Srgrimes } 4921590Srgrimes 4931590Srgrimes /* 4941590Srgrimes * Insert names from the command list into the group. 4951590Srgrimes * Who cares if there are duplicates? They get tossed 4961590Srgrimes * later anyway. 4971590Srgrimes */ 4981590Srgrimes 4991590Srgrimes for (ap = argv+1; *ap != NOSTR; ap++) { 5001590Srgrimes gp = (struct group *) calloc(sizeof *gp, 1); 5011590Srgrimes gp->ge_name = vcopy(*ap); 5021590Srgrimes gp->ge_link = gh->g_list; 5031590Srgrimes gh->g_list = gp; 5041590Srgrimes } 5051590Srgrimes return(0); 5061590Srgrimes} 5071590Srgrimes 5081590Srgrimes/* 5091590Srgrimes * Sort the passed string vecotor into ascending dictionary 5101590Srgrimes * order. 5111590Srgrimes */ 5121590Srgrimesvoid 5131590Srgrimessort(list) 5141590Srgrimes char **list; 5151590Srgrimes{ 5161590Srgrimes register char **ap; 5171590Srgrimes int diction(); 5181590Srgrimes 5191590Srgrimes for (ap = list; *ap != NOSTR; ap++) 5201590Srgrimes ; 5211590Srgrimes if (ap-list < 2) 5221590Srgrimes return; 5231590Srgrimes qsort(list, ap-list, sizeof(*list), diction); 5241590Srgrimes} 5251590Srgrimes 5261590Srgrimes/* 5271590Srgrimes * Do a dictionary order comparison of the arguments from 5281590Srgrimes * qsort. 5291590Srgrimes */ 5301590Srgrimesint 5311590Srgrimesdiction(a, b) 5321590Srgrimes const void *a, *b; 5331590Srgrimes{ 5341590Srgrimes return(strcmp(*(char **)a, *(char **)b)); 5351590Srgrimes} 5361590Srgrimes 5371590Srgrimes/* 5381590Srgrimes * The do nothing command for comments. 5391590Srgrimes */ 5401590Srgrimes 5411590Srgrimes/*ARGSUSED*/ 5421590Srgrimesint 5431590Srgrimesnull(e) 5441590Srgrimes int e; 5451590Srgrimes{ 5461590Srgrimes return 0; 5471590Srgrimes} 5481590Srgrimes 5491590Srgrimes/* 5501590Srgrimes * Change to another file. With no argument, print information about 5511590Srgrimes * the current file. 5521590Srgrimes */ 5531590Srgrimesint 5541590Srgrimesfile(argv) 5551590Srgrimes register char **argv; 5561590Srgrimes{ 5571590Srgrimes 5581590Srgrimes if (argv[0] == NOSTR) { 5591590Srgrimes newfileinfo(); 5601590Srgrimes return 0; 5611590Srgrimes } 5621590Srgrimes if (setfile(*argv) < 0) 5631590Srgrimes return 1; 5641590Srgrimes announce(); 5651590Srgrimes return 0; 5661590Srgrimes} 5671590Srgrimes 5681590Srgrimes/* 5691590Srgrimes * Expand file names like echo 5701590Srgrimes */ 5711590Srgrimesint 5721590Srgrimesecho(argv) 5731590Srgrimes char **argv; 5741590Srgrimes{ 5751590Srgrimes register char **ap; 5761590Srgrimes register char *cp; 5771590Srgrimes 5781590Srgrimes for (ap = argv; *ap != NOSTR; ap++) { 5791590Srgrimes cp = *ap; 5801590Srgrimes if ((cp = expand(cp)) != NOSTR) { 5811590Srgrimes if (ap != argv) 5821590Srgrimes putchar(' '); 5831590Srgrimes printf("%s", cp); 5841590Srgrimes } 5851590Srgrimes } 5861590Srgrimes putchar('\n'); 5871590Srgrimes return 0; 5881590Srgrimes} 5891590Srgrimes 5901590Srgrimesint 5911590SrgrimesRespond(msgvec) 5921590Srgrimes int *msgvec; 5931590Srgrimes{ 5941590Srgrimes if (value("Replyall") == NOSTR) 59532189Sjoerg return (doRespond(msgvec)); 5961590Srgrimes else 59732189Sjoerg return (dorespond(msgvec)); 5981590Srgrimes} 5991590Srgrimes 6001590Srgrimes/* 6011590Srgrimes * Reply to a series of messages by simply mailing to the senders 6021590Srgrimes * and not messing around with the To: and Cc: lists as in normal 6031590Srgrimes * reply. 6041590Srgrimes */ 6051590Srgrimesint 60632189SjoergdoRespond(msgvec) 6071590Srgrimes int msgvec[]; 6081590Srgrimes{ 6091590Srgrimes struct header head; 6101590Srgrimes struct message *mp; 6111590Srgrimes register int *ap; 6121590Srgrimes register char *cp; 61332189Sjoerg char *mid; 6141590Srgrimes 6151590Srgrimes head.h_to = NIL; 6161590Srgrimes for (ap = msgvec; *ap != 0; ap++) { 6171590Srgrimes mp = &message[*ap - 1]; 6181590Srgrimes touch(mp); 6191590Srgrimes dot = mp; 6201590Srgrimes if ((cp = skin(hfield("from", mp))) == NOSTR) 6211590Srgrimes cp = skin(nameof(mp, 2)); 6221590Srgrimes head.h_to = cat(head.h_to, extract(cp, GTO)); 62332189Sjoerg mid = skin(hfield("message-id", mp)); 6241590Srgrimes } 6251590Srgrimes if (head.h_to == NIL) 6261590Srgrimes return 0; 6271590Srgrimes mp = &message[msgvec[0] - 1]; 6281590Srgrimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 6291590Srgrimes head.h_subject = hfield("subj", mp); 6301590Srgrimes head.h_subject = reedit(head.h_subject); 6311590Srgrimes head.h_cc = NIL; 6321590Srgrimes head.h_bcc = NIL; 6331590Srgrimes head.h_smopts = NIL; 63432189Sjoerg if ((head.h_replyto = getenv("REPLYTO")) == NULL) 63532189Sjoerg head.h_replyto = NOSTR; 63632189Sjoerg head.h_inreplyto = mid; 6371590Srgrimes mail1(&head, 1); 6381590Srgrimes return 0; 6391590Srgrimes} 6401590Srgrimes 6411590Srgrimes/* 6421590Srgrimes * Conditional commands. These allow one to parameterize one's 6431590Srgrimes * .mailrc and do some things if sending, others if receiving. 6441590Srgrimes */ 6451590Srgrimesint 6461590Srgrimesifcmd(argv) 6471590Srgrimes char **argv; 6481590Srgrimes{ 6491590Srgrimes register char *cp; 6501590Srgrimes 6511590Srgrimes if (cond != CANY) { 6521590Srgrimes printf("Illegal nested \"if\"\n"); 6531590Srgrimes return(1); 6541590Srgrimes } 6551590Srgrimes cond = CANY; 6561590Srgrimes cp = argv[0]; 6571590Srgrimes switch (*cp) { 6581590Srgrimes case 'r': case 'R': 6591590Srgrimes cond = CRCV; 6601590Srgrimes break; 6611590Srgrimes 6621590Srgrimes case 's': case 'S': 6631590Srgrimes cond = CSEND; 6641590Srgrimes break; 6651590Srgrimes 6661590Srgrimes default: 6671590Srgrimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 6681590Srgrimes return(1); 6691590Srgrimes } 6701590Srgrimes return(0); 6711590Srgrimes} 6721590Srgrimes 6731590Srgrimes/* 6741590Srgrimes * Implement 'else'. This is pretty simple -- we just 6751590Srgrimes * flip over the conditional flag. 6761590Srgrimes */ 6771590Srgrimesint 6781590Srgrimeselsecmd() 6791590Srgrimes{ 6801590Srgrimes 6811590Srgrimes switch (cond) { 6821590Srgrimes case CANY: 6831590Srgrimes printf("\"Else\" without matching \"if\"\n"); 6841590Srgrimes return(1); 6851590Srgrimes 6861590Srgrimes case CSEND: 6871590Srgrimes cond = CRCV; 6881590Srgrimes break; 6891590Srgrimes 6901590Srgrimes case CRCV: 6911590Srgrimes cond = CSEND; 6921590Srgrimes break; 6931590Srgrimes 6941590Srgrimes default: 6951590Srgrimes printf("Mail's idea of conditions is screwed up\n"); 6961590Srgrimes cond = CANY; 6971590Srgrimes break; 6981590Srgrimes } 6991590Srgrimes return(0); 7001590Srgrimes} 7011590Srgrimes 7021590Srgrimes/* 7031590Srgrimes * End of if statement. Just set cond back to anything. 7041590Srgrimes */ 7051590Srgrimesint 7061590Srgrimesendifcmd() 7071590Srgrimes{ 7081590Srgrimes 7091590Srgrimes if (cond == CANY) { 7101590Srgrimes printf("\"Endif\" without matching \"if\"\n"); 7111590Srgrimes return(1); 7121590Srgrimes } 7131590Srgrimes cond = CANY; 7141590Srgrimes return(0); 7151590Srgrimes} 7161590Srgrimes 7171590Srgrimes/* 7181590Srgrimes * Set the list of alternate names. 7191590Srgrimes */ 7201590Srgrimesint 7211590Srgrimesalternates(namelist) 7221590Srgrimes char **namelist; 7231590Srgrimes{ 7241590Srgrimes register int c; 7251590Srgrimes register char **ap, **ap2, *cp; 7261590Srgrimes 7271590Srgrimes c = argcount(namelist) + 1; 7281590Srgrimes if (c == 1) { 7291590Srgrimes if (altnames == 0) 7301590Srgrimes return(0); 7311590Srgrimes for (ap = altnames; *ap; ap++) 7321590Srgrimes printf("%s ", *ap); 7331590Srgrimes printf("\n"); 7341590Srgrimes return(0); 7351590Srgrimes } 7361590Srgrimes if (altnames != 0) 7371590Srgrimes free((char *) altnames); 7381590Srgrimes altnames = (char **) calloc((unsigned) c, sizeof (char *)); 7391590Srgrimes for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) { 7401590Srgrimes cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char)); 7411590Srgrimes strcpy(cp, *ap); 7421590Srgrimes *ap2 = cp; 7431590Srgrimes } 7441590Srgrimes *ap2 = 0; 7451590Srgrimes return(0); 7461590Srgrimes} 747