10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
22*18Srobbin
23*18Srobbin /*
24*18Srobbin * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
25*18Srobbin * Use is subject to license terms.
26*18Srobbin */
27*18Srobbin
280Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
290Sstevel@tonic-gate /* All Rights Reserved */
300Sstevel@tonic-gate
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
330Sstevel@tonic-gate * The Regents of the University of California
340Sstevel@tonic-gate * All Rights Reserved
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
370Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
380Sstevel@tonic-gate * contributors.
390Sstevel@tonic-gate */
400Sstevel@tonic-gate
410Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include "rcv.h"
440Sstevel@tonic-gate #include <locale.h>
450Sstevel@tonic-gate
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley
480Sstevel@tonic-gate * mail program
490Sstevel@tonic-gate *
500Sstevel@tonic-gate * Still more user commands.
510Sstevel@tonic-gate */
520Sstevel@tonic-gate
530Sstevel@tonic-gate static int bangexp(char *str);
540Sstevel@tonic-gate static int diction(const void *a, const void *b);
550Sstevel@tonic-gate static char *getfilename(char *name, int *aedit);
560Sstevel@tonic-gate static int resp1(int *msgvec, int useauthor);
570Sstevel@tonic-gate static int Resp1(int *msgvec, int useauthor);
580Sstevel@tonic-gate static char *reedit(char *subj);
590Sstevel@tonic-gate static int shell1(char *str);
600Sstevel@tonic-gate static void sort(char **list);
610Sstevel@tonic-gate static char *replyto(struct message *mp, char **f);
620Sstevel@tonic-gate static int reply2sender(void);
630Sstevel@tonic-gate
640Sstevel@tonic-gate static char prevfile[PATHSIZE];
650Sstevel@tonic-gate static char origprevfile[PATHSIZE];
660Sstevel@tonic-gate static char lastbang[BUFSIZ];
670Sstevel@tonic-gate
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate * Process a shell escape by saving signals, ignoring signals,
700Sstevel@tonic-gate * and forking a sh -c
710Sstevel@tonic-gate */
720Sstevel@tonic-gate
730Sstevel@tonic-gate int
shell(char * str)740Sstevel@tonic-gate shell(char *str)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate shell1(str);
770Sstevel@tonic-gate printf("!\n");
780Sstevel@tonic-gate return(0);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
810Sstevel@tonic-gate static int
shell1(char * str)820Sstevel@tonic-gate shell1(char *str)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate void (*sig[2])(int);
850Sstevel@tonic-gate register int t;
860Sstevel@tonic-gate register pid_t p;
870Sstevel@tonic-gate char *Shell;
880Sstevel@tonic-gate char cmd[BUFSIZ];
890Sstevel@tonic-gate
900Sstevel@tonic-gate nstrcpy(cmd, sizeof (cmd), str);
910Sstevel@tonic-gate if (bangexp(cmd) < 0)
920Sstevel@tonic-gate return(-1);
930Sstevel@tonic-gate if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
940Sstevel@tonic-gate Shell = SHELL;
950Sstevel@tonic-gate for (t = SIGINT; t <= SIGQUIT; t++)
960Sstevel@tonic-gate sig[t-SIGINT] = sigset(t, SIG_IGN);
970Sstevel@tonic-gate p = vfork();
980Sstevel@tonic-gate if (p == 0) {
990Sstevel@tonic-gate setuid(getuid());
1000Sstevel@tonic-gate sigchild();
1010Sstevel@tonic-gate for (t = SIGINT; t <= SIGQUIT; t++)
1020Sstevel@tonic-gate if (sig[t-SIGINT] != SIG_IGN)
1030Sstevel@tonic-gate sigsys(t, SIG_DFL);
1040Sstevel@tonic-gate execlp(Shell, Shell, "-c", cmd, (char *)0);
1050Sstevel@tonic-gate perror(Shell);
1060Sstevel@tonic-gate _exit(1);
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate while (wait(0) != p)
1090Sstevel@tonic-gate ;
1100Sstevel@tonic-gate if (p == (pid_t)-1)
1110Sstevel@tonic-gate perror("fork");
1120Sstevel@tonic-gate for (t = SIGINT; t <= SIGQUIT; t++)
1130Sstevel@tonic-gate sigset(t, sig[t-SIGINT]);
1140Sstevel@tonic-gate return(0);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate * Fork an interactive shell.
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate int
1220Sstevel@tonic-gate #ifdef __cplusplus
dosh(char *)1230Sstevel@tonic-gate dosh(char *)
1240Sstevel@tonic-gate #else
1250Sstevel@tonic-gate /* ARGSUSED */
1260Sstevel@tonic-gate dosh(char *s)
1270Sstevel@tonic-gate #endif
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate void (*sig[2])(int);
1300Sstevel@tonic-gate register int t;
1310Sstevel@tonic-gate register pid_t p;
1320Sstevel@tonic-gate char *Shell;
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0')
1350Sstevel@tonic-gate Shell = SHELL;
1360Sstevel@tonic-gate for (t = SIGINT; t <= SIGQUIT; t++)
1370Sstevel@tonic-gate sig[t-SIGINT] = sigset(t, SIG_IGN);
1380Sstevel@tonic-gate p = vfork();
1390Sstevel@tonic-gate if (p == 0) {
1400Sstevel@tonic-gate setuid(getuid());
1410Sstevel@tonic-gate sigchild();
1420Sstevel@tonic-gate for (t = SIGINT; t <= SIGQUIT; t++)
1430Sstevel@tonic-gate if (sig[t-SIGINT] != SIG_IGN)
1440Sstevel@tonic-gate sigset(t, SIG_DFL);
1450Sstevel@tonic-gate execlp(Shell, Shell, (char *)0);
1460Sstevel@tonic-gate perror(Shell);
1470Sstevel@tonic-gate _exit(1);
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate while (wait(0) != p)
1500Sstevel@tonic-gate ;
1510Sstevel@tonic-gate if (p == (pid_t)-1)
1520Sstevel@tonic-gate perror("fork");
1530Sstevel@tonic-gate for (t = SIGINT; t <= SIGQUIT; t++)
1540Sstevel@tonic-gate sigset(t, sig[t-SIGINT]);
1550Sstevel@tonic-gate putchar('\n');
1560Sstevel@tonic-gate return(0);
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * Expand the shell escape by expanding unescaped !'s into the
1610Sstevel@tonic-gate * last issued command where possible.
1620Sstevel@tonic-gate */
1630Sstevel@tonic-gate static int
bangexp(char * str)1640Sstevel@tonic-gate bangexp(char *str)
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate char bangbuf[BUFSIZ];
1670Sstevel@tonic-gate register char *cp, *cp2;
1680Sstevel@tonic-gate register int n;
1690Sstevel@tonic-gate int changed = 0;
1700Sstevel@tonic-gate int bangit = (value("bang")!=NOSTR);
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate cp = str;
1730Sstevel@tonic-gate cp2 = bangbuf;
1740Sstevel@tonic-gate n = BUFSIZ;
1750Sstevel@tonic-gate while (*cp) {
1760Sstevel@tonic-gate if (*cp=='!' && bangit) {
1770Sstevel@tonic-gate if (n < (int)strlen(lastbang)) {
1780Sstevel@tonic-gate overf:
1790Sstevel@tonic-gate printf(gettext("Command buffer overflow\n"));
1800Sstevel@tonic-gate return(-1);
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate changed++;
1830Sstevel@tonic-gate strcpy(cp2, lastbang);
1840Sstevel@tonic-gate cp2 += strlen(lastbang);
1850Sstevel@tonic-gate n -= strlen(lastbang);
1860Sstevel@tonic-gate cp++;
1870Sstevel@tonic-gate continue;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate if (*cp == '\\' && cp[1] == '!') {
1900Sstevel@tonic-gate if (--n <= 1)
1910Sstevel@tonic-gate goto overf;
1920Sstevel@tonic-gate *cp2++ = '!';
1930Sstevel@tonic-gate cp += 2;
1940Sstevel@tonic-gate changed++;
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate if (--n <= 1)
1970Sstevel@tonic-gate goto overf;
1980Sstevel@tonic-gate *cp2++ = *cp++;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate *cp2 = 0;
2010Sstevel@tonic-gate if (changed) {
2020Sstevel@tonic-gate printf("!%s\n", bangbuf);
2030Sstevel@tonic-gate fflush(stdout);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate nstrcpy(str, BUFSIZ, bangbuf);
2060Sstevel@tonic-gate nstrcpy(lastbang, sizeof (lastbang), bangbuf);
2070Sstevel@tonic-gate return(0);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate * Print out a nice help message from some file or another.
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate int
help(void)2150Sstevel@tonic-gate help(void)
2160Sstevel@tonic-gate {
217*18Srobbin int c;
2180Sstevel@tonic-gate register FILE *f;
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate if ((f = fopen(HELPFILE, "r")) == NULL) {
2210Sstevel@tonic-gate printf(gettext("No help just now.\n"));
2220Sstevel@tonic-gate return(1);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate while ((c = getc(f)) != EOF)
2250Sstevel@tonic-gate putchar(c);
2260Sstevel@tonic-gate fclose(f);
2270Sstevel@tonic-gate return(0);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /*
2310Sstevel@tonic-gate * Change user's working directory.
2320Sstevel@tonic-gate */
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate int
schdir(char * str)2350Sstevel@tonic-gate schdir(char *str)
2360Sstevel@tonic-gate {
2370Sstevel@tonic-gate register char *cp;
2380Sstevel@tonic-gate char cwd[PATHSIZE], file[PATHSIZE];
2390Sstevel@tonic-gate static char efile[PATHSIZE];
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate for (cp = str; *cp == ' '; cp++)
2420Sstevel@tonic-gate ;
2430Sstevel@tonic-gate if (*cp == '\0')
2440Sstevel@tonic-gate cp = homedir;
2450Sstevel@tonic-gate else
2460Sstevel@tonic-gate if ((cp = expand(cp)) == NOSTR)
2470Sstevel@tonic-gate return(1);
2480Sstevel@tonic-gate if (editfile != NOSTR && (*editfile != '/' || mailname[0] != '/')) {
2490Sstevel@tonic-gate if (getcwd(cwd, (int)sizeof (cwd)) == 0) {
2500Sstevel@tonic-gate fprintf(stderr,
2510Sstevel@tonic-gate gettext("Can't get current directory: %s\n"), cwd);
2520Sstevel@tonic-gate return(1);
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate if (chdir(cp) < 0) {
2560Sstevel@tonic-gate perror(cp);
2570Sstevel@tonic-gate return(1);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate /*
2600Sstevel@tonic-gate * Convert previously relative names to absolute names.
2610Sstevel@tonic-gate */
2620Sstevel@tonic-gate if (editfile != NOSTR && *editfile != '/') {
2630Sstevel@tonic-gate snprintf(file, sizeof (file), "%s/%s", cwd, editfile);
2640Sstevel@tonic-gate nstrcpy(efile, sizeof (efile), file);
2650Sstevel@tonic-gate editfile = efile;
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate if (mailname[0] != '/') {
2680Sstevel@tonic-gate snprintf(file, sizeof (file), "%s/%s", cwd, mailname);
2690Sstevel@tonic-gate nstrcpy(mailname, PATHSIZE, file);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate return(0);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate /*
2750Sstevel@tonic-gate * Two versions of reply. Reply to all names in message or reply
2760Sstevel@tonic-gate * to only sender of message, depending on setting of "replyall".
2770Sstevel@tonic-gate */
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate int
respond(int * msgvec)2800Sstevel@tonic-gate respond(int *msgvec)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate if (reply2sender())
2830Sstevel@tonic-gate return(resp1(msgvec, 0));
2840Sstevel@tonic-gate else
2850Sstevel@tonic-gate return(Resp1(msgvec, 0));
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate int
followup(int * msgvec)2890Sstevel@tonic-gate followup(int *msgvec)
2900Sstevel@tonic-gate {
2910Sstevel@tonic-gate if (reply2sender())
2920Sstevel@tonic-gate return(resp1(msgvec, 1));
2930Sstevel@tonic-gate else
2940Sstevel@tonic-gate return(Resp1(msgvec, 1));
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate int
replyall(int * msgvec)2980Sstevel@tonic-gate replyall(int *msgvec)
2990Sstevel@tonic-gate {
3000Sstevel@tonic-gate return(resp1(msgvec, 0));
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate static int
resp1(int * msgvec,int useauthor)3040Sstevel@tonic-gate resp1(int *msgvec, int useauthor)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate struct message *mp;
3070Sstevel@tonic-gate char *cp, *buf, *rcv, *skin_rcv, *reply2, **ap, *returnaddr;
3080Sstevel@tonic-gate struct name *np;
3090Sstevel@tonic-gate struct header head;
3100Sstevel@tonic-gate char mylocalname[BUFSIZ], mydomname[BUFSIZ];
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate if (msgvec[1] != 0) {
3130Sstevel@tonic-gate printf(gettext(
3140Sstevel@tonic-gate "Sorry, can't reply to multiple messages at once\n"));
3150Sstevel@tonic-gate return(1);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate snprintf(mydomname, sizeof (mydomname), "%s@%s", myname, domain);
3180Sstevel@tonic-gate snprintf(mylocalname, sizeof (mylocalname), "%s@%s", myname, host);
3190Sstevel@tonic-gate returnaddr = value("returnaddr");
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate mp = &message[msgvec[0] - 1];
3220Sstevel@tonic-gate dot = mp;
3230Sstevel@tonic-gate reply2 = replyto(mp, &rcv);
3240Sstevel@tonic-gate cp = skin(hfield("to", mp, addto));
3250Sstevel@tonic-gate if (cp != NOSTR) {
3260Sstevel@tonic-gate buf = (char *)salloc(strlen(reply2) + strlen(cp) + 2);
3270Sstevel@tonic-gate strcpy(buf, reply2);
3280Sstevel@tonic-gate strcat(buf, " ");
3290Sstevel@tonic-gate strcat(buf, cp);
3300Sstevel@tonic-gate } else
3310Sstevel@tonic-gate buf = reply2;
3320Sstevel@tonic-gate np = elide(extract(buf, GTO));
3330Sstevel@tonic-gate #ifdef OPTIM
3340Sstevel@tonic-gate /* rcv = netrename(rcv); */
3350Sstevel@tonic-gate #endif /* OPTIM */
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate * Delete my name from the reply list,
3380Sstevel@tonic-gate * and with it, all my alternate names.
3390Sstevel@tonic-gate */
3400Sstevel@tonic-gate skin_rcv = skin(rcv);
3410Sstevel@tonic-gate mapf(np, skin_rcv);
3420Sstevel@tonic-gate np = delname(np, myname);
3430Sstevel@tonic-gate np = delname(np, mylocalname);
3440Sstevel@tonic-gate np = delname(np, mydomname);
3450Sstevel@tonic-gate if (returnaddr && *returnaddr)
3460Sstevel@tonic-gate np = delname(np, returnaddr);
3470Sstevel@tonic-gate if (altnames != 0)
3480Sstevel@tonic-gate for (ap = altnames; *ap; ap++)
3490Sstevel@tonic-gate np = delname(np, *ap);
3500Sstevel@tonic-gate head.h_seq = 1;
3510Sstevel@tonic-gate cp = detract(np, 0);
3520Sstevel@tonic-gate if (cp == NOSTR) {
3530Sstevel@tonic-gate if (reply2)
3540Sstevel@tonic-gate cp = unuucp(reply2);
3550Sstevel@tonic-gate else
3560Sstevel@tonic-gate cp = unuucp(rcv);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate head.h_to = cp;
3590Sstevel@tonic-gate head.h_subject = hfield("subject", mp, addone);
3600Sstevel@tonic-gate if (head.h_subject == NOSTR)
3610Sstevel@tonic-gate head.h_subject = hfield("subj", mp, addone);
3620Sstevel@tonic-gate head.h_subject = reedit(head.h_subject);
3630Sstevel@tonic-gate head.h_cc = NOSTR;
3640Sstevel@tonic-gate cp = skin(hfield("cc", mp, addto));
3650Sstevel@tonic-gate if (cp != NOSTR) {
3660Sstevel@tonic-gate np = elide(extract(cp, GCC));
3670Sstevel@tonic-gate mapf(np, skin_rcv);
3680Sstevel@tonic-gate np = delname(np, myname);
3690Sstevel@tonic-gate np = delname(np, mylocalname);
3700Sstevel@tonic-gate np = delname(np, mydomname);
3710Sstevel@tonic-gate if (returnaddr && *returnaddr)
3720Sstevel@tonic-gate np = delname(np, returnaddr);
3730Sstevel@tonic-gate np = delname(np, skin_rcv);
3740Sstevel@tonic-gate if (altnames != 0)
3750Sstevel@tonic-gate for (ap = altnames; *ap; ap++)
3760Sstevel@tonic-gate np = delname(np, *ap);
3770Sstevel@tonic-gate head.h_cc = detract(np, 0);
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate head.h_bcc = NOSTR;
3800Sstevel@tonic-gate head.h_defopt = NOSTR;
3810Sstevel@tonic-gate head.h_others = NOSTRPTR;
3820Sstevel@tonic-gate mail1(&head, useauthor, useauthor ? rcv : NOSTR);
3830Sstevel@tonic-gate return(0);
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate void
getrecf(char * buf,char * recfile,int useauthor,int sz_recfile)3870Sstevel@tonic-gate getrecf(char *buf, char *recfile, int useauthor, int sz_recfile)
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate register char *bp, *cp;
3900Sstevel@tonic-gate register char *recf = recfile;
3910Sstevel@tonic-gate register int folderize;
3920Sstevel@tonic-gate char fldr[BUFSIZ];
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate folderize = (value("outfolder")!=NOSTR && getfold(fldr) == 0);
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate if (useauthor) {
3970Sstevel@tonic-gate if (folderize)
3980Sstevel@tonic-gate *recf++ = '+';
3990Sstevel@tonic-gate if (debug) fprintf(stderr, "buf='%s'\n", buf);
4000Sstevel@tonic-gate for (bp=skin(buf), cp=recf; *bp && !any(*bp, ", "); bp++) {
4010Sstevel@tonic-gate if (*bp=='!')
4020Sstevel@tonic-gate cp = recf;
4030Sstevel@tonic-gate else
4040Sstevel@tonic-gate *cp++ = *bp;
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate if (cp >= &recfile[sz_recfile - 1]) {
4070Sstevel@tonic-gate printf(gettext("File name buffer overflow\n"));
4080Sstevel@tonic-gate break;
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate *cp = '\0';
4120Sstevel@tonic-gate if (cp==recf)
4130Sstevel@tonic-gate *recfile = '\0';
4140Sstevel@tonic-gate /* now strip off any Internet host names */
4150Sstevel@tonic-gate if ((cp = strchr(recf, '%')) == NOSTR)
4160Sstevel@tonic-gate cp = strchr(recf, '@');
4170Sstevel@tonic-gate if (cp != NOSTR)
4180Sstevel@tonic-gate *cp = '\0';
4190Sstevel@tonic-gate } else {
4200Sstevel@tonic-gate if (cp = value("record")) {
4210Sstevel@tonic-gate int sz = PATHSIZE;
4220Sstevel@tonic-gate if (folderize && *cp!='+' && *cp!='/'
4230Sstevel@tonic-gate && *safeexpand(cp)!='/') {
4240Sstevel@tonic-gate *recf++ = '+';
4250Sstevel@tonic-gate sz--;
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate nstrcpy(recf, sz, cp);
4280Sstevel@tonic-gate } else
4290Sstevel@tonic-gate *recf = '\0';
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate if (debug) fprintf(stderr, "recfile='%s'\n", recfile);
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate /*
4350Sstevel@tonic-gate * Modify the subject we are replying to to begin with Re: if
4360Sstevel@tonic-gate * it does not already.
4370Sstevel@tonic-gate */
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate static char *
reedit(char * subj)4400Sstevel@tonic-gate reedit(char *subj)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate char sbuf[10];
4430Sstevel@tonic-gate register char *newsubj;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate if (subj == NOSTR)
4460Sstevel@tonic-gate return(NOSTR);
4470Sstevel@tonic-gate strncpy(sbuf, subj, 3);
4480Sstevel@tonic-gate sbuf[3] = 0;
4490Sstevel@tonic-gate if (icequal(sbuf, "re:"))
4500Sstevel@tonic-gate return(subj);
4510Sstevel@tonic-gate newsubj = (char *)salloc((unsigned)(strlen(subj) + 5));
4520Sstevel@tonic-gate sprintf(newsubj, "Re: %s", subj);
4530Sstevel@tonic-gate return(newsubj);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate * Preserve the named messages, so that they will be sent
4580Sstevel@tonic-gate * back to the system mailbox.
4590Sstevel@tonic-gate */
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate int
preserve(int * msgvec)4620Sstevel@tonic-gate preserve(int *msgvec)
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate register struct message *mp;
4650Sstevel@tonic-gate register int *ip, mesg;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate if (edit) {
4680Sstevel@tonic-gate printf(gettext("Cannot \"preserve\" in edit mode\n"));
4690Sstevel@tonic-gate return(1);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate for (ip = msgvec; *ip != NULL; ip++) {
4720Sstevel@tonic-gate mesg = *ip;
4730Sstevel@tonic-gate mp = &message[mesg-1];
4740Sstevel@tonic-gate mp->m_flag |= MPRESERVE;
4750Sstevel@tonic-gate mp->m_flag &= ~MBOX;
4760Sstevel@tonic-gate dot = mp;
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate return(0);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate /*
4820Sstevel@tonic-gate * Mark all given messages as unread.
4830Sstevel@tonic-gate */
4840Sstevel@tonic-gate int
unread(int msgvec[])4850Sstevel@tonic-gate unread(int msgvec[])
4860Sstevel@tonic-gate {
4870Sstevel@tonic-gate register int *ip;
4880Sstevel@tonic-gate
4890Sstevel@tonic-gate for (ip = msgvec; *ip != NULL; ip++) {
4900Sstevel@tonic-gate dot = &message[*ip-1];
4910Sstevel@tonic-gate dot->m_flag &= ~(MREAD|MTOUCH);
4920Sstevel@tonic-gate dot->m_flag |= MSTATUS;
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate return(0);
4950Sstevel@tonic-gate }
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate /*
4980Sstevel@tonic-gate * Print the size of each message.
4990Sstevel@tonic-gate */
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate int
messize(int * msgvec)5020Sstevel@tonic-gate messize(int *msgvec)
5030Sstevel@tonic-gate {
5040Sstevel@tonic-gate register struct message *mp;
5050Sstevel@tonic-gate register int *ip, mesg;
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate for (ip = msgvec; *ip != NULL; ip++) {
5080Sstevel@tonic-gate mesg = *ip;
5090Sstevel@tonic-gate mp = &message[mesg-1];
5100Sstevel@tonic-gate dot = mp;
5110Sstevel@tonic-gate printf("%d: %ld\n", mesg, mp->m_size);
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate return(0);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate /*
5170Sstevel@tonic-gate * Quit quickly. If we are sourcing, just pop the input level
5180Sstevel@tonic-gate * by returning an error.
5190Sstevel@tonic-gate */
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate int
rexit(int e)5220Sstevel@tonic-gate rexit(int e)
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate if (sourcing)
5250Sstevel@tonic-gate return(1);
5260Sstevel@tonic-gate if (Tflag != NOSTR)
5270Sstevel@tonic-gate close(creat(Tflag, TEMPPERM));
5280Sstevel@tonic-gate if (!edit)
5290Sstevel@tonic-gate Verhogen();
5300Sstevel@tonic-gate exit(e ? e : rpterr);
5310Sstevel@tonic-gate /* NOTREACHED */
5320Sstevel@tonic-gate return (0); /* shut up lint and CC */
5330Sstevel@tonic-gate }
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate /*
5360Sstevel@tonic-gate * Set or display a variable value. Syntax is similar to that
5370Sstevel@tonic-gate * of csh.
5380Sstevel@tonic-gate */
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate int
set(char ** arglist)5410Sstevel@tonic-gate set(char **arglist)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate register struct var *vp;
5440Sstevel@tonic-gate register char *cp, *cp2;
5450Sstevel@tonic-gate char varbuf[BUFSIZ], **ap, **p;
5460Sstevel@tonic-gate int errs, h, s;
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate if (argcount(arglist) == 0) {
5490Sstevel@tonic-gate for (h = 0, s = 1; h < HSHSIZE; h++)
5500Sstevel@tonic-gate for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
5510Sstevel@tonic-gate s++;
5520Sstevel@tonic-gate ap = (char **) salloc(s * sizeof *ap);
5530Sstevel@tonic-gate for (h = 0, p = ap; h < HSHSIZE; h++)
5540Sstevel@tonic-gate for (vp = variables[h]; vp != NOVAR; vp = vp->v_link)
5550Sstevel@tonic-gate *p++ = vp->v_name;
5560Sstevel@tonic-gate *p = NOSTR;
5570Sstevel@tonic-gate sort(ap);
5580Sstevel@tonic-gate for (p = ap; *p != NOSTR; p++)
5590Sstevel@tonic-gate if (((cp = value(*p)) != 0) && *cp)
5600Sstevel@tonic-gate printf("%s=\"%s\"\n", *p, cp);
5610Sstevel@tonic-gate else
5620Sstevel@tonic-gate printf("%s\n", *p);
5630Sstevel@tonic-gate return(0);
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate errs = 0;
5660Sstevel@tonic-gate for (ap = arglist; *ap != NOSTR; ap++) {
5670Sstevel@tonic-gate cp = *ap;
5680Sstevel@tonic-gate cp2 = varbuf;
5690Sstevel@tonic-gate while (*cp != '=' && *cp != '\0')
5700Sstevel@tonic-gate *cp2++ = *cp++;
5710Sstevel@tonic-gate *cp2 = '\0';
5720Sstevel@tonic-gate if (*cp == '\0')
5730Sstevel@tonic-gate cp = "";
5740Sstevel@tonic-gate else
5750Sstevel@tonic-gate cp++;
5760Sstevel@tonic-gate if (equal(varbuf, "")) {
5770Sstevel@tonic-gate printf(gettext("Non-null variable name required\n"));
5780Sstevel@tonic-gate errs++;
5790Sstevel@tonic-gate continue;
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate assign(varbuf, cp);
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate return(errs);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate /*
5870Sstevel@tonic-gate * Unset a bunch of variable values.
5880Sstevel@tonic-gate */
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate int
unset(char ** arglist)5910Sstevel@tonic-gate unset(char **arglist)
5920Sstevel@tonic-gate {
5930Sstevel@tonic-gate register int errs;
5940Sstevel@tonic-gate register char **ap;
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate errs = 0;
5970Sstevel@tonic-gate for (ap = arglist; *ap != NOSTR; ap++)
5980Sstevel@tonic-gate errs += deassign(*ap);
5990Sstevel@tonic-gate return(errs);
6000Sstevel@tonic-gate }
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate /*
6030Sstevel@tonic-gate * Add users to a group.
6040Sstevel@tonic-gate */
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate int
group(char ** argv)6070Sstevel@tonic-gate group(char **argv)
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate register struct grouphead *gh;
6100Sstevel@tonic-gate register struct mgroup *gp;
6110Sstevel@tonic-gate register int h;
6120Sstevel@tonic-gate int s;
6130Sstevel@tonic-gate char **ap, *gname, **p;
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate if (argcount(argv) == 0) {
6160Sstevel@tonic-gate for (h = 0, s = 1; h < HSHSIZE; h++)
6170Sstevel@tonic-gate for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
6180Sstevel@tonic-gate s++;
6190Sstevel@tonic-gate ap = (char **) salloc(s * sizeof *ap);
6200Sstevel@tonic-gate for (h = 0, p = ap; h < HSHSIZE; h++)
6210Sstevel@tonic-gate for (gh = groups[h]; gh != NOGRP; gh = gh->g_link)
6220Sstevel@tonic-gate *p++ = gh->g_name;
6230Sstevel@tonic-gate *p = NOSTR;
6240Sstevel@tonic-gate sort(ap);
6250Sstevel@tonic-gate for (p = ap; *p != NOSTR; p++)
6260Sstevel@tonic-gate printgroup(*p);
6270Sstevel@tonic-gate return(0);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate if (argcount(argv) == 1) {
6300Sstevel@tonic-gate printgroup(*argv);
6310Sstevel@tonic-gate return(0);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate gname = *argv;
6340Sstevel@tonic-gate h = hash(gname);
6350Sstevel@tonic-gate if ((gh = findgroup(gname)) == NOGRP) {
6360Sstevel@tonic-gate if ((gh = (struct grouphead *)
6370Sstevel@tonic-gate calloc(sizeof (*gh), 1)) == NULL) {
6380Sstevel@tonic-gate panic("Failed to allocate memory for group");
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate gh->g_name = vcopy(gname);
6410Sstevel@tonic-gate gh->g_list = NOGE;
6420Sstevel@tonic-gate gh->g_link = groups[h];
6430Sstevel@tonic-gate groups[h] = gh;
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate /*
6470Sstevel@tonic-gate * Insert names from the command list into the group.
6480Sstevel@tonic-gate * Who cares if there are duplicates? They get tossed
6490Sstevel@tonic-gate * later anyway.
6500Sstevel@tonic-gate */
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate for (ap = argv+1; *ap != NOSTR; ap++) {
6530Sstevel@tonic-gate if ((gp = (struct mgroup *)
6540Sstevel@tonic-gate calloc(sizeof (*gp), 1)) == NULL) {
6550Sstevel@tonic-gate panic("Failed to allocate memory for group");
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate gp->ge_name = vcopy(*ap);
6580Sstevel@tonic-gate gp->ge_link = gh->g_list;
6590Sstevel@tonic-gate gh->g_list = gp;
6600Sstevel@tonic-gate }
6610Sstevel@tonic-gate return(0);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate /*
6650Sstevel@tonic-gate * Remove users from a group.
6660Sstevel@tonic-gate */
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate int
ungroup(char ** argv)6690Sstevel@tonic-gate ungroup(char **argv)
6700Sstevel@tonic-gate {
6710Sstevel@tonic-gate register struct grouphead *gh, **ghp;
6720Sstevel@tonic-gate register struct mgroup *gp, *gpnext;
6730Sstevel@tonic-gate register int h;
6740Sstevel@tonic-gate char **ap, *gname;
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate if (argcount(argv) == 0) {
6770Sstevel@tonic-gate printf("Must specify alias or group to remove\n");
6780Sstevel@tonic-gate return(1);
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate /*
6820Sstevel@tonic-gate * Remove names on the command list from the group list.
6830Sstevel@tonic-gate */
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate for (ap = argv; *ap != NOSTR; ap++) {
6860Sstevel@tonic-gate gname = *ap;
6870Sstevel@tonic-gate h = hash(gname);
6880Sstevel@tonic-gate for (ghp = &groups[h]; *ghp != NOGRP; ghp = &((*ghp)->g_link)) {
6890Sstevel@tonic-gate gh = *ghp;
6900Sstevel@tonic-gate if (equal(gh->g_name, gname)) {
6910Sstevel@tonic-gate /* remove from list */
6920Sstevel@tonic-gate *ghp = gh->g_link;
6930Sstevel@tonic-gate /* free each member of gorup */
6940Sstevel@tonic-gate for (gp = gh->g_list; gp != NOGE; gp = gpnext) {
6950Sstevel@tonic-gate gpnext = gp->ge_link;
6960Sstevel@tonic-gate vfree(gp->ge_name);
6970Sstevel@tonic-gate free(gp);
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate vfree(gh->g_name);
7000Sstevel@tonic-gate free(gh);
7010Sstevel@tonic-gate break;
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate }
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate return(0);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate /*
7090Sstevel@tonic-gate * Sort the passed string vecotor into ascending dictionary
7100Sstevel@tonic-gate * order.
7110Sstevel@tonic-gate */
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate static void
sort(char ** list)7140Sstevel@tonic-gate sort(char **list)
7150Sstevel@tonic-gate {
7160Sstevel@tonic-gate register char **ap;
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate for (ap = list; *ap != NOSTR; ap++)
7190Sstevel@tonic-gate ;
7200Sstevel@tonic-gate if (ap-list < 2)
7210Sstevel@tonic-gate return;
7220Sstevel@tonic-gate qsort((char *) list, (unsigned) (ap-list), sizeof *list, diction);
7230Sstevel@tonic-gate }
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate /*
7260Sstevel@tonic-gate * Do a dictionary order comparison of the arguments from
7270Sstevel@tonic-gate * qsort.
7280Sstevel@tonic-gate */
7290Sstevel@tonic-gate static int
diction(const void * a,const void * b)7300Sstevel@tonic-gate diction(const void *a, const void *b)
7310Sstevel@tonic-gate {
7320Sstevel@tonic-gate return(strcmp(*(char **)a, *(char **)b));
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate /*
7360Sstevel@tonic-gate * The do nothing command for comments.
7370Sstevel@tonic-gate */
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate int
7400Sstevel@tonic-gate #ifdef __cplusplus
null(char *)7410Sstevel@tonic-gate null(char *)
7420Sstevel@tonic-gate #else
7430Sstevel@tonic-gate /* ARGSUSED */
7440Sstevel@tonic-gate null(char *s)
7450Sstevel@tonic-gate #endif
7460Sstevel@tonic-gate {
7470Sstevel@tonic-gate return(0);
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate
7500Sstevel@tonic-gate /*
7510Sstevel@tonic-gate * Print out the current edit file, if we are editing.
7520Sstevel@tonic-gate * Otherwise, print the name of the person who's mail
7530Sstevel@tonic-gate * we are reading.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate int
file(char ** argv)7560Sstevel@tonic-gate file(char **argv)
7570Sstevel@tonic-gate {
7580Sstevel@tonic-gate register char *cp;
7590Sstevel@tonic-gate int editing, mdot;
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate if (argv[0] == NOSTR) {
7620Sstevel@tonic-gate mdot = newfileinfo(1);
7630Sstevel@tonic-gate dot = &message[mdot - 1];
7640Sstevel@tonic-gate return(0);
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate /*
7680Sstevel@tonic-gate * Acker's! Must switch to the new file.
7690Sstevel@tonic-gate * We use a funny interpretation --
7700Sstevel@tonic-gate * # -- gets the previous file
7710Sstevel@tonic-gate * % -- gets the invoker's post office box
7720Sstevel@tonic-gate * %user -- gets someone else's post office box
7730Sstevel@tonic-gate * & -- gets invoker's mbox file
7740Sstevel@tonic-gate * string -- reads the given file
7750Sstevel@tonic-gate */
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate cp = getfilename(argv[0], &editing);
7780Sstevel@tonic-gate if (cp == NOSTR)
7790Sstevel@tonic-gate return(-1);
7800Sstevel@tonic-gate if (setfile(cp, editing)) {
7810Sstevel@tonic-gate nstrcpy(origname, PATHSIZE, origprevfile);
7820Sstevel@tonic-gate return(-1);
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate mdot = newfileinfo(1);
7850Sstevel@tonic-gate dot = &message[mdot - 1];
7860Sstevel@tonic-gate return(0);
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate /*
7900Sstevel@tonic-gate * Evaluate the string given as a new mailbox name.
7910Sstevel@tonic-gate * Ultimately, we want this to support a number of meta characters.
7920Sstevel@tonic-gate * Possibly:
7930Sstevel@tonic-gate * % -- for my system mail box
7940Sstevel@tonic-gate * %user -- for user's system mail box
7950Sstevel@tonic-gate * # -- for previous file
7960Sstevel@tonic-gate * & -- get's invoker's mbox file
7970Sstevel@tonic-gate * file name -- for any other file
7980Sstevel@tonic-gate */
7990Sstevel@tonic-gate
8000Sstevel@tonic-gate static char *
getfilename(char * name,int * aedit)8010Sstevel@tonic-gate getfilename(char *name, int *aedit)
8020Sstevel@tonic-gate {
8030Sstevel@tonic-gate register char *cp;
8040Sstevel@tonic-gate char savename[BUFSIZ];
8050Sstevel@tonic-gate char oldmailname[BUFSIZ];
8060Sstevel@tonic-gate char tmp[BUFSIZ];
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate /*
8090Sstevel@tonic-gate * Assume we will be in "edit file" mode, until
8100Sstevel@tonic-gate * proven wrong.
8110Sstevel@tonic-gate */
8120Sstevel@tonic-gate *aedit = 1;
8130Sstevel@tonic-gate switch (*name) {
8140Sstevel@tonic-gate case '%':
8150Sstevel@tonic-gate *aedit = 0;
8160Sstevel@tonic-gate nstrcpy(prevfile, sizeof (prevfile), editfile);
8170Sstevel@tonic-gate nstrcpy(origprevfile, sizeof (origprevfile), origname);
8180Sstevel@tonic-gate if (name[1] != 0) {
8190Sstevel@tonic-gate nstrcpy(oldmailname, sizeof (oldmailname), mailname);
8200Sstevel@tonic-gate findmail(name+1);
8210Sstevel@tonic-gate cp = savestr(mailname);
8220Sstevel@tonic-gate nstrcpy(origname, PATHSIZE, cp);
8230Sstevel@tonic-gate nstrcpy(mailname, PATHSIZE, oldmailname);
8240Sstevel@tonic-gate return(cp);
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate nstrcpy(oldmailname, sizeof (oldmailname), mailname);
8270Sstevel@tonic-gate findmail(NULL);
8280Sstevel@tonic-gate cp = savestr(mailname);
8290Sstevel@tonic-gate nstrcpy(mailname, PATHSIZE, oldmailname);
8300Sstevel@tonic-gate nstrcpy(origname, PATHSIZE, cp);
8310Sstevel@tonic-gate return(cp);
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate case '#':
8340Sstevel@tonic-gate if (name[1] != 0)
8350Sstevel@tonic-gate goto regular;
8360Sstevel@tonic-gate if (prevfile[0] == 0) {
8370Sstevel@tonic-gate printf(gettext("No previous file\n"));
8380Sstevel@tonic-gate return(NOSTR);
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate cp = savestr(prevfile);
8410Sstevel@tonic-gate nstrcpy(prevfile, sizeof (prevfile), editfile);
8420Sstevel@tonic-gate nstrcpy(tmp, sizeof (tmp), origname);
8430Sstevel@tonic-gate nstrcpy(origname, PATHSIZE, origprevfile);
8440Sstevel@tonic-gate nstrcpy(origprevfile, sizeof (origprevfile), tmp);
8450Sstevel@tonic-gate return(cp);
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate case '&':
8480Sstevel@tonic-gate nstrcpy(prevfile, sizeof (prevfile), editfile);
8490Sstevel@tonic-gate nstrcpy(origprevfile, sizeof (origprevfile), origname);
8500Sstevel@tonic-gate if (name[1] == 0) {
8510Sstevel@tonic-gate cp=Getf("MBOX");
8520Sstevel@tonic-gate nstrcpy(origname, PATHSIZE, cp);
8530Sstevel@tonic-gate return(cp);
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate /* Fall into . . . */
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate default:
8580Sstevel@tonic-gate regular:
8590Sstevel@tonic-gate nstrcpy(prevfile, sizeof (prevfile), editfile);
8600Sstevel@tonic-gate nstrcpy(origprevfile, sizeof (origprevfile), origname);
8610Sstevel@tonic-gate cp = safeexpand(name);
8620Sstevel@tonic-gate nstrcpy(origname, PATHSIZE, cp);
8630Sstevel@tonic-gate if (cp[0] != '/') {
8640Sstevel@tonic-gate name = getcwd(NOSTR, PATHSIZE);
8650Sstevel@tonic-gate nstrcat(name, PATHSIZE, "/");
8660Sstevel@tonic-gate nstrcat(name, PATHSIZE, cp);
8670Sstevel@tonic-gate cp = name;
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate return(cp);
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate /*
8740Sstevel@tonic-gate * Expand file names like echo
8750Sstevel@tonic-gate */
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate int
echo(register char ** argv)8780Sstevel@tonic-gate echo(register char **argv)
8790Sstevel@tonic-gate {
8800Sstevel@tonic-gate register char *cp;
8810Sstevel@tonic-gate int neednl = 0;
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate while (*argv != NOSTR) {
8840Sstevel@tonic-gate cp = *argv++;
8850Sstevel@tonic-gate if ((cp = expand(cp)) != NOSTR) {
8860Sstevel@tonic-gate neednl++;
8870Sstevel@tonic-gate printf("%s", cp);
8880Sstevel@tonic-gate if (*argv!=NOSTR)
8890Sstevel@tonic-gate putchar(' ');
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate }
8920Sstevel@tonic-gate if (neednl)
8930Sstevel@tonic-gate putchar('\n');
8940Sstevel@tonic-gate return(0);
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate /*
8980Sstevel@tonic-gate * Reply to a series of messages by simply mailing to the senders
8990Sstevel@tonic-gate * and not messing around with the To: and Cc: lists as in normal
9000Sstevel@tonic-gate * reply.
9010Sstevel@tonic-gate */
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate int
Respond(int * msgvec)9040Sstevel@tonic-gate Respond(int *msgvec)
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate if (reply2sender())
9070Sstevel@tonic-gate return(Resp1(msgvec, 0));
9080Sstevel@tonic-gate else
9090Sstevel@tonic-gate return(resp1(msgvec, 0));
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate int
Followup(int * msgvec)9130Sstevel@tonic-gate Followup(int *msgvec)
9140Sstevel@tonic-gate {
9150Sstevel@tonic-gate if (reply2sender())
9160Sstevel@tonic-gate return(Resp1(msgvec, 1));
9170Sstevel@tonic-gate else
9180Sstevel@tonic-gate return(resp1(msgvec, 1));
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate int
replysender(int * msgvec)9220Sstevel@tonic-gate replysender(int *msgvec)
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate return(Resp1(msgvec, 0));
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate static int
Resp1(int * msgvec,int useauthor)9280Sstevel@tonic-gate Resp1(int *msgvec, int useauthor)
9290Sstevel@tonic-gate {
9300Sstevel@tonic-gate struct header head;
9310Sstevel@tonic-gate struct message *mp;
9320Sstevel@tonic-gate register int s, *ap;
9330Sstevel@tonic-gate register char *cp, *cp2, *subject;
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate for (s = 0, ap = msgvec; *ap != 0; ap++) {
9360Sstevel@tonic-gate mp = &message[*ap - 1];
9370Sstevel@tonic-gate dot = mp;
9380Sstevel@tonic-gate cp = replyto(mp, NOSTRPTR);
9390Sstevel@tonic-gate s += strlen(cp) + 1;
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate if (s == 0)
9420Sstevel@tonic-gate return(0);
9430Sstevel@tonic-gate cp = (char *)salloc(s + 2);
9440Sstevel@tonic-gate head.h_to = cp;
9450Sstevel@tonic-gate for (ap = msgvec; *ap != 0; ap++) {
9460Sstevel@tonic-gate mp = &message[*ap - 1];
9470Sstevel@tonic-gate cp2 = replyto(mp, NOSTRPTR);
9480Sstevel@tonic-gate cp = copy(cp2, cp);
9490Sstevel@tonic-gate *cp++ = ' ';
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate *--cp = 0;
9520Sstevel@tonic-gate mp = &message[msgvec[0] - 1];
9530Sstevel@tonic-gate subject = hfield("subject", mp, addone);
9540Sstevel@tonic-gate head.h_seq = 1;
9550Sstevel@tonic-gate if (subject == NOSTR)
9560Sstevel@tonic-gate subject = hfield("subj", mp, addone);
9570Sstevel@tonic-gate head.h_subject = reedit(subject);
9580Sstevel@tonic-gate if (subject != NOSTR)
9590Sstevel@tonic-gate head.h_seq++;
9600Sstevel@tonic-gate head.h_cc = NOSTR;
9610Sstevel@tonic-gate head.h_bcc = NOSTR;
9620Sstevel@tonic-gate head.h_defopt = NOSTR;
9630Sstevel@tonic-gate head.h_others = NOSTRPTR;
9640Sstevel@tonic-gate mail1(&head, useauthor, NOSTR);
9650Sstevel@tonic-gate return(0);
9660Sstevel@tonic-gate }
9670Sstevel@tonic-gate
9680Sstevel@tonic-gate /*
9690Sstevel@tonic-gate * Conditional commands. These allow one to parameterize one's
9700Sstevel@tonic-gate * .mailrc and do some things if sending, others if receiving.
9710Sstevel@tonic-gate */
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate int
ifcmd(char ** argv)9740Sstevel@tonic-gate ifcmd(char **argv)
9750Sstevel@tonic-gate {
9760Sstevel@tonic-gate register char *cp;
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate if (cond != CANY) {
9790Sstevel@tonic-gate printf(gettext("Illegal nested \"if\"\n"));
9800Sstevel@tonic-gate return(1);
9810Sstevel@tonic-gate }
9820Sstevel@tonic-gate cond = CANY;
9830Sstevel@tonic-gate cp = argv[0];
9840Sstevel@tonic-gate switch (*cp) {
9850Sstevel@tonic-gate case 'r': case 'R':
9860Sstevel@tonic-gate cond = CRCV;
9870Sstevel@tonic-gate break;
9880Sstevel@tonic-gate
9890Sstevel@tonic-gate case 's': case 'S':
9900Sstevel@tonic-gate cond = CSEND;
9910Sstevel@tonic-gate break;
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate case 't': case 'T':
9940Sstevel@tonic-gate cond = CTTY;
9950Sstevel@tonic-gate break;
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate default:
9980Sstevel@tonic-gate printf(gettext("Unrecognized if-keyword: \"%s\"\n"), cp);
9990Sstevel@tonic-gate return(1);
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate return(0);
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate /*
10050Sstevel@tonic-gate * Implement 'else'. This is pretty simple -- we just
10060Sstevel@tonic-gate * flip over the conditional flag.
10070Sstevel@tonic-gate */
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate int
elsecmd(void)10100Sstevel@tonic-gate elsecmd(void)
10110Sstevel@tonic-gate {
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate switch (cond) {
10140Sstevel@tonic-gate case CANY:
10150Sstevel@tonic-gate printf(gettext("\"Else\" without matching \"if\"\n"));
10160Sstevel@tonic-gate return(1);
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate case CSEND:
10190Sstevel@tonic-gate cond = CRCV;
10200Sstevel@tonic-gate break;
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate case CRCV:
10230Sstevel@tonic-gate cond = CSEND;
10240Sstevel@tonic-gate break;
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate case CTTY:
10270Sstevel@tonic-gate cond = CNOTTY;
10280Sstevel@tonic-gate break;
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate case CNOTTY:
10310Sstevel@tonic-gate cond = CTTY;
10320Sstevel@tonic-gate break;
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate default:
10350Sstevel@tonic-gate printf(gettext("invalid condition encountered\n"));
10360Sstevel@tonic-gate cond = CANY;
10370Sstevel@tonic-gate break;
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate return(0);
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate /*
10430Sstevel@tonic-gate * End of if statement. Just set cond back to anything.
10440Sstevel@tonic-gate */
10450Sstevel@tonic-gate
10460Sstevel@tonic-gate int
endifcmd(void)10470Sstevel@tonic-gate endifcmd(void)
10480Sstevel@tonic-gate {
10490Sstevel@tonic-gate
10500Sstevel@tonic-gate if (cond == CANY) {
10510Sstevel@tonic-gate printf(gettext("\"Endif\" without matching \"if\"\n"));
10520Sstevel@tonic-gate return(1);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate cond = CANY;
10550Sstevel@tonic-gate return(0);
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate
10580Sstevel@tonic-gate /*
10590Sstevel@tonic-gate * Set the list of alternate names.
10600Sstevel@tonic-gate */
10610Sstevel@tonic-gate int
alternates(char ** namelist)10620Sstevel@tonic-gate alternates(char **namelist)
10630Sstevel@tonic-gate {
10640Sstevel@tonic-gate register int c;
10650Sstevel@tonic-gate register char **ap, **ap2, *cp;
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate c = argcount(namelist) + 1;
10680Sstevel@tonic-gate if (c == 1) {
10690Sstevel@tonic-gate if (altnames == 0)
10700Sstevel@tonic-gate return(0);
10710Sstevel@tonic-gate for (ap = altnames; *ap; ap++)
10720Sstevel@tonic-gate printf("%s ", *ap);
10730Sstevel@tonic-gate printf("\n");
10740Sstevel@tonic-gate return (0);
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate if (altnames != 0)
10770Sstevel@tonic-gate free((char *)altnames);
10780Sstevel@tonic-gate if ((altnames = (char **)
10790Sstevel@tonic-gate calloc((unsigned)c, sizeof (char *))) == NULL)
10800Sstevel@tonic-gate panic("Failed to allocate memory");
10810Sstevel@tonic-gate for (ap = namelist, ap2 = altnames; *ap; ap++, ap2++) {
10820Sstevel@tonic-gate if ((cp = (char *)
10830Sstevel@tonic-gate calloc((unsigned)strlen(*ap) + 1, sizeof (char))) == NULL)
10840Sstevel@tonic-gate panic("Failed to allocate memory");
10850Sstevel@tonic-gate strcpy(cp, *ap);
10860Sstevel@tonic-gate *ap2 = cp;
10870Sstevel@tonic-gate }
10880Sstevel@tonic-gate *ap2 = 0;
10890Sstevel@tonic-gate return(0);
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate /*
10930Sstevel@tonic-gate * Figure out who to reply to.
10940Sstevel@tonic-gate * Return the real sender in *f.
10950Sstevel@tonic-gate */
10960Sstevel@tonic-gate static char *
replyto(struct message * mp,char ** f)10970Sstevel@tonic-gate replyto(struct message *mp, char **f)
10980Sstevel@tonic-gate {
10990Sstevel@tonic-gate char *r, *rf;
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate if ((rf = skin(hfield("from", mp, addto)))==NOSTR)
11020Sstevel@tonic-gate rf = skin(addto(NOSTR, nameof(mp)));
11030Sstevel@tonic-gate if ((r = skin(hfield("reply-to", mp, addto)))==NOSTR)
11040Sstevel@tonic-gate r = rf;
11050Sstevel@tonic-gate if (f)
11060Sstevel@tonic-gate *f = rf;
11070Sstevel@tonic-gate return (r);
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate /*
11110Sstevel@tonic-gate * reply2sender - determine whether a "reply" command should reply to the
11120Sstevel@tonic-gate * sender of the messages, or to all the recipients of the
11130Sstevel@tonic-gate * message.
11140Sstevel@tonic-gate *
11150Sstevel@tonic-gate * With the advent of POSIX.2 compliance, this has become
11160Sstevel@tonic-gate * a bit more complicated, and so should be done in one
11170Sstevel@tonic-gate * place, for all to use.
11180Sstevel@tonic-gate */
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate static int
reply2sender(void)11210Sstevel@tonic-gate reply2sender (void)
11220Sstevel@tonic-gate {
11230Sstevel@tonic-gate register int rep = (value("replyall") != NOSTR);
11240Sstevel@tonic-gate register int flp = (value("flipr") != NOSTR);
11250Sstevel@tonic-gate
11260Sstevel@tonic-gate return((rep && !flp)|| (!rep && flp));
11270Sstevel@tonic-gate }
1128