cmd3.c revision 32189
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char sccsid[] = "@(#)cmd3.c 8.1 (Berkeley) 6/6/93"; 361590Srgrimes#endif /* not lint */ 371590Srgrimes 381590Srgrimes#include "rcv.h" 391590Srgrimes#include "extern.h" 401590Srgrimes 411590Srgrimes/* 421590Srgrimes * Mail -- a mail program 431590Srgrimes * 441590Srgrimes * Still more user commands. 451590Srgrimes */ 461590Srgrimes 471590Srgrimes/* 481590Srgrimes * Process a shell escape by saving signals, ignoring signals, 491590Srgrimes * and forking a sh -c 501590Srgrimes */ 511590Srgrimesint 521590Srgrimesshell(str) 531590Srgrimes char *str; 541590Srgrimes{ 551590Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 561590Srgrimes char *shell; 571590Srgrimes char cmd[BUFSIZ]; 581590Srgrimes 591590Srgrimes (void) strcpy(cmd, str); 601590Srgrimes if (bangexp(cmd) < 0) 611590Srgrimes return 1; 621590Srgrimes if ((shell = value("SHELL")) == NOSTR) 631590Srgrimes shell = _PATH_CSHELL; 641590Srgrimes (void) run_command(shell, 0, -1, -1, "-c", cmd, NOSTR); 651590Srgrimes (void) signal(SIGINT, sigint); 661590Srgrimes printf("!\n"); 671590Srgrimes return 0; 681590Srgrimes} 691590Srgrimes 701590Srgrimes/* 711590Srgrimes * Fork an interactive shell. 721590Srgrimes */ 731590Srgrimes/*ARGSUSED*/ 741590Srgrimesint 751590Srgrimesdosh(str) 761590Srgrimes char *str; 771590Srgrimes{ 781590Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 791590Srgrimes char *shell; 801590Srgrimes 811590Srgrimes if ((shell = value("SHELL")) == NOSTR) 821590Srgrimes shell = _PATH_CSHELL; 831590Srgrimes (void) run_command(shell, 0, -1, -1, NOSTR, NOSTR, NOSTR); 841590Srgrimes (void) signal(SIGINT, sigint); 851590Srgrimes putchar('\n'); 861590Srgrimes return 0; 871590Srgrimes} 881590Srgrimes 891590Srgrimes/* 901590Srgrimes * Expand the shell escape by expanding unescaped !'s into the 911590Srgrimes * last issued command where possible. 921590Srgrimes */ 931590Srgrimes 941590Srgrimeschar lastbang[128]; 951590Srgrimes 961590Srgrimesint 971590Srgrimesbangexp(str) 981590Srgrimes char *str; 991590Srgrimes{ 1001590Srgrimes char bangbuf[BUFSIZ]; 1011590Srgrimes register char *cp, *cp2; 1021590Srgrimes register int n; 1031590Srgrimes int changed = 0; 1041590Srgrimes 1051590Srgrimes cp = str; 1061590Srgrimes cp2 = bangbuf; 1071590Srgrimes n = BUFSIZ; 1081590Srgrimes while (*cp) { 1091590Srgrimes if (*cp == '!') { 1101590Srgrimes if (n < strlen(lastbang)) { 1111590Srgrimesoverf: 1121590Srgrimes printf("Command buffer overflow\n"); 1131590Srgrimes return(-1); 1141590Srgrimes } 1151590Srgrimes changed++; 1161590Srgrimes strcpy(cp2, lastbang); 1171590Srgrimes cp2 += strlen(lastbang); 1181590Srgrimes n -= strlen(lastbang); 1191590Srgrimes cp++; 1201590Srgrimes continue; 1211590Srgrimes } 1221590Srgrimes if (*cp == '\\' && cp[1] == '!') { 1231590Srgrimes if (--n <= 1) 1241590Srgrimes goto overf; 1251590Srgrimes *cp2++ = '!'; 1261590Srgrimes cp += 2; 1271590Srgrimes changed++; 1281590Srgrimes } 1291590Srgrimes if (--n <= 1) 1301590Srgrimes goto overf; 1311590Srgrimes *cp2++ = *cp++; 1321590Srgrimes } 1331590Srgrimes *cp2 = 0; 1341590Srgrimes if (changed) { 1351590Srgrimes printf("!%s\n", bangbuf); 1361590Srgrimes fflush(stdout); 1371590Srgrimes } 1381590Srgrimes strcpy(str, bangbuf); 1391590Srgrimes strncpy(lastbang, bangbuf, 128); 1401590Srgrimes lastbang[127] = 0; 1411590Srgrimes return(0); 1421590Srgrimes} 1431590Srgrimes 1441590Srgrimes/* 1451590Srgrimes * Print out a nice help message from some file or another. 1461590Srgrimes */ 1471590Srgrimes 1481590Srgrimesint 1491590Srgrimeshelp() 1501590Srgrimes{ 1511590Srgrimes register c; 1521590Srgrimes register FILE *f; 1531590Srgrimes 1541590Srgrimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 1551590Srgrimes perror(_PATH_HELP); 1561590Srgrimes return(1); 1571590Srgrimes } 1581590Srgrimes while ((c = getc(f)) != EOF) 1591590Srgrimes putchar(c); 1601590Srgrimes Fclose(f); 1611590Srgrimes return(0); 1621590Srgrimes} 1631590Srgrimes 1641590Srgrimes/* 1651590Srgrimes * Change user's working directory. 1661590Srgrimes */ 1671590Srgrimesint 1681590Srgrimesschdir(arglist) 1691590Srgrimes char **arglist; 1701590Srgrimes{ 1711590Srgrimes char *cp; 1721590Srgrimes 1731590Srgrimes if (*arglist == NOSTR) 1741590Srgrimes cp = homedir; 1751590Srgrimes else 1761590Srgrimes if ((cp = expand(*arglist)) == NOSTR) 1771590Srgrimes return(1); 1781590Srgrimes if (chdir(cp) < 0) { 1791590Srgrimes perror(cp); 1801590Srgrimes return(1); 1811590Srgrimes } 1821590Srgrimes return 0; 1831590Srgrimes} 1841590Srgrimes 1851590Srgrimesint 1861590Srgrimesrespond(msgvec) 1871590Srgrimes int *msgvec; 1881590Srgrimes{ 1891590Srgrimes if (value("Replyall") == NOSTR) 19032189Sjoerg return (dorespond(msgvec)); 1911590Srgrimes else 19232189Sjoerg return (doRespond(msgvec)); 1931590Srgrimes} 1941590Srgrimes 1951590Srgrimes/* 1961590Srgrimes * Reply to a list of messages. Extract each name from the 1971590Srgrimes * message header and send them off to mail1() 1981590Srgrimes */ 1991590Srgrimesint 20032189Sjoergdorespond(msgvec) 2011590Srgrimes int *msgvec; 2021590Srgrimes{ 2031590Srgrimes struct message *mp; 2041590Srgrimes char *cp, *rcv, *replyto; 2051590Srgrimes char **ap; 2061590Srgrimes struct name *np; 2071590Srgrimes struct header head; 2081590Srgrimes 2091590Srgrimes if (msgvec[1] != 0) { 2101590Srgrimes printf("Sorry, can't reply to multiple messages at once\n"); 2111590Srgrimes return(1); 2121590Srgrimes } 2131590Srgrimes mp = &message[msgvec[0] - 1]; 2141590Srgrimes touch(mp); 2151590Srgrimes dot = mp; 2161590Srgrimes if ((rcv = skin(hfield("from", mp))) == NOSTR) 2171590Srgrimes rcv = skin(nameof(mp, 1)); 2181590Srgrimes if ((replyto = skin(hfield("reply-to", mp))) != NOSTR) 2191590Srgrimes np = extract(replyto, GTO); 2201590Srgrimes else if ((cp = skin(hfield("to", mp))) != NOSTR) 2211590Srgrimes np = extract(cp, GTO); 2221590Srgrimes else 2231590Srgrimes np = NIL; 2241590Srgrimes np = elide(np); 2251590Srgrimes /* 2261590Srgrimes * Delete my name from the reply list, 2271590Srgrimes * and with it, all my alternate names. 2281590Srgrimes */ 2291590Srgrimes np = delname(np, myname); 2301590Srgrimes if (altnames) 2311590Srgrimes for (ap = altnames; *ap; ap++) 2321590Srgrimes np = delname(np, *ap); 2331590Srgrimes if (np != NIL && replyto == NOSTR) 2341590Srgrimes np = cat(np, extract(rcv, GTO)); 2351590Srgrimes else if (np == NIL) { 2361590Srgrimes if (replyto != NOSTR) 2371590Srgrimes printf("Empty reply-to field -- replying to author\n"); 2381590Srgrimes np = extract(rcv, GTO); 2391590Srgrimes } 2401590Srgrimes head.h_to = np; 2411590Srgrimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 2421590Srgrimes head.h_subject = hfield("subj", mp); 2431590Srgrimes head.h_subject = reedit(head.h_subject); 2441590Srgrimes if (replyto == NOSTR && (cp = skin(hfield("cc", mp))) != NOSTR) { 2451590Srgrimes np = elide(extract(cp, GCC)); 2461590Srgrimes np = delname(np, myname); 2471590Srgrimes if (altnames != 0) 2481590Srgrimes for (ap = altnames; *ap; ap++) 2491590Srgrimes np = delname(np, *ap); 2501590Srgrimes head.h_cc = np; 2511590Srgrimes } else 2521590Srgrimes head.h_cc = NIL; 2531590Srgrimes head.h_bcc = NIL; 2541590Srgrimes head.h_smopts = NIL; 25532189Sjoerg if ((head.h_replyto = getenv("REPLYTO")) == NULL) 25632189Sjoerg head.h_replyto = NOSTR; 25732189Sjoerg head.h_inreplyto = skin(hfield("message-id", mp)); 2581590Srgrimes mail1(&head, 1); 2591590Srgrimes return(0); 2601590Srgrimes} 2611590Srgrimes 2621590Srgrimes/* 2631590Srgrimes * Modify the subject we are replying to to begin with Re: if 2641590Srgrimes * it does not already. 2651590Srgrimes */ 2661590Srgrimeschar * 2671590Srgrimesreedit(subj) 2681590Srgrimes register char *subj; 2691590Srgrimes{ 2701590Srgrimes char *newsubj; 2711590Srgrimes 2721590Srgrimes if (subj == NOSTR) 2731590Srgrimes return NOSTR; 2741590Srgrimes if ((subj[0] == 'r' || subj[0] == 'R') && 2751590Srgrimes (subj[1] == 'e' || subj[1] == 'E') && 2761590Srgrimes subj[2] == ':') 2771590Srgrimes return subj; 2781590Srgrimes newsubj = salloc(strlen(subj) + 5); 2791590Srgrimes strcpy(newsubj, "Re: "); 2801590Srgrimes strcpy(newsubj + 4, subj); 2811590Srgrimes return newsubj; 2821590Srgrimes} 2831590Srgrimes 2841590Srgrimes/* 2851590Srgrimes * Preserve the named messages, so that they will be sent 2861590Srgrimes * back to the system mailbox. 2871590Srgrimes */ 2881590Srgrimesint 2891590Srgrimespreserve(msgvec) 2901590Srgrimes int *msgvec; 2911590Srgrimes{ 2921590Srgrimes register struct message *mp; 2931590Srgrimes register int *ip, mesg; 2941590Srgrimes 2951590Srgrimes if (edit) { 2961590Srgrimes printf("Cannot \"preserve\" in edit mode\n"); 2971590Srgrimes return(1); 2981590Srgrimes } 29929574Sphk for (ip = msgvec; *ip != 0; ip++) { 3001590Srgrimes mesg = *ip; 3011590Srgrimes mp = &message[mesg-1]; 3021590Srgrimes mp->m_flag |= MPRESERVE; 3031590Srgrimes mp->m_flag &= ~MBOX; 3041590Srgrimes dot = mp; 3051590Srgrimes } 3061590Srgrimes return(0); 3071590Srgrimes} 3081590Srgrimes 3091590Srgrimes/* 3101590Srgrimes * Mark all given messages as unread. 3111590Srgrimes */ 3121590Srgrimesint 3131590Srgrimesunread(msgvec) 3141590Srgrimes int msgvec[]; 3151590Srgrimes{ 3161590Srgrimes register int *ip; 3171590Srgrimes 31829574Sphk for (ip = msgvec; *ip != 0; ip++) { 3191590Srgrimes dot = &message[*ip-1]; 3201590Srgrimes dot->m_flag &= ~(MREAD|MTOUCH); 3211590Srgrimes dot->m_flag |= MSTATUS; 3221590Srgrimes } 3231590Srgrimes return(0); 3241590Srgrimes} 3251590Srgrimes 3261590Srgrimes/* 3271590Srgrimes * Print the size of each message. 3281590Srgrimes */ 3291590Srgrimesint 3301590Srgrimesmessize(msgvec) 3311590Srgrimes int *msgvec; 3321590Srgrimes{ 3331590Srgrimes register struct message *mp; 3341590Srgrimes register int *ip, mesg; 3351590Srgrimes 33629574Sphk for (ip = msgvec; *ip != 0; ip++) { 3371590Srgrimes mesg = *ip; 3381590Srgrimes mp = &message[mesg-1]; 3391590Srgrimes printf("%d: %d/%ld\n", mesg, mp->m_lines, mp->m_size); 3401590Srgrimes } 3411590Srgrimes return(0); 3421590Srgrimes} 3431590Srgrimes 3441590Srgrimes/* 3451590Srgrimes * Quit quickly. If we are sourcing, just pop the input level 3461590Srgrimes * by returning an error. 3471590Srgrimes */ 3481590Srgrimesint 3491590Srgrimesrexit(e) 3501590Srgrimes int e; 3511590Srgrimes{ 3521590Srgrimes if (sourcing) 3531590Srgrimes return(1); 3541590Srgrimes exit(e); 3551590Srgrimes /*NOTREACHED*/ 3561590Srgrimes} 3571590Srgrimes 3581590Srgrimes/* 3591590Srgrimes * Set or display a variable value. Syntax is similar to that 3601590Srgrimes * of csh. 3611590Srgrimes */ 3621590Srgrimesint 3631590Srgrimesset(arglist) 3641590Srgrimes char **arglist; 3651590Srgrimes{ 3661590Srgrimes register struct var *vp; 3671590Srgrimes register char *cp, *cp2; 3681590Srgrimes char varbuf[BUFSIZ], **ap, **p; 3691590Srgrimes int errs, h, s; 3701590Srgrimes 3711590Srgrimes if (*arglist == NOSTR) { 3721590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 3731590Srgrimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3741590Srgrimes s++; 3751590Srgrimes ap = (char **) salloc(s * sizeof *ap); 3761590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 3771590Srgrimes for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) 3781590Srgrimes *p++ = vp->v_name; 3791590Srgrimes *p = NOSTR; 3801590Srgrimes sort(ap); 3811590Srgrimes for (p = ap; *p != NOSTR; p++) 3821590Srgrimes printf("%s\t%s\n", *p, value(*p)); 3831590Srgrimes return(0); 3841590Srgrimes } 3851590Srgrimes errs = 0; 3861590Srgrimes for (ap = arglist; *ap != NOSTR; ap++) { 3871590Srgrimes cp = *ap; 3881590Srgrimes cp2 = varbuf; 3891590Srgrimes while (*cp != '=' && *cp != '\0') 3901590Srgrimes *cp2++ = *cp++; 3911590Srgrimes *cp2 = '\0'; 3921590Srgrimes if (*cp == '\0') 3931590Srgrimes cp = ""; 3941590Srgrimes else 3951590Srgrimes cp++; 3961590Srgrimes if (equal(varbuf, "")) { 3971590Srgrimes printf("Non-null variable name required\n"); 3981590Srgrimes errs++; 3991590Srgrimes continue; 4001590Srgrimes } 4011590Srgrimes assign(varbuf, cp); 4021590Srgrimes } 4031590Srgrimes return(errs); 4041590Srgrimes} 4051590Srgrimes 4061590Srgrimes/* 4071590Srgrimes * Unset a bunch of variable values. 4081590Srgrimes */ 4091590Srgrimesint 4101590Srgrimesunset(arglist) 4111590Srgrimes char **arglist; 4121590Srgrimes{ 4131590Srgrimes register struct var *vp, *vp2; 4141590Srgrimes int errs, h; 4151590Srgrimes char **ap; 4161590Srgrimes 4171590Srgrimes errs = 0; 4181590Srgrimes for (ap = arglist; *ap != NOSTR; ap++) { 4191590Srgrimes if ((vp2 = lookup(*ap)) == NOVAR) { 4201590Srgrimes if (!sourcing) { 4211590Srgrimes printf("\"%s\": undefined variable\n", *ap); 4221590Srgrimes errs++; 4231590Srgrimes } 4241590Srgrimes continue; 4251590Srgrimes } 4261590Srgrimes h = hash(*ap); 4271590Srgrimes if (vp2 == variables[h]) { 4281590Srgrimes variables[h] = variables[h]->v_link; 4291590Srgrimes vfree(vp2->v_name); 4301590Srgrimes vfree(vp2->v_value); 4311590Srgrimes free((char *)vp2); 4321590Srgrimes continue; 4331590Srgrimes } 4341590Srgrimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4351590Srgrimes ; 4361590Srgrimes vp->v_link = vp2->v_link; 4371590Srgrimes vfree(vp2->v_name); 4381590Srgrimes vfree(vp2->v_value); 4391590Srgrimes free((char *) vp2); 4401590Srgrimes } 4411590Srgrimes return(errs); 4421590Srgrimes} 4431590Srgrimes 4441590Srgrimes/* 4451590Srgrimes * Put add users to a group. 4461590Srgrimes */ 4471590Srgrimesint 4481590Srgrimesgroup(argv) 4491590Srgrimes char **argv; 4501590Srgrimes{ 4511590Srgrimes register struct grouphead *gh; 4521590Srgrimes register struct group *gp; 4531590Srgrimes register int h; 4541590Srgrimes int s; 4551590Srgrimes char **ap, *gname, **p; 4561590Srgrimes 4571590Srgrimes if (*argv == NOSTR) { 4581590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 4591590Srgrimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4601590Srgrimes s++; 4611590Srgrimes ap = (char **) salloc(s * sizeof *ap); 4621590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 4631590Srgrimes for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) 4641590Srgrimes *p++ = gh->g_name; 4651590Srgrimes *p = NOSTR; 4661590Srgrimes sort(ap); 4671590Srgrimes for (p = ap; *p != NOSTR; p++) 4681590Srgrimes printgroup(*p); 4691590Srgrimes return(0); 4701590Srgrimes } 4711590Srgrimes if (argv[1] == NOSTR) { 4721590Srgrimes printgroup(*argv); 4731590Srgrimes return(0); 4741590Srgrimes } 4751590Srgrimes gname = *argv; 4761590Srgrimes h = hash(gname); 4771590Srgrimes if ((gh = findgroup(gname)) == NOGRP) { 4781590Srgrimes gh = (struct grouphead *) calloc(sizeof *gh, 1); 4791590Srgrimes gh->g_name = vcopy(gname); 4801590Srgrimes gh->g_list = NOGE; 4811590Srgrimes gh->g_link = groups[h]; 4821590Srgrimes groups[h] = gh; 4831590Srgrimes } 4841590Srgrimes 4851590Srgrimes /* 4861590Srgrimes * Insert names from the command list into the group. 4871590Srgrimes * Who cares if there are duplicates? They get tossed 4881590Srgrimes * later anyway. 4891590Srgrimes */ 4901590Srgrimes 4911590Srgrimes for (ap = argv+1; *ap != NOSTR; ap++) { 4921590Srgrimes gp = (struct group *) calloc(sizeof *gp, 1); 4931590Srgrimes gp->ge_name = vcopy(*ap); 4941590Srgrimes gp->ge_link = gh->g_list; 4951590Srgrimes gh->g_list = gp; 4961590Srgrimes } 4971590Srgrimes return(0); 4981590Srgrimes} 4991590Srgrimes 5001590Srgrimes/* 5011590Srgrimes * Sort the passed string vecotor into ascending dictionary 5021590Srgrimes * order. 5031590Srgrimes */ 5041590Srgrimesvoid 5051590Srgrimessort(list) 5061590Srgrimes char **list; 5071590Srgrimes{ 5081590Srgrimes register char **ap; 5091590Srgrimes int diction(); 5101590Srgrimes 5111590Srgrimes for (ap = list; *ap != NOSTR; ap++) 5121590Srgrimes ; 5131590Srgrimes if (ap-list < 2) 5141590Srgrimes return; 5151590Srgrimes qsort(list, ap-list, sizeof(*list), diction); 5161590Srgrimes} 5171590Srgrimes 5181590Srgrimes/* 5191590Srgrimes * Do a dictionary order comparison of the arguments from 5201590Srgrimes * qsort. 5211590Srgrimes */ 5221590Srgrimesint 5231590Srgrimesdiction(a, b) 5241590Srgrimes const void *a, *b; 5251590Srgrimes{ 5261590Srgrimes return(strcmp(*(char **)a, *(char **)b)); 5271590Srgrimes} 5281590Srgrimes 5291590Srgrimes/* 5301590Srgrimes * The do nothing command for comments. 5311590Srgrimes */ 5321590Srgrimes 5331590Srgrimes/*ARGSUSED*/ 5341590Srgrimesint 5351590Srgrimesnull(e) 5361590Srgrimes int e; 5371590Srgrimes{ 5381590Srgrimes return 0; 5391590Srgrimes} 5401590Srgrimes 5411590Srgrimes/* 5421590Srgrimes * Change to another file. With no argument, print information about 5431590Srgrimes * the current file. 5441590Srgrimes */ 5451590Srgrimesint 5461590Srgrimesfile(argv) 5471590Srgrimes register char **argv; 5481590Srgrimes{ 5491590Srgrimes 5501590Srgrimes if (argv[0] == NOSTR) { 5511590Srgrimes newfileinfo(); 5521590Srgrimes return 0; 5531590Srgrimes } 5541590Srgrimes if (setfile(*argv) < 0) 5551590Srgrimes return 1; 5561590Srgrimes announce(); 5571590Srgrimes return 0; 5581590Srgrimes} 5591590Srgrimes 5601590Srgrimes/* 5611590Srgrimes * Expand file names like echo 5621590Srgrimes */ 5631590Srgrimesint 5641590Srgrimesecho(argv) 5651590Srgrimes char **argv; 5661590Srgrimes{ 5671590Srgrimes register char **ap; 5681590Srgrimes register char *cp; 5691590Srgrimes 5701590Srgrimes for (ap = argv; *ap != NOSTR; ap++) { 5711590Srgrimes cp = *ap; 5721590Srgrimes if ((cp = expand(cp)) != NOSTR) { 5731590Srgrimes if (ap != argv) 5741590Srgrimes putchar(' '); 5751590Srgrimes printf("%s", cp); 5761590Srgrimes } 5771590Srgrimes } 5781590Srgrimes putchar('\n'); 5791590Srgrimes return 0; 5801590Srgrimes} 5811590Srgrimes 5821590Srgrimesint 5831590SrgrimesRespond(msgvec) 5841590Srgrimes int *msgvec; 5851590Srgrimes{ 5861590Srgrimes if (value("Replyall") == NOSTR) 58732189Sjoerg return (doRespond(msgvec)); 5881590Srgrimes else 58932189Sjoerg return (dorespond(msgvec)); 5901590Srgrimes} 5911590Srgrimes 5921590Srgrimes/* 5931590Srgrimes * Reply to a series of messages by simply mailing to the senders 5941590Srgrimes * and not messing around with the To: and Cc: lists as in normal 5951590Srgrimes * reply. 5961590Srgrimes */ 5971590Srgrimesint 59832189SjoergdoRespond(msgvec) 5991590Srgrimes int msgvec[]; 6001590Srgrimes{ 6011590Srgrimes struct header head; 6021590Srgrimes struct message *mp; 6031590Srgrimes register int *ap; 6041590Srgrimes register char *cp; 60532189Sjoerg char *mid; 6061590Srgrimes 6071590Srgrimes head.h_to = NIL; 6081590Srgrimes for (ap = msgvec; *ap != 0; ap++) { 6091590Srgrimes mp = &message[*ap - 1]; 6101590Srgrimes touch(mp); 6111590Srgrimes dot = mp; 6121590Srgrimes if ((cp = skin(hfield("from", mp))) == NOSTR) 6131590Srgrimes cp = skin(nameof(mp, 2)); 6141590Srgrimes head.h_to = cat(head.h_to, extract(cp, GTO)); 61532189Sjoerg mid = skin(hfield("message-id", mp)); 6161590Srgrimes } 6171590Srgrimes if (head.h_to == NIL) 6181590Srgrimes return 0; 6191590Srgrimes mp = &message[msgvec[0] - 1]; 6201590Srgrimes if ((head.h_subject = hfield("subject", mp)) == NOSTR) 6211590Srgrimes head.h_subject = hfield("subj", mp); 6221590Srgrimes head.h_subject = reedit(head.h_subject); 6231590Srgrimes head.h_cc = NIL; 6241590Srgrimes head.h_bcc = NIL; 6251590Srgrimes head.h_smopts = NIL; 62632189Sjoerg if ((head.h_replyto = getenv("REPLYTO")) == NULL) 62732189Sjoerg head.h_replyto = NOSTR; 62832189Sjoerg head.h_inreplyto = mid; 6291590Srgrimes mail1(&head, 1); 6301590Srgrimes return 0; 6311590Srgrimes} 6321590Srgrimes 6331590Srgrimes/* 6341590Srgrimes * Conditional commands. These allow one to parameterize one's 6351590Srgrimes * .mailrc and do some things if sending, others if receiving. 6361590Srgrimes */ 6371590Srgrimesint 6381590Srgrimesifcmd(argv) 6391590Srgrimes char **argv; 6401590Srgrimes{ 6411590Srgrimes register char *cp; 6421590Srgrimes 6431590Srgrimes if (cond != CANY) { 6441590Srgrimes printf("Illegal nested \"if\"\n"); 6451590Srgrimes return(1); 6461590Srgrimes } 6471590Srgrimes cond = CANY; 6481590Srgrimes cp = argv[0]; 6491590Srgrimes switch (*cp) { 6501590Srgrimes case 'r': case 'R': 6511590Srgrimes cond = CRCV; 6521590Srgrimes break; 6531590Srgrimes 6541590Srgrimes case 's': case 'S': 6551590Srgrimes cond = CSEND; 6561590Srgrimes break; 6571590Srgrimes 6581590Srgrimes default: 6591590Srgrimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 6601590Srgrimes return(1); 6611590Srgrimes } 6621590Srgrimes return(0); 6631590Srgrimes} 6641590Srgrimes 6651590Srgrimes/* 6661590Srgrimes * Implement 'else'. This is pretty simple -- we just 6671590Srgrimes * flip over the conditional flag. 6681590Srgrimes */ 6691590Srgrimesint 6701590Srgrimeselsecmd() 6711590Srgrimes{ 6721590Srgrimes 6731590Srgrimes switch (cond) { 6741590Srgrimes case CANY: 6751590Srgrimes printf("\"Else\" without matching \"if\"\n"); 6761590Srgrimes return(1); 6771590Srgrimes 6781590Srgrimes case CSEND: 6791590Srgrimes cond = CRCV; 6801590Srgrimes break; 6811590Srgrimes 6821590Srgrimes case CRCV: 6831590Srgrimes cond = CSEND; 6841590Srgrimes break; 6851590Srgrimes 6861590Srgrimes default: 6871590Srgrimes printf("Mail's idea of conditions is screwed up\n"); 6881590Srgrimes cond = CANY; 6891590Srgrimes break; 6901590Srgrimes } 6911590Srgrimes return(0); 6921590Srgrimes} 6931590Srgrimes 6941590Srgrimes/* 6951590Srgrimes * End of if statement. Just set cond back to anything. 6961590Srgrimes */ 6971590Srgrimesint 6981590Srgrimesendifcmd() 6991590Srgrimes{ 7001590Srgrimes 7011590Srgrimes if (cond == CANY) { 7021590Srgrimes printf("\"Endif\" without matching \"if\"\n"); 7031590Srgrimes return(1); 7041590Srgrimes } 7051590Srgrimes cond = CANY; 7061590Srgrimes return(0); 7071590Srgrimes} 7081590Srgrimes 7091590Srgrimes/* 7101590Srgrimes * Set the list of alternate names. 7111590Srgrimes */ 7121590Srgrimesint 7131590Srgrimesalternates(namelist) 7141590Srgrimes char **namelist; 7151590Srgrimes{ 7161590Srgrimes register int c; 7171590Srgrimes register char **ap, **ap2, *cp; 7181590Srgrimes 7191590Srgrimes c = argcount(namelist) + 1; 7201590Srgrimes if (c == 1) { 7211590Srgrimes if (altnames == 0) 7221590Srgrimes return(0); 7231590Srgrimes for (ap = altnames; *ap; ap++) 7241590Srgrimes printf("%s ", *ap); 7251590Srgrimes printf("\n"); 7261590Srgrimes return(0); 7271590Srgrimes } 7281590Srgrimes if (altnames != 0) 7291590Srgrimes free((char *) altnames); 7301590Srgrimes altnames = (char **) calloc((unsigned) c, sizeof (char *)); 7311590Srgrimes for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) { 7321590Srgrimes cp = (char *) calloc((unsigned) strlen(*ap) + 1, sizeof (char)); 7331590Srgrimes strcpy(cp, *ap); 7341590Srgrimes *ap2 = cp; 7351590Srgrimes } 7361590Srgrimes *ap2 = 0; 7371590Srgrimes return(0); 7381590Srgrimes} 739