1331722Seadler/* 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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3174769Smikeh#if 0 3288150Smikehstatic char sccsid[] = "@(#)cmd3.c 8.2 (Berkeley) 4/20/95"; 3374769Smikeh#endif 341590Srgrimes#endif /* not lint */ 3599112Sobrien#include <sys/cdefs.h> 3699112Sobrien__FBSDID("$FreeBSD: stable/11/usr.bin/mail/cmd3.c 336953 2018-07-31 00:37:25Z markj $"); 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 52216564Scharniershell(char *str) 531590Srgrimes{ 541590Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 5577274Smikeh char *sh; 561590Srgrimes char cmd[BUFSIZ]; 571590Srgrimes 5874769Smikeh if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd)) 5977274Smikeh return (1); 6074769Smikeh if (bangexp(cmd, sizeof(cmd)) < 0) 6177274Smikeh return (1); 6277274Smikeh if ((sh = value("SHELL")) == NULL) 6377274Smikeh sh = _PATH_CSHELL; 6477274Smikeh (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL); 6577274Smikeh (void)signal(SIGINT, sigint); 661590Srgrimes printf("!\n"); 6777274Smikeh return (0); 681590Srgrimes} 691590Srgrimes 701590Srgrimes/* 711590Srgrimes * Fork an interactive shell. 721590Srgrimes */ 731590Srgrimes/*ARGSUSED*/ 741590Srgrimesint 75216564Scharnierdosh(char *str __unused) 761590Srgrimes{ 771590Srgrimes sig_t sigint = signal(SIGINT, SIG_IGN); 7877274Smikeh char *sh; 791590Srgrimes 8077274Smikeh if ((sh = value("SHELL")) == NULL) 8177274Smikeh sh = _PATH_CSHELL; 82336953Smarkj (void)run_command(sh, 0, -1, -1, NULL, NULL, NULL); 8377274Smikeh (void)signal(SIGINT, sigint); 8477274Smikeh printf("\n"); 8577274Smikeh return (0); 861590Srgrimes} 871590Srgrimes 881590Srgrimes/* 891590Srgrimes * Expand the shell escape by expanding unescaped !'s into the 901590Srgrimes * last issued command where possible. 911590Srgrimes */ 921590Srgrimesint 93216564Scharnierbangexp(char *str, size_t strsize) 941590Srgrimes{ 951590Srgrimes char bangbuf[BUFSIZ]; 9674769Smikeh static char lastbang[BUFSIZ]; 9777274Smikeh char *cp, *cp2; 9877274Smikeh int n, changed = 0; 991590Srgrimes 1001590Srgrimes cp = str; 1011590Srgrimes cp2 = bangbuf; 10274769Smikeh n = sizeof(bangbuf); 10377274Smikeh while (*cp != '\0') { 1041590Srgrimes if (*cp == '!') { 105336953Smarkj if (n < strlen(lastbang)) { 1061590Srgrimesoverf: 1071590Srgrimes printf("Command buffer overflow\n"); 10877274Smikeh return (-1); 1091590Srgrimes } 1101590Srgrimes changed++; 11174769Smikeh if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf)) 11274769Smikeh >= sizeof(bangbuf) - (cp2 - bangbuf)) 11374769Smikeh goto overf; 1141590Srgrimes cp2 += strlen(lastbang); 1151590Srgrimes n -= strlen(lastbang); 1161590Srgrimes cp++; 1171590Srgrimes continue; 1181590Srgrimes } 1191590Srgrimes if (*cp == '\\' && cp[1] == '!') { 1201590Srgrimes if (--n <= 1) 1211590Srgrimes goto overf; 1221590Srgrimes *cp2++ = '!'; 1231590Srgrimes cp += 2; 1241590Srgrimes changed++; 1251590Srgrimes } 1261590Srgrimes if (--n <= 1) 1271590Srgrimes goto overf; 1281590Srgrimes *cp2++ = *cp++; 1291590Srgrimes } 1301590Srgrimes *cp2 = 0; 1311590Srgrimes if (changed) { 1321590Srgrimes printf("!%s\n", bangbuf); 13377274Smikeh (void)fflush(stdout); 1341590Srgrimes } 13574769Smikeh if (strlcpy(str, bangbuf, strsize) >= strsize) 13674769Smikeh goto overf; 13774769Smikeh if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang)) 13874769Smikeh goto overf; 13977274Smikeh return (0); 1401590Srgrimes} 1411590Srgrimes 1421590Srgrimes/* 1431590Srgrimes * Print out a nice help message from some file or another. 1441590Srgrimes */ 1451590Srgrimes 1461590Srgrimesint 147216564Scharnierhelp(void) 1481590Srgrimes{ 14977274Smikeh int c; 15077274Smikeh FILE *f; 1511590Srgrimes 1521590Srgrimes if ((f = Fopen(_PATH_HELP, "r")) == NULL) { 15374769Smikeh warn("%s", _PATH_HELP); 15477274Smikeh return (1); 1551590Srgrimes } 1561590Srgrimes while ((c = getc(f)) != EOF) 1571590Srgrimes putchar(c); 15877274Smikeh (void)Fclose(f); 15977274Smikeh return (0); 1601590Srgrimes} 1611590Srgrimes 1621590Srgrimes/* 1631590Srgrimes * Change user's working directory. 1641590Srgrimes */ 1651590Srgrimesint 166216564Scharnierschdir(char **arglist) 1671590Srgrimes{ 1681590Srgrimes char *cp; 1691590Srgrimes 17077274Smikeh if (*arglist == NULL) { 17177274Smikeh if (homedir == NULL) 17277274Smikeh return (1); 1731590Srgrimes cp = homedir; 17474769Smikeh } else 17577274Smikeh if ((cp = expand(*arglist)) == NULL) 17677274Smikeh return (1); 1771590Srgrimes if (chdir(cp) < 0) { 17874769Smikeh warn("%s", cp); 17977274Smikeh return (1); 1801590Srgrimes } 18177274Smikeh return (0); 1821590Srgrimes} 1831590Srgrimes 1841590Srgrimesint 185216564Scharnierrespond(int *msgvec) 1861590Srgrimes{ 18798805Smikeh if (value("Replyall") == NULL && value("flipr") == NULL) 18832189Sjoerg return (dorespond(msgvec)); 1891590Srgrimes else 19032189Sjoerg return (doRespond(msgvec)); 1911590Srgrimes} 1921590Srgrimes 1931590Srgrimes/* 1941590Srgrimes * Reply to a list of messages. Extract each name from the 1951590Srgrimes * message header and send them off to mail1() 1961590Srgrimes */ 1971590Srgrimesint 198216564Scharnierdorespond(int *msgvec) 1991590Srgrimes{ 2001590Srgrimes struct message *mp; 2011590Srgrimes char *cp, *rcv, *replyto; 2021590Srgrimes char **ap; 2031590Srgrimes struct name *np; 2041590Srgrimes struct header head; 2051590Srgrimes 2061590Srgrimes if (msgvec[1] != 0) { 2071590Srgrimes printf("Sorry, can't reply to multiple messages at once\n"); 20877274Smikeh return (1); 2091590Srgrimes } 2101590Srgrimes mp = &message[msgvec[0] - 1]; 2111590Srgrimes touch(mp); 2121590Srgrimes dot = mp; 21377274Smikeh if ((rcv = skin(hfield("from", mp))) == NULL) 2141590Srgrimes rcv = skin(nameof(mp, 1)); 21577274Smikeh if ((replyto = skin(hfield("reply-to", mp))) != NULL) 2161590Srgrimes np = extract(replyto, GTO); 21777274Smikeh else if ((cp = skin(hfield("to", mp))) != NULL) 2181590Srgrimes np = extract(cp, GTO); 2191590Srgrimes else 22077274Smikeh np = NULL; 2211590Srgrimes np = elide(np); 2221590Srgrimes /* 2231590Srgrimes * Delete my name from the reply list, 2241590Srgrimes * and with it, all my alternate names. 2251590Srgrimes */ 2261590Srgrimes np = delname(np, myname); 2271590Srgrimes if (altnames) 22877274Smikeh for (ap = altnames; *ap != NULL; ap++) 2291590Srgrimes np = delname(np, *ap); 23077274Smikeh if (np != NULL && replyto == NULL) 2311590Srgrimes np = cat(np, extract(rcv, GTO)); 23277274Smikeh else if (np == NULL) { 23377274Smikeh if (replyto != NULL) 2341590Srgrimes printf("Empty reply-to field -- replying to author\n"); 2351590Srgrimes np = extract(rcv, GTO); 2361590Srgrimes } 2371590Srgrimes head.h_to = np; 23877274Smikeh if ((head.h_subject = hfield("subject", mp)) == NULL) 2391590Srgrimes head.h_subject = hfield("subj", mp); 2401590Srgrimes head.h_subject = reedit(head.h_subject); 24177274Smikeh if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) { 2421590Srgrimes np = elide(extract(cp, GCC)); 2431590Srgrimes np = delname(np, myname); 2441590Srgrimes if (altnames != 0) 24577274Smikeh for (ap = altnames; *ap != NULL; ap++) 2461590Srgrimes np = delname(np, *ap); 2471590Srgrimes head.h_cc = np; 2481590Srgrimes } else 24977274Smikeh head.h_cc = NULL; 25077274Smikeh head.h_bcc = NULL; 25177274Smikeh head.h_smopts = NULL; 25278193Smikeh head.h_replyto = value("REPLYTO"); 25332189Sjoerg head.h_inreplyto = skin(hfield("message-id", mp)); 2541590Srgrimes mail1(&head, 1); 25577274Smikeh return (0); 2561590Srgrimes} 2571590Srgrimes 2581590Srgrimes/* 2591590Srgrimes * Modify the subject we are replying to to begin with Re: if 2601590Srgrimes * it does not already. 2611590Srgrimes */ 2621590Srgrimeschar * 263216564Scharnierreedit(char *subj) 2641590Srgrimes{ 2651590Srgrimes char *newsubj; 2661590Srgrimes 26777274Smikeh if (subj == NULL) 26877274Smikeh return (NULL); 2691590Srgrimes if ((subj[0] == 'r' || subj[0] == 'R') && 2701590Srgrimes (subj[1] == 'e' || subj[1] == 'E') && 2711590Srgrimes subj[2] == ':') 27277274Smikeh return (subj); 2731590Srgrimes newsubj = salloc(strlen(subj) + 5); 27474769Smikeh sprintf(newsubj, "Re: %s", subj); 27577274Smikeh return (newsubj); 2761590Srgrimes} 2771590Srgrimes 2781590Srgrimes/* 2791590Srgrimes * Preserve the named messages, so that they will be sent 2801590Srgrimes * back to the system mailbox. 2811590Srgrimes */ 2821590Srgrimesint 283216564Scharnierpreserve(int *msgvec) 2841590Srgrimes{ 28577274Smikeh int *ip, mesg; 28677274Smikeh struct message *mp; 2871590Srgrimes 2881590Srgrimes if (edit) { 2891590Srgrimes printf("Cannot \"preserve\" in edit mode\n"); 29077274Smikeh return (1); 2911590Srgrimes } 29229574Sphk for (ip = msgvec; *ip != 0; ip++) { 2931590Srgrimes mesg = *ip; 2941590Srgrimes mp = &message[mesg-1]; 2951590Srgrimes mp->m_flag |= MPRESERVE; 2961590Srgrimes mp->m_flag &= ~MBOX; 2971590Srgrimes dot = mp; 2981590Srgrimes } 29977274Smikeh return (0); 3001590Srgrimes} 3011590Srgrimes 3021590Srgrimes/* 3031590Srgrimes * Mark all given messages as unread. 3041590Srgrimes */ 3051590Srgrimesint 306216564Scharnierunread(int msgvec[]) 3071590Srgrimes{ 30877274Smikeh int *ip; 3091590Srgrimes 31029574Sphk for (ip = msgvec; *ip != 0; ip++) { 3111590Srgrimes dot = &message[*ip-1]; 3121590Srgrimes dot->m_flag &= ~(MREAD|MTOUCH); 3131590Srgrimes dot->m_flag |= MSTATUS; 3141590Srgrimes } 31577274Smikeh return (0); 3161590Srgrimes} 3171590Srgrimes 3181590Srgrimes/* 3191590Srgrimes * Print the size of each message. 3201590Srgrimes */ 3211590Srgrimesint 322216564Scharniermessize(int *msgvec) 3231590Srgrimes{ 32477274Smikeh struct message *mp; 32577274Smikeh int *ip, mesg; 3261590Srgrimes 32729574Sphk for (ip = msgvec; *ip != 0; ip++) { 3281590Srgrimes mesg = *ip; 3291590Srgrimes mp = &message[mesg-1]; 33037453Sbde printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size); 3311590Srgrimes } 33277274Smikeh return (0); 3331590Srgrimes} 3341590Srgrimes 3351590Srgrimes/* 3361590Srgrimes * Quit quickly. If we are sourcing, just pop the input level 3371590Srgrimes * by returning an error. 3381590Srgrimes */ 3391590Srgrimesint 340216564Scharnierrexit(int e __unused) 3411590Srgrimes{ 3421590Srgrimes if (sourcing) 34377274Smikeh return (1); 34488150Smikeh exit(0); 3451590Srgrimes /*NOTREACHED*/ 3461590Srgrimes} 3471590Srgrimes 3481590Srgrimes/* 3491590Srgrimes * Set or display a variable value. Syntax is similar to that 3501590Srgrimes * of csh. 3511590Srgrimes */ 3521590Srgrimesint 353216564Scharnierset(char **arglist) 3541590Srgrimes{ 35577274Smikeh struct var *vp; 35677274Smikeh char *cp, *cp2; 3571590Srgrimes char varbuf[BUFSIZ], **ap, **p; 3581590Srgrimes int errs, h, s; 3591590Srgrimes 36077274Smikeh if (*arglist == NULL) { 3611590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 36277274Smikeh for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3631590Srgrimes s++; 36477274Smikeh ap = (char **)salloc(s * sizeof(*ap)); 3651590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 36677274Smikeh for (vp = variables[h]; vp != NULL; vp = vp->v_link) 3671590Srgrimes *p++ = vp->v_name; 36877274Smikeh *p = NULL; 3691590Srgrimes sort(ap); 37077274Smikeh for (p = ap; *p != NULL; p++) 3711590Srgrimes printf("%s\t%s\n", *p, value(*p)); 37277274Smikeh return (0); 3731590Srgrimes } 3741590Srgrimes errs = 0; 37577274Smikeh for (ap = arglist; *ap != NULL; ap++) { 3761590Srgrimes cp = *ap; 3771590Srgrimes cp2 = varbuf; 37874769Smikeh while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0') 3791590Srgrimes *cp2++ = *cp++; 3801590Srgrimes *cp2 = '\0'; 3811590Srgrimes if (*cp == '\0') 3821590Srgrimes cp = ""; 3831590Srgrimes else 3841590Srgrimes cp++; 3851590Srgrimes if (equal(varbuf, "")) { 3861590Srgrimes printf("Non-null variable name required\n"); 3871590Srgrimes errs++; 3881590Srgrimes continue; 3891590Srgrimes } 3901590Srgrimes assign(varbuf, cp); 3911590Srgrimes } 39277274Smikeh return (errs); 3931590Srgrimes} 3941590Srgrimes 3951590Srgrimes/* 3961590Srgrimes * Unset a bunch of variable values. 3971590Srgrimes */ 3981590Srgrimesint 399216564Scharnierunset(char **arglist) 4001590Srgrimes{ 40177274Smikeh struct var *vp, *vp2; 4021590Srgrimes int errs, h; 4031590Srgrimes char **ap; 4041590Srgrimes 4051590Srgrimes errs = 0; 40677274Smikeh for (ap = arglist; *ap != NULL; ap++) { 40777274Smikeh if ((vp2 = lookup(*ap)) == NULL) { 40888150Smikeh if (getenv(*ap)) 40988150Smikeh unsetenv(*ap); 41088150Smikeh else if (!sourcing) { 4111590Srgrimes printf("\"%s\": undefined variable\n", *ap); 4121590Srgrimes errs++; 4131590Srgrimes } 4141590Srgrimes continue; 4151590Srgrimes } 4161590Srgrimes h = hash(*ap); 4171590Srgrimes if (vp2 == variables[h]) { 4181590Srgrimes variables[h] = variables[h]->v_link; 4191590Srgrimes vfree(vp2->v_name); 4201590Srgrimes vfree(vp2->v_value); 42177274Smikeh (void)free(vp2); 4221590Srgrimes continue; 4231590Srgrimes } 4241590Srgrimes for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) 4251590Srgrimes ; 4261590Srgrimes vp->v_link = vp2->v_link; 4271590Srgrimes vfree(vp2->v_name); 4281590Srgrimes vfree(vp2->v_value); 42977274Smikeh (void)free(vp2); 4301590Srgrimes } 43177274Smikeh return (errs); 4321590Srgrimes} 4331590Srgrimes 4341590Srgrimes/* 4351590Srgrimes * Put add users to a group. 4361590Srgrimes */ 4371590Srgrimesint 438216564Scharniergroup(char **argv) 4391590Srgrimes{ 44077274Smikeh struct grouphead *gh; 44177274Smikeh struct group *gp; 4421590Srgrimes char **ap, *gname, **p; 44377274Smikeh int h, s; 4441590Srgrimes 44577274Smikeh if (*argv == NULL) { 4461590Srgrimes for (h = 0, s = 1; h < HSHSIZE; h++) 44777274Smikeh for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4481590Srgrimes s++; 44977274Smikeh ap = (char **)salloc(s * sizeof(*ap)); 4501590Srgrimes for (h = 0, p = ap; h < HSHSIZE; h++) 45177274Smikeh for (gh = groups[h]; gh != NULL; gh = gh->g_link) 4521590Srgrimes *p++ = gh->g_name; 45377274Smikeh *p = NULL; 4541590Srgrimes sort(ap); 45577274Smikeh for (p = ap; *p != NULL; p++) 4561590Srgrimes printgroup(*p); 45777274Smikeh return (0); 4581590Srgrimes } 45977274Smikeh if (argv[1] == NULL) { 4601590Srgrimes printgroup(*argv); 46177274Smikeh return (0); 4621590Srgrimes } 4631590Srgrimes gname = *argv; 4641590Srgrimes h = hash(gname); 46577274Smikeh if ((gh = findgroup(gname)) == NULL) { 466302967Spfg if ((gh = calloc(1, sizeof(*gh))) == NULL) 467302967Spfg err(1, "Out of memory"); 4681590Srgrimes gh->g_name = vcopy(gname); 46977274Smikeh gh->g_list = NULL; 4701590Srgrimes gh->g_link = groups[h]; 4711590Srgrimes groups[h] = gh; 4721590Srgrimes } 4731590Srgrimes 4741590Srgrimes /* 4751590Srgrimes * Insert names from the command list into the group. 4761590Srgrimes * Who cares if there are duplicates? They get tossed 4771590Srgrimes * later anyway. 4781590Srgrimes */ 4791590Srgrimes 48077274Smikeh for (ap = argv+1; *ap != NULL; ap++) { 481302967Spfg if ((gp = calloc(1, sizeof(*gp))) == NULL) 482302967Spfg err(1, "Out of memory"); 4831590Srgrimes gp->ge_name = vcopy(*ap); 4841590Srgrimes gp->ge_link = gh->g_list; 4851590Srgrimes gh->g_list = gp; 4861590Srgrimes } 48777274Smikeh return (0); 4881590Srgrimes} 4891590Srgrimes 4901590Srgrimes/* 4911590Srgrimes * Sort the passed string vecotor into ascending dictionary 4921590Srgrimes * order. 4931590Srgrimes */ 4941590Srgrimesvoid 495216564Scharniersort(char **list) 4961590Srgrimes{ 49777274Smikeh char **ap; 4981590Srgrimes 49977274Smikeh for (ap = list; *ap != NULL; ap++) 5001590Srgrimes ; 5011590Srgrimes if (ap-list < 2) 5021590Srgrimes return; 5031590Srgrimes qsort(list, ap-list, sizeof(*list), diction); 5041590Srgrimes} 5051590Srgrimes 5061590Srgrimes/* 5071590Srgrimes * Do a dictionary order comparison of the arguments from 5081590Srgrimes * qsort. 5091590Srgrimes */ 5101590Srgrimesint 511216564Scharnierdiction(const void *a, const void *b) 5121590Srgrimes{ 51377274Smikeh return (strcmp(*(const char **)a, *(const char **)b)); 5141590Srgrimes} 5151590Srgrimes 5161590Srgrimes/* 5171590Srgrimes * The do nothing command for comments. 5181590Srgrimes */ 5191590Srgrimes 5201590Srgrimes/*ARGSUSED*/ 5211590Srgrimesint 522216564Scharniernull(int e __unused) 5231590Srgrimes{ 52477274Smikeh return (0); 5251590Srgrimes} 5261590Srgrimes 5271590Srgrimes/* 5281590Srgrimes * Change to another file. With no argument, print information about 5291590Srgrimes * the current file. 5301590Srgrimes */ 5311590Srgrimesint 532216564Scharnierfile(char **argv) 5331590Srgrimes{ 5341590Srgrimes 53577274Smikeh if (argv[0] == NULL) { 53688150Smikeh newfileinfo(0); 53777274Smikeh return (0); 5381590Srgrimes } 5391590Srgrimes if (setfile(*argv) < 0) 54077274Smikeh return (1); 5411590Srgrimes announce(); 54277274Smikeh return (0); 5431590Srgrimes} 5441590Srgrimes 5451590Srgrimes/* 5461590Srgrimes * Expand file names like echo 5471590Srgrimes */ 5481590Srgrimesint 549216564Scharnierecho(char **argv) 5501590Srgrimes{ 55177274Smikeh char **ap, *cp; 5521590Srgrimes 55377274Smikeh for (ap = argv; *ap != NULL; ap++) { 5541590Srgrimes cp = *ap; 55577274Smikeh if ((cp = expand(cp)) != NULL) { 5561590Srgrimes if (ap != argv) 55777274Smikeh printf(" "); 5581590Srgrimes printf("%s", cp); 5591590Srgrimes } 5601590Srgrimes } 56177274Smikeh printf("\n"); 56277274Smikeh return (0); 5631590Srgrimes} 5641590Srgrimes 5651590Srgrimesint 566216564ScharnierRespond(int *msgvec) 5671590Srgrimes{ 56898805Smikeh if (value("Replyall") == NULL && value("flipr") == NULL) 56932189Sjoerg return (doRespond(msgvec)); 5701590Srgrimes else 57132189Sjoerg return (dorespond(msgvec)); 5721590Srgrimes} 5731590Srgrimes 5741590Srgrimes/* 5751590Srgrimes * Reply to a series of messages by simply mailing to the senders 5761590Srgrimes * and not messing around with the To: and Cc: lists as in normal 5771590Srgrimes * reply. 5781590Srgrimes */ 5791590Srgrimesint 580216564ScharnierdoRespond(int msgvec[]) 5811590Srgrimes{ 5821590Srgrimes struct header head; 5831590Srgrimes struct message *mp; 58477274Smikeh int *ap; 58577274Smikeh char *cp, *mid; 5861590Srgrimes 58777274Smikeh head.h_to = NULL; 5881590Srgrimes for (ap = msgvec; *ap != 0; ap++) { 5891590Srgrimes mp = &message[*ap - 1]; 5901590Srgrimes touch(mp); 5911590Srgrimes dot = mp; 59277274Smikeh if ((cp = skin(hfield("from", mp))) == NULL) 5931590Srgrimes cp = skin(nameof(mp, 2)); 5941590Srgrimes head.h_to = cat(head.h_to, extract(cp, GTO)); 59532189Sjoerg mid = skin(hfield("message-id", mp)); 5961590Srgrimes } 59777274Smikeh if (head.h_to == NULL) 59877274Smikeh return (0); 5991590Srgrimes mp = &message[msgvec[0] - 1]; 60077274Smikeh if ((head.h_subject = hfield("subject", mp)) == NULL) 6011590Srgrimes head.h_subject = hfield("subj", mp); 6021590Srgrimes head.h_subject = reedit(head.h_subject); 60377274Smikeh head.h_cc = NULL; 60477274Smikeh head.h_bcc = NULL; 60577274Smikeh head.h_smopts = NULL; 60678193Smikeh head.h_replyto = value("REPLYTO"); 60732189Sjoerg head.h_inreplyto = mid; 6081590Srgrimes mail1(&head, 1); 60977274Smikeh return (0); 6101590Srgrimes} 6111590Srgrimes 6121590Srgrimes/* 6131590Srgrimes * Conditional commands. These allow one to parameterize one's 6141590Srgrimes * .mailrc and do some things if sending, others if receiving. 6151590Srgrimes */ 6161590Srgrimesint 617216564Scharnierifcmd(char **argv) 6181590Srgrimes{ 61977274Smikeh char *cp; 6201590Srgrimes 6211590Srgrimes if (cond != CANY) { 6221590Srgrimes printf("Illegal nested \"if\"\n"); 62377274Smikeh return (1); 6241590Srgrimes } 6251590Srgrimes cond = CANY; 6261590Srgrimes cp = argv[0]; 6271590Srgrimes switch (*cp) { 6281590Srgrimes case 'r': case 'R': 6291590Srgrimes cond = CRCV; 6301590Srgrimes break; 6311590Srgrimes 6321590Srgrimes case 's': case 'S': 6331590Srgrimes cond = CSEND; 6341590Srgrimes break; 6351590Srgrimes 6361590Srgrimes default: 6371590Srgrimes printf("Unrecognized if-keyword: \"%s\"\n", cp); 63877274Smikeh return (1); 6391590Srgrimes } 64077274Smikeh return (0); 6411590Srgrimes} 6421590Srgrimes 6431590Srgrimes/* 6441590Srgrimes * Implement 'else'. This is pretty simple -- we just 6451590Srgrimes * flip over the conditional flag. 6461590Srgrimes */ 6471590Srgrimesint 648216564Scharnierelsecmd(void) 6491590Srgrimes{ 6501590Srgrimes 6511590Srgrimes switch (cond) { 6521590Srgrimes case CANY: 6531590Srgrimes printf("\"Else\" without matching \"if\"\n"); 65477274Smikeh return (1); 6551590Srgrimes 6561590Srgrimes case CSEND: 6571590Srgrimes cond = CRCV; 6581590Srgrimes break; 6591590Srgrimes 6601590Srgrimes case CRCV: 6611590Srgrimes cond = CSEND; 6621590Srgrimes break; 6631590Srgrimes 6641590Srgrimes default: 6651590Srgrimes printf("Mail's idea of conditions is screwed up\n"); 6661590Srgrimes cond = CANY; 6671590Srgrimes break; 6681590Srgrimes } 66977274Smikeh return (0); 6701590Srgrimes} 6711590Srgrimes 6721590Srgrimes/* 6731590Srgrimes * End of if statement. Just set cond back to anything. 6741590Srgrimes */ 6751590Srgrimesint 676216564Scharnierendifcmd(void) 6771590Srgrimes{ 6781590Srgrimes 6791590Srgrimes if (cond == CANY) { 6801590Srgrimes printf("\"Endif\" without matching \"if\"\n"); 68177274Smikeh return (1); 6821590Srgrimes } 6831590Srgrimes cond = CANY; 68477274Smikeh return (0); 6851590Srgrimes} 6861590Srgrimes 6871590Srgrimes/* 6881590Srgrimes * Set the list of alternate names. 6891590Srgrimes */ 6901590Srgrimesint 691216564Scharnieralternates(char **namelist) 6921590Srgrimes{ 69377274Smikeh int c; 69477274Smikeh char **ap, **ap2, *cp; 6951590Srgrimes 6961590Srgrimes c = argcount(namelist) + 1; 6971590Srgrimes if (c == 1) { 6981590Srgrimes if (altnames == 0) 69977274Smikeh return (0); 70077274Smikeh for (ap = altnames; *ap != NULL; ap++) 7011590Srgrimes printf("%s ", *ap); 7021590Srgrimes printf("\n"); 70377274Smikeh return (0); 7041590Srgrimes } 7051590Srgrimes if (altnames != 0) 70677274Smikeh (void)free(altnames); 707302967Spfg if ((altnames = calloc((unsigned)c, sizeof(char *))) == NULL) 708302967Spfg err(1, "Out of memory"); 70977274Smikeh for (ap = namelist, ap2 = altnames; *ap != NULL; ap++, ap2++) { 71077274Smikeh cp = calloc((unsigned)strlen(*ap) + 1, sizeof(char)); 7111590Srgrimes strcpy(cp, *ap); 7121590Srgrimes *ap2 = cp; 7131590Srgrimes } 7141590Srgrimes *ap2 = 0; 71577274Smikeh return (0); 7161590Srgrimes} 717