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. 139b50d902SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 149b50d902SRodney W. Grimes * must display the following acknowledgement: 159b50d902SRodney W. Grimes * This product includes software developed by the University of 169b50d902SRodney W. Grimes * California, Berkeley and its contributors. 179b50d902SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 189b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 199b50d902SRodney W. Grimes * without specific prior written permission. 209b50d902SRodney W. Grimes * 219b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319b50d902SRodney W. Grimes * SUCH DAMAGE. 329b50d902SRodney W. Grimes */ 339b50d902SRodney W. Grimes 349b50d902SRodney W. Grimes #ifndef lint 350c3a8314SMike Heffner #if 0 369b50d902SRodney W. Grimes static char sccsid[] = "@(#)cmd3.c 8.1 (Berkeley) 6/6/93"; 370c3a8314SMike Heffner #endif 380c3a8314SMike Heffner static const char rcsid[] = 390c3a8314SMike Heffner "$FreeBSD$"; 409b50d902SRodney W. Grimes #endif /* not lint */ 419b50d902SRodney W. Grimes 429b50d902SRodney W. Grimes #include "rcv.h" 439b50d902SRodney W. Grimes #include "extern.h" 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes /* 469b50d902SRodney W. Grimes * Mail -- a mail program 479b50d902SRodney W. Grimes * 489b50d902SRodney W. Grimes * Still more user commands. 499b50d902SRodney W. Grimes */ 509b50d902SRodney W. Grimes 519b50d902SRodney W. Grimes /* 529b50d902SRodney W. Grimes * Process a shell escape by saving signals, ignoring signals, 539b50d902SRodney W. Grimes * and forking a sh -c 549b50d902SRodney W. Grimes */ 559b50d902SRodney W. Grimes int 569b50d902SRodney W. Grimes shell(str) 579b50d902SRodney W. Grimes char *str; 589b50d902SRodney W. Grimes { 599b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 609ce73e90SMike Heffner char *sh; 619b50d902SRodney W. Grimes char cmd[BUFSIZ]; 629b50d902SRodney W. Grimes 630c3a8314SMike Heffner if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd)) 649ce73e90SMike Heffner return (1); 650c3a8314SMike Heffner if (bangexp(cmd, sizeof(cmd)) < 0) 669ce73e90SMike Heffner return (1); 679ce73e90SMike Heffner if ((sh = value("SHELL")) == NULL) 689ce73e90SMike Heffner sh = _PATH_CSHELL; 699ce73e90SMike Heffner (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL); 709b50d902SRodney W. Grimes (void)signal(SIGINT, sigint); 719b50d902SRodney W. Grimes printf("!\n"); 729ce73e90SMike Heffner return (0); 739b50d902SRodney W. Grimes } 749b50d902SRodney W. Grimes 759b50d902SRodney W. Grimes /* 769b50d902SRodney W. Grimes * Fork an interactive shell. 779b50d902SRodney W. Grimes */ 789b50d902SRodney W. Grimes /*ARGSUSED*/ 799b50d902SRodney W. Grimes int 809b50d902SRodney W. Grimes dosh(str) 819b50d902SRodney W. Grimes char *str; 829b50d902SRodney W. Grimes { 839b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 849ce73e90SMike Heffner char *sh; 859b50d902SRodney W. Grimes 869ce73e90SMike Heffner if ((sh = value("SHELL")) == NULL) 879ce73e90SMike Heffner sh = _PATH_CSHELL; 889ce73e90SMike Heffner (void)run_command(sh, 0, -1, -1, NULL, NULL, NULL); 899b50d902SRodney W. Grimes (void)signal(SIGINT, sigint); 909ce73e90SMike Heffner printf("\n"); 919ce73e90SMike Heffner return (0); 929b50d902SRodney W. Grimes } 939b50d902SRodney W. Grimes 949b50d902SRodney W. Grimes /* 959b50d902SRodney W. Grimes * Expand the shell escape by expanding unescaped !'s into the 969b50d902SRodney W. Grimes * last issued command where possible. 979b50d902SRodney W. Grimes */ 989b50d902SRodney W. Grimes int 990c3a8314SMike Heffner bangexp(str, strsize) 1009b50d902SRodney W. Grimes char *str; 1010c3a8314SMike Heffner size_t strsize; 1029b50d902SRodney W. Grimes { 1039b50d902SRodney W. Grimes char bangbuf[BUFSIZ]; 1040c3a8314SMike Heffner static char lastbang[BUFSIZ]; 1059ce73e90SMike Heffner char *cp, *cp2; 1069ce73e90SMike Heffner int n, changed = 0; 1079b50d902SRodney W. Grimes 1089b50d902SRodney W. Grimes cp = str; 1099b50d902SRodney W. Grimes cp2 = bangbuf; 1100c3a8314SMike Heffner n = sizeof(bangbuf); 1119ce73e90SMike Heffner while (*cp != '\0') { 1129b50d902SRodney W. Grimes if (*cp == '!') { 1139b50d902SRodney W. Grimes if (n < strlen(lastbang)) { 1149b50d902SRodney W. Grimes overf: 1159b50d902SRodney W. Grimes printf("Command buffer overflow\n"); 1169b50d902SRodney W. Grimes return (-1); 1179b50d902SRodney W. Grimes } 1189b50d902SRodney W. Grimes changed++; 1190c3a8314SMike Heffner if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf)) 1200c3a8314SMike Heffner >= sizeof(bangbuf) - (cp2 - bangbuf)) 1210c3a8314SMike Heffner goto overf; 1229b50d902SRodney W. Grimes cp2 += strlen(lastbang); 1239b50d902SRodney W. Grimes n -= strlen(lastbang); 1249b50d902SRodney W. Grimes cp++; 1259b50d902SRodney W. Grimes continue; 1269b50d902SRodney W. Grimes } 1279b50d902SRodney W. Grimes if (*cp == '\\' && cp[1] == '!') { 1289b50d902SRodney W. Grimes if (--n <= 1) 1299b50d902SRodney W. Grimes goto overf; 1309b50d902SRodney W. Grimes *cp2++ = '!'; 1319b50d902SRodney W. Grimes cp += 2; 1329b50d902SRodney W. Grimes changed++; 1339b50d902SRodney W. Grimes } 1349b50d902SRodney W. Grimes if (--n <= 1) 1359b50d902SRodney W. Grimes goto overf; 1369b50d902SRodney W. Grimes *cp2++ = *cp++; 1379b50d902SRodney W. Grimes } 1389b50d902SRodney W. Grimes *cp2 = 0; 1399b50d902SRodney W. Grimes if (changed) { 1409b50d902SRodney W. Grimes printf("!%s\n", bangbuf); 1419ce73e90SMike Heffner (void)fflush(stdout); 1429b50d902SRodney W. Grimes } 1430c3a8314SMike Heffner if (strlcpy(str, bangbuf, strsize) >= strsize) 1440c3a8314SMike Heffner goto overf; 1450c3a8314SMike Heffner if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang)) 1460c3a8314SMike Heffner goto overf; 1479b50d902SRodney W. Grimes return (0); 1489b50d902SRodney W. Grimes } 1499b50d902SRodney W. Grimes 1509b50d902SRodney W. Grimes /* 1519b50d902SRodney W. Grimes * Print out a nice help message from some file or another. 1529b50d902SRodney W. Grimes */ 1539b50d902SRodney W. Grimes 1549b50d902SRodney W. Grimes int 1559b50d902SRodney W. Grimes help() 1569b50d902SRodney W. Grimes { 1579ce73e90SMike Heffner int c; 1589ce73e90SMike Heffner FILE *f; 1599b50d902SRodney W. Grimes 1609b50d902SRodney W. Grimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 1610c3a8314SMike Heffner warn("%s", _PATH_HELP); 1629b50d902SRodney W. Grimes return (1); 1639b50d902SRodney W. Grimes } 1649b50d902SRodney W. Grimes while ((c = getc(f)) != EOF) 1659b50d902SRodney W. Grimes putchar(c); 1669ce73e90SMike Heffner (void)Fclose(f); 1679b50d902SRodney W. Grimes return (0); 1689b50d902SRodney W. Grimes } 1699b50d902SRodney W. Grimes 1709b50d902SRodney W. Grimes /* 1719b50d902SRodney W. Grimes * Change user's working directory. 1729b50d902SRodney W. Grimes */ 1739b50d902SRodney W. Grimes int 1749b50d902SRodney W. Grimes schdir(arglist) 1759b50d902SRodney W. Grimes char **arglist; 1769b50d902SRodney W. Grimes { 1779b50d902SRodney W. Grimes char *cp; 1789b50d902SRodney W. Grimes 1799ce73e90SMike Heffner if (*arglist == NULL) { 1809ce73e90SMike Heffner if (homedir == NULL) 1810c3a8314SMike Heffner return (1); 1829b50d902SRodney W. Grimes cp = homedir; 1830c3a8314SMike Heffner } else 1849ce73e90SMike Heffner if ((cp = expand(*arglist)) == NULL) 1859b50d902SRodney W. Grimes return (1); 1869b50d902SRodney W. Grimes if (chdir(cp) < 0) { 1870c3a8314SMike Heffner warn("%s", cp); 1889b50d902SRodney W. Grimes return (1); 1899b50d902SRodney W. Grimes } 1909ce73e90SMike Heffner return (0); 1919b50d902SRodney W. Grimes } 1929b50d902SRodney W. Grimes 1939b50d902SRodney W. Grimes int 1949b50d902SRodney W. Grimes respond(msgvec) 1959b50d902SRodney W. Grimes int *msgvec; 1969b50d902SRodney W. Grimes { 1979ce73e90SMike Heffner if (value("Replyall") == NULL) 19899bd6601SJoerg Wunsch return (dorespond(msgvec)); 1999b50d902SRodney W. Grimes else 20099bd6601SJoerg Wunsch return (doRespond(msgvec)); 2019b50d902SRodney W. Grimes } 2029b50d902SRodney W. Grimes 2039b50d902SRodney W. Grimes /* 2049b50d902SRodney W. Grimes * Reply to a list of messages. Extract each name from the 2059b50d902SRodney W. Grimes * message header and send them off to mail1() 2069b50d902SRodney W. Grimes */ 2079b50d902SRodney W. Grimes int 20899bd6601SJoerg Wunsch dorespond(msgvec) 2099b50d902SRodney W. Grimes int *msgvec; 2109b50d902SRodney W. Grimes { 2119b50d902SRodney W. Grimes struct message *mp; 2129b50d902SRodney W. Grimes char *cp, *rcv, *replyto; 2139b50d902SRodney W. Grimes char **ap; 2149b50d902SRodney W. Grimes struct name *np; 2159b50d902SRodney W. Grimes struct header head; 2169b50d902SRodney W. Grimes 2179b50d902SRodney W. Grimes if (msgvec[1] != 0) { 2189b50d902SRodney W. Grimes printf("Sorry, can't reply to multiple messages at once\n"); 2199b50d902SRodney W. Grimes return (1); 2209b50d902SRodney W. Grimes } 2219b50d902SRodney W. Grimes mp = &message[msgvec[0] - 1]; 2229b50d902SRodney W. Grimes touch(mp); 2239b50d902SRodney W. Grimes dot = mp; 2249ce73e90SMike Heffner if ((rcv = skin(hfield("from", mp))) == NULL) 2259b50d902SRodney W. Grimes rcv = skin(nameof(mp, 1)); 2269ce73e90SMike Heffner if ((replyto = skin(hfield("reply-to", mp))) != NULL) 2279b50d902SRodney W. Grimes np = extract(replyto, GTO); 2289ce73e90SMike Heffner else if ((cp = skin(hfield("to", mp))) != NULL) 2299b50d902SRodney W. Grimes np = extract(cp, GTO); 2309b50d902SRodney W. Grimes else 2319ce73e90SMike Heffner np = NULL; 2329b50d902SRodney W. Grimes np = elide(np); 2339b50d902SRodney W. Grimes /* 2349b50d902SRodney W. Grimes * Delete my name from the reply list, 2359b50d902SRodney W. Grimes * and with it, all my alternate names. 2369b50d902SRodney W. Grimes */ 2379b50d902SRodney W. Grimes np = delname(np, myname); 2389b50d902SRodney W. Grimes if (altnames) 2399ce73e90SMike Heffner for (ap = altnames; *ap != NULL; ap++) 2409b50d902SRodney W. Grimes np = delname(np, *ap); 2419ce73e90SMike Heffner if (np != NULL && replyto == NULL) 2429b50d902SRodney W. Grimes np = cat(np, extract(rcv, GTO)); 2439ce73e90SMike Heffner else if (np == NULL) { 2449ce73e90SMike Heffner if (replyto != NULL) 2459b50d902SRodney W. Grimes printf("Empty reply-to field -- replying to author\n"); 2469b50d902SRodney W. Grimes np = extract(rcv, GTO); 2479b50d902SRodney W. Grimes } 2489b50d902SRodney W. Grimes head.h_to = np; 2499ce73e90SMike Heffner if ((head.h_subject = hfield("subject", mp)) == NULL) 2509b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 2519b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 2529ce73e90SMike Heffner if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) { 2539b50d902SRodney W. Grimes np = elide(extract(cp, GCC)); 2549b50d902SRodney W. Grimes np = delname(np, myname); 2559b50d902SRodney W. Grimes if (altnames != 0) 2569ce73e90SMike Heffner for (ap = altnames; *ap != NULL; ap++) 2579b50d902SRodney W. Grimes np = delname(np, *ap); 2589b50d902SRodney W. Grimes head.h_cc = np; 2599b50d902SRodney W. Grimes } else 2609ce73e90SMike Heffner head.h_cc = NULL; 2619ce73e90SMike Heffner head.h_bcc = NULL; 2629ce73e90SMike Heffner head.h_smopts = NULL; 26399bd6601SJoerg Wunsch if ((head.h_replyto = getenv("REPLYTO")) == NULL) 2649ce73e90SMike Heffner head.h_replyto = NULL; 26599bd6601SJoerg Wunsch head.h_inreplyto = skin(hfield("message-id", mp)); 2669b50d902SRodney W. Grimes mail1(&head, 1); 2679b50d902SRodney W. Grimes return (0); 2689b50d902SRodney W. Grimes } 2699b50d902SRodney W. Grimes 2709b50d902SRodney W. Grimes /* 2719b50d902SRodney W. Grimes * Modify the subject we are replying to to begin with Re: if 2729b50d902SRodney W. Grimes * it does not already. 2739b50d902SRodney W. Grimes */ 2749b50d902SRodney W. Grimes char * 2759b50d902SRodney W. Grimes reedit(subj) 2769ce73e90SMike Heffner char *subj; 2779b50d902SRodney W. Grimes { 2789b50d902SRodney W. Grimes char *newsubj; 2799b50d902SRodney W. Grimes 2809ce73e90SMike Heffner if (subj == NULL) 2819ce73e90SMike Heffner return (NULL); 2829b50d902SRodney W. Grimes if ((subj[0] == 'r' || subj[0] == 'R') && 2839b50d902SRodney W. Grimes (subj[1] == 'e' || subj[1] == 'E') && 2849b50d902SRodney W. Grimes subj[2] == ':') 2859ce73e90SMike Heffner return (subj); 2869b50d902SRodney W. Grimes newsubj = salloc(strlen(subj) + 5); 2870c3a8314SMike Heffner sprintf(newsubj, "Re: %s", subj); 2889ce73e90SMike Heffner return (newsubj); 2899b50d902SRodney W. Grimes } 2909b50d902SRodney W. Grimes 2919b50d902SRodney W. Grimes /* 2929b50d902SRodney W. Grimes * Preserve the named messages, so that they will be sent 2939b50d902SRodney W. Grimes * back to the system mailbox. 2949b50d902SRodney W. Grimes */ 2959b50d902SRodney W. Grimes int 2969b50d902SRodney W. Grimes preserve(msgvec) 2979b50d902SRodney W. Grimes int *msgvec; 2989b50d902SRodney W. Grimes { 2999ce73e90SMike Heffner int *ip, mesg; 3009ce73e90SMike Heffner struct message *mp; 3019b50d902SRodney W. Grimes 3029b50d902SRodney W. Grimes if (edit) { 3039b50d902SRodney W. Grimes printf("Cannot \"preserve\" in edit mode\n"); 3049b50d902SRodney W. Grimes return (1); 3059b50d902SRodney W. Grimes } 306d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3079b50d902SRodney W. Grimes mesg = *ip; 3089b50d902SRodney W. Grimes mp = &message[mesg-1]; 3099b50d902SRodney W. Grimes mp->m_flag |= MPRESERVE; 3109b50d902SRodney W. Grimes mp->m_flag &= ~MBOX; 3119b50d902SRodney W. Grimes dot = mp; 3129b50d902SRodney W. Grimes } 3139b50d902SRodney W. Grimes return (0); 3149b50d902SRodney W. Grimes } 3159b50d902SRodney W. Grimes 3169b50d902SRodney W. Grimes /* 3179b50d902SRodney W. Grimes * Mark all given messages as unread. 3189b50d902SRodney W. Grimes */ 3199b50d902SRodney W. Grimes int 3209b50d902SRodney W. Grimes unread(msgvec) 3219b50d902SRodney W. Grimes int msgvec[]; 3229b50d902SRodney W. Grimes { 3239ce73e90SMike Heffner int *ip; 3249b50d902SRodney W. Grimes 325d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3269b50d902SRodney W. Grimes dot = &message[*ip-1]; 3279b50d902SRodney W. Grimes dot->m_flag &= ~(MREAD|MTOUCH); 3289b50d902SRodney W. Grimes dot->m_flag |= MSTATUS; 3299b50d902SRodney W. Grimes } 3309b50d902SRodney W. Grimes return (0); 3319b50d902SRodney W. Grimes } 3329b50d902SRodney W. Grimes 3339b50d902SRodney W. Grimes /* 3349b50d902SRodney W. Grimes * Print the size of each message. 3359b50d902SRodney W. Grimes */ 3369b50d902SRodney W. Grimes int 3379b50d902SRodney W. Grimes messize(msgvec) 3389b50d902SRodney W. Grimes int *msgvec; 3399b50d902SRodney W. Grimes { 3409ce73e90SMike Heffner struct message *mp; 3419ce73e90SMike Heffner int *ip, mesg; 3429b50d902SRodney W. Grimes 343d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3449b50d902SRodney W. Grimes mesg = *ip; 3459b50d902SRodney W. Grimes mp = &message[mesg-1]; 34622694ebaSBruce Evans printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3479b50d902SRodney W. Grimes } 3489b50d902SRodney W. Grimes return (0); 3499b50d902SRodney W. Grimes } 3509b50d902SRodney W. Grimes 3519b50d902SRodney W. Grimes /* 3529b50d902SRodney W. Grimes * Quit quickly. If we are sourcing, just pop the input level 3539b50d902SRodney W. Grimes * by returning an error. 3549b50d902SRodney W. Grimes */ 3559b50d902SRodney W. Grimes int 3569b50d902SRodney W. Grimes rexit(e) 3579b50d902SRodney W. Grimes int e; 3589b50d902SRodney W. Grimes { 3599b50d902SRodney W. Grimes if (sourcing) 3609b50d902SRodney W. Grimes return (1); 3619b50d902SRodney W. Grimes exit(e); 3629b50d902SRodney W. Grimes /*NOTREACHED*/ 3639b50d902SRodney W. Grimes } 3649b50d902SRodney W. Grimes 3659b50d902SRodney W. Grimes /* 3669b50d902SRodney W. Grimes * Set or display a variable value. Syntax is similar to that 3679b50d902SRodney W. Grimes * of csh. 3689b50d902SRodney W. Grimes */ 3699b50d902SRodney W. Grimes int 3709b50d902SRodney W. Grimes set(arglist) 3719b50d902SRodney W. Grimes char **arglist; 3729b50d902SRodney W. Grimes { 3739ce73e90SMike Heffner struct var *vp; 3749ce73e90SMike Heffner char *cp, *cp2; 3759b50d902SRodney W. Grimes char varbuf[BUFSIZ], **ap, **p; 3769b50d902SRodney W. Grimes int errs, h, s; 3779b50d902SRodney W. Grimes 3789ce73e90SMike Heffner if (*arglist == NULL) { 3799b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 3809ce73e90SMike Heffner for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3819b50d902SRodney W. Grimes s++; 3829ce73e90SMike Heffner ap = (char **)salloc(s * sizeof(*ap)); 3839b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 3849ce73e90SMike Heffner for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3859b50d902SRodney W. Grimes *p++ = vp->v_name; 3869ce73e90SMike Heffner *p = NULL; 3879b50d902SRodney W. Grimes sort(ap); 3889ce73e90SMike Heffner for (p = ap; *p != NULL; p++) 3899b50d902SRodney W. Grimes printf("%s\t%s\n", *p, value(*p)); 3909b50d902SRodney W. Grimes return (0); 3919b50d902SRodney W. Grimes } 3929b50d902SRodney W. Grimes errs = 0; 3939ce73e90SMike Heffner for (ap = arglist; *ap != NULL; ap++) { 3949b50d902SRodney W. Grimes cp = *ap; 3959b50d902SRodney W. Grimes cp2 = varbuf; 3960c3a8314SMike Heffner while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3979b50d902SRodney W. Grimes *cp2++ = *cp++; 3989b50d902SRodney W. Grimes *cp2 = '\0'; 3999b50d902SRodney W. Grimes if (*cp == '\0') 4009b50d902SRodney W. Grimes cp = ""; 4019b50d902SRodney W. Grimes else 4029b50d902SRodney W. Grimes cp++; 4039b50d902SRodney W. Grimes if (equal(varbuf, "")) { 4049b50d902SRodney W. Grimes printf("Non-null variable name required\n"); 4059b50d902SRodney W. Grimes errs++; 4069b50d902SRodney W. Grimes continue; 4079b50d902SRodney W. Grimes } 4089b50d902SRodney W. Grimes assign(varbuf, cp); 4099b50d902SRodney W. Grimes } 4109b50d902SRodney W. Grimes return (errs); 4119b50d902SRodney W. Grimes } 4129b50d902SRodney W. Grimes 4139b50d902SRodney W. Grimes /* 4149b50d902SRodney W. Grimes * Unset a bunch of variable values. 4159b50d902SRodney W. Grimes */ 4169b50d902SRodney W. Grimes int 4179b50d902SRodney W. Grimes unset(arglist) 4189b50d902SRodney W. Grimes char **arglist; 4199b50d902SRodney W. Grimes { 4209ce73e90SMike Heffner struct var *vp, *vp2; 4219b50d902SRodney W. Grimes int errs, h; 4229b50d902SRodney W. Grimes char **ap; 4239b50d902SRodney W. Grimes 4249b50d902SRodney W. Grimes errs = 0; 4259ce73e90SMike Heffner for (ap = arglist; *ap != NULL; ap++) { 4269ce73e90SMike Heffner if ((vp2 = lookup(*ap)) == NULL) { 4279b50d902SRodney W. Grimes if (!sourcing) { 4289b50d902SRodney W. Grimes printf("\"%s\": undefined variable\n", *ap); 4299b50d902SRodney W. Grimes errs++; 4309b50d902SRodney W. Grimes } 4319b50d902SRodney W. Grimes continue; 4329b50d902SRodney W. Grimes } 4339b50d902SRodney W. Grimes h = hash(*ap); 4349b50d902SRodney W. Grimes if (vp2 == variables[h]) { 4359b50d902SRodney W. Grimes variables[h] = variables[h]->v_link; 4369b50d902SRodney W. Grimes vfree(vp2->v_name); 4379b50d902SRodney W. Grimes vfree(vp2->v_value); 4389ce73e90SMike Heffner (void)free(vp2); 4399b50d902SRodney W. Grimes continue; 4409b50d902SRodney W. Grimes } 4419b50d902SRodney W. Grimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4429b50d902SRodney W. Grimes ; 4439b50d902SRodney W. Grimes vp->v_link = vp2->v_link; 4449b50d902SRodney W. Grimes vfree(vp2->v_name); 4459b50d902SRodney W. Grimes vfree(vp2->v_value); 4469ce73e90SMike Heffner (void)free(vp2); 4479b50d902SRodney W. Grimes } 4489b50d902SRodney W. Grimes return (errs); 4499b50d902SRodney W. Grimes } 4509b50d902SRodney W. Grimes 4519b50d902SRodney W. Grimes /* 4529b50d902SRodney W. Grimes * Put add users to a group. 4539b50d902SRodney W. Grimes */ 4549b50d902SRodney W. Grimes int 4559b50d902SRodney W. Grimes group(argv) 4569b50d902SRodney W. Grimes char **argv; 4579b50d902SRodney W. Grimes { 4589ce73e90SMike Heffner struct grouphead *gh; 4599ce73e90SMike Heffner struct group *gp; 4609b50d902SRodney W. Grimes char **ap, *gname, **p; 4619ce73e90SMike Heffner int h, s; 4629b50d902SRodney W. Grimes 4639ce73e90SMike Heffner if (*argv == NULL) { 4649b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 4659ce73e90SMike Heffner for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4669b50d902SRodney W. Grimes s++; 4679ce73e90SMike Heffner ap = (char **)salloc(s * sizeof(*ap)); 4689b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 4699ce73e90SMike Heffner for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4709b50d902SRodney W. Grimes *p++ = gh->g_name; 4719ce73e90SMike Heffner *p = NULL; 4729b50d902SRodney W. Grimes sort(ap); 4739ce73e90SMike Heffner for (p = ap; *p != NULL; p++) 4749b50d902SRodney W. Grimes printgroup(*p); 4759b50d902SRodney W. Grimes return (0); 4769b50d902SRodney W. Grimes } 4779ce73e90SMike Heffner if (argv[1] == NULL) { 4789b50d902SRodney W. Grimes printgroup(*argv); 4799b50d902SRodney W. Grimes return (0); 4809b50d902SRodney W. Grimes } 4819b50d902SRodney W. Grimes gname = *argv; 4829b50d902SRodney W. Grimes h = hash(gname); 4839ce73e90SMike Heffner if ((gh = findgroup(gname)) == NULL) { 4849ce73e90SMike Heffner gh = calloc(sizeof(*gh), 1); 4859b50d902SRodney W. Grimes gh->g_name = vcopy(gname); 4869ce73e90SMike Heffner gh->g_list = NULL; 4879b50d902SRodney W. Grimes gh->g_link = groups[h]; 4889b50d902SRodney W. Grimes groups[h] = gh; 4899b50d902SRodney W. Grimes } 4909b50d902SRodney W. Grimes 4919b50d902SRodney W. Grimes /* 4929b50d902SRodney W. Grimes * Insert names from the command list into the group. 4939b50d902SRodney W. Grimes * Who cares if there are duplicates? They get tossed 4949b50d902SRodney W. Grimes * later anyway. 4959b50d902SRodney W. Grimes */ 4969b50d902SRodney W. Grimes 4979ce73e90SMike Heffner for (ap = argv+1; *ap != NULL; ap++) { 4989ce73e90SMike Heffner gp = calloc(sizeof(*gp), 1); 4999b50d902SRodney W. Grimes gp->ge_name = vcopy(*ap); 5009b50d902SRodney W. Grimes gp->ge_link = gh->g_list; 5019b50d902SRodney W. Grimes gh->g_list = gp; 5029b50d902SRodney W. Grimes } 5039b50d902SRodney W. Grimes return (0); 5049b50d902SRodney W. Grimes } 5059b50d902SRodney W. Grimes 5069b50d902SRodney W. Grimes /* 5079b50d902SRodney W. Grimes * Sort the passed string vecotor into ascending dictionary 5089b50d902SRodney W. Grimes * order. 5099b50d902SRodney W. Grimes */ 5109b50d902SRodney W. Grimes void 5119b50d902SRodney W. Grimes sort(list) 5129b50d902SRodney W. Grimes char **list; 5139b50d902SRodney W. Grimes { 5149ce73e90SMike Heffner char **ap; 5159b50d902SRodney W. Grimes 5169ce73e90SMike Heffner for (ap = list; *ap != NULL; ap++) 5179b50d902SRodney W. Grimes ; 5189b50d902SRodney W. Grimes if (ap-list < 2) 5199b50d902SRodney W. Grimes return; 5209b50d902SRodney W. Grimes qsort(list, ap-list, sizeof(*list), diction); 5219b50d902SRodney W. Grimes } 5229b50d902SRodney W. Grimes 5239b50d902SRodney W. Grimes /* 5249b50d902SRodney W. Grimes * Do a dictionary order comparison of the arguments from 5259b50d902SRodney W. Grimes * qsort. 5269b50d902SRodney W. Grimes */ 5279b50d902SRodney W. Grimes int 5289b50d902SRodney W. Grimes diction(a, b) 5299b50d902SRodney W. Grimes const void *a, *b; 5309b50d902SRodney W. Grimes { 5319ce73e90SMike Heffner return (strcmp(*(const char **)a, *(const char **)b)); 5329b50d902SRodney W. Grimes } 5339b50d902SRodney W. Grimes 5349b50d902SRodney W. Grimes /* 5359b50d902SRodney W. Grimes * The do nothing command for comments. 5369b50d902SRodney W. Grimes */ 5379b50d902SRodney W. Grimes 5389b50d902SRodney W. Grimes /*ARGSUSED*/ 5399b50d902SRodney W. Grimes int 5409b50d902SRodney W. Grimes null(e) 5419b50d902SRodney W. Grimes int e; 5429b50d902SRodney W. Grimes { 5439ce73e90SMike Heffner return (0); 5449b50d902SRodney W. Grimes } 5459b50d902SRodney W. Grimes 5469b50d902SRodney W. Grimes /* 5479b50d902SRodney W. Grimes * Change to another file. With no argument, print information about 5489b50d902SRodney W. Grimes * the current file. 5499b50d902SRodney W. Grimes */ 5509b50d902SRodney W. Grimes int 5519b50d902SRodney W. Grimes file(argv) 5529ce73e90SMike Heffner char **argv; 5539b50d902SRodney W. Grimes { 5549b50d902SRodney W. Grimes 5559ce73e90SMike Heffner if (argv[0] == NULL) { 5569b50d902SRodney W. Grimes newfileinfo(); 5579ce73e90SMike Heffner return (0); 5589b50d902SRodney W. Grimes } 5599b50d902SRodney W. Grimes if (setfile(*argv) < 0) 5609ce73e90SMike Heffner return (1); 5619b50d902SRodney W. Grimes announce(); 5629ce73e90SMike Heffner return (0); 5639b50d902SRodney W. Grimes } 5649b50d902SRodney W. Grimes 5659b50d902SRodney W. Grimes /* 5669b50d902SRodney W. Grimes * Expand file names like echo 5679b50d902SRodney W. Grimes */ 5689b50d902SRodney W. Grimes int 5699b50d902SRodney W. Grimes echo(argv) 5709b50d902SRodney W. Grimes char **argv; 5719b50d902SRodney W. Grimes { 5729ce73e90SMike Heffner char **ap, *cp; 5739b50d902SRodney W. Grimes 5749ce73e90SMike Heffner for (ap = argv; *ap != NULL; ap++) { 5759b50d902SRodney W. Grimes cp = *ap; 5769ce73e90SMike Heffner if ((cp = expand(cp)) != NULL) { 5779b50d902SRodney W. Grimes if (ap != argv) 5789ce73e90SMike Heffner printf(" "); 5799b50d902SRodney W. Grimes printf("%s", cp); 5809b50d902SRodney W. Grimes } 5819b50d902SRodney W. Grimes } 5829ce73e90SMike Heffner printf("\n"); 5839ce73e90SMike Heffner return (0); 5849b50d902SRodney W. Grimes } 5859b50d902SRodney W. Grimes 5869b50d902SRodney W. Grimes int 5879b50d902SRodney W. Grimes Respond(msgvec) 5889b50d902SRodney W. Grimes int *msgvec; 5899b50d902SRodney W. Grimes { 5909ce73e90SMike Heffner if (value("Replyall") == NULL) 59199bd6601SJoerg Wunsch return (doRespond(msgvec)); 5929b50d902SRodney W. Grimes else 59399bd6601SJoerg Wunsch return (dorespond(msgvec)); 5949b50d902SRodney W. Grimes } 5959b50d902SRodney W. Grimes 5969b50d902SRodney W. Grimes /* 5979b50d902SRodney W. Grimes * Reply to a series of messages by simply mailing to the senders 5989b50d902SRodney W. Grimes * and not messing around with the To: and Cc: lists as in normal 5999b50d902SRodney W. Grimes * reply. 6009b50d902SRodney W. Grimes */ 6019b50d902SRodney W. Grimes int 60299bd6601SJoerg Wunsch doRespond(msgvec) 6039b50d902SRodney W. Grimes int msgvec[]; 6049b50d902SRodney W. Grimes { 6059b50d902SRodney W. Grimes struct header head; 6069b50d902SRodney W. Grimes struct message *mp; 6079ce73e90SMike Heffner int *ap; 6089ce73e90SMike Heffner char *cp, *mid; 6099b50d902SRodney W. Grimes 6109ce73e90SMike Heffner head.h_to = NULL; 6119b50d902SRodney W. Grimes for (ap = msgvec; *ap != 0; ap++) { 6129b50d902SRodney W. Grimes mp = &message[*ap - 1]; 6139b50d902SRodney W. Grimes touch(mp); 6149b50d902SRodney W. Grimes dot = mp; 6159ce73e90SMike Heffner if ((cp = skin(hfield("from", mp))) == NULL) 6169b50d902SRodney W. Grimes cp = skin(nameof(mp, 2)); 6179b50d902SRodney W. Grimes head.h_to = cat(head.h_to, extract(cp, GTO)); 61899bd6601SJoerg Wunsch mid = skin(hfield("message-id", mp)); 6199b50d902SRodney W. Grimes } 6209ce73e90SMike Heffner if (head.h_to == NULL) 6219ce73e90SMike Heffner return (0); 6229b50d902SRodney W. Grimes mp = &message[msgvec[0] - 1]; 6239ce73e90SMike Heffner if ((head.h_subject = hfield("subject", mp)) == NULL) 6249b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 6259b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 6269ce73e90SMike Heffner head.h_cc = NULL; 6279ce73e90SMike Heffner head.h_bcc = NULL; 6289ce73e90SMike Heffner head.h_smopts = NULL; 62999bd6601SJoerg Wunsch if ((head.h_replyto = getenv("REPLYTO")) == NULL) 6309ce73e90SMike Heffner head.h_replyto = NULL; 63199bd6601SJoerg Wunsch head.h_inreplyto = mid; 6329b50d902SRodney W. Grimes mail1(&head, 1); 6339ce73e90SMike Heffner return (0); 6349b50d902SRodney W. Grimes } 6359b50d902SRodney W. Grimes 6369b50d902SRodney W. Grimes /* 6379b50d902SRodney W. Grimes * Conditional commands. These allow one to parameterize one's 6389b50d902SRodney W. Grimes * .mailrc and do some things if sending, others if receiving. 6399b50d902SRodney W. Grimes */ 6409b50d902SRodney W. Grimes int 6419b50d902SRodney W. Grimes ifcmd(argv) 6429b50d902SRodney W. Grimes char **argv; 6439b50d902SRodney W. Grimes { 6449ce73e90SMike Heffner char *cp; 6459b50d902SRodney W. Grimes 6469b50d902SRodney W. Grimes if (cond != CANY) { 6479b50d902SRodney W. Grimes printf("Illegal nested \"if\"\n"); 6489b50d902SRodney W. Grimes return (1); 6499b50d902SRodney W. Grimes } 6509b50d902SRodney W. Grimes cond = CANY; 6519b50d902SRodney W. Grimes cp = argv[0]; 6529b50d902SRodney W. Grimes switch (*cp) { 6539b50d902SRodney W. Grimes case 'r': case 'R': 6549b50d902SRodney W. Grimes cond = CRCV; 6559b50d902SRodney W. Grimes break; 6569b50d902SRodney W. Grimes 6579b50d902SRodney W. Grimes case 's': case 'S': 6589b50d902SRodney W. Grimes cond = CSEND; 6599b50d902SRodney W. Grimes break; 6609b50d902SRodney W. Grimes 6619b50d902SRodney W. Grimes default: 6629b50d902SRodney W. Grimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 6639b50d902SRodney W. Grimes return (1); 6649b50d902SRodney W. Grimes } 6659b50d902SRodney W. Grimes return (0); 6669b50d902SRodney W. Grimes } 6679b50d902SRodney W. Grimes 6689b50d902SRodney W. Grimes /* 6699b50d902SRodney W. Grimes * Implement 'else'. This is pretty simple -- we just 6709b50d902SRodney W. Grimes * flip over the conditional flag. 6719b50d902SRodney W. Grimes */ 6729b50d902SRodney W. Grimes int 6739b50d902SRodney W. Grimes elsecmd() 6749b50d902SRodney W. Grimes { 6759b50d902SRodney W. Grimes 6769b50d902SRodney W. Grimes switch (cond) { 6779b50d902SRodney W. Grimes case CANY: 6789b50d902SRodney W. Grimes printf("\"Else\" without matching \"if\"\n"); 6799b50d902SRodney W. Grimes return (1); 6809b50d902SRodney W. Grimes 6819b50d902SRodney W. Grimes case CSEND: 6829b50d902SRodney W. Grimes cond = CRCV; 6839b50d902SRodney W. Grimes break; 6849b50d902SRodney W. Grimes 6859b50d902SRodney W. Grimes case CRCV: 6869b50d902SRodney W. Grimes cond = CSEND; 6879b50d902SRodney W. Grimes break; 6889b50d902SRodney W. Grimes 6899b50d902SRodney W. Grimes default: 6909b50d902SRodney W. Grimes printf("Mail's idea of conditions is screwed up\n"); 6919b50d902SRodney W. Grimes cond = CANY; 6929b50d902SRodney W. Grimes break; 6939b50d902SRodney W. Grimes } 6949b50d902SRodney W. Grimes return (0); 6959b50d902SRodney W. Grimes } 6969b50d902SRodney W. Grimes 6979b50d902SRodney W. Grimes /* 6989b50d902SRodney W. Grimes * End of if statement. Just set cond back to anything. 6999b50d902SRodney W. Grimes */ 7009b50d902SRodney W. Grimes int 7019b50d902SRodney W. Grimes endifcmd() 7029b50d902SRodney W. Grimes { 7039b50d902SRodney W. Grimes 7049b50d902SRodney W. Grimes if (cond == CANY) { 7059b50d902SRodney W. Grimes printf("\"Endif\" without matching \"if\"\n"); 7069b50d902SRodney W. Grimes return (1); 7079b50d902SRodney W. Grimes } 7089b50d902SRodney W. Grimes cond = CANY; 7099b50d902SRodney W. Grimes return (0); 7109b50d902SRodney W. Grimes } 7119b50d902SRodney W. Grimes 7129b50d902SRodney W. Grimes /* 7139b50d902SRodney W. Grimes * Set the list of alternate names. 7149b50d902SRodney W. Grimes */ 7159b50d902SRodney W. Grimes int 7169b50d902SRodney W. Grimes alternates(namelist) 7179b50d902SRodney W. Grimes char **namelist; 7189b50d902SRodney W. Grimes { 7199ce73e90SMike Heffner int c; 7209ce73e90SMike Heffner char **ap, **ap2, *cp; 7219b50d902SRodney W. Grimes 7229b50d902SRodney W. Grimes c = argcount(namelist) + 1; 7239b50d902SRodney W. Grimes if (c == 1) { 7249b50d902SRodney W. Grimes if (altnames == 0) 7259b50d902SRodney W. Grimes return (0); 7269ce73e90SMike Heffner for (ap = altnames; *ap != NULL; ap++) 7279b50d902SRodney W. Grimes printf("%s ", *ap); 7289b50d902SRodney W. Grimes printf("\n"); 7299b50d902SRodney W. Grimes return (0); 7309b50d902SRodney W. Grimes } 7319b50d902SRodney W. Grimes if (altnames != 0) 7329ce73e90SMike Heffner (void)free(altnames); 7339ce73e90SMike Heffner altnames = calloc((unsigned)c, sizeof(char *)); 7349ce73e90SMike Heffner for (ap = namelist, ap2 = altnames; *ap != NULL; ap++, ap2++) { 7359ce73e90SMike Heffner cp = calloc((unsigned)strlen(*ap) + 1, sizeof(char)); 7369b50d902SRodney W. Grimes strcpy(cp, *ap); 7379b50d902SRodney W. Grimes *ap2 = cp; 7389b50d902SRodney W. Grimes } 7399b50d902SRodney W. Grimes *ap2 = 0; 7409b50d902SRodney W. Grimes return (0); 7419b50d902SRodney W. Grimes } 742