1*8a16b7a1SPedro F. Giffuni /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1980, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes #ifndef lint 330c3a8314SMike Heffner #if 0 34856f23edSMike Heffner static char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95"; 350c3a8314SMike Heffner #endif 369b50d902SRodney W. Grimes #endif /* not lint */ 37e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 38e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 399b50d902SRodney W. Grimes 409b50d902SRodney W. Grimes #include "rcv.h" 419b50d902SRodney W. Grimes #include "extern.h" 429b50d902SRodney W. Grimes 439b50d902SRodney W. Grimes /* 449b50d902SRodney W. Grimes * Mail -- a mail program 459b50d902SRodney W. Grimes * 469b50d902SRodney W. Grimes * Still more user commands. 479b50d902SRodney W. Grimes */ 489b50d902SRodney W. Grimes 499b50d902SRodney W. Grimes /* 509b50d902SRodney W. Grimes * Process a shell escape by saving signals, ignoring signals, 519b50d902SRodney W. Grimes * and forking a sh -c 529b50d902SRodney W. Grimes */ 539b50d902SRodney W. Grimes int 546d8484b0SPhilippe Charnier shell(char *str) 559b50d902SRodney W. Grimes { 569b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 579ce73e90SMike Heffner char *sh; 589b50d902SRodney W. Grimes char cmd[BUFSIZ]; 599b50d902SRodney W. Grimes 600c3a8314SMike Heffner if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd)) 619ce73e90SMike Heffner return (1); 620c3a8314SMike Heffner if (bangexp(cmd, sizeof(cmd)) < 0) 639ce73e90SMike Heffner return (1); 649ce73e90SMike Heffner if ((sh = value("SHELL")) == NULL) 659ce73e90SMike Heffner sh = _PATH_CSHELL; 669ce73e90SMike Heffner (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL); 679b50d902SRodney W. Grimes (void)signal(SIGINT, sigint); 689b50d902SRodney W. Grimes printf("!\n"); 699ce73e90SMike Heffner return (0); 709b50d902SRodney W. Grimes } 719b50d902SRodney W. Grimes 729b50d902SRodney W. Grimes /* 739b50d902SRodney W. Grimes * Fork an interactive shell. 749b50d902SRodney W. Grimes */ 759b50d902SRodney W. Grimes /*ARGSUSED*/ 769b50d902SRodney W. Grimes int 776d8484b0SPhilippe Charnier dosh(char *str __unused) 789b50d902SRodney W. Grimes { 799b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 809ce73e90SMike Heffner char *sh; 819b50d902SRodney W. Grimes 829ce73e90SMike Heffner if ((sh = value("SHELL")) == NULL) 839ce73e90SMike Heffner sh = _PATH_CSHELL; 84b22a8699SPedro F. Giffuni (void)run_command(sh, 0, -1, -1, NULL); 859b50d902SRodney W. Grimes (void)signal(SIGINT, sigint); 869ce73e90SMike Heffner printf("\n"); 879ce73e90SMike Heffner return (0); 889b50d902SRodney W. Grimes } 899b50d902SRodney W. Grimes 909b50d902SRodney W. Grimes /* 919b50d902SRodney W. Grimes * Expand the shell escape by expanding unescaped !'s into the 929b50d902SRodney W. Grimes * last issued command where possible. 939b50d902SRodney W. Grimes */ 949b50d902SRodney W. Grimes int 956d8484b0SPhilippe Charnier bangexp(char *str, size_t strsize) 969b50d902SRodney W. Grimes { 979b50d902SRodney W. Grimes char bangbuf[BUFSIZ]; 980c3a8314SMike Heffner static char lastbang[BUFSIZ]; 999ce73e90SMike Heffner char *cp, *cp2; 1009ce73e90SMike Heffner int n, changed = 0; 1019b50d902SRodney W. Grimes 1029b50d902SRodney W. Grimes cp = str; 1039b50d902SRodney W. Grimes cp2 = bangbuf; 1040c3a8314SMike Heffner n = sizeof(bangbuf); 1059ce73e90SMike Heffner while (*cp != '\0') { 1069b50d902SRodney W. Grimes if (*cp == '!') { 107b22a8699SPedro F. Giffuni if (n < (int)strlen(lastbang)) { 1089b50d902SRodney W. Grimes overf: 1099b50d902SRodney W. Grimes printf("Command buffer overflow\n"); 1109b50d902SRodney W. Grimes return (-1); 1119b50d902SRodney W. Grimes } 1129b50d902SRodney W. Grimes changed++; 1130c3a8314SMike Heffner if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf)) 1140c3a8314SMike Heffner >= sizeof(bangbuf) - (cp2 - bangbuf)) 1150c3a8314SMike Heffner goto overf; 1169b50d902SRodney W. Grimes cp2 += strlen(lastbang); 1179b50d902SRodney W. Grimes n -= strlen(lastbang); 1189b50d902SRodney W. Grimes cp++; 1199b50d902SRodney W. Grimes continue; 1209b50d902SRodney W. Grimes } 1219b50d902SRodney W. Grimes if (*cp == '\\' && cp[1] == '!') { 1229b50d902SRodney W. Grimes if (--n <= 1) 1239b50d902SRodney W. Grimes goto overf; 1249b50d902SRodney W. Grimes *cp2++ = '!'; 1259b50d902SRodney W. Grimes cp += 2; 1269b50d902SRodney W. Grimes changed++; 1279b50d902SRodney W. Grimes } 1289b50d902SRodney W. Grimes if (--n <= 1) 1299b50d902SRodney W. Grimes goto overf; 1309b50d902SRodney W. Grimes *cp2++ = *cp++; 1319b50d902SRodney W. Grimes } 1329b50d902SRodney W. Grimes *cp2 = 0; 1339b50d902SRodney W. Grimes if (changed) { 1349b50d902SRodney W. Grimes printf("!%s\n", bangbuf); 1359ce73e90SMike Heffner (void)fflush(stdout); 1369b50d902SRodney W. Grimes } 1370c3a8314SMike Heffner if (strlcpy(str, bangbuf, strsize) >= strsize) 1380c3a8314SMike Heffner goto overf; 1390c3a8314SMike Heffner if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang)) 1400c3a8314SMike Heffner goto overf; 1419b50d902SRodney W. Grimes return (0); 1429b50d902SRodney W. Grimes } 1439b50d902SRodney W. Grimes 1449b50d902SRodney W. Grimes /* 1459b50d902SRodney W. Grimes * Print out a nice help message from some file or another. 1469b50d902SRodney W. Grimes */ 1479b50d902SRodney W. Grimes 1489b50d902SRodney W. Grimes int 1496d8484b0SPhilippe Charnier help(void) 1509b50d902SRodney W. Grimes { 1519ce73e90SMike Heffner int c; 1529ce73e90SMike Heffner FILE *f; 1539b50d902SRodney W. Grimes 1549b50d902SRodney W. Grimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 1550c3a8314SMike Heffner warn("%s", _PATH_HELP); 1569b50d902SRodney W. Grimes return (1); 1579b50d902SRodney W. Grimes } 1589b50d902SRodney W. Grimes while ((c = getc(f)) != EOF) 1599b50d902SRodney W. Grimes putchar(c); 1609ce73e90SMike Heffner (void)Fclose(f); 1619b50d902SRodney W. Grimes return (0); 1629b50d902SRodney W. Grimes } 1639b50d902SRodney W. Grimes 1649b50d902SRodney W. Grimes /* 1659b50d902SRodney W. Grimes * Change user's working directory. 1669b50d902SRodney W. Grimes */ 1679b50d902SRodney W. Grimes int 168b948550dSPedro F. Giffuni schdir(void *v) 1699b50d902SRodney W. Grimes { 170b948550dSPedro F. Giffuni char **arglist = v; 1719b50d902SRodney W. Grimes char *cp; 1729b50d902SRodney W. Grimes 1739ce73e90SMike Heffner if (*arglist == NULL) { 1749ce73e90SMike Heffner if (homedir == NULL) 1750c3a8314SMike Heffner return (1); 1769b50d902SRodney W. Grimes cp = homedir; 1770c3a8314SMike Heffner } else 1789ce73e90SMike Heffner if ((cp = expand(*arglist)) == NULL) 1799b50d902SRodney W. Grimes return (1); 1809b50d902SRodney W. Grimes if (chdir(cp) < 0) { 1810c3a8314SMike Heffner warn("%s", cp); 1829b50d902SRodney W. Grimes return (1); 1839b50d902SRodney W. Grimes } 1849ce73e90SMike Heffner return (0); 1859b50d902SRodney W. Grimes } 1869b50d902SRodney W. Grimes 1879b50d902SRodney W. Grimes int 188b948550dSPedro F. Giffuni respond(void *v) 1899b50d902SRodney W. Grimes { 190b948550dSPedro F. Giffuni int *msgvec = v; 191b948550dSPedro F. Giffuni 1920077673eSMike Heffner if (value("Replyall") == NULL && value("flipr") == NULL) 19399bd6601SJoerg Wunsch return (dorespond(msgvec)); 1949b50d902SRodney W. Grimes else 19599bd6601SJoerg Wunsch return (doRespond(msgvec)); 1969b50d902SRodney W. Grimes } 1979b50d902SRodney W. Grimes 1989b50d902SRodney W. Grimes /* 1999b50d902SRodney W. Grimes * Reply to a list of messages. Extract each name from the 2009b50d902SRodney W. Grimes * message header and send them off to mail1() 2019b50d902SRodney W. Grimes */ 2029b50d902SRodney W. Grimes int 2036d8484b0SPhilippe Charnier dorespond(int *msgvec) 2049b50d902SRodney W. Grimes { 2059b50d902SRodney W. Grimes struct message *mp; 2069b50d902SRodney W. Grimes char *cp, *rcv, *replyto; 2079b50d902SRodney W. Grimes char **ap; 2089b50d902SRodney W. Grimes struct name *np; 2099b50d902SRodney W. Grimes struct header head; 2109b50d902SRodney W. Grimes 2119b50d902SRodney W. Grimes if (msgvec[1] != 0) { 2129b50d902SRodney W. Grimes printf("Sorry, can't reply to multiple messages at once\n"); 2139b50d902SRodney W. Grimes return (1); 2149b50d902SRodney W. Grimes } 2159b50d902SRodney W. Grimes mp = &message[msgvec[0] - 1]; 2169b50d902SRodney W. Grimes touch(mp); 2179b50d902SRodney W. Grimes dot = mp; 2189ce73e90SMike Heffner if ((rcv = skin(hfield("from", mp))) == NULL) 2199b50d902SRodney W. Grimes rcv = skin(nameof(mp, 1)); 2209ce73e90SMike Heffner if ((replyto = skin(hfield("reply-to", mp))) != NULL) 2219b50d902SRodney W. Grimes np = extract(replyto, GTO); 2229ce73e90SMike Heffner else if ((cp = skin(hfield("to", mp))) != NULL) 2239b50d902SRodney W. Grimes np = extract(cp, GTO); 2249b50d902SRodney W. Grimes else 2259ce73e90SMike Heffner np = NULL; 2269b50d902SRodney W. Grimes np = elide(np); 2279b50d902SRodney W. Grimes /* 2289b50d902SRodney W. Grimes * Delete my name from the reply list, 2299b50d902SRodney W. Grimes * and with it, all my alternate names. 2309b50d902SRodney W. Grimes */ 2319b50d902SRodney W. Grimes np = delname(np, myname); 2329b50d902SRodney W. Grimes if (altnames) 2339ce73e90SMike Heffner for (ap = altnames; *ap != NULL; ap++) 2349b50d902SRodney W. Grimes np = delname(np, *ap); 2359ce73e90SMike Heffner if (np != NULL && replyto == NULL) 2369b50d902SRodney W. Grimes np = cat(np, extract(rcv, GTO)); 2379ce73e90SMike Heffner else if (np == NULL) { 2389ce73e90SMike Heffner if (replyto != NULL) 2399b50d902SRodney W. Grimes printf("Empty reply-to field -- replying to author\n"); 2409b50d902SRodney W. Grimes np = extract(rcv, GTO); 2419b50d902SRodney W. Grimes } 2429b50d902SRodney W. Grimes head.h_to = np; 2439ce73e90SMike Heffner if ((head.h_subject = hfield("subject", mp)) == NULL) 2449b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 2459b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 2469ce73e90SMike Heffner if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) { 2479b50d902SRodney W. Grimes np = elide(extract(cp, GCC)); 2489b50d902SRodney W. Grimes np = delname(np, myname); 2499b50d902SRodney W. Grimes if (altnames != 0) 2509ce73e90SMike Heffner for (ap = altnames; *ap != NULL; ap++) 2519b50d902SRodney W. Grimes np = delname(np, *ap); 2529b50d902SRodney W. Grimes head.h_cc = np; 2539b50d902SRodney W. Grimes } else 2549ce73e90SMike Heffner head.h_cc = NULL; 2559ce73e90SMike Heffner head.h_bcc = NULL; 2569ce73e90SMike Heffner head.h_smopts = NULL; 25759c3f4f7SMike Heffner head.h_replyto = value("REPLYTO"); 25899bd6601SJoerg Wunsch head.h_inreplyto = skin(hfield("message-id", mp)); 2599b50d902SRodney W. Grimes mail1(&head, 1); 2609b50d902SRodney W. Grimes return (0); 2619b50d902SRodney W. Grimes } 2629b50d902SRodney W. Grimes 2639b50d902SRodney W. Grimes /* 2649b50d902SRodney W. Grimes * Modify the subject we are replying to to begin with Re: if 2659b50d902SRodney W. Grimes * it does not already. 2669b50d902SRodney W. Grimes */ 2679b50d902SRodney W. Grimes char * 2686d8484b0SPhilippe Charnier reedit(char *subj) 2699b50d902SRodney W. Grimes { 2709b50d902SRodney W. Grimes char *newsubj; 2719b50d902SRodney W. Grimes 2729ce73e90SMike Heffner if (subj == NULL) 2739ce73e90SMike Heffner return (NULL); 2749b50d902SRodney W. Grimes if ((subj[0] == 'r' || subj[0] == 'R') && 2759b50d902SRodney W. Grimes (subj[1] == 'e' || subj[1] == 'E') && 2769b50d902SRodney W. Grimes subj[2] == ':') 2779ce73e90SMike Heffner return (subj); 2789b50d902SRodney W. Grimes newsubj = salloc(strlen(subj) + 5); 2790c3a8314SMike Heffner sprintf(newsubj, "Re: %s", subj); 2809ce73e90SMike Heffner return (newsubj); 2819b50d902SRodney W. Grimes } 2829b50d902SRodney W. Grimes 2839b50d902SRodney W. Grimes /* 2849b50d902SRodney W. Grimes * Preserve the named messages, so that they will be sent 2859b50d902SRodney W. Grimes * back to the system mailbox. 2869b50d902SRodney W. Grimes */ 2879b50d902SRodney W. Grimes int 288b948550dSPedro F. Giffuni preserve(void *v) 2899b50d902SRodney W. Grimes { 290b948550dSPedro F. Giffuni int *msgvec = v; 2919ce73e90SMike Heffner int *ip, mesg; 2929ce73e90SMike Heffner struct message *mp; 2939b50d902SRodney W. Grimes 2949b50d902SRodney W. Grimes if (edit) { 2959b50d902SRodney W. Grimes printf("Cannot \"preserve\" in edit mode\n"); 2969b50d902SRodney W. Grimes return (1); 2979b50d902SRodney W. Grimes } 298d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 2999b50d902SRodney W. Grimes mesg = *ip; 3009b50d902SRodney W. Grimes mp = &message[mesg-1]; 3019b50d902SRodney W. Grimes mp->m_flag |= MPRESERVE; 3029b50d902SRodney W. Grimes mp->m_flag &= ~MBOX; 3039b50d902SRodney W. Grimes dot = mp; 3049b50d902SRodney W. Grimes } 3059b50d902SRodney W. Grimes return (0); 3069b50d902SRodney W. Grimes } 3079b50d902SRodney W. Grimes 3089b50d902SRodney W. Grimes /* 3099b50d902SRodney W. Grimes * Mark all given messages as unread. 3109b50d902SRodney W. Grimes */ 3119b50d902SRodney W. Grimes int 312b948550dSPedro F. Giffuni unread(void *v) 3139b50d902SRodney W. Grimes { 314b948550dSPedro F. Giffuni int *msgvec = v; 3159ce73e90SMike Heffner int *ip; 3169b50d902SRodney W. Grimes 317d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3189b50d902SRodney W. Grimes dot = &message[*ip-1]; 3199b50d902SRodney W. Grimes dot->m_flag &= ~(MREAD|MTOUCH); 3209b50d902SRodney W. Grimes dot->m_flag |= MSTATUS; 3219b50d902SRodney W. Grimes } 3229b50d902SRodney W. Grimes return (0); 3239b50d902SRodney W. Grimes } 3249b50d902SRodney W. Grimes 3259b50d902SRodney W. Grimes /* 3269b50d902SRodney W. Grimes * Print the size of each message. 3279b50d902SRodney W. Grimes */ 3289b50d902SRodney W. Grimes int 329b948550dSPedro F. Giffuni messize(void *v) 3309b50d902SRodney W. Grimes { 331b948550dSPedro F. Giffuni int *msgvec = v; 3329ce73e90SMike Heffner struct message *mp; 3339ce73e90SMike Heffner int *ip, mesg; 3349b50d902SRodney W. Grimes 335d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3369b50d902SRodney W. Grimes mesg = *ip; 3379b50d902SRodney W. Grimes mp = &message[mesg-1]; 33822694ebaSBruce Evans printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3399b50d902SRodney W. Grimes } 3409b50d902SRodney W. Grimes return (0); 3419b50d902SRodney W. Grimes } 3429b50d902SRodney W. Grimes 3439b50d902SRodney W. Grimes /* 3449b50d902SRodney W. Grimes * Quit quickly. If we are sourcing, just pop the input level 3459b50d902SRodney W. Grimes * by returning an error. 3469b50d902SRodney W. Grimes */ 3479b50d902SRodney W. Grimes int 348b948550dSPedro F. Giffuni rexit(void *v) 3499b50d902SRodney W. Grimes { 3509b50d902SRodney W. Grimes if (sourcing) 3519b50d902SRodney W. Grimes return (1); 352856f23edSMike Heffner exit(0); 3539b50d902SRodney W. Grimes /*NOTREACHED*/ 3549b50d902SRodney W. Grimes } 3559b50d902SRodney W. Grimes 3569b50d902SRodney W. Grimes /* 3579b50d902SRodney W. Grimes * Set or display a variable value. Syntax is similar to that 3589b50d902SRodney W. Grimes * of csh. 3599b50d902SRodney W. Grimes */ 3609b50d902SRodney W. Grimes int 361b948550dSPedro F. Giffuni set(void *v) 3629b50d902SRodney W. Grimes { 363b948550dSPedro F. Giffuni char **arglist = v; 3649ce73e90SMike Heffner struct var *vp; 3659ce73e90SMike Heffner char *cp, *cp2; 3669b50d902SRodney W. Grimes char varbuf[BUFSIZ], **ap, **p; 3679b50d902SRodney W. Grimes int errs, h, s; 3689b50d902SRodney W. Grimes 3699ce73e90SMike Heffner if (*arglist == NULL) { 3709b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 3719ce73e90SMike Heffner for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3729b50d902SRodney W. Grimes s++; 3739ce73e90SMike Heffner ap = (char **)salloc(s * sizeof(*ap)); 3749b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 3759ce73e90SMike Heffner for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3769b50d902SRodney W. Grimes *p++ = vp->v_name; 3779ce73e90SMike Heffner *p = NULL; 3789b50d902SRodney W. Grimes sort(ap); 3799ce73e90SMike Heffner for (p = ap; *p != NULL; p++) 3809b50d902SRodney W. Grimes printf("%s\t%s\n", *p, value(*p)); 3819b50d902SRodney W. Grimes return (0); 3829b50d902SRodney W. Grimes } 3839b50d902SRodney W. Grimes errs = 0; 3849ce73e90SMike Heffner for (ap = arglist; *ap != NULL; ap++) { 3859b50d902SRodney W. Grimes cp = *ap; 3869b50d902SRodney W. Grimes cp2 = varbuf; 3870c3a8314SMike Heffner while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3889b50d902SRodney W. Grimes *cp2++ = *cp++; 3899b50d902SRodney W. Grimes *cp2 = '\0'; 3909b50d902SRodney W. Grimes if (*cp == '\0') 3919b50d902SRodney W. Grimes cp = ""; 3929b50d902SRodney W. Grimes else 3939b50d902SRodney W. Grimes cp++; 3949b50d902SRodney W. Grimes if (equal(varbuf, "")) { 3959b50d902SRodney W. Grimes printf("Non-null variable name required\n"); 3969b50d902SRodney W. Grimes errs++; 3979b50d902SRodney W. Grimes continue; 3989b50d902SRodney W. Grimes } 3999b50d902SRodney W. Grimes assign(varbuf, cp); 4009b50d902SRodney W. Grimes } 4019b50d902SRodney W. Grimes return (errs); 4029b50d902SRodney W. Grimes } 4039b50d902SRodney W. Grimes 4049b50d902SRodney W. Grimes /* 4059b50d902SRodney W. Grimes * Unset a bunch of variable values. 4069b50d902SRodney W. Grimes */ 4079b50d902SRodney W. Grimes int 408b948550dSPedro F. Giffuni unset(void *v) 4099b50d902SRodney W. Grimes { 410b948550dSPedro F. Giffuni char **arglist = v; 4119ce73e90SMike Heffner struct var *vp, *vp2; 4129b50d902SRodney W. Grimes int errs, h; 4139b50d902SRodney W. Grimes char **ap; 4149b50d902SRodney W. Grimes 4159b50d902SRodney W. Grimes errs = 0; 4169ce73e90SMike Heffner for (ap = arglist; *ap != NULL; ap++) { 4179ce73e90SMike Heffner if ((vp2 = lookup(*ap)) == NULL) { 418856f23edSMike Heffner if (getenv(*ap)) 419856f23edSMike Heffner unsetenv(*ap); 420856f23edSMike Heffner else if (!sourcing) { 4219b50d902SRodney W. Grimes printf("\"%s\": undefined variable\n", *ap); 4229b50d902SRodney W. Grimes errs++; 4239b50d902SRodney W. Grimes } 4249b50d902SRodney W. Grimes continue; 4259b50d902SRodney W. Grimes } 4269b50d902SRodney W. Grimes h = hash(*ap); 4279b50d902SRodney W. Grimes if (vp2 == variables[h]) { 4289b50d902SRodney W. Grimes variables[h] = variables[h]->v_link; 4299b50d902SRodney W. Grimes vfree(vp2->v_name); 4309b50d902SRodney W. Grimes vfree(vp2->v_value); 4319ce73e90SMike Heffner (void)free(vp2); 4329b50d902SRodney W. Grimes continue; 4339b50d902SRodney W. Grimes } 4349b50d902SRodney W. Grimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4359b50d902SRodney W. Grimes ; 4369b50d902SRodney W. Grimes vp->v_link = vp2->v_link; 4379b50d902SRodney W. Grimes vfree(vp2->v_name); 4389b50d902SRodney W. Grimes vfree(vp2->v_value); 4399ce73e90SMike Heffner (void)free(vp2); 4409b50d902SRodney W. Grimes } 4419b50d902SRodney W. Grimes return (errs); 4429b50d902SRodney W. Grimes } 4439b50d902SRodney W. Grimes 4449b50d902SRodney W. Grimes /* 4459b50d902SRodney W. Grimes * Put add users to a group. 4469b50d902SRodney W. Grimes */ 4479b50d902SRodney W. Grimes int 448b948550dSPedro F. Giffuni group(void *v) 4499b50d902SRodney W. Grimes { 450b948550dSPedro F. Giffuni char **argv = v; 4519ce73e90SMike Heffner struct grouphead *gh; 4529ce73e90SMike Heffner struct group *gp; 4539b50d902SRodney W. Grimes char **ap, *gname, **p; 4549ce73e90SMike Heffner int h, s; 4559b50d902SRodney W. Grimes 4569ce73e90SMike Heffner if (*argv == NULL) { 4579b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 4589ce73e90SMike Heffner for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4599b50d902SRodney W. Grimes s++; 4609ce73e90SMike Heffner ap = (char **)salloc(s * sizeof(*ap)); 4619b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 4629ce73e90SMike Heffner for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4639b50d902SRodney W. Grimes *p++ = gh->g_name; 4649ce73e90SMike Heffner *p = NULL; 4659b50d902SRodney W. Grimes sort(ap); 4669ce73e90SMike Heffner for (p = ap; *p != NULL; p++) 4679b50d902SRodney W. Grimes printgroup(*p); 4689b50d902SRodney W. Grimes return (0); 4699b50d902SRodney W. Grimes } 4709ce73e90SMike Heffner if (argv[1] == NULL) { 4719b50d902SRodney W. Grimes printgroup(*argv); 4729b50d902SRodney W. Grimes return (0); 4739b50d902SRodney W. Grimes } 4749b50d902SRodney W. Grimes gname = *argv; 4759b50d902SRodney W. Grimes h = hash(gname); 4769ce73e90SMike Heffner if ((gh = findgroup(gname)) == NULL) { 477dde0f2bfSPedro F. Giffuni if ((gh = calloc(1, sizeof(*gh))) == NULL) 478dde0f2bfSPedro F. Giffuni err(1, "Out of memory"); 4799b50d902SRodney W. Grimes gh->g_name = vcopy(gname); 4809ce73e90SMike Heffner gh->g_list = NULL; 4819b50d902SRodney W. Grimes gh->g_link = groups[h]; 4829b50d902SRodney W. Grimes groups[h] = gh; 4839b50d902SRodney W. Grimes } 4849b50d902SRodney W. Grimes 4859b50d902SRodney W. Grimes /* 4869b50d902SRodney W. Grimes * Insert names from the command list into the group. 4879b50d902SRodney W. Grimes * Who cares if there are duplicates? They get tossed 4889b50d902SRodney W. Grimes * later anyway. 4899b50d902SRodney W. Grimes */ 4909b50d902SRodney W. Grimes 4919ce73e90SMike Heffner for (ap = argv+1; *ap != NULL; ap++) { 492dde0f2bfSPedro F. Giffuni if ((gp = calloc(1, sizeof(*gp))) == NULL) 493dde0f2bfSPedro F. Giffuni err(1, "Out of memory"); 4949b50d902SRodney W. Grimes gp->ge_name = vcopy(*ap); 4959b50d902SRodney W. Grimes gp->ge_link = gh->g_list; 4969b50d902SRodney W. Grimes gh->g_list = gp; 4979b50d902SRodney W. Grimes } 4989b50d902SRodney W. Grimes return (0); 4999b50d902SRodney W. Grimes } 5009b50d902SRodney W. Grimes 5019b50d902SRodney W. Grimes /* 5029b50d902SRodney W. Grimes * Sort the passed string vecotor into ascending dictionary 5039b50d902SRodney W. Grimes * order. 5049b50d902SRodney W. Grimes */ 5059b50d902SRodney W. Grimes void 5066d8484b0SPhilippe Charnier sort(char **list) 5079b50d902SRodney W. Grimes { 5089ce73e90SMike Heffner char **ap; 5099b50d902SRodney W. Grimes 5109ce73e90SMike Heffner for (ap = list; *ap != NULL; ap++) 5119b50d902SRodney W. Grimes ; 5129b50d902SRodney W. Grimes if (ap-list < 2) 5139b50d902SRodney W. Grimes return; 5149b50d902SRodney W. Grimes qsort(list, ap-list, sizeof(*list), diction); 5159b50d902SRodney W. Grimes } 5169b50d902SRodney W. Grimes 5179b50d902SRodney W. Grimes /* 5189b50d902SRodney W. Grimes * Do a dictionary order comparison of the arguments from 5199b50d902SRodney W. Grimes * qsort. 5209b50d902SRodney W. Grimes */ 5219b50d902SRodney W. Grimes int 5226d8484b0SPhilippe Charnier diction(const void *a, const void *b) 5239b50d902SRodney W. Grimes { 5249ce73e90SMike Heffner return (strcmp(*(const char **)a, *(const char **)b)); 5259b50d902SRodney W. Grimes } 5269b50d902SRodney W. Grimes 5279b50d902SRodney W. Grimes /* 5289b50d902SRodney W. Grimes * The do nothing command for comments. 5299b50d902SRodney W. Grimes */ 5309b50d902SRodney W. Grimes 5319b50d902SRodney W. Grimes /*ARGSUSED*/ 5329b50d902SRodney W. Grimes int 5336d8484b0SPhilippe Charnier null(int e __unused) 5349b50d902SRodney W. Grimes { 5359ce73e90SMike Heffner return (0); 5369b50d902SRodney W. Grimes } 5379b50d902SRodney W. Grimes 5389b50d902SRodney W. Grimes /* 5399b50d902SRodney W. Grimes * Change to another file. With no argument, print information about 5409b50d902SRodney W. Grimes * the current file. 5419b50d902SRodney W. Grimes */ 5429b50d902SRodney W. Grimes int 5436d8484b0SPhilippe Charnier file(char **argv) 5449b50d902SRodney W. Grimes { 5459b50d902SRodney W. Grimes 5469ce73e90SMike Heffner if (argv[0] == NULL) { 547856f23edSMike Heffner newfileinfo(0); 5489ce73e90SMike Heffner return (0); 5499b50d902SRodney W. Grimes } 5509b50d902SRodney W. Grimes if (setfile(*argv) < 0) 5519ce73e90SMike Heffner return (1); 5529b50d902SRodney W. Grimes announce(); 5539ce73e90SMike Heffner return (0); 5549b50d902SRodney W. Grimes } 5559b50d902SRodney W. Grimes 5569b50d902SRodney W. Grimes /* 5579b50d902SRodney W. Grimes * Expand file names like echo 5589b50d902SRodney W. Grimes */ 5599b50d902SRodney W. Grimes int 5606d8484b0SPhilippe Charnier echo(char **argv) 5619b50d902SRodney W. Grimes { 5629ce73e90SMike Heffner char **ap, *cp; 5639b50d902SRodney W. Grimes 5649ce73e90SMike Heffner for (ap = argv; *ap != NULL; ap++) { 5659b50d902SRodney W. Grimes cp = *ap; 5669ce73e90SMike Heffner if ((cp = expand(cp)) != NULL) { 5679b50d902SRodney W. Grimes if (ap != argv) 5689ce73e90SMike Heffner printf(" "); 5699b50d902SRodney W. Grimes printf("%s", cp); 5709b50d902SRodney W. Grimes } 5719b50d902SRodney W. Grimes } 5729ce73e90SMike Heffner printf("\n"); 5739ce73e90SMike Heffner return (0); 5749b50d902SRodney W. Grimes } 5759b50d902SRodney W. Grimes 5769b50d902SRodney W. Grimes int 5776d8484b0SPhilippe Charnier Respond(int *msgvec) 5789b50d902SRodney W. Grimes { 5790077673eSMike Heffner if (value("Replyall") == NULL && value("flipr") == NULL) 58099bd6601SJoerg Wunsch return (doRespond(msgvec)); 5819b50d902SRodney W. Grimes else 58299bd6601SJoerg Wunsch return (dorespond(msgvec)); 5839b50d902SRodney W. Grimes } 5849b50d902SRodney W. Grimes 5859b50d902SRodney W. Grimes /* 5869b50d902SRodney W. Grimes * Reply to a series of messages by simply mailing to the senders 5879b50d902SRodney W. Grimes * and not messing around with the To: and Cc: lists as in normal 5889b50d902SRodney W. Grimes * reply. 5899b50d902SRodney W. Grimes */ 5909b50d902SRodney W. Grimes int 5916d8484b0SPhilippe Charnier doRespond(int msgvec[]) 5929b50d902SRodney W. Grimes { 5939b50d902SRodney W. Grimes struct header head; 5949b50d902SRodney W. Grimes struct message *mp; 5959ce73e90SMike Heffner int *ap; 5969ce73e90SMike Heffner char *cp, *mid; 5979b50d902SRodney W. Grimes 5989ce73e90SMike Heffner head.h_to = NULL; 5999b50d902SRodney W. Grimes for (ap = msgvec; *ap != 0; ap++) { 6009b50d902SRodney W. Grimes mp = &message[*ap - 1]; 6019b50d902SRodney W. Grimes touch(mp); 6029b50d902SRodney W. Grimes dot = mp; 6039ce73e90SMike Heffner if ((cp = skin(hfield("from", mp))) == NULL) 6049b50d902SRodney W. Grimes cp = skin(nameof(mp, 2)); 6059b50d902SRodney W. Grimes head.h_to = cat(head.h_to, extract(cp, GTO)); 60699bd6601SJoerg Wunsch mid = skin(hfield("message-id", mp)); 6079b50d902SRodney W. Grimes } 6089ce73e90SMike Heffner if (head.h_to == NULL) 6099ce73e90SMike Heffner return (0); 6109b50d902SRodney W. Grimes mp = &message[msgvec[0] - 1]; 6119ce73e90SMike Heffner if ((head.h_subject = hfield("subject", mp)) == NULL) 6129b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 6139b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 6149ce73e90SMike Heffner head.h_cc = NULL; 6159ce73e90SMike Heffner head.h_bcc = NULL; 6169ce73e90SMike Heffner head.h_smopts = NULL; 61759c3f4f7SMike Heffner head.h_replyto = value("REPLYTO"); 61899bd6601SJoerg Wunsch head.h_inreplyto = mid; 6199b50d902SRodney W. Grimes mail1(&head, 1); 6209ce73e90SMike Heffner return (0); 6219b50d902SRodney W. Grimes } 6229b50d902SRodney W. Grimes 6239b50d902SRodney W. Grimes /* 6249b50d902SRodney W. Grimes * Conditional commands. These allow one to parameterize one's 6259b50d902SRodney W. Grimes * .mailrc and do some things if sending, others if receiving. 6269b50d902SRodney W. Grimes */ 6279b50d902SRodney W. Grimes int 6286d8484b0SPhilippe Charnier ifcmd(char **argv) 6299b50d902SRodney W. Grimes { 6309ce73e90SMike Heffner char *cp; 6319b50d902SRodney W. Grimes 6329b50d902SRodney W. Grimes if (cond != CANY) { 6339b50d902SRodney W. Grimes printf("Illegal nested \"if\"\n"); 6349b50d902SRodney W. Grimes return (1); 6359b50d902SRodney W. Grimes } 6369b50d902SRodney W. Grimes cond = CANY; 6379b50d902SRodney W. Grimes cp = argv[0]; 6389b50d902SRodney W. Grimes switch (*cp) { 6399b50d902SRodney W. Grimes case 'r': case 'R': 6409b50d902SRodney W. Grimes cond = CRCV; 6419b50d902SRodney W. Grimes break; 6429b50d902SRodney W. Grimes 6439b50d902SRodney W. Grimes case 's': case 'S': 6449b50d902SRodney W. Grimes cond = CSEND; 6459b50d902SRodney W. Grimes break; 6469b50d902SRodney W. Grimes 6479b50d902SRodney W. Grimes default: 6489b50d902SRodney W. Grimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 6499b50d902SRodney W. Grimes return (1); 6509b50d902SRodney W. Grimes } 6519b50d902SRodney W. Grimes return (0); 6529b50d902SRodney W. Grimes } 6539b50d902SRodney W. Grimes 6549b50d902SRodney W. Grimes /* 6559b50d902SRodney W. Grimes * Implement 'else'. This is pretty simple -- we just 6569b50d902SRodney W. Grimes * flip over the conditional flag. 6579b50d902SRodney W. Grimes */ 6589b50d902SRodney W. Grimes int 6596d8484b0SPhilippe Charnier elsecmd(void) 6609b50d902SRodney W. Grimes { 6619b50d902SRodney W. Grimes 6629b50d902SRodney W. Grimes switch (cond) { 6639b50d902SRodney W. Grimes case CANY: 6649b50d902SRodney W. Grimes printf("\"Else\" without matching \"if\"\n"); 6659b50d902SRodney W. Grimes return (1); 6669b50d902SRodney W. Grimes 6679b50d902SRodney W. Grimes case CSEND: 6689b50d902SRodney W. Grimes cond = CRCV; 6699b50d902SRodney W. Grimes break; 6709b50d902SRodney W. Grimes 6719b50d902SRodney W. Grimes case CRCV: 6729b50d902SRodney W. Grimes cond = CSEND; 6739b50d902SRodney W. Grimes break; 6749b50d902SRodney W. Grimes 6759b50d902SRodney W. Grimes default: 6769b50d902SRodney W. Grimes printf("Mail's idea of conditions is screwed up\n"); 6779b50d902SRodney W. Grimes cond = CANY; 6789b50d902SRodney W. Grimes break; 6799b50d902SRodney W. Grimes } 6809b50d902SRodney W. Grimes return (0); 6819b50d902SRodney W. Grimes } 6829b50d902SRodney W. Grimes 6839b50d902SRodney W. Grimes /* 6849b50d902SRodney W. Grimes * End of if statement. Just set cond back to anything. 6859b50d902SRodney W. Grimes */ 6869b50d902SRodney W. Grimes int 6876d8484b0SPhilippe Charnier endifcmd(void) 6889b50d902SRodney W. Grimes { 6899b50d902SRodney W. Grimes 6909b50d902SRodney W. Grimes if (cond == CANY) { 6919b50d902SRodney W. Grimes printf("\"Endif\" without matching \"if\"\n"); 6929b50d902SRodney W. Grimes return (1); 6939b50d902SRodney W. Grimes } 6949b50d902SRodney W. Grimes cond = CANY; 6959b50d902SRodney W. Grimes return (0); 6969b50d902SRodney W. Grimes } 6979b50d902SRodney W. Grimes 6989b50d902SRodney W. Grimes /* 6999b50d902SRodney W. Grimes * Set the list of alternate names. 7009b50d902SRodney W. Grimes */ 7019b50d902SRodney W. Grimes int 7026d8484b0SPhilippe Charnier alternates(char **namelist) 7039b50d902SRodney W. Grimes { 7049ce73e90SMike Heffner int c; 7059ce73e90SMike Heffner char **ap, **ap2, *cp; 7069b50d902SRodney W. Grimes 7079b50d902SRodney W. Grimes c = argcount(namelist) + 1; 7089b50d902SRodney W. Grimes if (c == 1) { 7099b50d902SRodney W. Grimes if (altnames == 0) 7109b50d902SRodney W. Grimes return (0); 7119ce73e90SMike Heffner for (ap = altnames; *ap != NULL; ap++) 7129b50d902SRodney W. Grimes printf("%s ", *ap); 7139b50d902SRodney W. Grimes printf("\n"); 7149b50d902SRodney W. Grimes return (0); 7159b50d902SRodney W. Grimes } 7169b50d902SRodney W. Grimes if (altnames != 0) 7179ce73e90SMike Heffner (void)free(altnames); 718dde0f2bfSPedro F. Giffuni if ((altnames = calloc((unsigned)c, sizeof(char *))) == NULL) 719dde0f2bfSPedro F. Giffuni err(1, "Out of memory"); 7209ce73e90SMike Heffner for (ap = namelist, ap2 = altnames; *ap != NULL; ap++, ap2++) { 7219ce73e90SMike Heffner cp = calloc((unsigned)strlen(*ap) + 1, sizeof(char)); 7229b50d902SRodney W. Grimes strcpy(cp, *ap); 7239b50d902SRodney W. Grimes *ap2 = cp; 7249b50d902SRodney W. Grimes } 7259b50d902SRodney W. Grimes *ap2 = 0; 7269b50d902SRodney W. Grimes return (0); 7279b50d902SRodney W. Grimes } 728