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) 1909b50d902SRodney W. Grimes return (_respond(msgvec)); 1919b50d902SRodney W. Grimes else 1929b50d902SRodney W. Grimes return (_Respond(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 2009b50d902SRodney W. Grimes _respond(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; 2559b50d902SRodney W. Grimes mail1(&head, 1); 2569b50d902SRodney W. Grimes return(0); 2579b50d902SRodney W. Grimes } 2589b50d902SRodney W. Grimes 2599b50d902SRodney W. Grimes /* 2609b50d902SRodney W. Grimes * Modify the subject we are replying to to begin with Re: if 2619b50d902SRodney W. Grimes * it does not already. 2629b50d902SRodney W. Grimes */ 2639b50d902SRodney W. Grimes char * 2649b50d902SRodney W. Grimes reedit(subj) 2659b50d902SRodney W. Grimes register char *subj; 2669b50d902SRodney W. Grimes { 2679b50d902SRodney W. Grimes char *newsubj; 2689b50d902SRodney W. Grimes 2699b50d902SRodney W. Grimes if (subj == NOSTR) 2709b50d902SRodney W. Grimes return NOSTR; 2719b50d902SRodney W. Grimes if ((subj[0] == 'r' || subj[0] == 'R') && 2729b50d902SRodney W. Grimes (subj[1] == 'e' || subj[1] == 'E') && 2739b50d902SRodney W. Grimes subj[2] == ':') 2749b50d902SRodney W. Grimes return subj; 2759b50d902SRodney W. Grimes newsubj = salloc(strlen(subj) + 5); 2769b50d902SRodney W. Grimes strcpy(newsubj, "Re: "); 2779b50d902SRodney W. Grimes strcpy(newsubj + 4, subj); 2789b50d902SRodney W. Grimes 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 2869b50d902SRodney W. Grimes preserve(msgvec) 2879b50d902SRodney W. Grimes int *msgvec; 2889b50d902SRodney W. Grimes { 2899b50d902SRodney W. Grimes register struct message *mp; 2909b50d902SRodney W. Grimes register int *ip, mesg; 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 } 2969b50d902SRodney W. Grimes for (ip = msgvec; *ip != NULL; 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 3109b50d902SRodney W. Grimes unread(msgvec) 3119b50d902SRodney W. Grimes int msgvec[]; 3129b50d902SRodney W. Grimes { 3139b50d902SRodney W. Grimes register int *ip; 3149b50d902SRodney W. Grimes 3159b50d902SRodney W. Grimes for (ip = msgvec; *ip != NULL; 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 3279b50d902SRodney W. Grimes messize(msgvec) 3289b50d902SRodney W. Grimes int *msgvec; 3299b50d902SRodney W. Grimes { 3309b50d902SRodney W. Grimes register struct message *mp; 3319b50d902SRodney W. Grimes register int *ip, mesg; 3329b50d902SRodney W. Grimes 3339b50d902SRodney W. Grimes for (ip = msgvec; *ip != NULL; ip++) { 3349b50d902SRodney W. Grimes mesg = *ip; 3359b50d902SRodney W. Grimes mp = &message[mesg-1]; 3369b50d902SRodney W. Grimes printf("%d: %d/%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 3469b50d902SRodney W. Grimes rexit(e) 3479b50d902SRodney W. Grimes int e; 3489b50d902SRodney W. Grimes { 3499b50d902SRodney W. Grimes if (sourcing) 3509b50d902SRodney W. Grimes return(1); 3519b50d902SRodney W. Grimes exit(e); 3529b50d902SRodney W. Grimes /*NOTREACHED*/ 3539b50d902SRodney W. Grimes } 3549b50d902SRodney W. Grimes 3559b50d902SRodney W. Grimes /* 3569b50d902SRodney W. Grimes * Set or display a variable value. Syntax is similar to that 3579b50d902SRodney W. Grimes * of csh. 3589b50d902SRodney W. Grimes */ 3599b50d902SRodney W. Grimes int 3609b50d902SRodney W. Grimes set(arglist) 3619b50d902SRodney W. Grimes char **arglist; 3629b50d902SRodney W. Grimes { 3639b50d902SRodney W. Grimes register struct var *vp; 3649b50d902SRodney W. Grimes register char *cp, *cp2; 3659b50d902SRodney W. Grimes char varbuf[BUFSIZ], **ap, **p; 3669b50d902SRodney W. Grimes int errs, h, s; 3679b50d902SRodney W. Grimes 3689b50d902SRodney W. Grimes if (*arglist == NOSTR) { 3699b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 3709b50d902SRodney W. Grimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3719b50d902SRodney W. Grimes s++; 3729b50d902SRodney W. Grimes ap = (char **) salloc(s * sizeof *ap); 3739b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 3749b50d902SRodney W. Grimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3759b50d902SRodney W. Grimes *p++ = vp->v_name; 3769b50d902SRodney W. Grimes *p = NOSTR; 3779b50d902SRodney W. Grimes sort(ap); 3789b50d902SRodney W. Grimes for (p = ap; *p != NOSTR; p++) 3799b50d902SRodney W. Grimes printf("%s\t%s\n", *p, value(*p)); 3809b50d902SRodney W. Grimes return(0); 3819b50d902SRodney W. Grimes } 3829b50d902SRodney W. Grimes errs = 0; 3839b50d902SRodney W. Grimes for (ap = arglist; *ap != NOSTR; ap++) { 3849b50d902SRodney W. Grimes cp = *ap; 3859b50d902SRodney W. Grimes cp2 = varbuf; 3869b50d902SRodney W. Grimes while (*cp != '=' && *cp != '\0') 3879b50d902SRodney W. Grimes *cp2++ = *cp++; 3889b50d902SRodney W. Grimes *cp2 = '\0'; 3899b50d902SRodney W. Grimes if (*cp == '\0') 3909b50d902SRodney W. Grimes cp = ""; 3919b50d902SRodney W. Grimes else 3929b50d902SRodney W. Grimes cp++; 3939b50d902SRodney W. Grimes if (equal(varbuf, "")) { 3949b50d902SRodney W. Grimes printf("Non-null variable name required\n"); 3959b50d902SRodney W. Grimes errs++; 3969b50d902SRodney W. Grimes continue; 3979b50d902SRodney W. Grimes } 3989b50d902SRodney W. Grimes assign(varbuf, cp); 3999b50d902SRodney W. Grimes } 4009b50d902SRodney W. Grimes return(errs); 4019b50d902SRodney W. Grimes } 4029b50d902SRodney W. Grimes 4039b50d902SRodney W. Grimes /* 4049b50d902SRodney W. Grimes * Unset a bunch of variable values. 4059b50d902SRodney W. Grimes */ 4069b50d902SRodney W. Grimes int 4079b50d902SRodney W. Grimes unset(arglist) 4089b50d902SRodney W. Grimes char **arglist; 4099b50d902SRodney W. Grimes { 4109b50d902SRodney W. Grimes register struct var *vp, *vp2; 4119b50d902SRodney W. Grimes int errs, h; 4129b50d902SRodney W. Grimes char **ap; 4139b50d902SRodney W. Grimes 4149b50d902SRodney W. Grimes errs = 0; 4159b50d902SRodney W. Grimes for (ap = arglist; *ap != NOSTR; ap++) { 4169b50d902SRodney W. Grimes if ((vp2 = lookup(*ap)) == NOVAR) { 4179b50d902SRodney W. Grimes if (!sourcing) { 4189b50d902SRodney W. Grimes printf("\"%s\": undefined variable\n", *ap); 4199b50d902SRodney W. Grimes errs++; 4209b50d902SRodney W. Grimes } 4219b50d902SRodney W. Grimes continue; 4229b50d902SRodney W. Grimes } 4239b50d902SRodney W. Grimes h = hash(*ap); 4249b50d902SRodney W. Grimes if (vp2 == variables[h]) { 4259b50d902SRodney W. Grimes variables[h] = variables[h]->v_link; 4269b50d902SRodney W. Grimes vfree(vp2->v_name); 4279b50d902SRodney W. Grimes vfree(vp2->v_value); 4289b50d902SRodney W. Grimes free((char *)vp2); 4299b50d902SRodney W. Grimes continue; 4309b50d902SRodney W. Grimes } 4319b50d902SRodney W. Grimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4329b50d902SRodney W. Grimes ; 4339b50d902SRodney W. Grimes vp->v_link = vp2->v_link; 4349b50d902SRodney W. Grimes vfree(vp2->v_name); 4359b50d902SRodney W. Grimes vfree(vp2->v_value); 4369b50d902SRodney W. Grimes free((char *) vp2); 4379b50d902SRodney W. Grimes } 4389b50d902SRodney W. Grimes return(errs); 4399b50d902SRodney W. Grimes } 4409b50d902SRodney W. Grimes 4419b50d902SRodney W. Grimes /* 4429b50d902SRodney W. Grimes * Put add users to a group. 4439b50d902SRodney W. Grimes */ 4449b50d902SRodney W. Grimes int 4459b50d902SRodney W. Grimes group(argv) 4469b50d902SRodney W. Grimes char **argv; 4479b50d902SRodney W. Grimes { 4489b50d902SRodney W. Grimes register struct grouphead *gh; 4499b50d902SRodney W. Grimes register struct group *gp; 4509b50d902SRodney W. Grimes register int h; 4519b50d902SRodney W. Grimes int s; 4529b50d902SRodney W. Grimes char **ap, *gname, **p; 4539b50d902SRodney W. Grimes 4549b50d902SRodney W. Grimes if (*argv == NOSTR) { 4559b50d902SRodney W. Grimes for (h = 0, s = 1; h < HSHSIZE; h++) 4569b50d902SRodney W. Grimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4579b50d902SRodney W. Grimes s++; 4589b50d902SRodney W. Grimes ap = (char **) salloc(s * sizeof *ap); 4599b50d902SRodney W. Grimes for (h = 0, p = ap; h < HSHSIZE; h++) 4609b50d902SRodney W. Grimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4619b50d902SRodney W. Grimes *p++ = gh->g_name; 4629b50d902SRodney W. Grimes *p = NOSTR; 4639b50d902SRodney W. Grimes sort(ap); 4649b50d902SRodney W. Grimes for (p = ap; *p != NOSTR; p++) 4659b50d902SRodney W. Grimes printgroup(*p); 4669b50d902SRodney W. Grimes return(0); 4679b50d902SRodney W. Grimes } 4689b50d902SRodney W. Grimes if (argv[1] == NOSTR) { 4699b50d902SRodney W. Grimes printgroup(*argv); 4709b50d902SRodney W. Grimes return(0); 4719b50d902SRodney W. Grimes } 4729b50d902SRodney W. Grimes gname = *argv; 4739b50d902SRodney W. Grimes h = hash(gname); 4749b50d902SRodney W. Grimes if ((gh = findgroup(gname)) == NOGRP) { 4759b50d902SRodney W. Grimes gh = (struct grouphead *) calloc(sizeof *gh, 1); 4769b50d902SRodney W. Grimes gh->g_name = vcopy(gname); 4779b50d902SRodney W. Grimes gh->g_list = NOGE; 4789b50d902SRodney W. Grimes gh->g_link = groups[h]; 4799b50d902SRodney W. Grimes groups[h] = gh; 4809b50d902SRodney W. Grimes } 4819b50d902SRodney W. Grimes 4829b50d902SRodney W. Grimes /* 4839b50d902SRodney W. Grimes * Insert names from the command list into the group. 4849b50d902SRodney W. Grimes * Who cares if there are duplicates? They get tossed 4859b50d902SRodney W. Grimes * later anyway. 4869b50d902SRodney W. Grimes */ 4879b50d902SRodney W. Grimes 4889b50d902SRodney W. Grimes for (ap = argv+1; *ap != NOSTR; ap++) { 4899b50d902SRodney W. Grimes gp = (struct group *) calloc(sizeof *gp, 1); 4909b50d902SRodney W. Grimes gp->ge_name = vcopy(*ap); 4919b50d902SRodney W. Grimes gp->ge_link = gh->g_list; 4929b50d902SRodney W. Grimes gh->g_list = gp; 4939b50d902SRodney W. Grimes } 4949b50d902SRodney W. Grimes return(0); 4959b50d902SRodney W. Grimes } 4969b50d902SRodney W. Grimes 4979b50d902SRodney W. Grimes /* 4989b50d902SRodney W. Grimes * Sort the passed string vecotor into ascending dictionary 4999b50d902SRodney W. Grimes * order. 5009b50d902SRodney W. Grimes */ 5019b50d902SRodney W. Grimes void 5029b50d902SRodney W. Grimes sort(list) 5039b50d902SRodney W. Grimes char **list; 5049b50d902SRodney W. Grimes { 5059b50d902SRodney W. Grimes register char **ap; 5069b50d902SRodney W. Grimes int diction(); 5079b50d902SRodney W. Grimes 5089b50d902SRodney W. Grimes for (ap = list; *ap != NOSTR; 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 5209b50d902SRodney W. Grimes diction(a, b) 5219b50d902SRodney W. Grimes const void *a, *b; 5229b50d902SRodney W. Grimes { 5239b50d902SRodney W. Grimes return(strcmp(*(char **)a, *(char **)b)); 5249b50d902SRodney W. Grimes } 5259b50d902SRodney W. Grimes 5269b50d902SRodney W. Grimes /* 5279b50d902SRodney W. Grimes * The do nothing command for comments. 5289b50d902SRodney W. Grimes */ 5299b50d902SRodney W. Grimes 5309b50d902SRodney W. Grimes /*ARGSUSED*/ 5319b50d902SRodney W. Grimes int 5329b50d902SRodney W. Grimes null(e) 5339b50d902SRodney W. Grimes int e; 5349b50d902SRodney W. Grimes { 5359b50d902SRodney W. Grimes return 0; 5369b50d902SRodney W. Grimes } 5379b50d902SRodney W. Grimes 5389b50d902SRodney W. Grimes /* 5399b50d902SRodney W. Grimes * Change to another file. With no argument, print information about 5409b50d902SRodney W. Grimes * the current file. 5419b50d902SRodney W. Grimes */ 5429b50d902SRodney W. Grimes int 5439b50d902SRodney W. Grimes file(argv) 5449b50d902SRodney W. Grimes register char **argv; 5459b50d902SRodney W. Grimes { 5469b50d902SRodney W. Grimes 5479b50d902SRodney W. Grimes if (argv[0] == NOSTR) { 5489b50d902SRodney W. Grimes newfileinfo(); 5499b50d902SRodney W. Grimes return 0; 5509b50d902SRodney W. Grimes } 5519b50d902SRodney W. Grimes if (setfile(*argv) < 0) 5529b50d902SRodney W. Grimes return 1; 5539b50d902SRodney W. Grimes announce(); 5549b50d902SRodney W. Grimes return 0; 5559b50d902SRodney W. Grimes } 5569b50d902SRodney W. Grimes 5579b50d902SRodney W. Grimes /* 5589b50d902SRodney W. Grimes * Expand file names like echo 5599b50d902SRodney W. Grimes */ 5609b50d902SRodney W. Grimes int 5619b50d902SRodney W. Grimes echo(argv) 5629b50d902SRodney W. Grimes char **argv; 5639b50d902SRodney W. Grimes { 5649b50d902SRodney W. Grimes register char **ap; 5659b50d902SRodney W. Grimes register char *cp; 5669b50d902SRodney W. Grimes 5679b50d902SRodney W. Grimes for (ap = argv; *ap != NOSTR; ap++) { 5689b50d902SRodney W. Grimes cp = *ap; 5699b50d902SRodney W. Grimes if ((cp = expand(cp)) != NOSTR) { 5709b50d902SRodney W. Grimes if (ap != argv) 5719b50d902SRodney W. Grimes putchar(' '); 5729b50d902SRodney W. Grimes printf("%s", cp); 5739b50d902SRodney W. Grimes } 5749b50d902SRodney W. Grimes } 5759b50d902SRodney W. Grimes putchar('\n'); 5769b50d902SRodney W. Grimes return 0; 5779b50d902SRodney W. Grimes } 5789b50d902SRodney W. Grimes 5799b50d902SRodney W. Grimes int 5809b50d902SRodney W. Grimes Respond(msgvec) 5819b50d902SRodney W. Grimes int *msgvec; 5829b50d902SRodney W. Grimes { 5839b50d902SRodney W. Grimes if (value("Replyall") == NOSTR) 5849b50d902SRodney W. Grimes return (_Respond(msgvec)); 5859b50d902SRodney W. Grimes else 5869b50d902SRodney W. Grimes return (_respond(msgvec)); 5879b50d902SRodney W. Grimes } 5889b50d902SRodney W. Grimes 5899b50d902SRodney W. Grimes /* 5909b50d902SRodney W. Grimes * Reply to a series of messages by simply mailing to the senders 5919b50d902SRodney W. Grimes * and not messing around with the To: and Cc: lists as in normal 5929b50d902SRodney W. Grimes * reply. 5939b50d902SRodney W. Grimes */ 5949b50d902SRodney W. Grimes int 5959b50d902SRodney W. Grimes _Respond(msgvec) 5969b50d902SRodney W. Grimes int msgvec[]; 5979b50d902SRodney W. Grimes { 5989b50d902SRodney W. Grimes struct header head; 5999b50d902SRodney W. Grimes struct message *mp; 6009b50d902SRodney W. Grimes register int *ap; 6019b50d902SRodney W. Grimes register char *cp; 6029b50d902SRodney W. Grimes 6039b50d902SRodney W. Grimes head.h_to = NIL; 6049b50d902SRodney W. Grimes for (ap = msgvec; *ap != 0; ap++) { 6059b50d902SRodney W. Grimes mp = &message[*ap - 1]; 6069b50d902SRodney W. Grimes touch(mp); 6079b50d902SRodney W. Grimes dot = mp; 6089b50d902SRodney W. Grimes if ((cp = skin(hfield("from", mp))) == NOSTR) 6099b50d902SRodney W. Grimes cp = skin(nameof(mp, 2)); 6109b50d902SRodney W. Grimes head.h_to = cat(head.h_to, extract(cp, GTO)); 6119b50d902SRodney W. Grimes } 6129b50d902SRodney W. Grimes if (head.h_to == NIL) 6139b50d902SRodney W. Grimes return 0; 6149b50d902SRodney W. Grimes mp = &message[msgvec[0] - 1]; 6159b50d902SRodney W. Grimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 6169b50d902SRodney W. Grimes head.h_subject = hfield("subj", mp); 6179b50d902SRodney W. Grimes head.h_subject = reedit(head.h_subject); 6189b50d902SRodney W. Grimes head.h_cc = NIL; 6199b50d902SRodney W. Grimes head.h_bcc = NIL; 6209b50d902SRodney W. Grimes head.h_smopts = NIL; 6219b50d902SRodney W. Grimes mail1(&head, 1); 6229b50d902SRodney W. Grimes return 0; 6239b50d902SRodney W. Grimes } 6249b50d902SRodney W. Grimes 6259b50d902SRodney W. Grimes /* 6269b50d902SRodney W. Grimes * Conditional commands. These allow one to parameterize one's 6279b50d902SRodney W. Grimes * .mailrc and do some things if sending, others if receiving. 6289b50d902SRodney W. Grimes */ 6299b50d902SRodney W. Grimes int 6309b50d902SRodney W. Grimes ifcmd(argv) 6319b50d902SRodney W. Grimes char **argv; 6329b50d902SRodney W. Grimes { 6339b50d902SRodney W. Grimes register char *cp; 6349b50d902SRodney W. Grimes 6359b50d902SRodney W. Grimes if (cond != CANY) { 6369b50d902SRodney W. Grimes printf("Illegal nested \"if\"\n"); 6379b50d902SRodney W. Grimes return(1); 6389b50d902SRodney W. Grimes } 6399b50d902SRodney W. Grimes cond = CANY; 6409b50d902SRodney W. Grimes cp = argv[0]; 6419b50d902SRodney W. Grimes switch (*cp) { 6429b50d902SRodney W. Grimes case 'r': case 'R': 6439b50d902SRodney W. Grimes cond = CRCV; 6449b50d902SRodney W. Grimes break; 6459b50d902SRodney W. Grimes 6469b50d902SRodney W. Grimes case 's': case 'S': 6479b50d902SRodney W. Grimes cond = CSEND; 6489b50d902SRodney W. Grimes break; 6499b50d902SRodney W. Grimes 6509b50d902SRodney W. Grimes default: 6519b50d902SRodney W. Grimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 6529b50d902SRodney W. Grimes return(1); 6539b50d902SRodney W. Grimes } 6549b50d902SRodney W. Grimes return(0); 6559b50d902SRodney W. Grimes } 6569b50d902SRodney W. Grimes 6579b50d902SRodney W. Grimes /* 6589b50d902SRodney W. Grimes * Implement 'else'. This is pretty simple -- we just 6599b50d902SRodney W. Grimes * flip over the conditional flag. 6609b50d902SRodney W. Grimes */ 6619b50d902SRodney W. Grimes int 6629b50d902SRodney W. Grimes elsecmd() 6639b50d902SRodney W. Grimes { 6649b50d902SRodney W. Grimes 6659b50d902SRodney W. Grimes switch (cond) { 6669b50d902SRodney W. Grimes case CANY: 6679b50d902SRodney W. Grimes printf("\"Else\" without matching \"if\"\n"); 6689b50d902SRodney W. Grimes return(1); 6699b50d902SRodney W. Grimes 6709b50d902SRodney W. Grimes case CSEND: 6719b50d902SRodney W. Grimes cond = CRCV; 6729b50d902SRodney W. Grimes break; 6739b50d902SRodney W. Grimes 6749b50d902SRodney W. Grimes case CRCV: 6759b50d902SRodney W. Grimes cond = CSEND; 6769b50d902SRodney W. Grimes break; 6779b50d902SRodney W. Grimes 6789b50d902SRodney W. Grimes default: 6799b50d902SRodney W. Grimes printf("Mail's idea of conditions is screwed up\n"); 6809b50d902SRodney W. Grimes cond = CANY; 6819b50d902SRodney W. Grimes break; 6829b50d902SRodney W. Grimes } 6839b50d902SRodney W. Grimes return(0); 6849b50d902SRodney W. Grimes } 6859b50d902SRodney W. Grimes 6869b50d902SRodney W. Grimes /* 6879b50d902SRodney W. Grimes * End of if statement. Just set cond back to anything. 6889b50d902SRodney W. Grimes */ 6899b50d902SRodney W. Grimes int 6909b50d902SRodney W. Grimes endifcmd() 6919b50d902SRodney W. Grimes { 6929b50d902SRodney W. Grimes 6939b50d902SRodney W. Grimes if (cond == CANY) { 6949b50d902SRodney W. Grimes printf("\"Endif\" without matching \"if\"\n"); 6959b50d902SRodney W. Grimes return(1); 6969b50d902SRodney W. Grimes } 6979b50d902SRodney W. Grimes cond = CANY; 6989b50d902SRodney W. Grimes return(0); 6999b50d902SRodney W. Grimes } 7009b50d902SRodney W. Grimes 7019b50d902SRodney W. Grimes /* 7029b50d902SRodney W. Grimes * Set the list of alternate names. 7039b50d902SRodney W. Grimes */ 7049b50d902SRodney W. Grimes int 7059b50d902SRodney W. Grimes alternates(namelist) 7069b50d902SRodney W. Grimes char **namelist; 7079b50d902SRodney W. Grimes { 7089b50d902SRodney W. Grimes register int c; 7099b50d902SRodney W. Grimes register char **ap, **ap2, *cp; 7109b50d902SRodney W. Grimes 7119b50d902SRodney W. Grimes c = argcount(namelist) + 1; 7129b50d902SRodney W. Grimes if (c == 1) { 7139b50d902SRodney W. Grimes if (altnames == 0) 7149b50d902SRodney W. Grimes return(0); 7159b50d902SRodney W. Grimes for (ap = altnames; *ap; ap++) 7169b50d902SRodney W. Grimes printf("%s ", *ap); 7179b50d902SRodney W. Grimes printf("\n"); 7189b50d902SRodney W. Grimes return(0); 7199b50d902SRodney W. Grimes } 7209b50d902SRodney W. Grimes if (altnames != 0) 7219b50d902SRodney W. Grimes free((char *) altnames); 7229b50d902SRodney W. Grimes altnames = (char **) calloc((unsigned) c, sizeof (char *)); 7239b50d902SRodney W. Grimes for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) { 7249b50d902SRodney W. Grimes cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char)); 7259b50d902SRodney W. Grimes strcpy(cp, *ap); 7269b50d902SRodney W. Grimes *ap2 = cp; 7279b50d902SRodney W. Grimes } 7289b50d902SRodney W. Grimes *ap2 = 0; 7299b50d902SRodney W. Grimes return(0); 7309b50d902SRodney W. Grimes } 731