1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 33*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 34*7c478bd9Sstevel@tonic-gate * All Rights Reserved 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 37*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 38*7c478bd9Sstevel@tonic-gate * contributors. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include "rcv.h" 44*7c478bd9Sstevel@tonic-gate #include <locale.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* 47*7c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 48*7c478bd9Sstevel@tonic-gate * mail program 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * Lexical processing of commands. 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 54*7c478bd9Sstevel@tonic-gate static void contin(int); 55*7c478bd9Sstevel@tonic-gate #endif 56*7c478bd9Sstevel@tonic-gate static int isprefix(char *as1, char *as2); 57*7c478bd9Sstevel@tonic-gate static const struct cmd *lex(char word[]); 58*7c478bd9Sstevel@tonic-gate static int Passeren(void); 59*7c478bd9Sstevel@tonic-gate static void setmsize(int sz); 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* 62*7c478bd9Sstevel@tonic-gate * Set up editing on the given file name. 63*7c478bd9Sstevel@tonic-gate * If isedit is true, we are considered to be editing the file, 64*7c478bd9Sstevel@tonic-gate * otherwise we are reading our mail which has signficance for 65*7c478bd9Sstevel@tonic-gate * mbox and so forth. 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate int 69*7c478bd9Sstevel@tonic-gate setfile(char *name, int isedit) 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate FILE *ibuf; 72*7c478bd9Sstevel@tonic-gate int i; 73*7c478bd9Sstevel@tonic-gate static int shudclob; 74*7c478bd9Sstevel@tonic-gate static char efile[PATHSIZE]; 75*7c478bd9Sstevel@tonic-gate char fortest[128]; 76*7c478bd9Sstevel@tonic-gate struct stat stbuf; 77*7c478bd9Sstevel@tonic-gate int exrc = 1; 78*7c478bd9Sstevel@tonic-gate int rc = -1; 79*7c478bd9Sstevel@tonic-gate int fd = -1; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate if (!isedit && issysmbox) 82*7c478bd9Sstevel@tonic-gate lockmail(); 83*7c478bd9Sstevel@tonic-gate if (stat(name, &stbuf) < 0 && errno == EOVERFLOW) { 84*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("mailbox %s is too large to" 85*7c478bd9Sstevel@tonic-gate " accept incoming mail\n"), name); 86*7c478bd9Sstevel@tonic-gate goto doret; 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate if ((ibuf = fopen(name, "r")) == NULL) { 89*7c478bd9Sstevel@tonic-gate extern int errno; 90*7c478bd9Sstevel@tonic-gate int sverrno = errno; 91*7c478bd9Sstevel@tonic-gate int filethere = (access(name,0) == 0); 92*7c478bd9Sstevel@tonic-gate errno = sverrno; 93*7c478bd9Sstevel@tonic-gate if (exitflg) 94*7c478bd9Sstevel@tonic-gate goto doexit; /* no mail, return error */ 95*7c478bd9Sstevel@tonic-gate if (isedit || filethere) 96*7c478bd9Sstevel@tonic-gate perror(name); 97*7c478bd9Sstevel@tonic-gate else if (!Hflag) { 98*7c478bd9Sstevel@tonic-gate char *f = strrchr(name,'/'); 99*7c478bd9Sstevel@tonic-gate if (f == NOSTR) 100*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail.\n")); 101*7c478bd9Sstevel@tonic-gate else 102*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail for %s\n"), 103*7c478bd9Sstevel@tonic-gate f+1); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate goto doret; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate fstat(fileno(ibuf), &stbuf); 108*7c478bd9Sstevel@tonic-gate if (stbuf.st_size == 0L || (stbuf.st_mode&S_IFMT) != S_IFREG) { 109*7c478bd9Sstevel@tonic-gate if (exitflg) 110*7c478bd9Sstevel@tonic-gate goto doexit; /* no mail, return error */ 111*7c478bd9Sstevel@tonic-gate if (isedit) 112*7c478bd9Sstevel@tonic-gate if (stbuf.st_size == 0L) 113*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: empty file\n"), 114*7c478bd9Sstevel@tonic-gate name); 115*7c478bd9Sstevel@tonic-gate else 116*7c478bd9Sstevel@tonic-gate fprintf(stderr, 117*7c478bd9Sstevel@tonic-gate gettext("%s: not a regular file\n"), name); 118*7c478bd9Sstevel@tonic-gate else if (!Hflag) { 119*7c478bd9Sstevel@tonic-gate if (strrchr(name,'/') == NOSTR) 120*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail.\n")); 121*7c478bd9Sstevel@tonic-gate else 122*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail for %s\n"), 123*7c478bd9Sstevel@tonic-gate strrchr(name, '/') + 1); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate fclose(ibuf); 126*7c478bd9Sstevel@tonic-gate goto doret; 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate fgets(fortest, sizeof fortest, ibuf); 130*7c478bd9Sstevel@tonic-gate fseek(ibuf, (long)(BUFSIZ+1), 0); /* flush input buffer */ 131*7c478bd9Sstevel@tonic-gate fseek(ibuf, 0L, 0); 132*7c478bd9Sstevel@tonic-gate if (strncmp(fortest, "Forward to ", 11) == 0) { 133*7c478bd9Sstevel@tonic-gate if (exitflg) 134*7c478bd9Sstevel@tonic-gate goto doexit; /* no mail, return error */ 135*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Your mail is being forwarded to %s"), 136*7c478bd9Sstevel@tonic-gate fortest+11); 137*7c478bd9Sstevel@tonic-gate fclose(ibuf); 138*7c478bd9Sstevel@tonic-gate goto doret; 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate if (exitflg) { 141*7c478bd9Sstevel@tonic-gate exrc = 0; 142*7c478bd9Sstevel@tonic-gate goto doexit; /* there is mail, return success */ 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * Looks like all will be well. Must hold signals 147*7c478bd9Sstevel@tonic-gate * while we are reading the new file, else we will ruin 148*7c478bd9Sstevel@tonic-gate * the message[] data structure. 149*7c478bd9Sstevel@tonic-gate * Copy the messages into /tmp and set pointers. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate holdsigs(); 153*7c478bd9Sstevel@tonic-gate if (shudclob) { 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate * Now that we know we can switch to the new file 156*7c478bd9Sstevel@tonic-gate * it's safe to close out the current file. 157*7c478bd9Sstevel@tonic-gate * 158*7c478bd9Sstevel@tonic-gate * If we're switching to the file we are currently 159*7c478bd9Sstevel@tonic-gate * editing, don't allow it to be removed as a side 160*7c478bd9Sstevel@tonic-gate * effect of closing it out. 161*7c478bd9Sstevel@tonic-gate */ 162*7c478bd9Sstevel@tonic-gate if (edit) 163*7c478bd9Sstevel@tonic-gate edstop(strcmp(editfile, name) == 0); 164*7c478bd9Sstevel@tonic-gate else { 165*7c478bd9Sstevel@tonic-gate quit(strcmp(editfile, name) == 0); 166*7c478bd9Sstevel@tonic-gate if (issysmbox) 167*7c478bd9Sstevel@tonic-gate Verhogen(); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate fflush(stdout); 170*7c478bd9Sstevel@tonic-gate fclose(itf); 171*7c478bd9Sstevel@tonic-gate fclose(otf); 172*7c478bd9Sstevel@tonic-gate free(message); 173*7c478bd9Sstevel@tonic-gate space=0; 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate readonly = 0; 176*7c478bd9Sstevel@tonic-gate if (!isedit && issysmbox && !Hflag) 177*7c478bd9Sstevel@tonic-gate readonly = Passeren()==-1; 178*7c478bd9Sstevel@tonic-gate lock(ibuf, "r", 1); 179*7c478bd9Sstevel@tonic-gate fstat(fileno(ibuf), &stbuf); 180*7c478bd9Sstevel@tonic-gate utimep->actime = stbuf.st_atime; 181*7c478bd9Sstevel@tonic-gate utimep->modtime = stbuf.st_mtime; 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if (!readonly) 184*7c478bd9Sstevel@tonic-gate if ((i = open(name, O_WRONLY)) < 0) 185*7c478bd9Sstevel@tonic-gate readonly++; 186*7c478bd9Sstevel@tonic-gate else 187*7c478bd9Sstevel@tonic-gate close(i); 188*7c478bd9Sstevel@tonic-gate shudclob = 1; 189*7c478bd9Sstevel@tonic-gate edit = isedit; 190*7c478bd9Sstevel@tonic-gate nstrcpy(efile, PATHSIZE, name); 191*7c478bd9Sstevel@tonic-gate editfile = efile; 192*7c478bd9Sstevel@tonic-gate #ifdef notdef 193*7c478bd9Sstevel@tonic-gate if (name != mailname) 194*7c478bd9Sstevel@tonic-gate nstrcpy(mailname, PATHSIZE, name); 195*7c478bd9Sstevel@tonic-gate #endif 196*7c478bd9Sstevel@tonic-gate mailsize = fsize(ibuf); 197*7c478bd9Sstevel@tonic-gate if ((fd = open(tempMesg, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 198*7c478bd9Sstevel@tonic-gate (otf = fdopen(fd, "w")) == NULL) { 199*7c478bd9Sstevel@tonic-gate perror(tempMesg); 200*7c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 201*7c478bd9Sstevel@tonic-gate Verhogen(); 202*7c478bd9Sstevel@tonic-gate goto doexit; 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate if ((itf = fopen(tempMesg, "r")) == NULL) { 205*7c478bd9Sstevel@tonic-gate perror(tempMesg); 206*7c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 207*7c478bd9Sstevel@tonic-gate Verhogen(); 208*7c478bd9Sstevel@tonic-gate goto doexit; 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate removefile(tempMesg); 211*7c478bd9Sstevel@tonic-gate setptr(ibuf); 212*7c478bd9Sstevel@tonic-gate setmsize(msgCount); 213*7c478bd9Sstevel@tonic-gate fclose(ibuf); 214*7c478bd9Sstevel@tonic-gate relsesigs(); 215*7c478bd9Sstevel@tonic-gate sawcom = 0; 216*7c478bd9Sstevel@tonic-gate rc = 0; 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate doret: 219*7c478bd9Sstevel@tonic-gate if (!isedit && issysmbox) 220*7c478bd9Sstevel@tonic-gate unlockmail(); 221*7c478bd9Sstevel@tonic-gate return(rc); 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate doexit: 224*7c478bd9Sstevel@tonic-gate if (!isedit && issysmbox) 225*7c478bd9Sstevel@tonic-gate unlockmail(); 226*7c478bd9Sstevel@tonic-gate exit(exrc ? exrc : rpterr); 227*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* global to semaphores */ 231*7c478bd9Sstevel@tonic-gate static char semfn[128]; 232*7c478bd9Sstevel@tonic-gate static FILE *semfp = NULL; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * return -1 if file is already being read, 0 otherwise 236*7c478bd9Sstevel@tonic-gate */ 237*7c478bd9Sstevel@tonic-gate static int 238*7c478bd9Sstevel@tonic-gate Passeren(void) 239*7c478bd9Sstevel@tonic-gate { 240*7c478bd9Sstevel@tonic-gate char *home; 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate if ((home = getenv("HOME")) == NULL) 243*7c478bd9Sstevel@tonic-gate return 0; 244*7c478bd9Sstevel@tonic-gate snprintf(semfn, sizeof (semfn), "%s%s", home, "/.Maillock"); 245*7c478bd9Sstevel@tonic-gate if ((semfp = fopen(semfn, "w")) == NULL) { 246*7c478bd9Sstevel@tonic-gate fprintf(stderr, 247*7c478bd9Sstevel@tonic-gate gettext("WARNING: Can't open mail lock file (%s).\n"), semfn); 248*7c478bd9Sstevel@tonic-gate fprintf(stderr, 249*7c478bd9Sstevel@tonic-gate gettext("\t Assuming you are not already reading mail.\n")); 250*7c478bd9Sstevel@tonic-gate return 0; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate if (lock(semfp, "w", 0) < 0) { 253*7c478bd9Sstevel@tonic-gate if (errno == ENOLCK) { 254*7c478bd9Sstevel@tonic-gate fprintf(stderr, 255*7c478bd9Sstevel@tonic-gate gettext("WARNING: Unable to acquire mail lock, no record locks available.\n")); 256*7c478bd9Sstevel@tonic-gate fprintf(stderr, 257*7c478bd9Sstevel@tonic-gate gettext("\t Assuming you are not already reading mail.\n")); 258*7c478bd9Sstevel@tonic-gate return 0; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate fprintf(stderr, 261*7c478bd9Sstevel@tonic-gate gettext("WARNING: You are already reading mail.\n")); 262*7c478bd9Sstevel@tonic-gate fprintf(stderr, 263*7c478bd9Sstevel@tonic-gate gettext("\t This instance of mail is read only.\n")); 264*7c478bd9Sstevel@tonic-gate fclose(semfp); 265*7c478bd9Sstevel@tonic-gate semfp = NULL; 266*7c478bd9Sstevel@tonic-gate return -1; 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate return 0; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate void 272*7c478bd9Sstevel@tonic-gate Verhogen(void) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate if (semfp != NULL) { 275*7c478bd9Sstevel@tonic-gate unlink(semfn); 276*7c478bd9Sstevel@tonic-gate fclose(semfp); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Interpret user commands one by one. If standard input is not a tty, 282*7c478bd9Sstevel@tonic-gate * print no prompt. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate static int *msgvec; 286*7c478bd9Sstevel@tonic-gate static int shudprompt; 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate void 289*7c478bd9Sstevel@tonic-gate commands(void) 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate int eofloop; 292*7c478bd9Sstevel@tonic-gate register int n; 293*7c478bd9Sstevel@tonic-gate char linebuf[LINESIZE]; 294*7c478bd9Sstevel@tonic-gate char line[LINESIZE]; 295*7c478bd9Sstevel@tonic-gate struct stat minfo; 296*7c478bd9Sstevel@tonic-gate FILE *ibuf; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 299*7c478bd9Sstevel@tonic-gate sigset(SIGCONT, SIG_DFL); 300*7c478bd9Sstevel@tonic-gate #endif 301*7c478bd9Sstevel@tonic-gate if (rcvmode && !sourcing) { 302*7c478bd9Sstevel@tonic-gate if (sigset(SIGINT, SIG_IGN) != SIG_IGN) 303*7c478bd9Sstevel@tonic-gate sigset(SIGINT, stop); 304*7c478bd9Sstevel@tonic-gate if (sigset(SIGHUP, SIG_IGN) != SIG_IGN) 305*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, hangup); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate for (;;) { 308*7c478bd9Sstevel@tonic-gate setjmp(srbuf); 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * Print the prompt, if needed. Clear out 312*7c478bd9Sstevel@tonic-gate * string space, and flush the output. 313*7c478bd9Sstevel@tonic-gate */ 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate if (!rcvmode && !sourcing) 316*7c478bd9Sstevel@tonic-gate return; 317*7c478bd9Sstevel@tonic-gate eofloop = 0; 318*7c478bd9Sstevel@tonic-gate top: 319*7c478bd9Sstevel@tonic-gate if ((shudprompt = (intty && !sourcing)) != 0) { 320*7c478bd9Sstevel@tonic-gate if (prompt==NOSTR) { 321*7c478bd9Sstevel@tonic-gate if ((int)value("bsdcompat")) 322*7c478bd9Sstevel@tonic-gate prompt = "& "; 323*7c478bd9Sstevel@tonic-gate else 324*7c478bd9Sstevel@tonic-gate prompt = ""; 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 327*7c478bd9Sstevel@tonic-gate sigset(SIGCONT, contin); 328*7c478bd9Sstevel@tonic-gate #endif 329*7c478bd9Sstevel@tonic-gate if (intty && value("autoinc") && 330*7c478bd9Sstevel@tonic-gate stat(editfile, &minfo) >=0 && 331*7c478bd9Sstevel@tonic-gate minfo.st_size > mailsize) { 332*7c478bd9Sstevel@tonic-gate int OmsgCount, i; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate OmsgCount = msgCount; 335*7c478bd9Sstevel@tonic-gate fseek(otf, 0L, 2); 336*7c478bd9Sstevel@tonic-gate holdsigs(); 337*7c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 338*7c478bd9Sstevel@tonic-gate lockmail(); 339*7c478bd9Sstevel@tonic-gate if ((ibuf = fopen(editfile, "r")) == NULL ) { 340*7c478bd9Sstevel@tonic-gate fprintf(stderr, 341*7c478bd9Sstevel@tonic-gate gettext("Can't reopen %s\n"), 342*7c478bd9Sstevel@tonic-gate editfile); 343*7c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 344*7c478bd9Sstevel@tonic-gate unlockmail(); 345*7c478bd9Sstevel@tonic-gate exit(1); 346*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate if (edit || !issysmbox) 349*7c478bd9Sstevel@tonic-gate lock(ibuf, "r", 1); 350*7c478bd9Sstevel@tonic-gate fseek(ibuf, mailsize, 0); 351*7c478bd9Sstevel@tonic-gate mailsize = fsize(ibuf); 352*7c478bd9Sstevel@tonic-gate setptr(ibuf); 353*7c478bd9Sstevel@tonic-gate setmsize(msgCount); 354*7c478bd9Sstevel@tonic-gate fclose(ibuf); 355*7c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 356*7c478bd9Sstevel@tonic-gate unlockmail(); 357*7c478bd9Sstevel@tonic-gate if (msgCount-OmsgCount > 0) { 358*7c478bd9Sstevel@tonic-gate printf(gettext( 359*7c478bd9Sstevel@tonic-gate "New mail has arrived.\n")); 360*7c478bd9Sstevel@tonic-gate if (msgCount - OmsgCount == 1) 361*7c478bd9Sstevel@tonic-gate printf(gettext( 362*7c478bd9Sstevel@tonic-gate "Loaded 1 new message\n")); 363*7c478bd9Sstevel@tonic-gate else 364*7c478bd9Sstevel@tonic-gate printf(gettext( 365*7c478bd9Sstevel@tonic-gate "Loaded %d new messages\n"), 366*7c478bd9Sstevel@tonic-gate msgCount-OmsgCount); 367*7c478bd9Sstevel@tonic-gate if (value("header") != NOSTR) 368*7c478bd9Sstevel@tonic-gate for (i = OmsgCount+1; 369*7c478bd9Sstevel@tonic-gate i <= msgCount; i++) { 370*7c478bd9Sstevel@tonic-gate printhead(i); 371*7c478bd9Sstevel@tonic-gate sreset(); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate relsesigs(); 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate printf("%s", prompt); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate flush(); 379*7c478bd9Sstevel@tonic-gate sreset(); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* 382*7c478bd9Sstevel@tonic-gate * Read a line of commands from the current input 383*7c478bd9Sstevel@tonic-gate * and handle end of file specially. 384*7c478bd9Sstevel@tonic-gate */ 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate n = 0; 387*7c478bd9Sstevel@tonic-gate linebuf[0] = '\0'; 388*7c478bd9Sstevel@tonic-gate for (;;) { 389*7c478bd9Sstevel@tonic-gate if (readline(input, line) <= 0) { 390*7c478bd9Sstevel@tonic-gate if (n != 0) 391*7c478bd9Sstevel@tonic-gate break; 392*7c478bd9Sstevel@tonic-gate if (loading) 393*7c478bd9Sstevel@tonic-gate return; 394*7c478bd9Sstevel@tonic-gate if (sourcing) { 395*7c478bd9Sstevel@tonic-gate unstack(); 396*7c478bd9Sstevel@tonic-gate goto more; 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate if (value("ignoreeof") != NOSTR && shudprompt) { 399*7c478bd9Sstevel@tonic-gate if (++eofloop < 25) { 400*7c478bd9Sstevel@tonic-gate printf(gettext( 401*7c478bd9Sstevel@tonic-gate "Use \"quit\" to quit.\n")); 402*7c478bd9Sstevel@tonic-gate goto top; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate return; 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate if ((n = strlen(line)) == 0) 408*7c478bd9Sstevel@tonic-gate break; 409*7c478bd9Sstevel@tonic-gate n--; 410*7c478bd9Sstevel@tonic-gate if (line[n] != '\\') 411*7c478bd9Sstevel@tonic-gate break; 412*7c478bd9Sstevel@tonic-gate line[n++] = ' '; 413*7c478bd9Sstevel@tonic-gate if (n > LINESIZE - (int)strlen(linebuf) - 1) 414*7c478bd9Sstevel@tonic-gate break; 415*7c478bd9Sstevel@tonic-gate strcat(linebuf, line); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate n = LINESIZE - strlen(linebuf) - 1; 418*7c478bd9Sstevel@tonic-gate if ((int)strlen(line) > n) { 419*7c478bd9Sstevel@tonic-gate printf(gettext( 420*7c478bd9Sstevel@tonic-gate "Line plus continuation line too long:\n\t%s\n\nplus\n\t%s\n"), 421*7c478bd9Sstevel@tonic-gate linebuf, line); 422*7c478bd9Sstevel@tonic-gate if (loading) 423*7c478bd9Sstevel@tonic-gate return; 424*7c478bd9Sstevel@tonic-gate if (sourcing) { 425*7c478bd9Sstevel@tonic-gate unstack(); 426*7c478bd9Sstevel@tonic-gate goto more; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate return; 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate strncat(linebuf, line, n); 431*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 432*7c478bd9Sstevel@tonic-gate sigset(SIGCONT, SIG_DFL); 433*7c478bd9Sstevel@tonic-gate #endif 434*7c478bd9Sstevel@tonic-gate if (execute(linebuf, 0)) 435*7c478bd9Sstevel@tonic-gate return; 436*7c478bd9Sstevel@tonic-gate more: ; 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * Execute a single command. If the command executed 442*7c478bd9Sstevel@tonic-gate * is "quit," then return non-zero so that the caller 443*7c478bd9Sstevel@tonic-gate * will know to return back to main, if he cares. 444*7c478bd9Sstevel@tonic-gate * Contxt is non-zero if called while composing mail. 445*7c478bd9Sstevel@tonic-gate */ 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate int 448*7c478bd9Sstevel@tonic-gate execute(char linebuf[], int contxt) 449*7c478bd9Sstevel@tonic-gate { 450*7c478bd9Sstevel@tonic-gate char word[LINESIZE]; 451*7c478bd9Sstevel@tonic-gate char *arglist[MAXARGC]; 452*7c478bd9Sstevel@tonic-gate const struct cmd *com; 453*7c478bd9Sstevel@tonic-gate register char *cp, *cp2; 454*7c478bd9Sstevel@tonic-gate register int c, e; 455*7c478bd9Sstevel@tonic-gate int muvec[2]; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate /* 458*7c478bd9Sstevel@tonic-gate * Strip the white space away from the beginning 459*7c478bd9Sstevel@tonic-gate * of the command, then scan out a word, which 460*7c478bd9Sstevel@tonic-gate * consists of anything except digits and white space. 461*7c478bd9Sstevel@tonic-gate * 462*7c478bd9Sstevel@tonic-gate * Handle |, ! and # differently to get the correct 463*7c478bd9Sstevel@tonic-gate * lexical conventions. 464*7c478bd9Sstevel@tonic-gate */ 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate cp = linebuf; 467*7c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 468*7c478bd9Sstevel@tonic-gate cp++; 469*7c478bd9Sstevel@tonic-gate cp2 = word; 470*7c478bd9Sstevel@tonic-gate if (any(*cp, "!|#")) 471*7c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 472*7c478bd9Sstevel@tonic-gate else 473*7c478bd9Sstevel@tonic-gate while (*cp && !any(*cp, " \t0123456789$^.:/-+*'\"")) 474*7c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 475*7c478bd9Sstevel@tonic-gate *cp2 = '\0'; 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * Look up the command; if not found, complain. 479*7c478bd9Sstevel@tonic-gate * Normally, a blank command would map to the 480*7c478bd9Sstevel@tonic-gate * first command in the table; while sourcing, 481*7c478bd9Sstevel@tonic-gate * however, we ignore blank lines to eliminate 482*7c478bd9Sstevel@tonic-gate * confusion. 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate if (sourcing && equal(word, "")) 486*7c478bd9Sstevel@tonic-gate return(0); 487*7c478bd9Sstevel@tonic-gate com = lex(word); 488*7c478bd9Sstevel@tonic-gate if (com == NONE) { 489*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Unknown command: \"%s\"\n"), word); 490*7c478bd9Sstevel@tonic-gate if (loading) { 491*7c478bd9Sstevel@tonic-gate cond = CANY; 492*7c478bd9Sstevel@tonic-gate return(1); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate if (sourcing) { 495*7c478bd9Sstevel@tonic-gate cond = CANY; 496*7c478bd9Sstevel@tonic-gate unstack(); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate return(0); 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate /* 502*7c478bd9Sstevel@tonic-gate * See if we should execute the command -- if a conditional 503*7c478bd9Sstevel@tonic-gate * we always execute it, otherwise, check the state of cond. 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if ((com->c_argtype & F) == 0) 507*7c478bd9Sstevel@tonic-gate if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode || 508*7c478bd9Sstevel@tonic-gate cond == CTTY && !intty || cond == CNOTTY && intty) 509*7c478bd9Sstevel@tonic-gate return(0); 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate /* 512*7c478bd9Sstevel@tonic-gate * Special case so that quit causes a return to 513*7c478bd9Sstevel@tonic-gate * main, who will call the quit code directly. 514*7c478bd9Sstevel@tonic-gate * If we are in a source file, just unstack. 515*7c478bd9Sstevel@tonic-gate */ 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (com->c_func == (int (*)(void *))edstop) { 518*7c478bd9Sstevel@tonic-gate if (sourcing) { 519*7c478bd9Sstevel@tonic-gate if (loading) 520*7c478bd9Sstevel@tonic-gate return(1); 521*7c478bd9Sstevel@tonic-gate unstack(); 522*7c478bd9Sstevel@tonic-gate return(0); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate return(1); 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate /* 528*7c478bd9Sstevel@tonic-gate * Process the arguments to the command, depending 529*7c478bd9Sstevel@tonic-gate * on the type he expects. Default to an error. 530*7c478bd9Sstevel@tonic-gate * If we are sourcing an interactive command, it's 531*7c478bd9Sstevel@tonic-gate * an error. 532*7c478bd9Sstevel@tonic-gate */ 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate if (!rcvmode && (com->c_argtype & M) == 0) { 535*7c478bd9Sstevel@tonic-gate fprintf(stderr, 536*7c478bd9Sstevel@tonic-gate gettext("May not execute \"%s\" while sending\n"), 537*7c478bd9Sstevel@tonic-gate com->c_name); 538*7c478bd9Sstevel@tonic-gate if (loading) 539*7c478bd9Sstevel@tonic-gate return(1); 540*7c478bd9Sstevel@tonic-gate if (sourcing) 541*7c478bd9Sstevel@tonic-gate unstack(); 542*7c478bd9Sstevel@tonic-gate return(0); 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate if (sourcing && com->c_argtype & I) { 545*7c478bd9Sstevel@tonic-gate fprintf(stderr, 546*7c478bd9Sstevel@tonic-gate gettext("May not execute \"%s\" while sourcing\n"), 547*7c478bd9Sstevel@tonic-gate com->c_name); 548*7c478bd9Sstevel@tonic-gate rpterr = 1; 549*7c478bd9Sstevel@tonic-gate if (loading) 550*7c478bd9Sstevel@tonic-gate return(1); 551*7c478bd9Sstevel@tonic-gate unstack(); 552*7c478bd9Sstevel@tonic-gate return(0); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate if (readonly && com->c_argtype & W) { 555*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 556*7c478bd9Sstevel@tonic-gate "May not execute \"%s\" -- message file is read only\n"), 557*7c478bd9Sstevel@tonic-gate com->c_name); 558*7c478bd9Sstevel@tonic-gate if (loading) 559*7c478bd9Sstevel@tonic-gate return(1); 560*7c478bd9Sstevel@tonic-gate if (sourcing) 561*7c478bd9Sstevel@tonic-gate unstack(); 562*7c478bd9Sstevel@tonic-gate return(0); 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate if (contxt && com->c_argtype & R) { 565*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Cannot recursively invoke \"%s\"\n"), 566*7c478bd9Sstevel@tonic-gate com->c_name); 567*7c478bd9Sstevel@tonic-gate return(0); 568*7c478bd9Sstevel@tonic-gate } 569*7c478bd9Sstevel@tonic-gate e = 1; 570*7c478bd9Sstevel@tonic-gate switch (com->c_argtype & ~(F|P|I|M|T|W|R)) { 571*7c478bd9Sstevel@tonic-gate case MSGLIST: 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * A message list defaulting to nearest forward 574*7c478bd9Sstevel@tonic-gate * legal message. 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate if (msgvec == 0) { 577*7c478bd9Sstevel@tonic-gate fprintf(stderr, 578*7c478bd9Sstevel@tonic-gate gettext("Illegal use of \"message list\"\n")); 579*7c478bd9Sstevel@tonic-gate return(-1); 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0) 582*7c478bd9Sstevel@tonic-gate break; 583*7c478bd9Sstevel@tonic-gate if (c == 0) 584*7c478bd9Sstevel@tonic-gate if (msgCount == 0) 585*7c478bd9Sstevel@tonic-gate *msgvec = NULL; 586*7c478bd9Sstevel@tonic-gate else { 587*7c478bd9Sstevel@tonic-gate *msgvec = first(com->c_msgflag, 588*7c478bd9Sstevel@tonic-gate com->c_msgmask); 589*7c478bd9Sstevel@tonic-gate msgvec[1] = NULL; 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 592*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No applicable messages\n")); 593*7c478bd9Sstevel@tonic-gate break; 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate e = (*com->c_func)(msgvec); 596*7c478bd9Sstevel@tonic-gate break; 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate case NDMLIST: 599*7c478bd9Sstevel@tonic-gate /* 600*7c478bd9Sstevel@tonic-gate * A message list with no defaults, but no error 601*7c478bd9Sstevel@tonic-gate * if none exist. 602*7c478bd9Sstevel@tonic-gate */ 603*7c478bd9Sstevel@tonic-gate if (msgvec == 0) { 604*7c478bd9Sstevel@tonic-gate fprintf(stderr, 605*7c478bd9Sstevel@tonic-gate gettext("Illegal use of \"message list\"\n")); 606*7c478bd9Sstevel@tonic-gate return(-1); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate if (getmsglist(cp, msgvec, com->c_msgflag) < 0) 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate e = (*com->c_func)(msgvec); 611*7c478bd9Sstevel@tonic-gate break; 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate case STRLIST: 614*7c478bd9Sstevel@tonic-gate /* 615*7c478bd9Sstevel@tonic-gate * Just the straight string, with 616*7c478bd9Sstevel@tonic-gate * leading blanks removed. 617*7c478bd9Sstevel@tonic-gate */ 618*7c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 619*7c478bd9Sstevel@tonic-gate cp++; 620*7c478bd9Sstevel@tonic-gate e = (*com->c_func)(cp); 621*7c478bd9Sstevel@tonic-gate break; 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate case RAWLIST: 624*7c478bd9Sstevel@tonic-gate /* 625*7c478bd9Sstevel@tonic-gate * A vector of strings, in shell style. 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate if ((c = getrawlist(cp, arglist, 628*7c478bd9Sstevel@tonic-gate sizeof arglist / sizeof *arglist)) < 0) 629*7c478bd9Sstevel@tonic-gate break; 630*7c478bd9Sstevel@tonic-gate if (c < com->c_minargs) { 631*7c478bd9Sstevel@tonic-gate fprintf(stderr, 632*7c478bd9Sstevel@tonic-gate gettext("%s requires at least %d arg(s)\n"), 633*7c478bd9Sstevel@tonic-gate com->c_name, com->c_minargs); 634*7c478bd9Sstevel@tonic-gate break; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate if (c > com->c_maxargs) { 637*7c478bd9Sstevel@tonic-gate fprintf(stderr, 638*7c478bd9Sstevel@tonic-gate gettext("%s takes no more than %d arg(s)\n"), 639*7c478bd9Sstevel@tonic-gate com->c_name, com->c_maxargs); 640*7c478bd9Sstevel@tonic-gate break; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate e = (*com->c_func)(arglist); 643*7c478bd9Sstevel@tonic-gate break; 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate case NOLIST: 646*7c478bd9Sstevel@tonic-gate /* 647*7c478bd9Sstevel@tonic-gate * Just the constant zero, for exiting, 648*7c478bd9Sstevel@tonic-gate * eg. 649*7c478bd9Sstevel@tonic-gate */ 650*7c478bd9Sstevel@tonic-gate e = (*com->c_func)(0); 651*7c478bd9Sstevel@tonic-gate break; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate default: 654*7c478bd9Sstevel@tonic-gate panic("Unknown argtype"); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate /* 658*7c478bd9Sstevel@tonic-gate * Exit the current source file on 659*7c478bd9Sstevel@tonic-gate * error. 660*7c478bd9Sstevel@tonic-gate */ 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate if (e && loading) 663*7c478bd9Sstevel@tonic-gate return(1); 664*7c478bd9Sstevel@tonic-gate if (e && sourcing) 665*7c478bd9Sstevel@tonic-gate unstack(); 666*7c478bd9Sstevel@tonic-gate if (com->c_func == (int (*)(void *))edstop) 667*7c478bd9Sstevel@tonic-gate return(1); 668*7c478bd9Sstevel@tonic-gate if (value("autoprint") != NOSTR && com->c_argtype & P) 669*7c478bd9Sstevel@tonic-gate if ((dot->m_flag & MDELETED) == 0) { 670*7c478bd9Sstevel@tonic-gate muvec[0] = dot - &message[0] + 1; 671*7c478bd9Sstevel@tonic-gate muvec[1] = 0; 672*7c478bd9Sstevel@tonic-gate type(muvec); 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate if (!sourcing && (com->c_argtype & T) == 0) 675*7c478bd9Sstevel@tonic-gate sawcom = 1; 676*7c478bd9Sstevel@tonic-gate return(0); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * When we wake up after ^Z, reprint the prompt. 682*7c478bd9Sstevel@tonic-gate */ 683*7c478bd9Sstevel@tonic-gate static void 684*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 685*7c478bd9Sstevel@tonic-gate contin(int) 686*7c478bd9Sstevel@tonic-gate #else 687*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 688*7c478bd9Sstevel@tonic-gate contin(int s) 689*7c478bd9Sstevel@tonic-gate #endif 690*7c478bd9Sstevel@tonic-gate { 691*7c478bd9Sstevel@tonic-gate if (shudprompt) 692*7c478bd9Sstevel@tonic-gate printf("%s", prompt); 693*7c478bd9Sstevel@tonic-gate fflush(stdout); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate #endif 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate /* 698*7c478bd9Sstevel@tonic-gate * Branch here on hangup signal and simulate quit. 699*7c478bd9Sstevel@tonic-gate */ 700*7c478bd9Sstevel@tonic-gate void 701*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 702*7c478bd9Sstevel@tonic-gate hangup(int) 703*7c478bd9Sstevel@tonic-gate #else 704*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 705*7c478bd9Sstevel@tonic-gate hangup(int s) 706*7c478bd9Sstevel@tonic-gate #endif 707*7c478bd9Sstevel@tonic-gate { 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate holdsigs(); 710*7c478bd9Sstevel@tonic-gate # ifdef OLD_BSD_SIGS 711*7c478bd9Sstevel@tonic-gate sigignore(SIGHUP); 712*7c478bd9Sstevel@tonic-gate # endif 713*7c478bd9Sstevel@tonic-gate if (edit) { 714*7c478bd9Sstevel@tonic-gate if (setjmp(srbuf)) 715*7c478bd9Sstevel@tonic-gate exit(rpterr); 716*7c478bd9Sstevel@tonic-gate edstop(0); 717*7c478bd9Sstevel@tonic-gate } else { 718*7c478bd9Sstevel@tonic-gate if (issysmbox) 719*7c478bd9Sstevel@tonic-gate Verhogen(); 720*7c478bd9Sstevel@tonic-gate if (value("exit") != NOSTR) 721*7c478bd9Sstevel@tonic-gate exit(1); 722*7c478bd9Sstevel@tonic-gate else 723*7c478bd9Sstevel@tonic-gate quit(0); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate exit(rpterr); 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate /* 729*7c478bd9Sstevel@tonic-gate * Set the size of the message vector used to construct argument 730*7c478bd9Sstevel@tonic-gate * lists to message list functions. 731*7c478bd9Sstevel@tonic-gate */ 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate static void 734*7c478bd9Sstevel@tonic-gate setmsize(int sz) 735*7c478bd9Sstevel@tonic-gate { 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate if (msgvec != (int *) 0) 738*7c478bd9Sstevel@tonic-gate free(msgvec); 739*7c478bd9Sstevel@tonic-gate if (sz < 1) 740*7c478bd9Sstevel@tonic-gate sz = 1; /* need at least one cell for terminating 0 */ 741*7c478bd9Sstevel@tonic-gate if ((msgvec = (int *) 742*7c478bd9Sstevel@tonic-gate calloc((unsigned)(sz + 1), sizeof (*msgvec))) == NULL) 743*7c478bd9Sstevel@tonic-gate panic("Failed to allocate memory for message vector"); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* 747*7c478bd9Sstevel@tonic-gate * Find the correct command in the command table corresponding 748*7c478bd9Sstevel@tonic-gate * to the passed command "word" 749*7c478bd9Sstevel@tonic-gate */ 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate static const struct cmd * 752*7c478bd9Sstevel@tonic-gate lex(char word[]) 753*7c478bd9Sstevel@tonic-gate { 754*7c478bd9Sstevel@tonic-gate register const struct cmd *cp; 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate for (cp = &cmdtab[0]; cp->c_name != NOSTR; cp++) 757*7c478bd9Sstevel@tonic-gate if (isprefix(word, cp->c_name)) 758*7c478bd9Sstevel@tonic-gate return(cp); 759*7c478bd9Sstevel@tonic-gate return(NONE); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * Determine if as1 is a valid prefix of as2. 764*7c478bd9Sstevel@tonic-gate */ 765*7c478bd9Sstevel@tonic-gate static int 766*7c478bd9Sstevel@tonic-gate isprefix(char *as1, char *as2) 767*7c478bd9Sstevel@tonic-gate { 768*7c478bd9Sstevel@tonic-gate register char *s1, *s2; 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate s1 = as1; 771*7c478bd9Sstevel@tonic-gate s2 = as2; 772*7c478bd9Sstevel@tonic-gate while (*s1++ == *s2) 773*7c478bd9Sstevel@tonic-gate if (*s2++ == '\0') 774*7c478bd9Sstevel@tonic-gate return(1); 775*7c478bd9Sstevel@tonic-gate return(*--s1 == '\0'); 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate /* 779*7c478bd9Sstevel@tonic-gate * The following gets called on receipt of a rubout. This is 780*7c478bd9Sstevel@tonic-gate * to abort printout of a command, mainly. 781*7c478bd9Sstevel@tonic-gate * Dispatching here when command() is inactive crashes rcv. 782*7c478bd9Sstevel@tonic-gate * Close all open files except 0, 1, 2, and the temporary. 783*7c478bd9Sstevel@tonic-gate * The special call to getuserid() is needed so it won't get 784*7c478bd9Sstevel@tonic-gate * annoyed about losing its open file. 785*7c478bd9Sstevel@tonic-gate * Also, unstack all source files. 786*7c478bd9Sstevel@tonic-gate */ 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate static int inithdr; /* am printing startup headers */ 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate void 791*7c478bd9Sstevel@tonic-gate stop(int s) 792*7c478bd9Sstevel@tonic-gate { 793*7c478bd9Sstevel@tonic-gate register NODE *head; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate noreset = 0; 796*7c478bd9Sstevel@tonic-gate if (!inithdr) 797*7c478bd9Sstevel@tonic-gate sawcom++; 798*7c478bd9Sstevel@tonic-gate inithdr = 0; 799*7c478bd9Sstevel@tonic-gate while (sourcing) 800*7c478bd9Sstevel@tonic-gate unstack(); 801*7c478bd9Sstevel@tonic-gate getuserid((char *) 0); 802*7c478bd9Sstevel@tonic-gate for (head = fplist; head != (NODE *)NULL; head = head->next) { 803*7c478bd9Sstevel@tonic-gate if (head->fp == stdin || head->fp == stdout) 804*7c478bd9Sstevel@tonic-gate continue; 805*7c478bd9Sstevel@tonic-gate if (head->fp == itf || head->fp == otf) 806*7c478bd9Sstevel@tonic-gate continue; 807*7c478bd9Sstevel@tonic-gate if (head->fp == stderr) 808*7c478bd9Sstevel@tonic-gate continue; 809*7c478bd9Sstevel@tonic-gate if (head->fp == semfp) 810*7c478bd9Sstevel@tonic-gate continue; 811*7c478bd9Sstevel@tonic-gate if (head->fp == pipef) { 812*7c478bd9Sstevel@tonic-gate npclose(pipef); 813*7c478bd9Sstevel@tonic-gate pipef = NULL; 814*7c478bd9Sstevel@tonic-gate continue; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate fclose(head->fp); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate if (image >= 0) { 819*7c478bd9Sstevel@tonic-gate close(image); 820*7c478bd9Sstevel@tonic-gate image = -1; 821*7c478bd9Sstevel@tonic-gate } 822*7c478bd9Sstevel@tonic-gate if (s) { 823*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Interrupt\n")); 824*7c478bd9Sstevel@tonic-gate fflush(stderr); 825*7c478bd9Sstevel@tonic-gate # ifdef OLD_BSD_SIGS 826*7c478bd9Sstevel@tonic-gate sigrelse(s); 827*7c478bd9Sstevel@tonic-gate # endif 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate longjmp(srbuf, 1); 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate /* 833*7c478bd9Sstevel@tonic-gate * Announce the presence of the current mailx version, 834*7c478bd9Sstevel@tonic-gate * give the message count, and print a header listing. 835*7c478bd9Sstevel@tonic-gate */ 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate #define GREETING "%s Type ? for help.\n" 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate void 840*7c478bd9Sstevel@tonic-gate announce(void) 841*7c478bd9Sstevel@tonic-gate { 842*7c478bd9Sstevel@tonic-gate int vec[2], mdot; 843*7c478bd9Sstevel@tonic-gate extern const char *const version; 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate if (!Hflag && value("quiet")==NOSTR) 846*7c478bd9Sstevel@tonic-gate printf(gettext(GREETING), version); 847*7c478bd9Sstevel@tonic-gate mdot = newfileinfo(1); 848*7c478bd9Sstevel@tonic-gate vec[0] = mdot; 849*7c478bd9Sstevel@tonic-gate vec[1] = 0; 850*7c478bd9Sstevel@tonic-gate dot = &message[mdot - 1]; 851*7c478bd9Sstevel@tonic-gate if (msgCount > 0 && !noheader) { 852*7c478bd9Sstevel@tonic-gate inithdr++; 853*7c478bd9Sstevel@tonic-gate headers(vec); 854*7c478bd9Sstevel@tonic-gate inithdr = 0; 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate /* 859*7c478bd9Sstevel@tonic-gate * Announce information about the file we are editing. 860*7c478bd9Sstevel@tonic-gate * Return a likely place to set dot. 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate int 863*7c478bd9Sstevel@tonic-gate newfileinfo(int start) 864*7c478bd9Sstevel@tonic-gate { 865*7c478bd9Sstevel@tonic-gate register struct message *mp; 866*7c478bd9Sstevel@tonic-gate register int u, n, mdot, d, s; 867*7c478bd9Sstevel@tonic-gate char fname[BUFSIZ], zname[BUFSIZ], *ename; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate if (Hflag) 870*7c478bd9Sstevel@tonic-gate return(1); /* fake it--return message 1 */ 871*7c478bd9Sstevel@tonic-gate for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) 872*7c478bd9Sstevel@tonic-gate if ((mp->m_flag & (MNEW|MREAD)) == MNEW) 873*7c478bd9Sstevel@tonic-gate break; 874*7c478bd9Sstevel@tonic-gate if (mp >= &message[msgCount]) 875*7c478bd9Sstevel@tonic-gate for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) 876*7c478bd9Sstevel@tonic-gate if ((mp->m_flag & MREAD) == 0) 877*7c478bd9Sstevel@tonic-gate break; 878*7c478bd9Sstevel@tonic-gate if (mp < &message[msgCount]) 879*7c478bd9Sstevel@tonic-gate mdot = mp - &message[0] + 1; 880*7c478bd9Sstevel@tonic-gate else 881*7c478bd9Sstevel@tonic-gate mdot = 1; 882*7c478bd9Sstevel@tonic-gate n = u = d = s = 0; 883*7c478bd9Sstevel@tonic-gate for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) { 884*7c478bd9Sstevel@tonic-gate if (mp->m_flag & MNEW) 885*7c478bd9Sstevel@tonic-gate n++; 886*7c478bd9Sstevel@tonic-gate if ((mp->m_flag & MREAD) == 0) 887*7c478bd9Sstevel@tonic-gate u++; 888*7c478bd9Sstevel@tonic-gate if (mp->m_flag & MDELETED) 889*7c478bd9Sstevel@tonic-gate d++; 890*7c478bd9Sstevel@tonic-gate if (mp->m_flag & MSAVED) 891*7c478bd9Sstevel@tonic-gate s++; 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate ename=origname; 894*7c478bd9Sstevel@tonic-gate if (getfold(fname) >= 0) { 895*7c478bd9Sstevel@tonic-gate nstrcat(fname, sizeof (fname), "/"); 896*7c478bd9Sstevel@tonic-gate if (strncmp(fname, editfile, strlen(fname)) == 0) { 897*7c478bd9Sstevel@tonic-gate snprintf(zname, sizeof (zname), 898*7c478bd9Sstevel@tonic-gate "+%s", editfile + strlen(fname)); 899*7c478bd9Sstevel@tonic-gate ename = zname; 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate printf("\"%s\": ", ename); 903*7c478bd9Sstevel@tonic-gate if (msgCount == 1) 904*7c478bd9Sstevel@tonic-gate printf(gettext("1 message")); 905*7c478bd9Sstevel@tonic-gate else 906*7c478bd9Sstevel@tonic-gate printf(gettext("%d messages"), msgCount); 907*7c478bd9Sstevel@tonic-gate if (n > 0) 908*7c478bd9Sstevel@tonic-gate printf(gettext(" %d new"), n); 909*7c478bd9Sstevel@tonic-gate if (u-n > 0) 910*7c478bd9Sstevel@tonic-gate printf(gettext(" %d unread"), u); 911*7c478bd9Sstevel@tonic-gate if (d > 0) 912*7c478bd9Sstevel@tonic-gate printf(gettext(" %d deleted"), d); 913*7c478bd9Sstevel@tonic-gate if (s > 0) 914*7c478bd9Sstevel@tonic-gate printf(gettext(" %d saved"), s); 915*7c478bd9Sstevel@tonic-gate if (readonly) 916*7c478bd9Sstevel@tonic-gate printf(gettext(" [Read only]")); 917*7c478bd9Sstevel@tonic-gate printf("\n"); 918*7c478bd9Sstevel@tonic-gate return(mdot); 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate /* 922*7c478bd9Sstevel@tonic-gate * Print the current version number. 923*7c478bd9Sstevel@tonic-gate */ 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate int 926*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 927*7c478bd9Sstevel@tonic-gate pversion(char *) 928*7c478bd9Sstevel@tonic-gate #else 929*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 930*7c478bd9Sstevel@tonic-gate pversion(char *s) 931*7c478bd9Sstevel@tonic-gate #endif 932*7c478bd9Sstevel@tonic-gate { 933*7c478bd9Sstevel@tonic-gate printf("%s\n", version); 934*7c478bd9Sstevel@tonic-gate return(0); 935*7c478bd9Sstevel@tonic-gate } 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate /* 938*7c478bd9Sstevel@tonic-gate * Load a file of user definitions. 939*7c478bd9Sstevel@tonic-gate */ 940*7c478bd9Sstevel@tonic-gate void 941*7c478bd9Sstevel@tonic-gate load(char *name) 942*7c478bd9Sstevel@tonic-gate { 943*7c478bd9Sstevel@tonic-gate register FILE *in, *oldin; 944*7c478bd9Sstevel@tonic-gate 945*7c478bd9Sstevel@tonic-gate if ((in = fopen(name, "r")) == NULL) 946*7c478bd9Sstevel@tonic-gate return; 947*7c478bd9Sstevel@tonic-gate oldin = input; 948*7c478bd9Sstevel@tonic-gate input = in; 949*7c478bd9Sstevel@tonic-gate loading = 1; 950*7c478bd9Sstevel@tonic-gate sourcing = 1; 951*7c478bd9Sstevel@tonic-gate commands(); 952*7c478bd9Sstevel@tonic-gate loading = 0; 953*7c478bd9Sstevel@tonic-gate sourcing = 0; 954*7c478bd9Sstevel@tonic-gate input = oldin; 955*7c478bd9Sstevel@tonic-gate fclose(in); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate /* 959*7c478bd9Sstevel@tonic-gate * Incorporate any new mail into the current session. 960*7c478bd9Sstevel@tonic-gate * 961*7c478bd9Sstevel@tonic-gate * XXX - Since autoinc works on "edited" files as well as the 962*7c478bd9Sstevel@tonic-gate * system mailbox, this probably ought to as well. 963*7c478bd9Sstevel@tonic-gate */ 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate int 966*7c478bd9Sstevel@tonic-gate inc(void) 967*7c478bd9Sstevel@tonic-gate { 968*7c478bd9Sstevel@tonic-gate FILE *ibuf; 969*7c478bd9Sstevel@tonic-gate int mdot; 970*7c478bd9Sstevel@tonic-gate struct stat stbuf; 971*7c478bd9Sstevel@tonic-gate int firstnewmsg = msgCount + 1; 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (edit) { 974*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Not in system mailbox\n")); 975*7c478bd9Sstevel@tonic-gate return(-1); 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate if (((ibuf = fopen(mailname, "r")) == NULL) || 978*7c478bd9Sstevel@tonic-gate (fstat(fileno(ibuf), &stbuf) < 0) || stbuf.st_size == 0L || 979*7c478bd9Sstevel@tonic-gate stbuf.st_size == mailsize || (stbuf.st_mode&S_IFMT) != S_IFREG) { 980*7c478bd9Sstevel@tonic-gate if (strrchr(mailname, '/') == NOSTR) 981*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No new mail.\n")); 982*7c478bd9Sstevel@tonic-gate else 983*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No new mail for %s\n"), 984*7c478bd9Sstevel@tonic-gate strrchr(mailname, '/')+1); 985*7c478bd9Sstevel@tonic-gate if (ibuf != NULL) 986*7c478bd9Sstevel@tonic-gate fclose(ibuf); 987*7c478bd9Sstevel@tonic-gate return(-1); 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate fseek(otf, 0L, 2); 991*7c478bd9Sstevel@tonic-gate holdsigs(); 992*7c478bd9Sstevel@tonic-gate if (issysmbox) 993*7c478bd9Sstevel@tonic-gate lockmail(); 994*7c478bd9Sstevel@tonic-gate fseek(ibuf, mailsize, 0); 995*7c478bd9Sstevel@tonic-gate mailsize = fsize(ibuf); 996*7c478bd9Sstevel@tonic-gate setptr(ibuf); 997*7c478bd9Sstevel@tonic-gate setmsize(msgCount); 998*7c478bd9Sstevel@tonic-gate fclose(ibuf); 999*7c478bd9Sstevel@tonic-gate if (issysmbox) 1000*7c478bd9Sstevel@tonic-gate unlockmail(); 1001*7c478bd9Sstevel@tonic-gate relsesigs(); 1002*7c478bd9Sstevel@tonic-gate mdot = newfileinfo(firstnewmsg); 1003*7c478bd9Sstevel@tonic-gate dot = &message[mdot - 1]; 1004*7c478bd9Sstevel@tonic-gate sawcom = 0; 1005*7c478bd9Sstevel@tonic-gate return(0); 1006*7c478bd9Sstevel@tonic-gate } 1007