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