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 359b50d902SRodney W. Grimes static char sccsid[] = "@(#)cmd3.c 8.1 (Berkeley) 6/6/93"; 369b50d902SRodney W. Grimes #endif /* not lint */ 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 529b50d902SRodney W. Grimes shell(str) 539b50d902SRodney W. Grimes char *str; 549b50d902SRodney W. Grimes { 559b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 569b50d902SRodney W. Grimes char *shell; 579b50d902SRodney W. Grimes char cmd[BUFSIZ]; 589b50d902SRodney W. Grimes 599b50d902SRodney W. Grimes (void) strcpy(cmd, str); 609b50d902SRodney W. Grimes if (bangexp(cmd) < 0) 619b50d902SRodney W. Grimes return 1; 629b50d902SRodney W. Grimes if ((shell = value("SHELL")) == NOSTR) 639b50d902SRodney W. Grimes shell = _PATH_CSHELL; 649b50d902SRodney W. Grimes (void) run_command(shell, 0, -1, -1, "-c", cmd, NOSTR); 659b50d902SRodney W. Grimes (void) signal(SIGINT, sigint); 669b50d902SRodney W. Grimes printf("!\n"); 679b50d902SRodney W. Grimes 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 759b50d902SRodney W. Grimes dosh(str) 769b50d902SRodney W. Grimes char *str; 779b50d902SRodney W. Grimes { 789b50d902SRodney W. Grimes sig_t sigint = signal(SIGINT, SIG_IGN); 799b50d902SRodney W. Grimes char *shell; 809b50d902SRodney W. Grimes 819b50d902SRodney W. Grimes if ((shell = value("SHELL")) == NOSTR) 829b50d902SRodney W. Grimes shell = _PATH_CSHELL; 839b50d902SRodney W. Grimes (void) run_command(shell, 0, -1, -1, NOSTR, NOSTR, NOSTR); 849b50d902SRodney W. Grimes (void) signal(SIGINT, sigint); 859b50d902SRodney W. Grimes putchar('\n'); 869b50d902SRodney W. Grimes return 0; 879b50d902SRodney W. Grimes } 889b50d902SRodney W. Grimes 899b50d902SRodney W. Grimes /* 909b50d902SRodney W. Grimes * Expand the shell escape by expanding unescaped !'s into the 919b50d902SRodney W. Grimes * last issued command where possible. 929b50d902SRodney W. Grimes */ 939b50d902SRodney W. Grimes 949b50d902SRodney W. Grimes char lastbang[128]; 959b50d902SRodney W. Grimes 969b50d902SRodney W. Grimes int 979b50d902SRodney W. Grimes bangexp(str) 989b50d902SRodney W. Grimes char *str; 999b50d902SRodney W. Grimes { 1009b50d902SRodney W. Grimes char bangbuf[BUFSIZ]; 1019b50d902SRodney W. Grimes register char *cp, *cp2; 1029b50d902SRodney W. Grimes register int n; 1039b50d902SRodney W. Grimes int changed = 0; 1049b50d902SRodney W. Grimes 1059b50d902SRodney W. Grimes cp = str; 1069b50d902SRodney W. Grimes cp2 = bangbuf; 1079b50d902SRodney W. Grimes n = BUFSIZ; 1089b50d902SRodney W. Grimes while (*cp) { 1099b50d902SRodney W. Grimes if (*cp == '!') { 1109b50d902SRodney W. Grimes if (n < strlen(lastbang)) { 1119b50d902SRodney W. Grimes overf: 1129b50d902SRodney W. Grimes printf("Command buffer overflow\n"); 1139b50d902SRodney W. Grimes return(-1); 1149b50d902SRodney W. Grimes } 1159b50d902SRodney W. Grimes changed++; 1169b50d902SRodney W. Grimes strcpy(cp2, lastbang); 1179b50d902SRodney W. Grimes cp2 += strlen(lastbang); 1189b50d902SRodney W. Grimes n -= strlen(lastbang); 1199b50d902SRodney W. Grimes cp++; 1209b50d902SRodney W. Grimes continue; 1219b50d902SRodney W. Grimes } 1229b50d902SRodney W. Grimes if (*cp == '\\' && cp[1] == '!') { 1239b50d902SRodney W. Grimes if (--n <= 1) 1249b50d902SRodney W. Grimes goto overf; 1259b50d902SRodney W. Grimes *cp2++ = '!'; 1269b50d902SRodney W. Grimes cp += 2; 1279b50d902SRodney W. Grimes changed++; 1289b50d902SRodney W. Grimes } 1299b50d902SRodney W. Grimes if (--n <= 1) 1309b50d902SRodney W. Grimes goto overf; 1319b50d902SRodney W. Grimes *cp2++ = *cp++; 1329b50d902SRodney W. Grimes } 1339b50d902SRodney W. Grimes *cp2 = 0; 1349b50d902SRodney W. Grimes if (changed) { 1359b50d902SRodney W. Grimes printf("!%s\n", bangbuf); 1369b50d902SRodney W. Grimes fflush(stdout); 1379b50d902SRodney W. Grimes } 1389b50d902SRodney W. Grimes strcpy(str, bangbuf); 1399b50d902SRodney W. Grimes strncpy(lastbang, bangbuf, 128); 1409b50d902SRodney W. Grimes lastbang[127] = 0; 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 1499b50d902SRodney W. Grimes help() 1509b50d902SRodney W. Grimes { 1519b50d902SRodney W. Grimes register c; 1529b50d902SRodney W. Grimes register FILE *f; 1539b50d902SRodney W. Grimes 1549b50d902SRodney W. Grimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 1559b50d902SRodney W. Grimes perror(_PATH_HELP); 1569b50d902SRodney W. Grimes return(1); 1579b50d902SRodney W. Grimes } 1589b50d902SRodney W. Grimes while ((c = getc(f)) != EOF) 1599b50d902SRodney W. Grimes putchar(c); 1609b50d902SRodney W. Grimes 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 1689b50d902SRodney W. Grimes schdir(arglist) 1699b50d902SRodney W. Grimes char **arglist; 1709b50d902SRodney W. Grimes { 1719b50d902SRodney W. Grimes char *cp; 1729b50d902SRodney W. Grimes 1739b50d902SRodney W. Grimes if (*arglist == NOSTR) 1749b50d902SRodney W. Grimes cp = homedir; 1759b50d902SRodney W. Grimes else 1769b50d902SRodney W. Grimes if ((cp = expand(*arglist)) == NOSTR) 1779b50d902SRodney W. Grimes return(1); 1789b50d902SRodney W. Grimes if (chdir(cp) < 0) { 1799b50d902SRodney W. Grimes perror(cp); 1809b50d902SRodney W. Grimes return(1); 1819b50d902SRodney W. Grimes } 1829b50d902SRodney W. Grimes return 0; 1839b50d902SRodney W. Grimes } 1849b50d902SRodney W. Grimes 1859b50d902SRodney W. Grimes int 1869b50d902SRodney W. Grimes respond(msgvec) 1879b50d902SRodney W. Grimes int *msgvec; 1889b50d902SRodney W. Grimes { 1899b50d902SRodney W. Grimes if (value("Replyall") == NOSTR) 19099bd6601SJoerg Wunsch return (dorespond(msgvec)); 1919b50d902SRodney W. Grimes else 19299bd6601SJoerg Wunsch return (doRespond(msgvec)); 1939b50d902SRodney W. Grimes } 1949b50d902SRodney W. Grimes 1959b50d902SRodney W. Grimes /* 1969b50d902SRodney W. Grimes * Reply to a list of messages. Extract each name from the 1979b50d902SRodney W. Grimes * message header and send them off to mail1() 1989b50d902SRodney W. Grimes */ 1999b50d902SRodney W. Grimes int 20099bd6601SJoerg Wunsch dorespond(msgvec) 2019b50d902SRodney W. Grimes 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; 2169b50d902SRodney W. Grimes if ((rcv = skin(hfield("from", mp))) == NOSTR) 2179b50d902SRodney W. Grimes rcv = skin(nameof(mp, 1)); 2189b50d902SRodney W. Grimes if ((replyto = skin(hfield("reply-to", mp))) != NOSTR) 2199b50d902SRodney W. Grimes np = extract(replyto, GTO); 2209b50d902SRodney W. Grimes else if ((cp = skin(hfield("to", mp))) != NOSTR) 2219b50d902SRodney W. Grimes np = extract(cp, GTO); 2229b50d902SRodney W. Grimes else 2239b50d902SRodney W. Grimes np = NIL; 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) 2319b50d902SRodney W. Grimes for (ap = altnames; *ap; ap++) 2329b50d902SRodney W. Grimes np = delname(np, *ap); 2339b50d902SRodney W. Grimes if (np != NIL && replyto == NOSTR) 2349b50d902SRodney W. Grimes np = cat(np, extract(rcv, GTO)); 2359b50d902SRodney W. Grimes else if (np == NIL) { 2369b50d902SRodney W. Grimes if (replyto != NOSTR) 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; 2419b50d902SRodney W. Grimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 2429b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 2439b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 2449b50d902SRodney W. Grimes if (replyto == NOSTR && (cp = skin(hfield("cc", mp))) != NOSTR) { 2459b50d902SRodney W. Grimes np = elide(extract(cp, GCC)); 2469b50d902SRodney W. Grimes np = delname(np, myname); 2479b50d902SRodney W. Grimes if (altnames != 0) 2489b50d902SRodney W. Grimes for (ap = altnames; *ap; ap++) 2499b50d902SRodney W. Grimes np = delname(np, *ap); 2509b50d902SRodney W. Grimes head.h_cc = np; 2519b50d902SRodney W. Grimes } else 2529b50d902SRodney W. Grimes head.h_cc = NIL; 2539b50d902SRodney W. Grimes head.h_bcc = NIL; 2549b50d902SRodney W. Grimes head.h_smopts = NIL; 25599bd6601SJoerg Wunsch if ((head.h_replyto = getenv("REPLYTO")) == NULL) 25699bd6601SJoerg Wunsch head.h_replyto = NOSTR; 25799bd6601SJoerg Wunsch head.h_inreplyto = skin(hfield("message-id", mp)); 2589b50d902SRodney W. Grimes mail1(&head, 1); 2599b50d902SRodney W. Grimes return(0); 2609b50d902SRodney W. Grimes } 2619b50d902SRodney W. Grimes 2629b50d902SRodney W. Grimes /* 2639b50d902SRodney W. Grimes * Modify the subject we are replying to to begin with Re: if 2649b50d902SRodney W. Grimes * it does not already. 2659b50d902SRodney W. Grimes */ 2669b50d902SRodney W. Grimes char * 2679b50d902SRodney W. Grimes reedit(subj) 2689b50d902SRodney W. Grimes register char *subj; 2699b50d902SRodney W. Grimes { 2709b50d902SRodney W. Grimes char *newsubj; 2719b50d902SRodney W. Grimes 2729b50d902SRodney W. Grimes if (subj == NOSTR) 2739b50d902SRodney W. Grimes return NOSTR; 2749b50d902SRodney W. Grimes if ((subj[0] == 'r' || subj[0] == 'R') && 2759b50d902SRodney W. Grimes (subj[1] == 'e' || subj[1] == 'E') && 2769b50d902SRodney W. Grimes subj[2] == ':') 2779b50d902SRodney W. Grimes return subj; 2789b50d902SRodney W. Grimes newsubj = salloc(strlen(subj) + 5); 2799b50d902SRodney W. Grimes strcpy(newsubj, "Re: "); 2809b50d902SRodney W. Grimes strcpy(newsubj + 4, subj); 2819b50d902SRodney W. Grimes return newsubj; 2829b50d902SRodney W. Grimes } 2839b50d902SRodney W. Grimes 2849b50d902SRodney W. Grimes /* 2859b50d902SRodney W. Grimes * Preserve the named messages, so that they will be sent 2869b50d902SRodney W. Grimes * back to the system mailbox. 2879b50d902SRodney W. Grimes */ 2889b50d902SRodney W. Grimes int 2899b50d902SRodney W. Grimes preserve(msgvec) 2909b50d902SRodney W. Grimes int *msgvec; 2919b50d902SRodney W. Grimes { 2929b50d902SRodney W. Grimes register struct message *mp; 2939b50d902SRodney W. Grimes register int *ip, mesg; 2949b50d902SRodney W. Grimes 2959b50d902SRodney W. Grimes if (edit) { 2969b50d902SRodney W. Grimes printf("Cannot \"preserve\" in edit mode\n"); 2979b50d902SRodney W. Grimes return(1); 2989b50d902SRodney W. Grimes } 299d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3009b50d902SRodney W. Grimes mesg = *ip; 3019b50d902SRodney W. Grimes mp = &message[mesg-1]; 3029b50d902SRodney W. Grimes mp->m_flag |= MPRESERVE; 3039b50d902SRodney W. Grimes mp->m_flag &= ~MBOX; 3049b50d902SRodney W. Grimes dot = mp; 3059b50d902SRodney W. Grimes } 3069b50d902SRodney W. Grimes return(0); 3079b50d902SRodney W. Grimes } 3089b50d902SRodney W. Grimes 3099b50d902SRodney W. Grimes /* 3109b50d902SRodney W. Grimes * Mark all given messages as unread. 3119b50d902SRodney W. Grimes */ 3129b50d902SRodney W. Grimes int 3139b50d902SRodney W. Grimes unread(msgvec) 3149b50d902SRodney W. Grimes int msgvec[]; 3159b50d902SRodney W. Grimes { 3169b50d902SRodney W. Grimes register int *ip; 3179b50d902SRodney W. Grimes 318d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3199b50d902SRodney W. Grimes dot = &message[*ip-1]; 3209b50d902SRodney W. Grimes dot->m_flag &= ~(MREAD|MTOUCH); 3219b50d902SRodney W. Grimes dot->m_flag |= MSTATUS; 3229b50d902SRodney W. Grimes } 3239b50d902SRodney W. Grimes return(0); 3249b50d902SRodney W. Grimes } 3259b50d902SRodney W. Grimes 3269b50d902SRodney W. Grimes /* 3279b50d902SRodney W. Grimes * Print the size of each message. 3289b50d902SRodney W. Grimes */ 3299b50d902SRodney W. Grimes int 3309b50d902SRodney W. Grimes messize(msgvec) 3319b50d902SRodney W. Grimes int *msgvec; 3329b50d902SRodney W. Grimes { 3339b50d902SRodney W. Grimes register struct message *mp; 3349b50d902SRodney W. Grimes register int *ip, mesg; 3359b50d902SRodney W. Grimes 336d030d2d2SPoul-Henning Kamp for (ip = msgvec; *ip != 0; ip++) { 3379b50d902SRodney W. Grimes mesg = *ip; 3389b50d902SRodney W. Grimes mp = &message[mesg-1]; 33922694ebaSBruce Evans printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3409b50d902SRodney W. Grimes } 3419b50d902SRodney W. Grimes return(0); 3429b50d902SRodney W. Grimes } 3439b50d902SRodney W. Grimes 3449b50d902SRodney W. Grimes /* 3459b50d902SRodney W. Grimes * Quit quickly. If we are sourcing, just pop the input level 3469b50d902SRodney W. Grimes * by returning an error. 3479b50d902SRodney W. Grimes */ 3489b50d902SRodney W. Grimes int 3499b50d902SRodney W. Grimes rexit(e) 3509b50d902SRodney W. Grimes int e; 3519b50d902SRodney W. Grimes { 3529b50d902SRodney W. Grimes if (sourcing) 3539b50d902SRodney W. Grimes return(1); 3549b50d902SRodney W. Grimes exit(e); 3559b50d902SRodney W. Grimes /*NOTREACHED*/ 3569b50d902SRodney W. Grimes } 3579b50d902SRodney W. Grimes 3589b50d902SRodney W. Grimes /* 3599b50d902SRodney W. Grimes * Set or display a variable value. Syntax is similar to that 3609b50d902SRodney W. Grimes * of csh. 3619b50d902SRodney W. Grimes */ 3629b50d902SRodney W. Grimes int 3639b50d902SRodney W. Grimes set(arglist) 3649b50d902SRodney W. Grimes char **arglist; 3659b50d902SRodney W. Grimes { 3669b50d902SRodney W. Grimes register struct var *vp; 3679b50d902SRodney W. Grimes register char *cp, *cp2; 3689b50d902SRodney W. Grimes char varbuf[BUFSIZ], **ap, **p; 3699b50d902SRodney W. Grimes int errs, h, s; 3709b50d902SRodney W. Grimes 3719b50d902SRodney W. Grimes if (*arglist == NOSTR) { 3729b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 3739b50d902SRodney W. Grimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3749b50d902SRodney W. Grimes s++; 3759b50d902SRodney W. Grimes ap = (char **) salloc(s * sizeof *ap); 3769b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 3779b50d902SRodney W. Grimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3789b50d902SRodney W. Grimes *p++ = vp->v_name; 3799b50d902SRodney W. Grimes *p = NOSTR; 3809b50d902SRodney W. Grimes sort(ap); 3819b50d902SRodney W. Grimes for (p = ap; *p != NOSTR; p++) 3829b50d902SRodney W. Grimes printf("%s\t%s\n", *p, value(*p)); 3839b50d902SRodney W. Grimes return(0); 3849b50d902SRodney W. Grimes } 3859b50d902SRodney W. Grimes errs = 0; 3869b50d902SRodney W. Grimes for (ap = arglist; *ap != NOSTR; ap++) { 3879b50d902SRodney W. Grimes cp = *ap; 3889b50d902SRodney W. Grimes cp2 = varbuf; 3899b50d902SRodney W. Grimes while (*cp != '=' && *cp != '\0') 3909b50d902SRodney W. Grimes *cp2++ = *cp++; 3919b50d902SRodney W. Grimes *cp2 = '\0'; 3929b50d902SRodney W. Grimes if (*cp == '\0') 3939b50d902SRodney W. Grimes cp = ""; 3949b50d902SRodney W. Grimes else 3959b50d902SRodney W. Grimes cp++; 3969b50d902SRodney W. Grimes if (equal(varbuf, "")) { 3979b50d902SRodney W. Grimes printf("Non-null variable name required\n"); 3989b50d902SRodney W. Grimes errs++; 3999b50d902SRodney W. Grimes continue; 4009b50d902SRodney W. Grimes } 4019b50d902SRodney W. Grimes assign(varbuf, cp); 4029b50d902SRodney W. Grimes } 4039b50d902SRodney W. Grimes return(errs); 4049b50d902SRodney W. Grimes } 4059b50d902SRodney W. Grimes 4069b50d902SRodney W. Grimes /* 4079b50d902SRodney W. Grimes * Unset a bunch of variable values. 4089b50d902SRodney W. Grimes */ 4099b50d902SRodney W. Grimes int 4109b50d902SRodney W. Grimes unset(arglist) 4119b50d902SRodney W. Grimes char **arglist; 4129b50d902SRodney W. Grimes { 4139b50d902SRodney W. Grimes register struct var *vp, *vp2; 4149b50d902SRodney W. Grimes int errs, h; 4159b50d902SRodney W. Grimes char **ap; 4169b50d902SRodney W. Grimes 4179b50d902SRodney W. Grimes errs = 0; 4189b50d902SRodney W. Grimes for (ap = arglist; *ap != NOSTR; ap++) { 4199b50d902SRodney W. Grimes if ((vp2 = lookup(*ap)) == NOVAR) { 4209b50d902SRodney W. Grimes 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); 4319b50d902SRodney W. Grimes free((char *)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); 4399b50d902SRodney W. Grimes free((char *) 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 4489b50d902SRodney W. Grimes group(argv) 4499b50d902SRodney W. Grimes char **argv; 4509b50d902SRodney W. Grimes { 4519b50d902SRodney W. Grimes register struct grouphead *gh; 4529b50d902SRodney W. Grimes register struct group *gp; 4539b50d902SRodney W. Grimes register int h; 4549b50d902SRodney W. Grimes int s; 4559b50d902SRodney W. Grimes char **ap, *gname, **p; 4569b50d902SRodney W. Grimes 4579b50d902SRodney W. Grimes if (*argv == NOSTR) { 4589b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 4599b50d902SRodney W. Grimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4609b50d902SRodney W. Grimes s++; 4619b50d902SRodney W. Grimes ap = (char **) salloc(s * sizeof *ap); 4629b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 4639b50d902SRodney W. Grimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4649b50d902SRodney W. Grimes *p++ = gh->g_name; 4659b50d902SRodney W. Grimes *p = NOSTR; 4669b50d902SRodney W. Grimes sort(ap); 4679b50d902SRodney W. Grimes for (p = ap; *p != NOSTR; p++) 4689b50d902SRodney W. Grimes printgroup(*p); 4699b50d902SRodney W. Grimes return(0); 4709b50d902SRodney W. Grimes } 4719b50d902SRodney W. Grimes if (argv[1] == NOSTR) { 4729b50d902SRodney W. Grimes printgroup(*argv); 4739b50d902SRodney W. Grimes return(0); 4749b50d902SRodney W. Grimes } 4759b50d902SRodney W. Grimes gname = *argv; 4769b50d902SRodney W. Grimes h = hash(gname); 4779b50d902SRodney W. Grimes if ((gh = findgroup(gname)) == NOGRP) { 4789b50d902SRodney W. Grimes gh = (struct grouphead *) calloc(sizeof *gh, 1); 4799b50d902SRodney W. Grimes gh->g_name = vcopy(gname); 4809b50d902SRodney W. Grimes gh->g_list = NOGE; 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 4919b50d902SRodney W. Grimes for (ap = argv+1; *ap != NOSTR; ap++) { 4929b50d902SRodney W. Grimes gp = (struct group *) calloc(sizeof *gp, 1); 4939b50d902SRodney W. Grimes gp->ge_name = vcopy(*ap); 4949b50d902SRodney W. Grimes gp->ge_link = gh->g_list; 4959b50d902SRodney W. Grimes gh->g_list = gp; 4969b50d902SRodney W. Grimes } 4979b50d902SRodney W. Grimes return(0); 4989b50d902SRodney W. Grimes } 4999b50d902SRodney W. Grimes 5009b50d902SRodney W. Grimes /* 5019b50d902SRodney W. Grimes * Sort the passed string vecotor into ascending dictionary 5029b50d902SRodney W. Grimes * order. 5039b50d902SRodney W. Grimes */ 5049b50d902SRodney W. Grimes void 5059b50d902SRodney W. Grimes sort(list) 5069b50d902SRodney W. Grimes char **list; 5079b50d902SRodney W. Grimes { 5089b50d902SRodney W. Grimes register char **ap; 5099b50d902SRodney W. Grimes int diction(); 5109b50d902SRodney W. Grimes 5119b50d902SRodney W. Grimes for (ap = list; *ap != NOSTR; ap++) 5129b50d902SRodney W. Grimes ; 5139b50d902SRodney W. Grimes if (ap-list < 2) 5149b50d902SRodney W. Grimes return; 5159b50d902SRodney W. Grimes qsort(list, ap-list, sizeof(*list), diction); 5169b50d902SRodney W. Grimes } 5179b50d902SRodney W. Grimes 5189b50d902SRodney W. Grimes /* 5199b50d902SRodney W. Grimes * Do a dictionary order comparison of the arguments from 5209b50d902SRodney W. Grimes * qsort. 5219b50d902SRodney W. Grimes */ 5229b50d902SRodney W. Grimes int 5239b50d902SRodney W. Grimes diction(a, b) 5249b50d902SRodney W. Grimes const void *a, *b; 5259b50d902SRodney W. Grimes { 5269b50d902SRodney W. Grimes return(strcmp(*(char **)a, *(char **)b)); 5279b50d902SRodney W. Grimes } 5289b50d902SRodney W. Grimes 5299b50d902SRodney W. Grimes /* 5309b50d902SRodney W. Grimes * The do nothing command for comments. 5319b50d902SRodney W. Grimes */ 5329b50d902SRodney W. Grimes 5339b50d902SRodney W. Grimes /*ARGSUSED*/ 5349b50d902SRodney W. Grimes int 5359b50d902SRodney W. Grimes null(e) 5369b50d902SRodney W. Grimes int e; 5379b50d902SRodney W. Grimes { 5389b50d902SRodney W. Grimes return 0; 5399b50d902SRodney W. Grimes } 5409b50d902SRodney W. Grimes 5419b50d902SRodney W. Grimes /* 5429b50d902SRodney W. Grimes * Change to another file. With no argument, print information about 5439b50d902SRodney W. Grimes * the current file. 5449b50d902SRodney W. Grimes */ 5459b50d902SRodney W. Grimes int 5469b50d902SRodney W. Grimes file(argv) 5479b50d902SRodney W. Grimes register char **argv; 5489b50d902SRodney W. Grimes { 5499b50d902SRodney W. Grimes 5509b50d902SRodney W. Grimes if (argv[0] == NOSTR) { 5519b50d902SRodney W. Grimes newfileinfo(); 5529b50d902SRodney W. Grimes return 0; 5539b50d902SRodney W. Grimes } 5549b50d902SRodney W. Grimes if (setfile(*argv) < 0) 5559b50d902SRodney W. Grimes return 1; 5569b50d902SRodney W. Grimes announce(); 5579b50d902SRodney W. Grimes return 0; 5589b50d902SRodney W. Grimes } 5599b50d902SRodney W. Grimes 5609b50d902SRodney W. Grimes /* 5619b50d902SRodney W. Grimes * Expand file names like echo 5629b50d902SRodney W. Grimes */ 5639b50d902SRodney W. Grimes int 5649b50d902SRodney W. Grimes echo(argv) 5659b50d902SRodney W. Grimes char **argv; 5669b50d902SRodney W. Grimes { 5679b50d902SRodney W. Grimes register char **ap; 5689b50d902SRodney W. Grimes register char *cp; 5699b50d902SRodney W. Grimes 5709b50d902SRodney W. Grimes for (ap = argv; *ap != NOSTR; ap++) { 5719b50d902SRodney W. Grimes cp = *ap; 5729b50d902SRodney W. Grimes if ((cp = expand(cp)) != NOSTR) { 5739b50d902SRodney W. Grimes if (ap != argv) 5749b50d902SRodney W. Grimes putchar(' '); 5759b50d902SRodney W. Grimes printf("%s", cp); 5769b50d902SRodney W. Grimes } 5779b50d902SRodney W. Grimes } 5789b50d902SRodney W. Grimes putchar('\n'); 5799b50d902SRodney W. Grimes return 0; 5809b50d902SRodney W. Grimes } 5819b50d902SRodney W. Grimes 5829b50d902SRodney W. Grimes int 5839b50d902SRodney W. Grimes Respond(msgvec) 5849b50d902SRodney W. Grimes int *msgvec; 5859b50d902SRodney W. Grimes { 5869b50d902SRodney W. Grimes if (value("Replyall") == NOSTR) 58799bd6601SJoerg Wunsch return (doRespond(msgvec)); 5889b50d902SRodney W. Grimes else 58999bd6601SJoerg Wunsch return (dorespond(msgvec)); 5909b50d902SRodney W. Grimes } 5919b50d902SRodney W. Grimes 5929b50d902SRodney W. Grimes /* 5939b50d902SRodney W. Grimes * Reply to a series of messages by simply mailing to the senders 5949b50d902SRodney W. Grimes * and not messing around with the To: and Cc: lists as in normal 5959b50d902SRodney W. Grimes * reply. 5969b50d902SRodney W. Grimes */ 5979b50d902SRodney W. Grimes int 59899bd6601SJoerg Wunsch doRespond(msgvec) 5999b50d902SRodney W. Grimes int msgvec[]; 6009b50d902SRodney W. Grimes { 6019b50d902SRodney W. Grimes struct header head; 6029b50d902SRodney W. Grimes struct message *mp; 6039b50d902SRodney W. Grimes register int *ap; 6049b50d902SRodney W. Grimes register char *cp; 60599bd6601SJoerg Wunsch char *mid; 6069b50d902SRodney W. Grimes 6079b50d902SRodney W. Grimes head.h_to = NIL; 6089b50d902SRodney W. Grimes for (ap = msgvec; *ap != 0; ap++) { 6099b50d902SRodney W. Grimes mp = &message[*ap - 1]; 6109b50d902SRodney W. Grimes touch(mp); 6119b50d902SRodney W. Grimes dot = mp; 6129b50d902SRodney W. Grimes if ((cp = skin(hfield("from", mp))) == NOSTR) 6139b50d902SRodney W. Grimes cp = skin(nameof(mp, 2)); 6149b50d902SRodney W. Grimes head.h_to = cat(head.h_to, extract(cp, GTO)); 61599bd6601SJoerg Wunsch mid = skin(hfield("message-id", mp)); 6169b50d902SRodney W. Grimes } 6179b50d902SRodney W. Grimes if (head.h_to == NIL) 6189b50d902SRodney W. Grimes return 0; 6199b50d902SRodney W. Grimes mp = &message[msgvec[0] - 1]; 6209b50d902SRodney W. Grimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 6219b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 6229b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 6239b50d902SRodney W. Grimes head.h_cc = NIL; 6249b50d902SRodney W. Grimes head.h_bcc = NIL; 6259b50d902SRodney W. Grimes head.h_smopts = NIL; 62699bd6601SJoerg Wunsch if ((head.h_replyto = getenv("REPLYTO")) == NULL) 62799bd6601SJoerg Wunsch head.h_replyto = NOSTR; 62899bd6601SJoerg Wunsch head.h_inreplyto = mid; 6299b50d902SRodney W. Grimes mail1(&head, 1); 6309b50d902SRodney W. Grimes return 0; 6319b50d902SRodney W. Grimes } 6329b50d902SRodney W. Grimes 6339b50d902SRodney W. Grimes /* 6349b50d902SRodney W. Grimes * Conditional commands. These allow one to parameterize one's 6359b50d902SRodney W. Grimes * .mailrc and do some things if sending, others if receiving. 6369b50d902SRodney W. Grimes */ 6379b50d902SRodney W. Grimes int 6389b50d902SRodney W. Grimes ifcmd(argv) 6399b50d902SRodney W. Grimes char **argv; 6409b50d902SRodney W. Grimes { 6419b50d902SRodney W. Grimes register char *cp; 6429b50d902SRodney W. Grimes 6439b50d902SRodney W. Grimes if (cond != CANY) { 6449b50d902SRodney W. Grimes printf("Illegal nested \"if\"\n"); 6459b50d902SRodney W. Grimes return(1); 6469b50d902SRodney W. Grimes } 6479b50d902SRodney W. Grimes cond = CANY; 6489b50d902SRodney W. Grimes cp = argv[0]; 6499b50d902SRodney W. Grimes switch (*cp) { 6509b50d902SRodney W. Grimes case 'r': case 'R': 6519b50d902SRodney W. Grimes cond = CRCV; 6529b50d902SRodney W. Grimes break; 6539b50d902SRodney W. Grimes 6549b50d902SRodney W. Grimes case 's': case 'S': 6559b50d902SRodney W. Grimes cond = CSEND; 6569b50d902SRodney W. Grimes break; 6579b50d902SRodney W. Grimes 6589b50d902SRodney W. Grimes default: 6599b50d902SRodney W. Grimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 6609b50d902SRodney W. Grimes return(1); 6619b50d902SRodney W. Grimes } 6629b50d902SRodney W. Grimes return(0); 6639b50d902SRodney W. Grimes } 6649b50d902SRodney W. Grimes 6659b50d902SRodney W. Grimes /* 6669b50d902SRodney W. Grimes * Implement 'else'. This is pretty simple -- we just 6679b50d902SRodney W. Grimes * flip over the conditional flag. 6689b50d902SRodney W. Grimes */ 6699b50d902SRodney W. Grimes int 6709b50d902SRodney W. Grimes elsecmd() 6719b50d902SRodney W. Grimes { 6729b50d902SRodney W. Grimes 6739b50d902SRodney W. Grimes switch (cond) { 6749b50d902SRodney W. Grimes case CANY: 6759b50d902SRodney W. Grimes printf("\"Else\" without matching \"if\"\n"); 6769b50d902SRodney W. Grimes return(1); 6779b50d902SRodney W. Grimes 6789b50d902SRodney W. Grimes case CSEND: 6799b50d902SRodney W. Grimes cond = CRCV; 6809b50d902SRodney W. Grimes break; 6819b50d902SRodney W. Grimes 6829b50d902SRodney W. Grimes case CRCV: 6839b50d902SRodney W. Grimes cond = CSEND; 6849b50d902SRodney W. Grimes break; 6859b50d902SRodney W. Grimes 6869b50d902SRodney W. Grimes default: 6879b50d902SRodney W. Grimes printf("Mail's idea of conditions is screwed up\n"); 6889b50d902SRodney W. Grimes cond = CANY; 6899b50d902SRodney W. Grimes break; 6909b50d902SRodney W. Grimes } 6919b50d902SRodney W. Grimes return(0); 6929b50d902SRodney W. Grimes } 6939b50d902SRodney W. Grimes 6949b50d902SRodney W. Grimes /* 6959b50d902SRodney W. Grimes * End of if statement. Just set cond back to anything. 6969b50d902SRodney W. Grimes */ 6979b50d902SRodney W. Grimes int 6989b50d902SRodney W. Grimes endifcmd() 6999b50d902SRodney W. Grimes { 7009b50d902SRodney W. Grimes 7019b50d902SRodney W. Grimes if (cond == CANY) { 7029b50d902SRodney W. Grimes printf("\"Endif\" without matching \"if\"\n"); 7039b50d902SRodney W. Grimes return(1); 7049b50d902SRodney W. Grimes } 7059b50d902SRodney W. Grimes cond = CANY; 7069b50d902SRodney W. Grimes return(0); 7079b50d902SRodney W. Grimes } 7089b50d902SRodney W. Grimes 7099b50d902SRodney W. Grimes /* 7109b50d902SRodney W. Grimes * Set the list of alternate names. 7119b50d902SRodney W. Grimes */ 7129b50d902SRodney W. Grimes int 7139b50d902SRodney W. Grimes alternates(namelist) 7149b50d902SRodney W. Grimes char **namelist; 7159b50d902SRodney W. Grimes { 7169b50d902SRodney W. Grimes register int c; 7179b50d902SRodney W. Grimes register char **ap, **ap2, *cp; 7189b50d902SRodney W. Grimes 7199b50d902SRodney W. Grimes c = argcount(namelist) + 1; 7209b50d902SRodney W. Grimes if (c == 1) { 7219b50d902SRodney W. Grimes if (altnames == 0) 7229b50d902SRodney W. Grimes return(0); 7239b50d902SRodney W. Grimes for (ap = altnames; *ap; ap++) 7249b50d902SRodney W. Grimes printf("%s ", *ap); 7259b50d902SRodney W. Grimes printf("\n"); 7269b50d902SRodney W. Grimes return(0); 7279b50d902SRodney W. Grimes } 7289b50d902SRodney W. Grimes if (altnames != 0) 7299b50d902SRodney W. Grimes free((char *) altnames); 7309b50d902SRodney W. Grimes altnames = (char **) calloc((unsigned) c, sizeof (char *)); 7319b50d902SRodney W. Grimes for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) { 7329b50d902SRodney W. Grimes cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char)); 7339b50d902SRodney W. Grimes strcpy(cp, *ap); 7349b50d902SRodney W. Grimes *ap2 = cp; 7359b50d902SRodney W. Grimes } 7369b50d902SRodney W. Grimes *ap2 = 0; 7379b50d902SRodney W. Grimes return(0); 7389b50d902SRodney W. Grimes } 739