17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*eb2b0a61Sas145665 * Common Development and Distribution License (the "License"). 6*eb2b0a61Sas145665 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 23*eb2b0a61Sas145665 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*eb2b0a61Sas145665 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*eb2b0a61Sas145665 /* All Rights Reserved */ 29*eb2b0a61Sas145665 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 327c478bd9Sstevel@tonic-gate * The Regents of the University of California 337c478bd9Sstevel@tonic-gate * All Rights Reserved 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 367c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 377c478bd9Sstevel@tonic-gate * contributors. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include "rcv.h" 437c478bd9Sstevel@tonic-gate #include <locale.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 467c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 477c478bd9Sstevel@tonic-gate * mail program 487c478bd9Sstevel@tonic-gate * 497c478bd9Sstevel@tonic-gate * Lexical processing of commands. 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #ifdef SIGCONT 537c478bd9Sstevel@tonic-gate static void contin(int); 547c478bd9Sstevel@tonic-gate #endif 557c478bd9Sstevel@tonic-gate static int isprefix(char *as1, char *as2); 567c478bd9Sstevel@tonic-gate static const struct cmd *lex(char word[]); 577c478bd9Sstevel@tonic-gate static int Passeren(void); 587c478bd9Sstevel@tonic-gate static void setmsize(int sz); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * Set up editing on the given file name. 627c478bd9Sstevel@tonic-gate * If isedit is true, we are considered to be editing the file, 637c478bd9Sstevel@tonic-gate * otherwise we are reading our mail which has signficance for 647c478bd9Sstevel@tonic-gate * mbox and so forth. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate int 687c478bd9Sstevel@tonic-gate setfile(char *name, int isedit) 697c478bd9Sstevel@tonic-gate { 707c478bd9Sstevel@tonic-gate FILE *ibuf; 717c478bd9Sstevel@tonic-gate int i; 727c478bd9Sstevel@tonic-gate static int shudclob; 737c478bd9Sstevel@tonic-gate static char efile[PATHSIZE]; 747c478bd9Sstevel@tonic-gate char fortest[128]; 757c478bd9Sstevel@tonic-gate struct stat stbuf; 767c478bd9Sstevel@tonic-gate int exrc = 1; 777c478bd9Sstevel@tonic-gate int rc = -1; 787c478bd9Sstevel@tonic-gate int fd = -1; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate if (!isedit && issysmbox) 817c478bd9Sstevel@tonic-gate lockmail(); 827c478bd9Sstevel@tonic-gate if (stat(name, &stbuf) < 0 && errno == EOVERFLOW) { 837c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("mailbox %s is too large to" 847c478bd9Sstevel@tonic-gate " accept incoming mail\n"), name); 857c478bd9Sstevel@tonic-gate goto doret; 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate if ((ibuf = fopen(name, "r")) == NULL) { 887c478bd9Sstevel@tonic-gate extern int errno; 897c478bd9Sstevel@tonic-gate int sverrno = errno; 907c478bd9Sstevel@tonic-gate int filethere = (access(name, 0) == 0); 917c478bd9Sstevel@tonic-gate errno = sverrno; 927c478bd9Sstevel@tonic-gate if (exitflg) 937c478bd9Sstevel@tonic-gate goto doexit; /* no mail, return error */ 947c478bd9Sstevel@tonic-gate if (isedit || filethere) 957c478bd9Sstevel@tonic-gate perror(name); 967c478bd9Sstevel@tonic-gate else if (!Hflag) { 977c478bd9Sstevel@tonic-gate char *f = strrchr(name, '/'); 987c478bd9Sstevel@tonic-gate if (f == NOSTR) 997c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail.\n")); 1007c478bd9Sstevel@tonic-gate else 1017c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail for %s\n"), 1027c478bd9Sstevel@tonic-gate f+1); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate goto doret; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate fstat(fileno(ibuf), &stbuf); 1077c478bd9Sstevel@tonic-gate if (stbuf.st_size == 0L || (stbuf.st_mode&S_IFMT) != S_IFREG) { 1087c478bd9Sstevel@tonic-gate if (exitflg) 1097c478bd9Sstevel@tonic-gate goto doexit; /* no mail, return error */ 1107c478bd9Sstevel@tonic-gate if (isedit) 1117c478bd9Sstevel@tonic-gate if (stbuf.st_size == 0L) 1127c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: empty file\n"), 1137c478bd9Sstevel@tonic-gate name); 1147c478bd9Sstevel@tonic-gate else 1157c478bd9Sstevel@tonic-gate fprintf(stderr, 1167c478bd9Sstevel@tonic-gate gettext("%s: not a regular file\n"), name); 1177c478bd9Sstevel@tonic-gate else if (!Hflag) { 1187c478bd9Sstevel@tonic-gate if (strrchr(name, '/') == NOSTR) 1197c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail.\n")); 1207c478bd9Sstevel@tonic-gate else 1217c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No mail for %s\n"), 1227c478bd9Sstevel@tonic-gate strrchr(name, '/') + 1); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate fclose(ibuf); 1257c478bd9Sstevel@tonic-gate goto doret; 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 128*eb2b0a61Sas145665 if (fgets(fortest, sizeof (fortest), ibuf) == NULL) { 129*eb2b0a61Sas145665 perror(gettext("mailx: Unable to read from mail file")); 130*eb2b0a61Sas145665 goto doexit; 131*eb2b0a61Sas145665 } 132*eb2b0a61Sas145665 1337c478bd9Sstevel@tonic-gate fseek(ibuf, (long)(BUFSIZ+1), 0); /* flush input buffer */ 1347c478bd9Sstevel@tonic-gate fseek(ibuf, 0L, 0); 1357c478bd9Sstevel@tonic-gate if (strncmp(fortest, "Forward to ", 11) == 0) { 1367c478bd9Sstevel@tonic-gate if (exitflg) 1377c478bd9Sstevel@tonic-gate goto doexit; /* no mail, return error */ 1387c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Your mail is being forwarded to %s"), 1397c478bd9Sstevel@tonic-gate fortest+11); 1407c478bd9Sstevel@tonic-gate fclose(ibuf); 1417c478bd9Sstevel@tonic-gate goto doret; 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate if (exitflg) { 1447c478bd9Sstevel@tonic-gate exrc = 0; 1457c478bd9Sstevel@tonic-gate goto doexit; /* there is mail, return success */ 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * Looks like all will be well. Must hold signals 1507c478bd9Sstevel@tonic-gate * while we are reading the new file, else we will ruin 1517c478bd9Sstevel@tonic-gate * the message[] data structure. 1527c478bd9Sstevel@tonic-gate * Copy the messages into /tmp and set pointers. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate holdsigs(); 1567c478bd9Sstevel@tonic-gate if (shudclob) { 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Now that we know we can switch to the new file 1597c478bd9Sstevel@tonic-gate * it's safe to close out the current file. 1607c478bd9Sstevel@tonic-gate * 1617c478bd9Sstevel@tonic-gate * If we're switching to the file we are currently 1627c478bd9Sstevel@tonic-gate * editing, don't allow it to be removed as a side 1637c478bd9Sstevel@tonic-gate * effect of closing it out. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate if (edit) 1667c478bd9Sstevel@tonic-gate edstop(strcmp(editfile, name) == 0); 1677c478bd9Sstevel@tonic-gate else { 1687c478bd9Sstevel@tonic-gate quit(strcmp(editfile, name) == 0); 1697c478bd9Sstevel@tonic-gate if (issysmbox) 1707c478bd9Sstevel@tonic-gate Verhogen(); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate fflush(stdout); 1737c478bd9Sstevel@tonic-gate fclose(itf); 1747c478bd9Sstevel@tonic-gate fclose(otf); 1757c478bd9Sstevel@tonic-gate free(message); 1767c478bd9Sstevel@tonic-gate space = 0; 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate readonly = 0; 1797c478bd9Sstevel@tonic-gate if (!isedit && issysmbox && !Hflag) 1807c478bd9Sstevel@tonic-gate readonly = Passeren() == -1; 1817c478bd9Sstevel@tonic-gate lock(ibuf, "r", 1); 1827c478bd9Sstevel@tonic-gate fstat(fileno(ibuf), &stbuf); 1837c478bd9Sstevel@tonic-gate utimep->actime = stbuf.st_atime; 1847c478bd9Sstevel@tonic-gate utimep->modtime = stbuf.st_mtime; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate if (!readonly) 1877c478bd9Sstevel@tonic-gate if ((i = open(name, O_WRONLY)) < 0) 1887c478bd9Sstevel@tonic-gate readonly++; 1897c478bd9Sstevel@tonic-gate else 1907c478bd9Sstevel@tonic-gate close(i); 1917c478bd9Sstevel@tonic-gate shudclob = 1; 1927c478bd9Sstevel@tonic-gate edit = isedit; 1937c478bd9Sstevel@tonic-gate nstrcpy(efile, PATHSIZE, name); 1947c478bd9Sstevel@tonic-gate editfile = efile; 1957c478bd9Sstevel@tonic-gate #ifdef notdef 1967c478bd9Sstevel@tonic-gate if (name != mailname) 1977c478bd9Sstevel@tonic-gate nstrcpy(mailname, PATHSIZE, name); 1987c478bd9Sstevel@tonic-gate #endif 1997c478bd9Sstevel@tonic-gate mailsize = fsize(ibuf); 2007c478bd9Sstevel@tonic-gate if ((fd = open(tempMesg, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 2017c478bd9Sstevel@tonic-gate (otf = fdopen(fd, "w")) == NULL) { 2027c478bd9Sstevel@tonic-gate perror(tempMesg); 2037c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 2047c478bd9Sstevel@tonic-gate Verhogen(); 2057c478bd9Sstevel@tonic-gate goto doexit; 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate if ((itf = fopen(tempMesg, "r")) == NULL) { 2087c478bd9Sstevel@tonic-gate perror(tempMesg); 2097c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 2107c478bd9Sstevel@tonic-gate Verhogen(); 2117c478bd9Sstevel@tonic-gate goto doexit; 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate removefile(tempMesg); 2147c478bd9Sstevel@tonic-gate setptr(ibuf); 2157c478bd9Sstevel@tonic-gate setmsize(msgCount); 2167c478bd9Sstevel@tonic-gate fclose(ibuf); 2177c478bd9Sstevel@tonic-gate relsesigs(); 2187c478bd9Sstevel@tonic-gate sawcom = 0; 2197c478bd9Sstevel@tonic-gate rc = 0; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate doret: 2227c478bd9Sstevel@tonic-gate if (!isedit && issysmbox) 2237c478bd9Sstevel@tonic-gate unlockmail(); 2247c478bd9Sstevel@tonic-gate return (rc); 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate doexit: 2277c478bd9Sstevel@tonic-gate if (!isedit && issysmbox) 2287c478bd9Sstevel@tonic-gate unlockmail(); 2297c478bd9Sstevel@tonic-gate exit(exrc ? exrc : rpterr); 2307c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* global to semaphores */ 2347c478bd9Sstevel@tonic-gate static char semfn[128]; 2357c478bd9Sstevel@tonic-gate static FILE *semfp = NULL; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * return -1 if file is already being read, 0 otherwise 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate static int 2417c478bd9Sstevel@tonic-gate Passeren(void) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate char *home; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate if ((home = getenv("HOME")) == NULL) 246*eb2b0a61Sas145665 return (0); 2477c478bd9Sstevel@tonic-gate snprintf(semfn, sizeof (semfn), "%s%s", home, "/.Maillock"); 2487c478bd9Sstevel@tonic-gate if ((semfp = fopen(semfn, "w")) == NULL) { 2497c478bd9Sstevel@tonic-gate fprintf(stderr, 2507c478bd9Sstevel@tonic-gate gettext("WARNING: Can't open mail lock file (%s).\n"), semfn); 2517c478bd9Sstevel@tonic-gate fprintf(stderr, 2527c478bd9Sstevel@tonic-gate gettext("\t Assuming you are not already reading mail.\n")); 253*eb2b0a61Sas145665 return (0); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate if (lock(semfp, "w", 0) < 0) { 2567c478bd9Sstevel@tonic-gate if (errno == ENOLCK) { 2577c478bd9Sstevel@tonic-gate fprintf(stderr, 2587c478bd9Sstevel@tonic-gate gettext("WARNING: Unable to acquire mail lock, no record locks available.\n")); 2597c478bd9Sstevel@tonic-gate fprintf(stderr, 2607c478bd9Sstevel@tonic-gate gettext("\t Assuming you are not already reading mail.\n")); 261*eb2b0a61Sas145665 return (0); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate fprintf(stderr, 2647c478bd9Sstevel@tonic-gate gettext("WARNING: You are already reading mail.\n")); 2657c478bd9Sstevel@tonic-gate fprintf(stderr, 2667c478bd9Sstevel@tonic-gate gettext("\t This instance of mail is read only.\n")); 2677c478bd9Sstevel@tonic-gate fclose(semfp); 2687c478bd9Sstevel@tonic-gate semfp = NULL; 269*eb2b0a61Sas145665 return (-1); 2707c478bd9Sstevel@tonic-gate } 271*eb2b0a61Sas145665 return (0); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate void 2757c478bd9Sstevel@tonic-gate Verhogen(void) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate if (semfp != NULL) { 2787c478bd9Sstevel@tonic-gate unlink(semfn); 2797c478bd9Sstevel@tonic-gate fclose(semfp); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * Interpret user commands one by one. If standard input is not a tty, 2857c478bd9Sstevel@tonic-gate * print no prompt. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate static int *msgvec; 2897c478bd9Sstevel@tonic-gate static int shudprompt; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate void 2927c478bd9Sstevel@tonic-gate commands(void) 2937c478bd9Sstevel@tonic-gate { 2947c478bd9Sstevel@tonic-gate int eofloop; 2957c478bd9Sstevel@tonic-gate register int n; 2967c478bd9Sstevel@tonic-gate char linebuf[LINESIZE]; 2977c478bd9Sstevel@tonic-gate char line[LINESIZE]; 2987c478bd9Sstevel@tonic-gate struct stat minfo; 2997c478bd9Sstevel@tonic-gate FILE *ibuf; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate #ifdef SIGCONT 3027c478bd9Sstevel@tonic-gate sigset(SIGCONT, SIG_DFL); 3037c478bd9Sstevel@tonic-gate #endif 3047c478bd9Sstevel@tonic-gate if (rcvmode && !sourcing) { 3057c478bd9Sstevel@tonic-gate if (sigset(SIGINT, SIG_IGN) != SIG_IGN) 3067c478bd9Sstevel@tonic-gate sigset(SIGINT, stop); 3077c478bd9Sstevel@tonic-gate if (sigset(SIGHUP, SIG_IGN) != SIG_IGN) 3087c478bd9Sstevel@tonic-gate sigset(SIGHUP, hangup); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate for (;;) { 3117c478bd9Sstevel@tonic-gate setjmp(srbuf); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* 3147c478bd9Sstevel@tonic-gate * Print the prompt, if needed. Clear out 3157c478bd9Sstevel@tonic-gate * string space, and flush the output. 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate if (!rcvmode && !sourcing) 3197c478bd9Sstevel@tonic-gate return; 3207c478bd9Sstevel@tonic-gate eofloop = 0; 3217c478bd9Sstevel@tonic-gate top: 3227c478bd9Sstevel@tonic-gate if ((shudprompt = (intty && !sourcing)) != 0) { 3237c478bd9Sstevel@tonic-gate if (prompt == NOSTR) { 3247c478bd9Sstevel@tonic-gate if ((int)value("bsdcompat")) 3257c478bd9Sstevel@tonic-gate prompt = "& "; 3267c478bd9Sstevel@tonic-gate else 3277c478bd9Sstevel@tonic-gate prompt = ""; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate #ifdef SIGCONT 3307c478bd9Sstevel@tonic-gate sigset(SIGCONT, contin); 3317c478bd9Sstevel@tonic-gate #endif 3327c478bd9Sstevel@tonic-gate if (intty && value("autoinc") && 3337c478bd9Sstevel@tonic-gate stat(editfile, &minfo) >= 0 && 3347c478bd9Sstevel@tonic-gate minfo.st_size > mailsize) { 3357c478bd9Sstevel@tonic-gate int OmsgCount, i; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate OmsgCount = msgCount; 3387c478bd9Sstevel@tonic-gate fseek(otf, 0L, 2); 3397c478bd9Sstevel@tonic-gate holdsigs(); 3407c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 3417c478bd9Sstevel@tonic-gate lockmail(); 3427c478bd9Sstevel@tonic-gate if ((ibuf = fopen(editfile, "r")) == NULL) { 3437c478bd9Sstevel@tonic-gate fprintf(stderr, 3447c478bd9Sstevel@tonic-gate gettext("Can't reopen %s\n"), 3457c478bd9Sstevel@tonic-gate editfile); 3467c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 3477c478bd9Sstevel@tonic-gate unlockmail(); 3487c478bd9Sstevel@tonic-gate exit(1); 3497c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate if (edit || !issysmbox) 3527c478bd9Sstevel@tonic-gate lock(ibuf, "r", 1); 3537c478bd9Sstevel@tonic-gate fseek(ibuf, mailsize, 0); 3547c478bd9Sstevel@tonic-gate mailsize = fsize(ibuf); 3557c478bd9Sstevel@tonic-gate setptr(ibuf); 3567c478bd9Sstevel@tonic-gate setmsize(msgCount); 3577c478bd9Sstevel@tonic-gate fclose(ibuf); 3587c478bd9Sstevel@tonic-gate if (!edit && issysmbox) 3597c478bd9Sstevel@tonic-gate unlockmail(); 3607c478bd9Sstevel@tonic-gate if (msgCount-OmsgCount > 0) { 3617c478bd9Sstevel@tonic-gate printf(gettext( 3627c478bd9Sstevel@tonic-gate "New mail has arrived.\n")); 3637c478bd9Sstevel@tonic-gate if (msgCount - OmsgCount == 1) 3647c478bd9Sstevel@tonic-gate printf(gettext( 3657c478bd9Sstevel@tonic-gate "Loaded 1 new message\n")); 3667c478bd9Sstevel@tonic-gate else 3677c478bd9Sstevel@tonic-gate printf(gettext( 3687c478bd9Sstevel@tonic-gate "Loaded %d new messages\n"), 3697c478bd9Sstevel@tonic-gate msgCount-OmsgCount); 3707c478bd9Sstevel@tonic-gate if (value("header") != NOSTR) 3717c478bd9Sstevel@tonic-gate for (i = OmsgCount+1; 3727c478bd9Sstevel@tonic-gate i <= msgCount; i++) { 3737c478bd9Sstevel@tonic-gate printhead(i); 3747c478bd9Sstevel@tonic-gate sreset(); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate relsesigs(); 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate printf("%s", prompt); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate flush(); 3827c478bd9Sstevel@tonic-gate sreset(); 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* 3857c478bd9Sstevel@tonic-gate * Read a line of commands from the current input 3867c478bd9Sstevel@tonic-gate * and handle end of file specially. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate n = 0; 3907c478bd9Sstevel@tonic-gate linebuf[0] = '\0'; 3917c478bd9Sstevel@tonic-gate for (;;) { 3927c478bd9Sstevel@tonic-gate if (readline(input, line) <= 0) { 3937c478bd9Sstevel@tonic-gate if (n != 0) 3947c478bd9Sstevel@tonic-gate break; 3957c478bd9Sstevel@tonic-gate if (loading) 3967c478bd9Sstevel@tonic-gate return; 3977c478bd9Sstevel@tonic-gate if (sourcing) { 3987c478bd9Sstevel@tonic-gate unstack(); 3997c478bd9Sstevel@tonic-gate goto more; 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate if (value("ignoreeof") != NOSTR && shudprompt) { 4027c478bd9Sstevel@tonic-gate if (++eofloop < 25) { 4037c478bd9Sstevel@tonic-gate printf(gettext( 4047c478bd9Sstevel@tonic-gate "Use \"quit\" to quit.\n")); 4057c478bd9Sstevel@tonic-gate goto top; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate return; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate if ((n = strlen(line)) == 0) 4117c478bd9Sstevel@tonic-gate break; 4127c478bd9Sstevel@tonic-gate n--; 4137c478bd9Sstevel@tonic-gate if (line[n] != '\\') 4147c478bd9Sstevel@tonic-gate break; 4157c478bd9Sstevel@tonic-gate line[n++] = ' '; 4167c478bd9Sstevel@tonic-gate if (n > LINESIZE - (int)strlen(linebuf) - 1) 4177c478bd9Sstevel@tonic-gate break; 4187c478bd9Sstevel@tonic-gate strcat(linebuf, line); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate n = LINESIZE - strlen(linebuf) - 1; 4217c478bd9Sstevel@tonic-gate if ((int)strlen(line) > n) { 4227c478bd9Sstevel@tonic-gate printf(gettext( 4237c478bd9Sstevel@tonic-gate "Line plus continuation line too long:\n\t%s\n\nplus\n\t%s\n"), 4247c478bd9Sstevel@tonic-gate linebuf, line); 4257c478bd9Sstevel@tonic-gate if (loading) 4267c478bd9Sstevel@tonic-gate return; 4277c478bd9Sstevel@tonic-gate if (sourcing) { 4287c478bd9Sstevel@tonic-gate unstack(); 4297c478bd9Sstevel@tonic-gate goto more; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate return; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate strncat(linebuf, line, n); 4347c478bd9Sstevel@tonic-gate #ifdef SIGCONT 4357c478bd9Sstevel@tonic-gate sigset(SIGCONT, SIG_DFL); 4367c478bd9Sstevel@tonic-gate #endif 4377c478bd9Sstevel@tonic-gate if (execute(linebuf, 0)) 4387c478bd9Sstevel@tonic-gate return; 4397c478bd9Sstevel@tonic-gate more:; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * Execute a single command. If the command executed 4457c478bd9Sstevel@tonic-gate * is "quit," then return non-zero so that the caller 4467c478bd9Sstevel@tonic-gate * will know to return back to main, if he cares. 4477c478bd9Sstevel@tonic-gate * Contxt is non-zero if called while composing mail. 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate int 4517c478bd9Sstevel@tonic-gate execute(char linebuf[], int contxt) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate char word[LINESIZE]; 4547c478bd9Sstevel@tonic-gate char *arglist[MAXARGC]; 4557c478bd9Sstevel@tonic-gate const struct cmd *com; 4567c478bd9Sstevel@tonic-gate register char *cp, *cp2; 4577c478bd9Sstevel@tonic-gate register int c, e; 4587c478bd9Sstevel@tonic-gate int muvec[2]; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* 4617c478bd9Sstevel@tonic-gate * Strip the white space away from the beginning 4627c478bd9Sstevel@tonic-gate * of the command, then scan out a word, which 4637c478bd9Sstevel@tonic-gate * consists of anything except digits and white space. 4647c478bd9Sstevel@tonic-gate * 4657c478bd9Sstevel@tonic-gate * Handle |, ! and # differently to get the correct 4667c478bd9Sstevel@tonic-gate * lexical conventions. 4677c478bd9Sstevel@tonic-gate */ 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate cp = linebuf; 4707c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 4717c478bd9Sstevel@tonic-gate cp++; 4727c478bd9Sstevel@tonic-gate cp2 = word; 4737c478bd9Sstevel@tonic-gate if (any(*cp, "!|#")) 4747c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 4757c478bd9Sstevel@tonic-gate else 4767c478bd9Sstevel@tonic-gate while (*cp && !any(*cp, " \t0123456789$^.:/-+*'\"")) 4777c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 4787c478bd9Sstevel@tonic-gate *cp2 = '\0'; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* 4817c478bd9Sstevel@tonic-gate * Look up the command; if not found, complain. 4827c478bd9Sstevel@tonic-gate * Normally, a blank command would map to the 4837c478bd9Sstevel@tonic-gate * first command in the table; while sourcing, 4847c478bd9Sstevel@tonic-gate * however, we ignore blank lines to eliminate 4857c478bd9Sstevel@tonic-gate * confusion. 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate if (sourcing && equal(word, "")) 4897c478bd9Sstevel@tonic-gate return (0); 4907c478bd9Sstevel@tonic-gate com = lex(word); 4917c478bd9Sstevel@tonic-gate if (com == NONE) { 4927c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Unknown command: \"%s\"\n"), word); 4937c478bd9Sstevel@tonic-gate if (loading) { 4947c478bd9Sstevel@tonic-gate cond = CANY; 4957c478bd9Sstevel@tonic-gate return (1); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate if (sourcing) { 4987c478bd9Sstevel@tonic-gate cond = CANY; 4997c478bd9Sstevel@tonic-gate unstack(); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate return (0); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * See if we should execute the command -- if a conditional 5067c478bd9Sstevel@tonic-gate * we always execute it, otherwise, check the state of cond. 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if ((com->c_argtype & F) == 0) 5107c478bd9Sstevel@tonic-gate if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode || 5117c478bd9Sstevel@tonic-gate cond == CTTY && !intty || cond == CNOTTY && intty) 5127c478bd9Sstevel@tonic-gate return (0); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate /* 5157c478bd9Sstevel@tonic-gate * Special case so that quit causes a return to 5167c478bd9Sstevel@tonic-gate * main, who will call the quit code directly. 5177c478bd9Sstevel@tonic-gate * If we are in a source file, just unstack. 5187c478bd9Sstevel@tonic-gate */ 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (com->c_func == (int (*)(void *))edstop) { 5217c478bd9Sstevel@tonic-gate if (sourcing) { 5227c478bd9Sstevel@tonic-gate if (loading) 5237c478bd9Sstevel@tonic-gate return (1); 5247c478bd9Sstevel@tonic-gate unstack(); 5257c478bd9Sstevel@tonic-gate return (0); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate return (1); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * Process the arguments to the command, depending 5327c478bd9Sstevel@tonic-gate * on the type he expects. Default to an error. 5337c478bd9Sstevel@tonic-gate * If we are sourcing an interactive command, it's 5347c478bd9Sstevel@tonic-gate * an error. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate if (!rcvmode && (com->c_argtype & M) == 0) { 5387c478bd9Sstevel@tonic-gate fprintf(stderr, 5397c478bd9Sstevel@tonic-gate gettext("May not execute \"%s\" while sending\n"), 5407c478bd9Sstevel@tonic-gate com->c_name); 5417c478bd9Sstevel@tonic-gate if (loading) 5427c478bd9Sstevel@tonic-gate return (1); 5437c478bd9Sstevel@tonic-gate if (sourcing) 5447c478bd9Sstevel@tonic-gate unstack(); 5457c478bd9Sstevel@tonic-gate return (0); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate if (sourcing && com->c_argtype & I) { 5487c478bd9Sstevel@tonic-gate fprintf(stderr, 5497c478bd9Sstevel@tonic-gate gettext("May not execute \"%s\" while sourcing\n"), 5507c478bd9Sstevel@tonic-gate com->c_name); 5517c478bd9Sstevel@tonic-gate rpterr = 1; 5527c478bd9Sstevel@tonic-gate if (loading) 5537c478bd9Sstevel@tonic-gate return (1); 5547c478bd9Sstevel@tonic-gate unstack(); 5557c478bd9Sstevel@tonic-gate return (0); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate if (readonly && com->c_argtype & W) { 5587c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 5597c478bd9Sstevel@tonic-gate "May not execute \"%s\" -- message file is read only\n"), 5607c478bd9Sstevel@tonic-gate com->c_name); 5617c478bd9Sstevel@tonic-gate if (loading) 5627c478bd9Sstevel@tonic-gate return (1); 5637c478bd9Sstevel@tonic-gate if (sourcing) 5647c478bd9Sstevel@tonic-gate unstack(); 5657c478bd9Sstevel@tonic-gate return (0); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate if (contxt && com->c_argtype & R) { 5687c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Cannot recursively invoke \"%s\"\n"), 5697c478bd9Sstevel@tonic-gate com->c_name); 5707c478bd9Sstevel@tonic-gate return (0); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate e = 1; 5737c478bd9Sstevel@tonic-gate switch (com->c_argtype & ~(F|P|I|M|T|W|R)) { 5747c478bd9Sstevel@tonic-gate case MSGLIST: 5757c478bd9Sstevel@tonic-gate /* 5767c478bd9Sstevel@tonic-gate * A message list defaulting to nearest forward 5777c478bd9Sstevel@tonic-gate * legal message. 5787c478bd9Sstevel@tonic-gate */ 5797c478bd9Sstevel@tonic-gate if (msgvec == 0) { 5807c478bd9Sstevel@tonic-gate fprintf(stderr, 5817c478bd9Sstevel@tonic-gate gettext("Illegal use of \"message list\"\n")); 5827c478bd9Sstevel@tonic-gate return (-1); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0) 5857c478bd9Sstevel@tonic-gate break; 5867c478bd9Sstevel@tonic-gate if (c == 0) 5877c478bd9Sstevel@tonic-gate if (msgCount == 0) 5887c478bd9Sstevel@tonic-gate *msgvec = NULL; 5897c478bd9Sstevel@tonic-gate else { 5907c478bd9Sstevel@tonic-gate *msgvec = first(com->c_msgflag, 5917c478bd9Sstevel@tonic-gate com->c_msgmask); 5927c478bd9Sstevel@tonic-gate msgvec[1] = NULL; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 5957c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No applicable messages\n")); 5967c478bd9Sstevel@tonic-gate break; 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate e = (*com->c_func)(msgvec); 5997c478bd9Sstevel@tonic-gate break; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate case NDMLIST: 6027c478bd9Sstevel@tonic-gate /* 603*eb2b0a61Sas145665 * A message operand with no defaults, but no error 604*eb2b0a61Sas145665 * if none exists. There will be an error if the 605*eb2b0a61Sas145665 * msgvec pointer is of zero value. 6067c478bd9Sstevel@tonic-gate */ 6077c478bd9Sstevel@tonic-gate if (msgvec == 0) { 6087c478bd9Sstevel@tonic-gate fprintf(stderr, 609*eb2b0a61Sas145665 gettext("Illegal use of \"message operand\"\n")); 6107c478bd9Sstevel@tonic-gate return (-1); 6117c478bd9Sstevel@tonic-gate } 612*eb2b0a61Sas145665 if (getmessage(cp, msgvec, com->c_msgflag) < 0) 6137c478bd9Sstevel@tonic-gate break; 6147c478bd9Sstevel@tonic-gate e = (*com->c_func)(msgvec); 6157c478bd9Sstevel@tonic-gate break; 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate case STRLIST: 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * Just the straight string, with 6207c478bd9Sstevel@tonic-gate * leading blanks removed. 6217c478bd9Sstevel@tonic-gate */ 6227c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 6237c478bd9Sstevel@tonic-gate cp++; 6247c478bd9Sstevel@tonic-gate e = (*com->c_func)(cp); 6257c478bd9Sstevel@tonic-gate break; 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate case RAWLIST: 6287c478bd9Sstevel@tonic-gate /* 6297c478bd9Sstevel@tonic-gate * A vector of strings, in shell style. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate if ((c = getrawlist(cp, arglist, 632*eb2b0a61Sas145665 sizeof (arglist) / sizeof (*arglist))) < 0) 6337c478bd9Sstevel@tonic-gate break; 6347c478bd9Sstevel@tonic-gate if (c < com->c_minargs) { 6357c478bd9Sstevel@tonic-gate fprintf(stderr, 6367c478bd9Sstevel@tonic-gate gettext("%s requires at least %d arg(s)\n"), 6377c478bd9Sstevel@tonic-gate com->c_name, com->c_minargs); 6387c478bd9Sstevel@tonic-gate break; 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate if (c > com->c_maxargs) { 6417c478bd9Sstevel@tonic-gate fprintf(stderr, 6427c478bd9Sstevel@tonic-gate gettext("%s takes no more than %d arg(s)\n"), 6437c478bd9Sstevel@tonic-gate com->c_name, com->c_maxargs); 6447c478bd9Sstevel@tonic-gate break; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate e = (*com->c_func)(arglist); 6477c478bd9Sstevel@tonic-gate break; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate case NOLIST: 6507c478bd9Sstevel@tonic-gate /* 6517c478bd9Sstevel@tonic-gate * Just the constant zero, for exiting, 6527c478bd9Sstevel@tonic-gate * eg. 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate e = (*com->c_func)(0); 6557c478bd9Sstevel@tonic-gate break; 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate default: 6587c478bd9Sstevel@tonic-gate panic("Unknown argtype"); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * Exit the current source file on 6637c478bd9Sstevel@tonic-gate * error. 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (e && loading) 6677c478bd9Sstevel@tonic-gate return (1); 6687c478bd9Sstevel@tonic-gate if (e && sourcing) 6697c478bd9Sstevel@tonic-gate unstack(); 6707c478bd9Sstevel@tonic-gate if (com->c_func == (int (*)(void *))edstop) 6717c478bd9Sstevel@tonic-gate return (1); 6727c478bd9Sstevel@tonic-gate if (value("autoprint") != NOSTR && com->c_argtype & P) 6737c478bd9Sstevel@tonic-gate if ((dot->m_flag & MDELETED) == 0) { 6747c478bd9Sstevel@tonic-gate muvec[0] = dot - &message[0] + 1; 6757c478bd9Sstevel@tonic-gate muvec[1] = 0; 6767c478bd9Sstevel@tonic-gate type(muvec); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate if (!sourcing && (com->c_argtype & T) == 0) 6797c478bd9Sstevel@tonic-gate sawcom = 1; 6807c478bd9Sstevel@tonic-gate return (0); 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate #ifdef SIGCONT 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * When we wake up after ^Z, reprint the prompt. 6867c478bd9Sstevel@tonic-gate */ 6877c478bd9Sstevel@tonic-gate static void 6887c478bd9Sstevel@tonic-gate #ifdef __cplusplus 6897c478bd9Sstevel@tonic-gate contin(int) 6907c478bd9Sstevel@tonic-gate #else 6917c478bd9Sstevel@tonic-gate /* ARGSUSED */ 6927c478bd9Sstevel@tonic-gate contin(int s) 6937c478bd9Sstevel@tonic-gate #endif 6947c478bd9Sstevel@tonic-gate { 6957c478bd9Sstevel@tonic-gate if (shudprompt) 6967c478bd9Sstevel@tonic-gate printf("%s", prompt); 6977c478bd9Sstevel@tonic-gate fflush(stdout); 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate #endif 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* 7027c478bd9Sstevel@tonic-gate * Branch here on hangup signal and simulate quit. 7037c478bd9Sstevel@tonic-gate */ 7047c478bd9Sstevel@tonic-gate void 7057c478bd9Sstevel@tonic-gate #ifdef __cplusplus 7067c478bd9Sstevel@tonic-gate hangup(int) 7077c478bd9Sstevel@tonic-gate #else 7087c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7097c478bd9Sstevel@tonic-gate hangup(int s) 7107c478bd9Sstevel@tonic-gate #endif 7117c478bd9Sstevel@tonic-gate { 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate holdsigs(); 7147c478bd9Sstevel@tonic-gate #ifdef OLD_BSD_SIGS 7157c478bd9Sstevel@tonic-gate sigignore(SIGHUP); 7167c478bd9Sstevel@tonic-gate #endif 7177c478bd9Sstevel@tonic-gate if (edit) { 7187c478bd9Sstevel@tonic-gate if (setjmp(srbuf)) 7197c478bd9Sstevel@tonic-gate exit(rpterr); 7207c478bd9Sstevel@tonic-gate edstop(0); 7217c478bd9Sstevel@tonic-gate } else { 7227c478bd9Sstevel@tonic-gate if (issysmbox) 7237c478bd9Sstevel@tonic-gate Verhogen(); 7247c478bd9Sstevel@tonic-gate if (value("exit") != NOSTR) 7257c478bd9Sstevel@tonic-gate exit(1); 7267c478bd9Sstevel@tonic-gate else 7277c478bd9Sstevel@tonic-gate quit(0); 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate exit(rpterr); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * Set the size of the message vector used to construct argument 7347c478bd9Sstevel@tonic-gate * lists to message list functions. 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate static void 7387c478bd9Sstevel@tonic-gate setmsize(int sz) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate if (msgvec != (int *)0) 7427c478bd9Sstevel@tonic-gate free(msgvec); 7437c478bd9Sstevel@tonic-gate if (sz < 1) 7447c478bd9Sstevel@tonic-gate sz = 1; /* need at least one cell for terminating 0 */ 7457c478bd9Sstevel@tonic-gate if ((msgvec = (int *) 7467c478bd9Sstevel@tonic-gate calloc((unsigned)(sz + 1), sizeof (*msgvec))) == NULL) 7477c478bd9Sstevel@tonic-gate panic("Failed to allocate memory for message vector"); 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate /* 7517c478bd9Sstevel@tonic-gate * Find the correct command in the command table corresponding 7527c478bd9Sstevel@tonic-gate * to the passed command "word" 7537c478bd9Sstevel@tonic-gate */ 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate static const struct cmd * 7567c478bd9Sstevel@tonic-gate lex(char word[]) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate register const struct cmd *cp; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate for (cp = &cmdtab[0]; cp->c_name != NOSTR; cp++) 7617c478bd9Sstevel@tonic-gate if (isprefix(word, cp->c_name)) 7627c478bd9Sstevel@tonic-gate return (cp); 7637c478bd9Sstevel@tonic-gate return (NONE); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate /* 7677c478bd9Sstevel@tonic-gate * Determine if as1 is a valid prefix of as2. 7687c478bd9Sstevel@tonic-gate */ 7697c478bd9Sstevel@tonic-gate static int 7707c478bd9Sstevel@tonic-gate isprefix(char *as1, char *as2) 7717c478bd9Sstevel@tonic-gate { 7727c478bd9Sstevel@tonic-gate register char *s1, *s2; 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate s1 = as1; 7757c478bd9Sstevel@tonic-gate s2 = as2; 7767c478bd9Sstevel@tonic-gate while (*s1++ == *s2) 7777c478bd9Sstevel@tonic-gate if (*s2++ == '\0') 7787c478bd9Sstevel@tonic-gate return (1); 7797c478bd9Sstevel@tonic-gate return (*--s1 == '\0'); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate /* 7837c478bd9Sstevel@tonic-gate * The following gets called on receipt of a rubout. This is 7847c478bd9Sstevel@tonic-gate * to abort printout of a command, mainly. 7857c478bd9Sstevel@tonic-gate * Dispatching here when command() is inactive crashes rcv. 7867c478bd9Sstevel@tonic-gate * Close all open files except 0, 1, 2, and the temporary. 7877c478bd9Sstevel@tonic-gate * The special call to getuserid() is needed so it won't get 7887c478bd9Sstevel@tonic-gate * annoyed about losing its open file. 7897c478bd9Sstevel@tonic-gate * Also, unstack all source files. 7907c478bd9Sstevel@tonic-gate */ 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate static int inithdr; /* am printing startup headers */ 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate void 7957c478bd9Sstevel@tonic-gate stop(int s) 7967c478bd9Sstevel@tonic-gate { 7977c478bd9Sstevel@tonic-gate register NODE *head; 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate noreset = 0; 8007c478bd9Sstevel@tonic-gate if (!inithdr) 8017c478bd9Sstevel@tonic-gate sawcom++; 8027c478bd9Sstevel@tonic-gate inithdr = 0; 8037c478bd9Sstevel@tonic-gate while (sourcing) 8047c478bd9Sstevel@tonic-gate unstack(); 805*eb2b0a61Sas145665 (void) getuserid((char *)0); 8067c478bd9Sstevel@tonic-gate for (head = fplist; head != (NODE *)NULL; head = head->next) { 8077c478bd9Sstevel@tonic-gate if (head->fp == stdin || head->fp == stdout) 8087c478bd9Sstevel@tonic-gate continue; 8097c478bd9Sstevel@tonic-gate if (head->fp == itf || head->fp == otf) 8107c478bd9Sstevel@tonic-gate continue; 8117c478bd9Sstevel@tonic-gate if (head->fp == stderr) 8127c478bd9Sstevel@tonic-gate continue; 8137c478bd9Sstevel@tonic-gate if (head->fp == semfp) 8147c478bd9Sstevel@tonic-gate continue; 8157c478bd9Sstevel@tonic-gate if (head->fp == pipef) { 8167c478bd9Sstevel@tonic-gate npclose(pipef); 8177c478bd9Sstevel@tonic-gate pipef = NULL; 8187c478bd9Sstevel@tonic-gate continue; 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate fclose(head->fp); 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate if (image >= 0) { 8237c478bd9Sstevel@tonic-gate close(image); 8247c478bd9Sstevel@tonic-gate image = -1; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate if (s) { 8277c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Interrupt\n")); 8287c478bd9Sstevel@tonic-gate fflush(stderr); 8297c478bd9Sstevel@tonic-gate #ifdef OLD_BSD_SIGS 8307c478bd9Sstevel@tonic-gate sigrelse(s); 8317c478bd9Sstevel@tonic-gate #endif 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate longjmp(srbuf, 1); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate /* 8377c478bd9Sstevel@tonic-gate * Announce the presence of the current mailx version, 8387c478bd9Sstevel@tonic-gate * give the message count, and print a header listing. 8397c478bd9Sstevel@tonic-gate */ 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate #define GREETING "%s Type ? for help.\n" 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate void 8447c478bd9Sstevel@tonic-gate announce(void) 8457c478bd9Sstevel@tonic-gate { 8467c478bd9Sstevel@tonic-gate int vec[2], mdot; 8477c478bd9Sstevel@tonic-gate extern const char *const version; 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate if (!Hflag && value("quiet") == NOSTR) 8507c478bd9Sstevel@tonic-gate printf(gettext(GREETING), version); 8517c478bd9Sstevel@tonic-gate mdot = newfileinfo(1); 8527c478bd9Sstevel@tonic-gate vec[0] = mdot; 8537c478bd9Sstevel@tonic-gate vec[1] = 0; 8547c478bd9Sstevel@tonic-gate dot = &message[mdot - 1]; 8557c478bd9Sstevel@tonic-gate if (msgCount > 0 && !noheader) { 8567c478bd9Sstevel@tonic-gate inithdr++; 8577c478bd9Sstevel@tonic-gate headers(vec); 8587c478bd9Sstevel@tonic-gate inithdr = 0; 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate /* 8637c478bd9Sstevel@tonic-gate * Announce information about the file we are editing. 8647c478bd9Sstevel@tonic-gate * Return a likely place to set dot. 8657c478bd9Sstevel@tonic-gate */ 8667c478bd9Sstevel@tonic-gate int 8677c478bd9Sstevel@tonic-gate newfileinfo(int start) 8687c478bd9Sstevel@tonic-gate { 8697c478bd9Sstevel@tonic-gate register struct message *mp; 8707c478bd9Sstevel@tonic-gate register int u, n, mdot, d, s; 8717c478bd9Sstevel@tonic-gate char fname[BUFSIZ], zname[BUFSIZ], *ename; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate if (Hflag) 8747c478bd9Sstevel@tonic-gate return (1); /* fake it--return message 1 */ 8757c478bd9Sstevel@tonic-gate for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) 8767c478bd9Sstevel@tonic-gate if ((mp->m_flag & (MNEW|MREAD)) == MNEW) 8777c478bd9Sstevel@tonic-gate break; 8787c478bd9Sstevel@tonic-gate if (mp >= &message[msgCount]) 8797c478bd9Sstevel@tonic-gate for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) 8807c478bd9Sstevel@tonic-gate if ((mp->m_flag & MREAD) == 0) 8817c478bd9Sstevel@tonic-gate break; 8827c478bd9Sstevel@tonic-gate if (mp < &message[msgCount]) 8837c478bd9Sstevel@tonic-gate mdot = mp - &message[0] + 1; 8847c478bd9Sstevel@tonic-gate else 8857c478bd9Sstevel@tonic-gate mdot = 1; 8867c478bd9Sstevel@tonic-gate n = u = d = s = 0; 8877c478bd9Sstevel@tonic-gate for (mp = &message[start - 1]; mp < &message[msgCount]; mp++) { 8887c478bd9Sstevel@tonic-gate if (mp->m_flag & MNEW) 8897c478bd9Sstevel@tonic-gate n++; 8907c478bd9Sstevel@tonic-gate if ((mp->m_flag & MREAD) == 0) 8917c478bd9Sstevel@tonic-gate u++; 8927c478bd9Sstevel@tonic-gate if (mp->m_flag & MDELETED) 8937c478bd9Sstevel@tonic-gate d++; 8947c478bd9Sstevel@tonic-gate if (mp->m_flag & MSAVED) 8957c478bd9Sstevel@tonic-gate s++; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate ename = origname; 8987c478bd9Sstevel@tonic-gate if (getfold(fname) >= 0) { 8997c478bd9Sstevel@tonic-gate nstrcat(fname, sizeof (fname), "/"); 9007c478bd9Sstevel@tonic-gate if (strncmp(fname, editfile, strlen(fname)) == 0) { 9017c478bd9Sstevel@tonic-gate snprintf(zname, sizeof (zname), 9027c478bd9Sstevel@tonic-gate "+%s", editfile + strlen(fname)); 9037c478bd9Sstevel@tonic-gate ename = zname; 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate printf("\"%s\": ", ename); 9077c478bd9Sstevel@tonic-gate if (msgCount == 1) 9087c478bd9Sstevel@tonic-gate printf(gettext("1 message")); 9097c478bd9Sstevel@tonic-gate else 9107c478bd9Sstevel@tonic-gate printf(gettext("%d messages"), msgCount); 9117c478bd9Sstevel@tonic-gate if (n > 0) 9127c478bd9Sstevel@tonic-gate printf(gettext(" %d new"), n); 9137c478bd9Sstevel@tonic-gate if (u-n > 0) 9147c478bd9Sstevel@tonic-gate printf(gettext(" %d unread"), u); 9157c478bd9Sstevel@tonic-gate if (d > 0) 9167c478bd9Sstevel@tonic-gate printf(gettext(" %d deleted"), d); 9177c478bd9Sstevel@tonic-gate if (s > 0) 9187c478bd9Sstevel@tonic-gate printf(gettext(" %d saved"), s); 9197c478bd9Sstevel@tonic-gate if (readonly) 9207c478bd9Sstevel@tonic-gate printf(gettext(" [Read only]")); 9217c478bd9Sstevel@tonic-gate printf("\n"); 9227c478bd9Sstevel@tonic-gate return (mdot); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * Print the current version number. 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate int 9307c478bd9Sstevel@tonic-gate #ifdef __cplusplus 9317c478bd9Sstevel@tonic-gate pversion(char *) 9327c478bd9Sstevel@tonic-gate #else 9337c478bd9Sstevel@tonic-gate /* ARGSUSED */ 9347c478bd9Sstevel@tonic-gate pversion(char *s) 9357c478bd9Sstevel@tonic-gate #endif 9367c478bd9Sstevel@tonic-gate { 9377c478bd9Sstevel@tonic-gate printf("%s\n", version); 9387c478bd9Sstevel@tonic-gate return (0); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * Load a file of user definitions. 9437c478bd9Sstevel@tonic-gate */ 9447c478bd9Sstevel@tonic-gate void 9457c478bd9Sstevel@tonic-gate load(char *name) 9467c478bd9Sstevel@tonic-gate { 9477c478bd9Sstevel@tonic-gate register FILE *in, *oldin; 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate if ((in = fopen(name, "r")) == NULL) 9507c478bd9Sstevel@tonic-gate return; 9517c478bd9Sstevel@tonic-gate oldin = input; 9527c478bd9Sstevel@tonic-gate input = in; 9537c478bd9Sstevel@tonic-gate loading = 1; 9547c478bd9Sstevel@tonic-gate sourcing = 1; 9557c478bd9Sstevel@tonic-gate commands(); 9567c478bd9Sstevel@tonic-gate loading = 0; 9577c478bd9Sstevel@tonic-gate sourcing = 0; 9587c478bd9Sstevel@tonic-gate input = oldin; 9597c478bd9Sstevel@tonic-gate fclose(in); 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate /* 9637c478bd9Sstevel@tonic-gate * Incorporate any new mail into the current session. 9647c478bd9Sstevel@tonic-gate * 9657c478bd9Sstevel@tonic-gate * XXX - Since autoinc works on "edited" files as well as the 9667c478bd9Sstevel@tonic-gate * system mailbox, this probably ought to as well. 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate int 9707c478bd9Sstevel@tonic-gate inc(void) 9717c478bd9Sstevel@tonic-gate { 9727c478bd9Sstevel@tonic-gate FILE *ibuf; 9737c478bd9Sstevel@tonic-gate int mdot; 9747c478bd9Sstevel@tonic-gate struct stat stbuf; 9757c478bd9Sstevel@tonic-gate int firstnewmsg = msgCount + 1; 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate if (edit) { 9787c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Not in system mailbox\n")); 9797c478bd9Sstevel@tonic-gate return (-1); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate if (((ibuf = fopen(mailname, "r")) == NULL) || 9827c478bd9Sstevel@tonic-gate (fstat(fileno(ibuf), &stbuf) < 0) || stbuf.st_size == 0L || 9837c478bd9Sstevel@tonic-gate stbuf.st_size == mailsize || (stbuf.st_mode&S_IFMT) != S_IFREG) { 9847c478bd9Sstevel@tonic-gate if (strrchr(mailname, '/') == NOSTR) 9857c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No new mail.\n")); 9867c478bd9Sstevel@tonic-gate else 9877c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No new mail for %s\n"), 9887c478bd9Sstevel@tonic-gate strrchr(mailname, '/')+1); 9897c478bd9Sstevel@tonic-gate if (ibuf != NULL) 9907c478bd9Sstevel@tonic-gate fclose(ibuf); 9917c478bd9Sstevel@tonic-gate return (-1); 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate fseek(otf, 0L, 2); 9957c478bd9Sstevel@tonic-gate holdsigs(); 9967c478bd9Sstevel@tonic-gate if (issysmbox) 9977c478bd9Sstevel@tonic-gate lockmail(); 9987c478bd9Sstevel@tonic-gate fseek(ibuf, mailsize, 0); 9997c478bd9Sstevel@tonic-gate mailsize = fsize(ibuf); 10007c478bd9Sstevel@tonic-gate setptr(ibuf); 10017c478bd9Sstevel@tonic-gate setmsize(msgCount); 10027c478bd9Sstevel@tonic-gate fclose(ibuf); 10037c478bd9Sstevel@tonic-gate if (issysmbox) 10047c478bd9Sstevel@tonic-gate unlockmail(); 10057c478bd9Sstevel@tonic-gate relsesigs(); 10067c478bd9Sstevel@tonic-gate mdot = newfileinfo(firstnewmsg); 10077c478bd9Sstevel@tonic-gate dot = &message[mdot - 1]; 10087c478bd9Sstevel@tonic-gate sawcom = 0; 10097c478bd9Sstevel@tonic-gate return (0); 10107c478bd9Sstevel@tonic-gate } 1011