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 /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 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 /* 44*7c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 45*7c478bd9Sstevel@tonic-gate * mail program 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * Collect input from standard input, handling 48*7c478bd9Sstevel@tonic-gate * ~ escapes. 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include "rcv.h" 52*7c478bd9Sstevel@tonic-gate #include <locale.h> 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 55*7c478bd9Sstevel@tonic-gate static void collcont(int); 56*7c478bd9Sstevel@tonic-gate #endif 57*7c478bd9Sstevel@tonic-gate static void collrub(int s); 58*7c478bd9Sstevel@tonic-gate static void cpout(char *str, FILE *ofd); 59*7c478bd9Sstevel@tonic-gate static int exwrite(char name[], FILE *ibuf); 60*7c478bd9Sstevel@tonic-gate static int forward(char ms[], FILE *obuf, int f); 61*7c478bd9Sstevel@tonic-gate static void intack(int); 62*7c478bd9Sstevel@tonic-gate static int forward(char ms[], FILE *obuf, int f); 63*7c478bd9Sstevel@tonic-gate static FILE *mesedit(FILE *ibuf, FILE *obuf, int c, struct header *hp); 64*7c478bd9Sstevel@tonic-gate static FILE *mespipe(FILE *ibuf, FILE *obuf, char cmd[]); 65*7c478bd9Sstevel@tonic-gate static void resetsigs(int resethup); 66*7c478bd9Sstevel@tonic-gate static int stripnulls(register char *linebuf, register int nread); 67*7c478bd9Sstevel@tonic-gate static void xhalt(void); 68*7c478bd9Sstevel@tonic-gate static char **Xaddone(char **hf, char news[]); 69*7c478bd9Sstevel@tonic-gate static int tabputs(const char *line, FILE *obuf); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * Read a message from standard output and return a read file to it 73*7c478bd9Sstevel@tonic-gate * or NULL on error. 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * The following hokiness with global variables is so that on 78*7c478bd9Sstevel@tonic-gate * receipt of an interrupt signal, the partial message can be salted 79*7c478bd9Sstevel@tonic-gate * away on dead.letter. The output file must be available to flush, 80*7c478bd9Sstevel@tonic-gate * and the input to read. Several open files could be saved all through 81*7c478bd9Sstevel@tonic-gate * mailx if stdio allowed simultaneous read/write access. 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate static void (*savesig)(int); /* Previous SIGINT value */ 85*7c478bd9Sstevel@tonic-gate static void (*savehup)(int); /* Previous SIGHUP value */ 86*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 87*7c478bd9Sstevel@tonic-gate static void (*savecont)(int); /* Previous SIGCONT value */ 88*7c478bd9Sstevel@tonic-gate #endif 89*7c478bd9Sstevel@tonic-gate static FILE *newi; /* File for saving away */ 90*7c478bd9Sstevel@tonic-gate static FILE *newo; /* Output side of same */ 91*7c478bd9Sstevel@tonic-gate static int ignintr; /* Ignore interrups */ 92*7c478bd9Sstevel@tonic-gate static int hadintr; /* Have seen one SIGINT so far */ 93*7c478bd9Sstevel@tonic-gate static struct header *savehp; 94*7c478bd9Sstevel@tonic-gate static jmp_buf coljmp; /* To get back to work */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate FILE * 97*7c478bd9Sstevel@tonic-gate collect(struct header *hp) 98*7c478bd9Sstevel@tonic-gate { 99*7c478bd9Sstevel@tonic-gate FILE *ibuf, *fbuf, *obuf; 100*7c478bd9Sstevel@tonic-gate int escape, eof; 101*7c478bd9Sstevel@tonic-gate long lc, cc; 102*7c478bd9Sstevel@tonic-gate register int c, t; 103*7c478bd9Sstevel@tonic-gate int hdrs; 104*7c478bd9Sstevel@tonic-gate char linebuf[LINESIZE+1], *cp; 105*7c478bd9Sstevel@tonic-gate char *iprompt; 106*7c478bd9Sstevel@tonic-gate int inhead; 107*7c478bd9Sstevel@tonic-gate void (*sigpipe)(int), (*sigint)(int); 108*7c478bd9Sstevel@tonic-gate int fd = -1; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate noreset++; 111*7c478bd9Sstevel@tonic-gate ibuf = obuf = NULL; 112*7c478bd9Sstevel@tonic-gate newi = newo = NULL; 113*7c478bd9Sstevel@tonic-gate if ((fd = open(tempMail, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 114*7c478bd9Sstevel@tonic-gate (obuf = fdopen(fd, "w")) == NULL) { 115*7c478bd9Sstevel@tonic-gate perror(tempMail); 116*7c478bd9Sstevel@tonic-gate goto err; 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate newo = obuf; 119*7c478bd9Sstevel@tonic-gate if ((ibuf = fopen(tempMail, "r")) == NULL) { 120*7c478bd9Sstevel@tonic-gate perror(tempMail); 121*7c478bd9Sstevel@tonic-gate newo = NULL; 122*7c478bd9Sstevel@tonic-gate fclose(obuf); 123*7c478bd9Sstevel@tonic-gate goto err; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate newi = ibuf; 126*7c478bd9Sstevel@tonic-gate removefile(tempMail); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate ignintr = (int)value("ignore"); 129*7c478bd9Sstevel@tonic-gate hadintr = 1; 130*7c478bd9Sstevel@tonic-gate inhead = 1; 131*7c478bd9Sstevel@tonic-gate savehp = hp; 132*7c478bd9Sstevel@tonic-gate # ifdef VMUNIX 133*7c478bd9Sstevel@tonic-gate if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN) 134*7c478bd9Sstevel@tonic-gate sigset(SIGINT, ignintr ? intack : collrub), sigblock(sigmask(SIGINT)); 135*7c478bd9Sstevel@tonic-gate if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN) 136*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, collrub), sigblock(sigmask(SIGHUP)); 137*7c478bd9Sstevel@tonic-gate # else VMUNIX 138*7c478bd9Sstevel@tonic-gate # ifdef OLD_BSD_SIGS 139*7c478bd9Sstevel@tonic-gate if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN) 140*7c478bd9Sstevel@tonic-gate sigset(SIGINT, ignintr ? intack : collrub); 141*7c478bd9Sstevel@tonic-gate if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN) 142*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, collrub); 143*7c478bd9Sstevel@tonic-gate # else 144*7c478bd9Sstevel@tonic-gate if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN) { 145*7c478bd9Sstevel@tonic-gate sigset_t mask; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate sigemptyset(&mask); 148*7c478bd9Sstevel@tonic-gate sigaddset(&mask, SIGINT); 149*7c478bd9Sstevel@tonic-gate sigset(SIGINT, ignintr ? intack : collrub); 150*7c478bd9Sstevel@tonic-gate sigprocmask(SIG_BLOCK, &mask, NULL); 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN) { 153*7c478bd9Sstevel@tonic-gate sigset_t mask; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate sigemptyset(&mask); 156*7c478bd9Sstevel@tonic-gate sigaddset(&mask, SIGHUP); 157*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, collrub); 158*7c478bd9Sstevel@tonic-gate sigprocmask(SIG_BLOCK, &mask, NULL); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate # endif 161*7c478bd9Sstevel@tonic-gate # endif VMUNIX 162*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 163*7c478bd9Sstevel@tonic-gate savecont = sigset(SIGCONT, collcont); 164*7c478bd9Sstevel@tonic-gate #endif 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * If we are going to prompt for subject/cc/bcc, 167*7c478bd9Sstevel@tonic-gate * refrain from printing a newline after 168*7c478bd9Sstevel@tonic-gate * the headers (since some people mind). 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate if (hp->h_subject == NOSTR) { 172*7c478bd9Sstevel@tonic-gate hp->h_subject = sflag; 173*7c478bd9Sstevel@tonic-gate sflag = NOSTR; 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate if (hp->h_cc == NOSTR) { 176*7c478bd9Sstevel@tonic-gate hp->h_cc = cflag; 177*7c478bd9Sstevel@tonic-gate cflag = NOSTR; 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate if (hp->h_bcc == NOSTR) { 180*7c478bd9Sstevel@tonic-gate hp->h_bcc = bflag; 181*7c478bd9Sstevel@tonic-gate bflag = NOSTR; 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate t = GMASK; 184*7c478bd9Sstevel@tonic-gate hdrs = 0; 185*7c478bd9Sstevel@tonic-gate if (intty && !tflag) { 186*7c478bd9Sstevel@tonic-gate if (hp->h_to == NOSTR) 187*7c478bd9Sstevel@tonic-gate hdrs |= GTO; 188*7c478bd9Sstevel@tonic-gate if (hp->h_subject == NOSTR && value("asksub")) 189*7c478bd9Sstevel@tonic-gate hdrs |= GSUBJECT; 190*7c478bd9Sstevel@tonic-gate if (hp->h_cc == NOSTR && value("askcc")) 191*7c478bd9Sstevel@tonic-gate hdrs |= GCC; 192*7c478bd9Sstevel@tonic-gate if (hp->h_bcc == NOSTR && value("askbcc")) 193*7c478bd9Sstevel@tonic-gate hdrs |= GBCC; 194*7c478bd9Sstevel@tonic-gate if (hdrs) 195*7c478bd9Sstevel@tonic-gate t &= ~GNL; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate if (hp->h_seq != 0) { 198*7c478bd9Sstevel@tonic-gate puthead(hp, stdout, t, 0); 199*7c478bd9Sstevel@tonic-gate fflush(stdout); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate if (setjmp(coljmp)) 202*7c478bd9Sstevel@tonic-gate goto err; 203*7c478bd9Sstevel@tonic-gate escape = SENDESC; 204*7c478bd9Sstevel@tonic-gate if ((cp = value("escape")) != NOSTR) 205*7c478bd9Sstevel@tonic-gate escape = *cp; 206*7c478bd9Sstevel@tonic-gate eof = 0; 207*7c478bd9Sstevel@tonic-gate if ((cp = value("MAILX_HEAD")) != NOSTR) { 208*7c478bd9Sstevel@tonic-gate cpout( cp, obuf); 209*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) 210*7c478bd9Sstevel@tonic-gate cpout( cp, stdout); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate iprompt = value("iprompt"); 213*7c478bd9Sstevel@tonic-gate fflush(obuf); 214*7c478bd9Sstevel@tonic-gate hadintr = 0; 215*7c478bd9Sstevel@tonic-gate for (;;) { 216*7c478bd9Sstevel@tonic-gate int nread, hasnulls; 217*7c478bd9Sstevel@tonic-gate # ifdef VMUNIX 218*7c478bd9Sstevel@tonic-gate int omask = sigblock(0) &~ (sigmask(SIGINT)|sigmask(SIGHUP)); 219*7c478bd9Sstevel@tonic-gate # else 220*7c478bd9Sstevel@tonic-gate # ifndef OLD_BSD_SIGS 221*7c478bd9Sstevel@tonic-gate sigset_t omask; 222*7c478bd9Sstevel@tonic-gate sigprocmask(0, NULL, &omask); 223*7c478bd9Sstevel@tonic-gate sigdelset(&omask, SIGINT); 224*7c478bd9Sstevel@tonic-gate sigdelset(&omask, SIGHUP); 225*7c478bd9Sstevel@tonic-gate # endif 226*7c478bd9Sstevel@tonic-gate # endif 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate setjmp(coljmp); 229*7c478bd9Sstevel@tonic-gate # ifdef VMUNIX 230*7c478bd9Sstevel@tonic-gate sigsetmask(omask); 231*7c478bd9Sstevel@tonic-gate # else VMUNIX 232*7c478bd9Sstevel@tonic-gate # ifdef OLD_BSD_SIGS 233*7c478bd9Sstevel@tonic-gate sigrelse(SIGINT); 234*7c478bd9Sstevel@tonic-gate sigrelse(SIGHUP); 235*7c478bd9Sstevel@tonic-gate # else 236*7c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, &omask, NULL); 237*7c478bd9Sstevel@tonic-gate # endif 238*7c478bd9Sstevel@tonic-gate # endif VMUNIX 239*7c478bd9Sstevel@tonic-gate if (intty && !tflag && outtty && iprompt) 240*7c478bd9Sstevel@tonic-gate fputs(iprompt, stdout); 241*7c478bd9Sstevel@tonic-gate flush(); 242*7c478bd9Sstevel@tonic-gate if (hdrs) { 243*7c478bd9Sstevel@tonic-gate grabh(hp, hdrs, 1); 244*7c478bd9Sstevel@tonic-gate hdrs = 0; 245*7c478bd9Sstevel@tonic-gate continue; 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate if ((nread = getline(linebuf,LINESIZE,stdin,&hasnulls)) == NULL) { 248*7c478bd9Sstevel@tonic-gate if (intty && value("ignoreeof") != NOSTR) { 249*7c478bd9Sstevel@tonic-gate if (++eof > 35) 250*7c478bd9Sstevel@tonic-gate break; 251*7c478bd9Sstevel@tonic-gate printf(gettext( 252*7c478bd9Sstevel@tonic-gate "Use \".\" to terminate letter\n")); 253*7c478bd9Sstevel@tonic-gate continue; 254*7c478bd9Sstevel@tonic-gate } 255*7c478bd9Sstevel@tonic-gate break; 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate eof = 0; 258*7c478bd9Sstevel@tonic-gate hadintr = 0; 259*7c478bd9Sstevel@tonic-gate if (intty && equal(".\n", linebuf) && 260*7c478bd9Sstevel@tonic-gate (value("dot") != NOSTR || value("ignoreeof") != NOSTR)) 261*7c478bd9Sstevel@tonic-gate break; 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * If -t, scan text for headers. 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate if (tflag) { 266*7c478bd9Sstevel@tonic-gate char *cp2; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate if (!inhead) { 269*7c478bd9Sstevel@tonic-gate writeit: 270*7c478bd9Sstevel@tonic-gate if (write(fileno(obuf),linebuf,nread) != nread) 271*7c478bd9Sstevel@tonic-gate goto werr; 272*7c478bd9Sstevel@tonic-gate continue; 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate if (linebuf[0] == '\n') { 275*7c478bd9Sstevel@tonic-gate /* got blank line after header, ignore it */ 276*7c478bd9Sstevel@tonic-gate inhead = 0; 277*7c478bd9Sstevel@tonic-gate continue; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate if (!headerp(linebuf)) { 280*7c478bd9Sstevel@tonic-gate /* got non-header line, save it */ 281*7c478bd9Sstevel@tonic-gate inhead = 0; 282*7c478bd9Sstevel@tonic-gate goto writeit; 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate if (hasnulls) 285*7c478bd9Sstevel@tonic-gate nread = stripnulls(linebuf, nread); 286*7c478bd9Sstevel@tonic-gate for (;;) { 287*7c478bd9Sstevel@tonic-gate char line2[LINESIZE]; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate c = getc(stdin); 290*7c478bd9Sstevel@tonic-gate ungetc(c, stdin); 291*7c478bd9Sstevel@tonic-gate if (!isspace(c) || c == '\n') 292*7c478bd9Sstevel@tonic-gate break; 293*7c478bd9Sstevel@tonic-gate if (readline(stdin, line2) < 0) 294*7c478bd9Sstevel@tonic-gate break; 295*7c478bd9Sstevel@tonic-gate for (cp2 = line2; *cp2 != 0 && isspace(*cp2); 296*7c478bd9Sstevel@tonic-gate cp2++) 297*7c478bd9Sstevel@tonic-gate ; 298*7c478bd9Sstevel@tonic-gate if (strlen(linebuf) + strlen(cp2) >= 299*7c478bd9Sstevel@tonic-gate (unsigned)LINESIZE-2) 300*7c478bd9Sstevel@tonic-gate break; 301*7c478bd9Sstevel@tonic-gate cp = &linebuf[strlen(linebuf)]; 302*7c478bd9Sstevel@tonic-gate while (cp > linebuf && 303*7c478bd9Sstevel@tonic-gate (isspace(cp[-1]) || cp[-1] == '\\')) 304*7c478bd9Sstevel@tonic-gate cp--; 305*7c478bd9Sstevel@tonic-gate *cp++ = ' '; 306*7c478bd9Sstevel@tonic-gate strcpy(cp, cp2); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate if ((c = strlen(linebuf)) > 0) { 309*7c478bd9Sstevel@tonic-gate cp = &linebuf[c-1]; 310*7c478bd9Sstevel@tonic-gate while (cp > linebuf && isspace(*cp)) 311*7c478bd9Sstevel@tonic-gate cp--; 312*7c478bd9Sstevel@tonic-gate *++cp = 0; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate if (ishfield(linebuf, "to")) 315*7c478bd9Sstevel@tonic-gate hp->h_to = addto(hp->h_to, hcontents(linebuf)); 316*7c478bd9Sstevel@tonic-gate else if (ishfield(linebuf, "subject")) 317*7c478bd9Sstevel@tonic-gate hp->h_subject = 318*7c478bd9Sstevel@tonic-gate addone(hp->h_subject, hcontents(linebuf)); 319*7c478bd9Sstevel@tonic-gate else if (ishfield(linebuf, "cc")) 320*7c478bd9Sstevel@tonic-gate hp->h_cc = addto(hp->h_cc, hcontents(linebuf)); 321*7c478bd9Sstevel@tonic-gate else if (ishfield(linebuf, "bcc")) 322*7c478bd9Sstevel@tonic-gate hp->h_bcc = 323*7c478bd9Sstevel@tonic-gate addto(hp->h_bcc, hcontents(linebuf)); 324*7c478bd9Sstevel@tonic-gate else if (ishfield(linebuf, "default-options")) 325*7c478bd9Sstevel@tonic-gate hp->h_defopt = 326*7c478bd9Sstevel@tonic-gate addone(hp->h_defopt, hcontents(linebuf)); 327*7c478bd9Sstevel@tonic-gate else 328*7c478bd9Sstevel@tonic-gate hp->h_others = Xaddone(hp->h_others, linebuf); 329*7c478bd9Sstevel@tonic-gate hp->h_seq++; 330*7c478bd9Sstevel@tonic-gate continue; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate if ((linebuf[0] != escape) || (rflag != NOSTR) || 333*7c478bd9Sstevel@tonic-gate (!intty && !(int)value("escapeok"))) { 334*7c478bd9Sstevel@tonic-gate if (write(fileno(obuf),linebuf,nread) != nread) 335*7c478bd9Sstevel@tonic-gate goto werr; 336*7c478bd9Sstevel@tonic-gate continue; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * On double escape, just send the single one. 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate if ((nread > 1) && (linebuf[1] == escape)) { 342*7c478bd9Sstevel@tonic-gate if (write(fileno(obuf),linebuf+1,nread-1) != (nread-1)) 343*7c478bd9Sstevel@tonic-gate goto werr; 344*7c478bd9Sstevel@tonic-gate continue; 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate if (hasnulls) 347*7c478bd9Sstevel@tonic-gate nread = stripnulls(linebuf, nread); 348*7c478bd9Sstevel@tonic-gate c = linebuf[1]; 349*7c478bd9Sstevel@tonic-gate linebuf[nread - 1] = '\0'; 350*7c478bd9Sstevel@tonic-gate switch (c) { 351*7c478bd9Sstevel@tonic-gate default: 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Otherwise, it's an error. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate printf(gettext("Unknown tilde escape.\n")); 356*7c478bd9Sstevel@tonic-gate break; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate case 'a': 359*7c478bd9Sstevel@tonic-gate case 'A': 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * autograph; sign the letter. 362*7c478bd9Sstevel@tonic-gate */ 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate if (cp = value(c=='a' ? "sign":"Sign")) { 365*7c478bd9Sstevel@tonic-gate if (*cp) 366*7c478bd9Sstevel@tonic-gate cpout( cp, obuf); 367*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) { 368*7c478bd9Sstevel@tonic-gate if (*cp) 369*7c478bd9Sstevel@tonic-gate cpout( cp, stdout); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate break; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate case 'i': 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * insert string 378*7c478bd9Sstevel@tonic-gate */ 379*7c478bd9Sstevel@tonic-gate for (cp = &linebuf[2]; any(*cp, " \t"); cp++) 380*7c478bd9Sstevel@tonic-gate ; 381*7c478bd9Sstevel@tonic-gate if (*cp) 382*7c478bd9Sstevel@tonic-gate cp = value(cp); 383*7c478bd9Sstevel@tonic-gate if (cp != NOSTR) { 384*7c478bd9Sstevel@tonic-gate if (*cp) 385*7c478bd9Sstevel@tonic-gate cpout(cp, obuf); 386*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdout))) { 387*7c478bd9Sstevel@tonic-gate if (*cp) 388*7c478bd9Sstevel@tonic-gate cpout(cp, stdout); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate break; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate case '!': 394*7c478bd9Sstevel@tonic-gate /* 395*7c478bd9Sstevel@tonic-gate * Shell escape, send the balance of the 396*7c478bd9Sstevel@tonic-gate * line to sh -c. 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate shell(&linebuf[2]); 400*7c478bd9Sstevel@tonic-gate break; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate case ':': 403*7c478bd9Sstevel@tonic-gate case '_': 404*7c478bd9Sstevel@tonic-gate /* 405*7c478bd9Sstevel@tonic-gate * Escape to command mode, but be nice! 406*7c478bd9Sstevel@tonic-gate */ 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate execute(&linebuf[2], 1); 409*7c478bd9Sstevel@tonic-gate iprompt = value("iprompt"); 410*7c478bd9Sstevel@tonic-gate if (cp = value("escape")) 411*7c478bd9Sstevel@tonic-gate escape = *cp; 412*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 413*7c478bd9Sstevel@tonic-gate break; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate case '.': 416*7c478bd9Sstevel@tonic-gate /* 417*7c478bd9Sstevel@tonic-gate * Simulate end of file on input. 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate goto eofl; 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate case 'q': 422*7c478bd9Sstevel@tonic-gate case 'Q': 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * Force a quit of sending mail. 425*7c478bd9Sstevel@tonic-gate * Act like an interrupt happened. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate hadintr++; 429*7c478bd9Sstevel@tonic-gate collrub(SIGINT); 430*7c478bd9Sstevel@tonic-gate exit(1); 431*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate case 'x': 434*7c478bd9Sstevel@tonic-gate xhalt(); 435*7c478bd9Sstevel@tonic-gate break; /* not reached */ 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate case 'h': 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * Grab a bunch of headers. 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate if (!intty || !outtty) { 442*7c478bd9Sstevel@tonic-gate printf(gettext("~h: no can do!?\n")); 443*7c478bd9Sstevel@tonic-gate break; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate grabh(hp, GMASK, (int)value("bsdcompat")); 446*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 447*7c478bd9Sstevel@tonic-gate break; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate case 't': 450*7c478bd9Sstevel@tonic-gate /* 451*7c478bd9Sstevel@tonic-gate * Add to the To list. 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate hp->h_to = addto(hp->h_to, &linebuf[2]); 455*7c478bd9Sstevel@tonic-gate hp->h_seq++; 456*7c478bd9Sstevel@tonic-gate break; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate case 's': 459*7c478bd9Sstevel@tonic-gate /* 460*7c478bd9Sstevel@tonic-gate * Set the Subject list. 461*7c478bd9Sstevel@tonic-gate */ 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate cp = &linebuf[2]; 464*7c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 465*7c478bd9Sstevel@tonic-gate cp++; 466*7c478bd9Sstevel@tonic-gate hp->h_subject = savestr(cp); 467*7c478bd9Sstevel@tonic-gate hp->h_seq++; 468*7c478bd9Sstevel@tonic-gate break; 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate case 'c': 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate * Add to the CC list. 473*7c478bd9Sstevel@tonic-gate */ 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate hp->h_cc = addto(hp->h_cc, &linebuf[2]); 476*7c478bd9Sstevel@tonic-gate hp->h_seq++; 477*7c478bd9Sstevel@tonic-gate break; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate case 'b': 480*7c478bd9Sstevel@tonic-gate /* 481*7c478bd9Sstevel@tonic-gate * Add stuff to blind carbon copies list. 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate hp->h_bcc = addto(hp->h_bcc, &linebuf[2]); 484*7c478bd9Sstevel@tonic-gate hp->h_seq++; 485*7c478bd9Sstevel@tonic-gate break; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate case 'R': 488*7c478bd9Sstevel@tonic-gate hp->h_defopt = addone(hp->h_defopt, myname); 489*7c478bd9Sstevel@tonic-gate hp->h_seq++; 490*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Return receipt marked.\n")); 491*7c478bd9Sstevel@tonic-gate receipt_flg = 1; 492*7c478bd9Sstevel@tonic-gate break; 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate case 'd': 495*7c478bd9Sstevel@tonic-gate copy(Getf("DEAD"), &linebuf[2]); 496*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate case '<': 499*7c478bd9Sstevel@tonic-gate case 'r': { 500*7c478bd9Sstevel@tonic-gate int ispip; 501*7c478bd9Sstevel@tonic-gate /* 502*7c478bd9Sstevel@tonic-gate * Invoke a file: 503*7c478bd9Sstevel@tonic-gate * Search for the file name, 504*7c478bd9Sstevel@tonic-gate * then open it and copy the contents to obuf. 505*7c478bd9Sstevel@tonic-gate * 506*7c478bd9Sstevel@tonic-gate * if name begins with '!', read from a command 507*7c478bd9Sstevel@tonic-gate */ 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate cp = &linebuf[2]; 510*7c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 511*7c478bd9Sstevel@tonic-gate cp++; 512*7c478bd9Sstevel@tonic-gate if (*cp == '\0') { 513*7c478bd9Sstevel@tonic-gate printf(gettext("Interpolate what file?\n")); 514*7c478bd9Sstevel@tonic-gate break; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate if (*cp=='!') { 517*7c478bd9Sstevel@tonic-gate /* take input from a command */ 518*7c478bd9Sstevel@tonic-gate ispip = 1; 519*7c478bd9Sstevel@tonic-gate if ((fbuf = npopen(++cp, "r"))==NULL) { 520*7c478bd9Sstevel@tonic-gate perror(""); 521*7c478bd9Sstevel@tonic-gate break; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate sigint = sigset(SIGINT, SIG_IGN); 524*7c478bd9Sstevel@tonic-gate } else { 525*7c478bd9Sstevel@tonic-gate ispip = 0; 526*7c478bd9Sstevel@tonic-gate cp = expand(cp); 527*7c478bd9Sstevel@tonic-gate if (cp == NOSTR) 528*7c478bd9Sstevel@tonic-gate break; 529*7c478bd9Sstevel@tonic-gate if (isdir(cp)) { 530*7c478bd9Sstevel@tonic-gate printf(gettext("%s: directory\n"), cp); 531*7c478bd9Sstevel@tonic-gate break; 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate if ((fbuf = fopen(cp, "r")) == NULL) { 534*7c478bd9Sstevel@tonic-gate perror(cp); 535*7c478bd9Sstevel@tonic-gate break; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate printf("\"%s\" ", cp); 539*7c478bd9Sstevel@tonic-gate flush(); 540*7c478bd9Sstevel@tonic-gate lc = cc = 0; 541*7c478bd9Sstevel@tonic-gate while ((t = getc(fbuf)) != EOF) { 542*7c478bd9Sstevel@tonic-gate if (t == '\n') 543*7c478bd9Sstevel@tonic-gate lc++; 544*7c478bd9Sstevel@tonic-gate if (putc(t, obuf) == EOF) { 545*7c478bd9Sstevel@tonic-gate if (ispip) { 546*7c478bd9Sstevel@tonic-gate npclose(fbuf); 547*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 548*7c478bd9Sstevel@tonic-gate } else 549*7c478bd9Sstevel@tonic-gate fclose(fbuf); 550*7c478bd9Sstevel@tonic-gate goto werr; 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate cc++; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate if (ispip) { 555*7c478bd9Sstevel@tonic-gate npclose(fbuf); 556*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 557*7c478bd9Sstevel@tonic-gate } else 558*7c478bd9Sstevel@tonic-gate fclose(fbuf); 559*7c478bd9Sstevel@tonic-gate printf("%ld/%ld\n", lc, cc); 560*7c478bd9Sstevel@tonic-gate fflush(obuf); 561*7c478bd9Sstevel@tonic-gate break; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate case 'w': 565*7c478bd9Sstevel@tonic-gate /* 566*7c478bd9Sstevel@tonic-gate * Write the message on a file. 567*7c478bd9Sstevel@tonic-gate */ 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate cp = &linebuf[2]; 570*7c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 571*7c478bd9Sstevel@tonic-gate cp++; 572*7c478bd9Sstevel@tonic-gate if (*cp == '\0') { 573*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Write what file!?\n")); 574*7c478bd9Sstevel@tonic-gate break; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate if ((cp = expand(cp)) == NOSTR) 577*7c478bd9Sstevel@tonic-gate break; 578*7c478bd9Sstevel@tonic-gate fflush(obuf); 579*7c478bd9Sstevel@tonic-gate rewind(ibuf); 580*7c478bd9Sstevel@tonic-gate exwrite(cp, ibuf); 581*7c478bd9Sstevel@tonic-gate break; 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate case 'm': 584*7c478bd9Sstevel@tonic-gate case 'M': 585*7c478bd9Sstevel@tonic-gate case 'f': 586*7c478bd9Sstevel@tonic-gate case 'F': 587*7c478bd9Sstevel@tonic-gate /* 588*7c478bd9Sstevel@tonic-gate * Interpolate the named messages, if we 589*7c478bd9Sstevel@tonic-gate * are in receiving mail mode. Does the 590*7c478bd9Sstevel@tonic-gate * standard list processing garbage. 591*7c478bd9Sstevel@tonic-gate * If ~f or ~F is given, we don't shift over. 592*7c478bd9Sstevel@tonic-gate */ 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate if (!rcvmode) { 595*7c478bd9Sstevel@tonic-gate printf(gettext( 596*7c478bd9Sstevel@tonic-gate "No messages to send from!?!\n")); 597*7c478bd9Sstevel@tonic-gate break; 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate cp = &linebuf[2]; 600*7c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 601*7c478bd9Sstevel@tonic-gate cp++; 602*7c478bd9Sstevel@tonic-gate if (forward(cp, obuf, c) < 0) 603*7c478bd9Sstevel@tonic-gate goto werr; 604*7c478bd9Sstevel@tonic-gate fflush(obuf); 605*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 606*7c478bd9Sstevel@tonic-gate break; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate case '?': 609*7c478bd9Sstevel@tonic-gate if ((fbuf = fopen(THELPFILE, "r")) == NULL) { 610*7c478bd9Sstevel@tonic-gate printf(gettext("No help just now.\n")); 611*7c478bd9Sstevel@tonic-gate break; 612*7c478bd9Sstevel@tonic-gate } 613*7c478bd9Sstevel@tonic-gate t = getc(fbuf); 614*7c478bd9Sstevel@tonic-gate while (t != -1) { 615*7c478bd9Sstevel@tonic-gate putchar(t); 616*7c478bd9Sstevel@tonic-gate t = getc(fbuf); 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate fclose(fbuf); 619*7c478bd9Sstevel@tonic-gate break; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate case 'p': { 622*7c478bd9Sstevel@tonic-gate /* 623*7c478bd9Sstevel@tonic-gate * Print out the current state of the 624*7c478bd9Sstevel@tonic-gate * message without altering anything. 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate int nlines; 627*7c478bd9Sstevel@tonic-gate extern jmp_buf pipestop; 628*7c478bd9Sstevel@tonic-gate extern void brokpipe(int); 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate fflush(obuf); 631*7c478bd9Sstevel@tonic-gate rewind(ibuf); 632*7c478bd9Sstevel@tonic-gate fbuf = stdout; 633*7c478bd9Sstevel@tonic-gate if (setjmp(pipestop)) 634*7c478bd9Sstevel@tonic-gate goto ret0; 635*7c478bd9Sstevel@tonic-gate if (intty && outtty && (cp = value("crt")) != NOSTR) { 636*7c478bd9Sstevel@tonic-gate nlines = 637*7c478bd9Sstevel@tonic-gate (*cp == '\0' ? screensize() : atoi(cp)) - 7; 638*7c478bd9Sstevel@tonic-gate /* 7 for hdr lines */ 639*7c478bd9Sstevel@tonic-gate while ((t = getc(ibuf)) != EOF) { 640*7c478bd9Sstevel@tonic-gate if (t == '\n') 641*7c478bd9Sstevel@tonic-gate if (--nlines <= 0) 642*7c478bd9Sstevel@tonic-gate break; 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate rewind(ibuf); 645*7c478bd9Sstevel@tonic-gate if (nlines <= 0) { 646*7c478bd9Sstevel@tonic-gate fbuf = npopen(MORE, "w"); 647*7c478bd9Sstevel@tonic-gate if (fbuf == NULL) { 648*7c478bd9Sstevel@tonic-gate perror(MORE); 649*7c478bd9Sstevel@tonic-gate fbuf = stdout; 650*7c478bd9Sstevel@tonic-gate } else { 651*7c478bd9Sstevel@tonic-gate sigint = sigset(SIGINT, SIG_IGN); 652*7c478bd9Sstevel@tonic-gate sigpipe = sigset(SIGPIPE, brokpipe); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate fprintf(fbuf, gettext("-------\nMessage contains:\n")); 657*7c478bd9Sstevel@tonic-gate puthead(hp, fbuf, GMASK, 0); 658*7c478bd9Sstevel@tonic-gate while ((t = getc(ibuf))!=EOF) 659*7c478bd9Sstevel@tonic-gate putc(t, fbuf); 660*7c478bd9Sstevel@tonic-gate ret0: 661*7c478bd9Sstevel@tonic-gate if (fbuf != stdout) { 662*7c478bd9Sstevel@tonic-gate npclose(fbuf); 663*7c478bd9Sstevel@tonic-gate sigset(SIGPIPE, sigpipe); 664*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 667*7c478bd9Sstevel@tonic-gate break; 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate case '^': 671*7c478bd9Sstevel@tonic-gate case '|': 672*7c478bd9Sstevel@tonic-gate /* 673*7c478bd9Sstevel@tonic-gate * Pipe message through command. 674*7c478bd9Sstevel@tonic-gate * Collect output as new message. 675*7c478bd9Sstevel@tonic-gate */ 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate obuf = mespipe(ibuf, obuf, &linebuf[2]); 678*7c478bd9Sstevel@tonic-gate newo = obuf; 679*7c478bd9Sstevel@tonic-gate ibuf = newi; 680*7c478bd9Sstevel@tonic-gate newi = ibuf; 681*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 682*7c478bd9Sstevel@tonic-gate break; 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate case 'v': 685*7c478bd9Sstevel@tonic-gate case 'e': 686*7c478bd9Sstevel@tonic-gate /* 687*7c478bd9Sstevel@tonic-gate * Edit the current message. 688*7c478bd9Sstevel@tonic-gate * 'e' means to use EDITOR 689*7c478bd9Sstevel@tonic-gate * 'v' means to use VISUAL 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate if ((obuf = mesedit(ibuf, obuf, c, hp)) == NULL) 693*7c478bd9Sstevel@tonic-gate goto err; 694*7c478bd9Sstevel@tonic-gate newo = obuf; 695*7c478bd9Sstevel@tonic-gate ibuf = newi; 696*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 697*7c478bd9Sstevel@tonic-gate break; 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate fflush(obuf); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate eofl: 702*7c478bd9Sstevel@tonic-gate fflush(obuf); 703*7c478bd9Sstevel@tonic-gate if ((cp = value("MAILX_TAIL")) != NOSTR) { 704*7c478bd9Sstevel@tonic-gate cpout( cp, obuf); 705*7c478bd9Sstevel@tonic-gate if (isatty(fileno(stdin))) 706*7c478bd9Sstevel@tonic-gate cpout( cp, stdout); 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate fclose(obuf); 709*7c478bd9Sstevel@tonic-gate rewind(ibuf); 710*7c478bd9Sstevel@tonic-gate resetsigs(0); 711*7c478bd9Sstevel@tonic-gate noreset = 0; 712*7c478bd9Sstevel@tonic-gate return(ibuf); 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate werr: 715*7c478bd9Sstevel@tonic-gate /* 716*7c478bd9Sstevel@tonic-gate * Write error occurred on tmp file, save partial 717*7c478bd9Sstevel@tonic-gate * message in dead.letter. 718*7c478bd9Sstevel@tonic-gate */ 719*7c478bd9Sstevel@tonic-gate perror(tempMail); 720*7c478bd9Sstevel@tonic-gate fflush(obuf); 721*7c478bd9Sstevel@tonic-gate rewind(ibuf); 722*7c478bd9Sstevel@tonic-gate if (fsize(ibuf) > 0) { 723*7c478bd9Sstevel@tonic-gate char *deadletter; 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate deadletter = Getf("DEAD"); 726*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Saving partial message in %s\n"), 727*7c478bd9Sstevel@tonic-gate deadletter); 728*7c478bd9Sstevel@tonic-gate if ((fbuf = fopen(deadletter, 729*7c478bd9Sstevel@tonic-gate value("appenddeadletter") == NOSTR ? "w" : "a")) != NULL) { 730*7c478bd9Sstevel@tonic-gate chmod(deadletter, DEADPERM); 731*7c478bd9Sstevel@tonic-gate puthead(hp, fbuf, GMASK|GCLEN, fsize(ibuf)); 732*7c478bd9Sstevel@tonic-gate lcwrite(deadletter, ibuf, fbuf, value("appenddeadletter") != NOSTR); 733*7c478bd9Sstevel@tonic-gate fclose(fbuf); 734*7c478bd9Sstevel@tonic-gate } else 735*7c478bd9Sstevel@tonic-gate perror(deadletter); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate err: 739*7c478bd9Sstevel@tonic-gate if (ibuf != NULL) 740*7c478bd9Sstevel@tonic-gate fclose(ibuf); 741*7c478bd9Sstevel@tonic-gate if (obuf != NULL) 742*7c478bd9Sstevel@tonic-gate fclose(obuf); 743*7c478bd9Sstevel@tonic-gate resetsigs(0); 744*7c478bd9Sstevel@tonic-gate noreset = 0; 745*7c478bd9Sstevel@tonic-gate return(NULL); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate static void 749*7c478bd9Sstevel@tonic-gate resetsigs(int resethup) 750*7c478bd9Sstevel@tonic-gate { 751*7c478bd9Sstevel@tonic-gate (void) sigset(SIGINT, savesig); 752*7c478bd9Sstevel@tonic-gate if (resethup) 753*7c478bd9Sstevel@tonic-gate (void) sigset(SIGHUP, savehup); 754*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 755*7c478bd9Sstevel@tonic-gate # ifdef preSVr4 756*7c478bd9Sstevel@tonic-gate (void) sigset(SIGCONT, savecont); 757*7c478bd9Sstevel@tonic-gate # else 758*7c478bd9Sstevel@tonic-gate { 759*7c478bd9Sstevel@tonic-gate struct sigaction nsig; 760*7c478bd9Sstevel@tonic-gate nsig.sa_handler = (void (*)())savecont; 761*7c478bd9Sstevel@tonic-gate sigemptyset(&nsig.sa_mask); 762*7c478bd9Sstevel@tonic-gate nsig.sa_flags = SA_RESTART; 763*7c478bd9Sstevel@tonic-gate (void) sigaction(SIGCONT, &nsig, (struct sigaction*)0); 764*7c478bd9Sstevel@tonic-gate } 765*7c478bd9Sstevel@tonic-gate # endif 766*7c478bd9Sstevel@tonic-gate #endif 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate /* 770*7c478bd9Sstevel@tonic-gate * Write a file ex-like. 771*7c478bd9Sstevel@tonic-gate */ 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate static int 774*7c478bd9Sstevel@tonic-gate exwrite(char name[], FILE *ibuf) 775*7c478bd9Sstevel@tonic-gate { 776*7c478bd9Sstevel@tonic-gate register FILE *of; 777*7c478bd9Sstevel@tonic-gate struct stat junk; 778*7c478bd9Sstevel@tonic-gate void (*sigint)(int), (*sigpipe)(int); 779*7c478bd9Sstevel@tonic-gate int pi = (*name == '!'); 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate if ((of = pi ? npopen(++name, "w") : fopen(name, "a")) == NULL) { 782*7c478bd9Sstevel@tonic-gate perror(name); 783*7c478bd9Sstevel@tonic-gate return(-1); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate if (pi) { 786*7c478bd9Sstevel@tonic-gate sigint = sigset(SIGINT, SIG_IGN); 787*7c478bd9Sstevel@tonic-gate sigpipe = sigset(SIGPIPE, SIG_IGN); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate lcwrite(name, ibuf, of, 0); 790*7c478bd9Sstevel@tonic-gate pi ? npclose(of) : fclose(of); 791*7c478bd9Sstevel@tonic-gate if (pi) { 792*7c478bd9Sstevel@tonic-gate sigset(SIGPIPE, sigpipe); 793*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate return(0); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate void 799*7c478bd9Sstevel@tonic-gate lcwrite(char *fn, FILE *fi, FILE *fo, int addnl) 800*7c478bd9Sstevel@tonic-gate { 801*7c478bd9Sstevel@tonic-gate register int c; 802*7c478bd9Sstevel@tonic-gate long lc, cc; 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate printf("\"%s\" ", fn); 805*7c478bd9Sstevel@tonic-gate fflush(stdout); 806*7c478bd9Sstevel@tonic-gate lc = cc = 0; 807*7c478bd9Sstevel@tonic-gate while ((c = getc(fi)) != EOF) { 808*7c478bd9Sstevel@tonic-gate cc++; 809*7c478bd9Sstevel@tonic-gate if (putc(c, fo) == '\n') 810*7c478bd9Sstevel@tonic-gate lc++; 811*7c478bd9Sstevel@tonic-gate if (ferror(fo)) { 812*7c478bd9Sstevel@tonic-gate perror(""); 813*7c478bd9Sstevel@tonic-gate return; 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate if (addnl) { 817*7c478bd9Sstevel@tonic-gate putc('\n', fo); 818*7c478bd9Sstevel@tonic-gate lc++; 819*7c478bd9Sstevel@tonic-gate cc++; 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate fflush(fo); 822*7c478bd9Sstevel@tonic-gate if (fferror(fo)) { 823*7c478bd9Sstevel@tonic-gate perror(""); 824*7c478bd9Sstevel@tonic-gate return; 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate printf("%ld/%ld\n", lc, cc); 827*7c478bd9Sstevel@tonic-gate fflush(stdout); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * Edit the message being collected on ibuf and obuf. 832*7c478bd9Sstevel@tonic-gate * Write the message out onto some poorly-named temp file 833*7c478bd9Sstevel@tonic-gate * and point an editor at it. 834*7c478bd9Sstevel@tonic-gate * 835*7c478bd9Sstevel@tonic-gate * On return, make the edit file the new temp file. 836*7c478bd9Sstevel@tonic-gate */ 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate static FILE * 839*7c478bd9Sstevel@tonic-gate mesedit(FILE *ibuf, FILE *obuf, int c, struct header *hp) 840*7c478bd9Sstevel@tonic-gate { 841*7c478bd9Sstevel@tonic-gate pid_t pid; 842*7c478bd9Sstevel@tonic-gate FILE *fbuf; 843*7c478bd9Sstevel@tonic-gate register int t; 844*7c478bd9Sstevel@tonic-gate void (*sigint)(int); 845*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 846*7c478bd9Sstevel@tonic-gate void (*sigcont)(int); 847*7c478bd9Sstevel@tonic-gate #endif 848*7c478bd9Sstevel@tonic-gate struct stat sbuf; 849*7c478bd9Sstevel@tonic-gate register char *edit; 850*7c478bd9Sstevel@tonic-gate char hdr[LINESIZE]; 851*7c478bd9Sstevel@tonic-gate char *oto, *osubject, *occ, *obcc, **oothers; 852*7c478bd9Sstevel@tonic-gate int fd = -1; 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate if (stat(tempEdit, &sbuf) >= 0) { 855*7c478bd9Sstevel@tonic-gate printf(gettext("%s: file exists\n"), tempEdit); 856*7c478bd9Sstevel@tonic-gate goto out; 857*7c478bd9Sstevel@tonic-gate } 858*7c478bd9Sstevel@tonic-gate if ((fd = open(tempEdit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 859*7c478bd9Sstevel@tonic-gate (fbuf = fdopen(fd, "w")) == NULL) { 860*7c478bd9Sstevel@tonic-gate perror(tempEdit); 861*7c478bd9Sstevel@tonic-gate goto out; 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate fflush(obuf); 864*7c478bd9Sstevel@tonic-gate rewind(ibuf); 865*7c478bd9Sstevel@tonic-gate puthead(hp, fbuf, GMASK, 0); 866*7c478bd9Sstevel@tonic-gate while ((t = getc(ibuf)) != EOF) 867*7c478bd9Sstevel@tonic-gate putc(t, fbuf); 868*7c478bd9Sstevel@tonic-gate fflush(fbuf); 869*7c478bd9Sstevel@tonic-gate if (fferror(fbuf)) { 870*7c478bd9Sstevel@tonic-gate perror(tempEdit); 871*7c478bd9Sstevel@tonic-gate removefile(tempEdit); 872*7c478bd9Sstevel@tonic-gate goto out; 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate fclose(fbuf); 875*7c478bd9Sstevel@tonic-gate if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR || 876*7c478bd9Sstevel@tonic-gate *edit == '\0') 877*7c478bd9Sstevel@tonic-gate edit = c == 'e' ? EDITOR : VISUAL; 878*7c478bd9Sstevel@tonic-gate edit = safeexpand(edit); 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate /* 881*7c478bd9Sstevel@tonic-gate * Fork/execlp the editor on the edit file 882*7c478bd9Sstevel@tonic-gate */ 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate pid = vfork(); 885*7c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) { 886*7c478bd9Sstevel@tonic-gate perror("fork"); 887*7c478bd9Sstevel@tonic-gate removefile(tempEdit); 888*7c478bd9Sstevel@tonic-gate goto out; 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate if (pid == 0) { 891*7c478bd9Sstevel@tonic-gate char ecmd[BUFSIZ]; 892*7c478bd9Sstevel@tonic-gate char *Shell; 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate sigchild(); 895*7c478bd9Sstevel@tonic-gate execlp(edit, edit, tempEdit, (char *)0); 896*7c478bd9Sstevel@tonic-gate /* 897*7c478bd9Sstevel@tonic-gate * If execlp fails, "edit" might really be a complete 898*7c478bd9Sstevel@tonic-gate * shell command, not a simple pathname. Try using 899*7c478bd9Sstevel@tonic-gate * the shell to run it. 900*7c478bd9Sstevel@tonic-gate */ 901*7c478bd9Sstevel@tonic-gate snprintf(ecmd, sizeof (ecmd), "exec %s %s", edit, tempEdit); 902*7c478bd9Sstevel@tonic-gate if ((Shell = value("SHELL")) == NULL || *Shell=='\0') 903*7c478bd9Sstevel@tonic-gate Shell = SHELL; 904*7c478bd9Sstevel@tonic-gate execlp(Shell, Shell, "-c", ecmd, NULL); 905*7c478bd9Sstevel@tonic-gate perror(edit); 906*7c478bd9Sstevel@tonic-gate _exit(1); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate sigint = sigset(SIGINT, SIG_IGN); 909*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 910*7c478bd9Sstevel@tonic-gate sigcont = sigset(SIGCONT, SIG_DFL); 911*7c478bd9Sstevel@tonic-gate #endif 912*7c478bd9Sstevel@tonic-gate while (wait((int *)0) != pid) 913*7c478bd9Sstevel@tonic-gate ; 914*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 915*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 916*7c478bd9Sstevel@tonic-gate sigset(SIGCONT, sigcont); 917*7c478bd9Sstevel@tonic-gate #endif 918*7c478bd9Sstevel@tonic-gate /* 919*7c478bd9Sstevel@tonic-gate * Now switch to new file. 920*7c478bd9Sstevel@tonic-gate */ 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate if ((fbuf = fopen(tempEdit, "r")) == NULL) { 923*7c478bd9Sstevel@tonic-gate perror(tempEdit); 924*7c478bd9Sstevel@tonic-gate removefile(tempEdit); 925*7c478bd9Sstevel@tonic-gate goto out; 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate removefile(tempEdit); 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate /* save the old headers, in case they are accidentally deleted */ 930*7c478bd9Sstevel@tonic-gate osubject = hp->h_subject; 931*7c478bd9Sstevel@tonic-gate oto = hp->h_to; 932*7c478bd9Sstevel@tonic-gate occ = hp->h_cc; 933*7c478bd9Sstevel@tonic-gate obcc = hp->h_bcc; 934*7c478bd9Sstevel@tonic-gate oothers = hp->h_others; 935*7c478bd9Sstevel@tonic-gate hp->h_to = hp->h_subject = hp->h_cc = hp->h_bcc = hp->h_defopt = NOSTR; 936*7c478bd9Sstevel@tonic-gate hp->h_others = NOSTRPTR; 937*7c478bd9Sstevel@tonic-gate hp->h_seq = 0; 938*7c478bd9Sstevel@tonic-gate while (gethfield(fbuf, hdr, 9999L) > 0) { 939*7c478bd9Sstevel@tonic-gate if (ishfield(hdr, "to")) 940*7c478bd9Sstevel@tonic-gate hp->h_to = addto(hp->h_to, hcontents(hdr)); 941*7c478bd9Sstevel@tonic-gate else if (ishfield(hdr, "subject")) 942*7c478bd9Sstevel@tonic-gate hp->h_subject = addone(hp->h_subject, hcontents(hdr)); 943*7c478bd9Sstevel@tonic-gate else if (ishfield(hdr, "cc")) 944*7c478bd9Sstevel@tonic-gate hp->h_cc = addto(hp->h_cc, hcontents(hdr)); 945*7c478bd9Sstevel@tonic-gate else if (ishfield(hdr, "bcc")) 946*7c478bd9Sstevel@tonic-gate hp->h_bcc = addto(hp->h_bcc, hcontents(hdr)); 947*7c478bd9Sstevel@tonic-gate else if (ishfield(hdr, "default-options")) 948*7c478bd9Sstevel@tonic-gate hp->h_defopt = addone(hp->h_defopt, hcontents(hdr)); 949*7c478bd9Sstevel@tonic-gate else 950*7c478bd9Sstevel@tonic-gate hp->h_others = Xaddone(hp->h_others, hdr); 951*7c478bd9Sstevel@tonic-gate hp->h_seq++; 952*7c478bd9Sstevel@tonic-gate } 953*7c478bd9Sstevel@tonic-gate if (hp->h_seq == 0) { 954*7c478bd9Sstevel@tonic-gate /* if we didn't see any headers, restore the original headers */ 955*7c478bd9Sstevel@tonic-gate hp->h_subject = osubject; 956*7c478bd9Sstevel@tonic-gate hp->h_to = oto; 957*7c478bd9Sstevel@tonic-gate hp->h_cc = occ; 958*7c478bd9Sstevel@tonic-gate hp->h_bcc = obcc; 959*7c478bd9Sstevel@tonic-gate hp->h_others = oothers; 960*7c478bd9Sstevel@tonic-gate printf(gettext( 961*7c478bd9Sstevel@tonic-gate "(Deleted headers restored to original values)\n")); 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate if ((fd = open(tempMail, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 964*7c478bd9Sstevel@tonic-gate (obuf = fdopen(fd, "w")) == NULL) { 965*7c478bd9Sstevel@tonic-gate perror(tempMail); 966*7c478bd9Sstevel@tonic-gate fclose(fbuf); 967*7c478bd9Sstevel@tonic-gate goto out; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate if ((ibuf = fopen(tempMail, "r")) == NULL) { 970*7c478bd9Sstevel@tonic-gate perror(tempMail); 971*7c478bd9Sstevel@tonic-gate removefile(tempMail); 972*7c478bd9Sstevel@tonic-gate fclose(fbuf); 973*7c478bd9Sstevel@tonic-gate fclose(obuf); 974*7c478bd9Sstevel@tonic-gate goto out; 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate removefile(tempMail); 977*7c478bd9Sstevel@tonic-gate if (strlen(hdr) != 0) { 978*7c478bd9Sstevel@tonic-gate fputs(hdr, obuf); 979*7c478bd9Sstevel@tonic-gate putc('\n', obuf); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate while ((t = getc(fbuf)) != EOF) 982*7c478bd9Sstevel@tonic-gate putc(t, obuf); 983*7c478bd9Sstevel@tonic-gate fclose(fbuf); 984*7c478bd9Sstevel@tonic-gate fclose(newo); 985*7c478bd9Sstevel@tonic-gate fclose(newi); 986*7c478bd9Sstevel@tonic-gate newo = obuf; 987*7c478bd9Sstevel@tonic-gate newi = ibuf; 988*7c478bd9Sstevel@tonic-gate out: 989*7c478bd9Sstevel@tonic-gate return(newo); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate /* 993*7c478bd9Sstevel@tonic-gate * Pipe the message through the command. 994*7c478bd9Sstevel@tonic-gate * Old message is on stdin of command; 995*7c478bd9Sstevel@tonic-gate * New message collected from stdout. 996*7c478bd9Sstevel@tonic-gate * Sh -c must return 0 to accept the new message. 997*7c478bd9Sstevel@tonic-gate */ 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate static FILE * 1000*7c478bd9Sstevel@tonic-gate mespipe(FILE *ibuf, FILE *obuf, char cmd[]) 1001*7c478bd9Sstevel@tonic-gate { 1002*7c478bd9Sstevel@tonic-gate register FILE *ni, *no; 1003*7c478bd9Sstevel@tonic-gate pid_t pid; 1004*7c478bd9Sstevel@tonic-gate int s; 1005*7c478bd9Sstevel@tonic-gate void (*sigint)(int); 1006*7c478bd9Sstevel@tonic-gate char *Shell; 1007*7c478bd9Sstevel@tonic-gate int fd = -1; 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate newi = ibuf; 1010*7c478bd9Sstevel@tonic-gate if ((fd = open(tempEdit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 1011*7c478bd9Sstevel@tonic-gate (no = fdopen(fd, "w")) == NULL) { 1012*7c478bd9Sstevel@tonic-gate perror(tempEdit); 1013*7c478bd9Sstevel@tonic-gate return(obuf); 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate if ((ni = fopen(tempEdit, "r")) == NULL) { 1016*7c478bd9Sstevel@tonic-gate perror(tempEdit); 1017*7c478bd9Sstevel@tonic-gate fclose(no); 1018*7c478bd9Sstevel@tonic-gate removefile(tempEdit); 1019*7c478bd9Sstevel@tonic-gate return(obuf); 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate removefile(tempEdit); 1022*7c478bd9Sstevel@tonic-gate fflush(obuf); 1023*7c478bd9Sstevel@tonic-gate rewind(ibuf); 1024*7c478bd9Sstevel@tonic-gate if ((Shell = value("SHELL")) == NULL || *Shell=='\0') 1025*7c478bd9Sstevel@tonic-gate Shell = SHELL; 1026*7c478bd9Sstevel@tonic-gate if ((pid = vfork()) == (pid_t)-1) { 1027*7c478bd9Sstevel@tonic-gate perror("fork"); 1028*7c478bd9Sstevel@tonic-gate goto err; 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate if (pid == 0) { 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate * stdin = current message. 1033*7c478bd9Sstevel@tonic-gate * stdout = new message. 1034*7c478bd9Sstevel@tonic-gate */ 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate sigchild(); 1037*7c478bd9Sstevel@tonic-gate close(0); 1038*7c478bd9Sstevel@tonic-gate dup(fileno(ibuf)); 1039*7c478bd9Sstevel@tonic-gate close(1); 1040*7c478bd9Sstevel@tonic-gate dup(fileno(no)); 1041*7c478bd9Sstevel@tonic-gate for (s = 4; s < 15; s++) 1042*7c478bd9Sstevel@tonic-gate close(s); 1043*7c478bd9Sstevel@tonic-gate execlp(Shell, Shell, "-c", cmd, (char *)0); 1044*7c478bd9Sstevel@tonic-gate perror(Shell); 1045*7c478bd9Sstevel@tonic-gate _exit(1); 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate sigint = sigset(SIGINT, SIG_IGN); 1048*7c478bd9Sstevel@tonic-gate while (wait(&s) != pid) 1049*7c478bd9Sstevel@tonic-gate ; 1050*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 1051*7c478bd9Sstevel@tonic-gate if (s != 0 || pid == (pid_t)-1) { 1052*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\"%s\" failed!?\n"), cmd); 1053*7c478bd9Sstevel@tonic-gate goto err; 1054*7c478bd9Sstevel@tonic-gate } 1055*7c478bd9Sstevel@tonic-gate if (fsize(ni) == 0) { 1056*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No bytes from \"%s\" !?\n"), cmd); 1057*7c478bd9Sstevel@tonic-gate goto err; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate /* 1061*7c478bd9Sstevel@tonic-gate * Take new files. 1062*7c478bd9Sstevel@tonic-gate */ 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate newi = ni; 1065*7c478bd9Sstevel@tonic-gate fclose(ibuf); 1066*7c478bd9Sstevel@tonic-gate fclose(obuf); 1067*7c478bd9Sstevel@tonic-gate return(no); 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate err: 1070*7c478bd9Sstevel@tonic-gate fclose(no); 1071*7c478bd9Sstevel@tonic-gate fclose(ni); 1072*7c478bd9Sstevel@tonic-gate return(obuf); 1073*7c478bd9Sstevel@tonic-gate } 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate static char *indentprefix; /* used instead of tab by tabputs */ 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate /* 1078*7c478bd9Sstevel@tonic-gate * Interpolate the named messages into the current 1079*7c478bd9Sstevel@tonic-gate * message, preceding each line with a tab. 1080*7c478bd9Sstevel@tonic-gate * Return a count of the number of characters now in 1081*7c478bd9Sstevel@tonic-gate * the message, or -1 if an error is encountered writing 1082*7c478bd9Sstevel@tonic-gate * the message temporary. The flag argument is 'm' if we 1083*7c478bd9Sstevel@tonic-gate * should shift over and 'f' if not. 1084*7c478bd9Sstevel@tonic-gate */ 1085*7c478bd9Sstevel@tonic-gate static int 1086*7c478bd9Sstevel@tonic-gate forward(char ms[], FILE *obuf, int f) 1087*7c478bd9Sstevel@tonic-gate { 1088*7c478bd9Sstevel@tonic-gate register int *msgvec, *ip; 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec); 1091*7c478bd9Sstevel@tonic-gate if (msgvec == NOINTPTR) 1092*7c478bd9Sstevel@tonic-gate return(0); 1093*7c478bd9Sstevel@tonic-gate if (getmsglist(ms, msgvec, 0) < 0) 1094*7c478bd9Sstevel@tonic-gate return(0); 1095*7c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 1096*7c478bd9Sstevel@tonic-gate *msgvec = first(0, MMNORM); 1097*7c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 1098*7c478bd9Sstevel@tonic-gate printf(gettext("No appropriate messages\n")); 1099*7c478bd9Sstevel@tonic-gate return(0); 1100*7c478bd9Sstevel@tonic-gate } 1101*7c478bd9Sstevel@tonic-gate msgvec[1] = NULL; 1102*7c478bd9Sstevel@tonic-gate } 1103*7c478bd9Sstevel@tonic-gate if (tolower(f) == 'm') 1104*7c478bd9Sstevel@tonic-gate indentprefix = value("indentprefix"); 1105*7c478bd9Sstevel@tonic-gate printf(gettext("Interpolating:")); 1106*7c478bd9Sstevel@tonic-gate for (ip = msgvec; *ip != NULL; ip++) { 1107*7c478bd9Sstevel@tonic-gate touch(*ip); 1108*7c478bd9Sstevel@tonic-gate printf(" %d", *ip); 1109*7c478bd9Sstevel@tonic-gate if (msend(&message[*ip-1], obuf, islower(f) ? M_IGNORE : 0, 1110*7c478bd9Sstevel@tonic-gate tolower(f) == 'm' ? tabputs : fputs) < 0) { 1111*7c478bd9Sstevel@tonic-gate perror(tempMail); 1112*7c478bd9Sstevel@tonic-gate return(-1); 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate fflush(obuf); 1116*7c478bd9Sstevel@tonic-gate if (fferror(obuf)) { 1117*7c478bd9Sstevel@tonic-gate perror(tempMail); 1118*7c478bd9Sstevel@tonic-gate return(-1); 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate printf("\n"); 1121*7c478bd9Sstevel@tonic-gate return(0); 1122*7c478bd9Sstevel@tonic-gate } 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate static int 1125*7c478bd9Sstevel@tonic-gate tabputs(const char *line, FILE *obuf) 1126*7c478bd9Sstevel@tonic-gate { 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate if (indentprefix) 1129*7c478bd9Sstevel@tonic-gate fputs(indentprefix, obuf); 1130*7c478bd9Sstevel@tonic-gate /* Don't create lines with only a tab on them */ 1131*7c478bd9Sstevel@tonic-gate else if (line[0] != '\n') 1132*7c478bd9Sstevel@tonic-gate fputc('\t', obuf); 1133*7c478bd9Sstevel@tonic-gate return (fputs(line, obuf)); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate /* 1137*7c478bd9Sstevel@tonic-gate * Print (continue) when continued after ^Z. 1138*7c478bd9Sstevel@tonic-gate */ 1139*7c478bd9Sstevel@tonic-gate #ifdef SIGCONT 1140*7c478bd9Sstevel@tonic-gate static void 1141*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 1142*7c478bd9Sstevel@tonic-gate collcont(int) 1143*7c478bd9Sstevel@tonic-gate #else 1144*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1145*7c478bd9Sstevel@tonic-gate collcont(int s) 1146*7c478bd9Sstevel@tonic-gate #endif 1147*7c478bd9Sstevel@tonic-gate { 1148*7c478bd9Sstevel@tonic-gate printf(gettext("(continue)\n")); 1149*7c478bd9Sstevel@tonic-gate fflush(stdout); 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate #endif /* SIGCONT */ 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate /* 1154*7c478bd9Sstevel@tonic-gate * On interrupt, go here to save the partial 1155*7c478bd9Sstevel@tonic-gate * message on ~/dead.letter. 1156*7c478bd9Sstevel@tonic-gate * Then restore signals and execute the normal 1157*7c478bd9Sstevel@tonic-gate * signal routine. We only come here if signals 1158*7c478bd9Sstevel@tonic-gate * were previously set anyway. 1159*7c478bd9Sstevel@tonic-gate */ 1160*7c478bd9Sstevel@tonic-gate static void 1161*7c478bd9Sstevel@tonic-gate collrub(int s) 1162*7c478bd9Sstevel@tonic-gate { 1163*7c478bd9Sstevel@tonic-gate register FILE *dbuf; 1164*7c478bd9Sstevel@tonic-gate register char *deadletter; 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate # ifdef OLD_BSD_SIGS 1167*7c478bd9Sstevel@tonic-gate if (s == SIGHUP) 1168*7c478bd9Sstevel@tonic-gate sigignore(SIGHUP); 1169*7c478bd9Sstevel@tonic-gate # endif 1170*7c478bd9Sstevel@tonic-gate if (s == SIGINT && hadintr == 0) { 1171*7c478bd9Sstevel@tonic-gate hadintr++; 1172*7c478bd9Sstevel@tonic-gate fflush(stdout); 1173*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1174*7c478bd9Sstevel@tonic-gate gettext("\n(Interrupt -- one more to kill letter)\n")); 1175*7c478bd9Sstevel@tonic-gate # ifdef OLD_BSD_SIGS 1176*7c478bd9Sstevel@tonic-gate sigrelse(s); 1177*7c478bd9Sstevel@tonic-gate # endif 1178*7c478bd9Sstevel@tonic-gate longjmp(coljmp, 1); 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate fclose(newo); 1181*7c478bd9Sstevel@tonic-gate rewind(newi); 1182*7c478bd9Sstevel@tonic-gate if (s == SIGINT && value("save")==NOSTR || fsize(newi) == 0) 1183*7c478bd9Sstevel@tonic-gate goto done; 1184*7c478bd9Sstevel@tonic-gate deadletter = Getf("DEAD"); 1185*7c478bd9Sstevel@tonic-gate if ((dbuf = fopen(deadletter, 1186*7c478bd9Sstevel@tonic-gate (value("appenddeadletter") == NOSTR ? "w" : "a"))) == NULL) { 1187*7c478bd9Sstevel@tonic-gate perror(deadletter); 1188*7c478bd9Sstevel@tonic-gate goto done; 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate chmod(deadletter, DEADPERM); 1191*7c478bd9Sstevel@tonic-gate puthead(savehp, dbuf, GMASK|GCLEN, fsize(newi)); 1192*7c478bd9Sstevel@tonic-gate lcwrite(deadletter, newi, dbuf, value("appenddeadletter") != NOSTR); 1193*7c478bd9Sstevel@tonic-gate fclose(dbuf); 1194*7c478bd9Sstevel@tonic-gate done: 1195*7c478bd9Sstevel@tonic-gate fclose(newi); 1196*7c478bd9Sstevel@tonic-gate resetsigs(1); 1197*7c478bd9Sstevel@tonic-gate if (rcvmode) { 1198*7c478bd9Sstevel@tonic-gate if (s == SIGHUP) 1199*7c478bd9Sstevel@tonic-gate hangup(s); 1200*7c478bd9Sstevel@tonic-gate else 1201*7c478bd9Sstevel@tonic-gate stop(s); 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate else 1204*7c478bd9Sstevel@tonic-gate exit(1); 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate 1207*7c478bd9Sstevel@tonic-gate /* 1208*7c478bd9Sstevel@tonic-gate * Acknowledge an interrupt signal from the tty by typing an @ 1209*7c478bd9Sstevel@tonic-gate */ 1210*7c478bd9Sstevel@tonic-gate static void 1211*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 1212*7c478bd9Sstevel@tonic-gate intack(int) 1213*7c478bd9Sstevel@tonic-gate #else 1214*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1215*7c478bd9Sstevel@tonic-gate intack(int s) 1216*7c478bd9Sstevel@tonic-gate #endif 1217*7c478bd9Sstevel@tonic-gate { 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate puts("@"); 1220*7c478bd9Sstevel@tonic-gate fflush(stdout); 1221*7c478bd9Sstevel@tonic-gate clearerr(stdin); 1222*7c478bd9Sstevel@tonic-gate longjmp(coljmp,1); 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate /* Read line from stdin, noting any NULL characters. 1226*7c478bd9Sstevel@tonic-gate Return the number of characters read. Note that the buffer 1227*7c478bd9Sstevel@tonic-gate passed must be 1 larger than "size" for the trailing NUL byte. 1228*7c478bd9Sstevel@tonic-gate */ 1229*7c478bd9Sstevel@tonic-gate int 1230*7c478bd9Sstevel@tonic-gate getline(char *line, int size, FILE *f, int *hasnulls) 1231*7c478bd9Sstevel@tonic-gate { 1232*7c478bd9Sstevel@tonic-gate register int i, ch; 1233*7c478bd9Sstevel@tonic-gate for (i = 0; (i < size) && ((ch=getc(f)) != EOF); ) { 1234*7c478bd9Sstevel@tonic-gate if ( ch == '\0' ) 1235*7c478bd9Sstevel@tonic-gate *hasnulls = 1; 1236*7c478bd9Sstevel@tonic-gate if ((line[i++] = (char)ch) == '\n') break; 1237*7c478bd9Sstevel@tonic-gate } 1238*7c478bd9Sstevel@tonic-gate line[i] = '\0'; 1239*7c478bd9Sstevel@tonic-gate return(i); 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate void 1243*7c478bd9Sstevel@tonic-gate #ifdef __cplusplus 1244*7c478bd9Sstevel@tonic-gate savedead(int) 1245*7c478bd9Sstevel@tonic-gate #else 1246*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1247*7c478bd9Sstevel@tonic-gate savedead(int s) 1248*7c478bd9Sstevel@tonic-gate #endif 1249*7c478bd9Sstevel@tonic-gate { 1250*7c478bd9Sstevel@tonic-gate collrub(SIGINT); 1251*7c478bd9Sstevel@tonic-gate exit(1); 1252*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1253*7c478bd9Sstevel@tonic-gate } 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate /* 1256*7c478bd9Sstevel@tonic-gate * Add a list of addresses to the end of a header entry field. 1257*7c478bd9Sstevel@tonic-gate */ 1258*7c478bd9Sstevel@tonic-gate char * 1259*7c478bd9Sstevel@tonic-gate addto(char hf[], char news[]) 1260*7c478bd9Sstevel@tonic-gate { 1261*7c478bd9Sstevel@tonic-gate char name[LINESIZE]; 1262*7c478bd9Sstevel@tonic-gate int comma = docomma(news); 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate while (news = yankword(news, name, sizeof (name), comma)) { 1265*7c478bd9Sstevel@tonic-gate nstrcat(name, sizeof (name), ", "); 1266*7c478bd9Sstevel@tonic-gate hf = addone(hf, name); 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate return hf; 1269*7c478bd9Sstevel@tonic-gate } 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate /* 1272*7c478bd9Sstevel@tonic-gate * Add a string to the end of a header entry field. 1273*7c478bd9Sstevel@tonic-gate */ 1274*7c478bd9Sstevel@tonic-gate char * 1275*7c478bd9Sstevel@tonic-gate addone(char hf[], char news[]) 1276*7c478bd9Sstevel@tonic-gate { 1277*7c478bd9Sstevel@tonic-gate register char *cp, *cp2, *linebuf; 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate if (hf == NOSTR) 1280*7c478bd9Sstevel@tonic-gate hf = savestr(""); 1281*7c478bd9Sstevel@tonic-gate if (*news == '\0') 1282*7c478bd9Sstevel@tonic-gate return(hf); 1283*7c478bd9Sstevel@tonic-gate linebuf = (char *)srealloc(hf, (unsigned)(strlen(hf) + strlen(news) + 2)); 1284*7c478bd9Sstevel@tonic-gate cp2 = strchr(linebuf, '\0'); 1285*7c478bd9Sstevel@tonic-gate if (cp2 > linebuf && cp2[-1] != ' ') 1286*7c478bd9Sstevel@tonic-gate *cp2++ = ' '; 1287*7c478bd9Sstevel@tonic-gate for (cp = news; any(*cp, " \t"); cp++) 1288*7c478bd9Sstevel@tonic-gate ; 1289*7c478bd9Sstevel@tonic-gate while (*cp != '\0') 1290*7c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 1291*7c478bd9Sstevel@tonic-gate *cp2 = '\0'; 1292*7c478bd9Sstevel@tonic-gate return(linebuf); 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate 1295*7c478bd9Sstevel@tonic-gate static int 1296*7c478bd9Sstevel@tonic-gate nptrs(char **hf) 1297*7c478bd9Sstevel@tonic-gate { 1298*7c478bd9Sstevel@tonic-gate register int i; 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate if (!hf) 1301*7c478bd9Sstevel@tonic-gate return(0); 1302*7c478bd9Sstevel@tonic-gate for (i = 0; *hf; hf++) 1303*7c478bd9Sstevel@tonic-gate i++; 1304*7c478bd9Sstevel@tonic-gate return(i); 1305*7c478bd9Sstevel@tonic-gate } 1306*7c478bd9Sstevel@tonic-gate 1307*7c478bd9Sstevel@tonic-gate /* 1308*7c478bd9Sstevel@tonic-gate * Add a non-standard header to the end of the non-standard headers. 1309*7c478bd9Sstevel@tonic-gate */ 1310*7c478bd9Sstevel@tonic-gate static char ** 1311*7c478bd9Sstevel@tonic-gate Xaddone(char **hf, char news[]) 1312*7c478bd9Sstevel@tonic-gate { 1313*7c478bd9Sstevel@tonic-gate register char *linebuf; 1314*7c478bd9Sstevel@tonic-gate char **ohf = hf; 1315*7c478bd9Sstevel@tonic-gate int nhf = nptrs(hf); 1316*7c478bd9Sstevel@tonic-gate 1317*7c478bd9Sstevel@tonic-gate if (hf == NOSTRPTR) 1318*7c478bd9Sstevel@tonic-gate hf = (char**)salloc(sizeof(char*) * 2); 1319*7c478bd9Sstevel@tonic-gate else 1320*7c478bd9Sstevel@tonic-gate hf = (char**)srealloc(hf, sizeof(char*) * (nhf + 2)); 1321*7c478bd9Sstevel@tonic-gate if (hf == NOSTRPTR) { 1322*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("No room, header lost: %s\n"), news); 1323*7c478bd9Sstevel@tonic-gate return(ohf); 1324*7c478bd9Sstevel@tonic-gate } 1325*7c478bd9Sstevel@tonic-gate linebuf = (char *)salloc((unsigned)(strlen(news) + 1)); 1326*7c478bd9Sstevel@tonic-gate strcpy(linebuf, news); 1327*7c478bd9Sstevel@tonic-gate hf[nhf++] = linebuf; 1328*7c478bd9Sstevel@tonic-gate hf[nhf] = NOSTR; 1329*7c478bd9Sstevel@tonic-gate return(hf); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate static void 1333*7c478bd9Sstevel@tonic-gate cpout(char *str, FILE *ofd) 1334*7c478bd9Sstevel@tonic-gate { 1335*7c478bd9Sstevel@tonic-gate register char *cp = str; 1336*7c478bd9Sstevel@tonic-gate 1337*7c478bd9Sstevel@tonic-gate while (*cp) { 1338*7c478bd9Sstevel@tonic-gate if (*cp == '\\') { 1339*7c478bd9Sstevel@tonic-gate switch (*(cp+1)) { 1340*7c478bd9Sstevel@tonic-gate case 'n': 1341*7c478bd9Sstevel@tonic-gate putc('\n', ofd); 1342*7c478bd9Sstevel@tonic-gate cp++; 1343*7c478bd9Sstevel@tonic-gate break; 1344*7c478bd9Sstevel@tonic-gate case 't': 1345*7c478bd9Sstevel@tonic-gate putc('\t', ofd); 1346*7c478bd9Sstevel@tonic-gate cp++; 1347*7c478bd9Sstevel@tonic-gate break; 1348*7c478bd9Sstevel@tonic-gate default: 1349*7c478bd9Sstevel@tonic-gate putc('\\', ofd); 1350*7c478bd9Sstevel@tonic-gate } 1351*7c478bd9Sstevel@tonic-gate } else { 1352*7c478bd9Sstevel@tonic-gate putc(*cp, ofd); 1353*7c478bd9Sstevel@tonic-gate } 1354*7c478bd9Sstevel@tonic-gate cp++; 1355*7c478bd9Sstevel@tonic-gate } 1356*7c478bd9Sstevel@tonic-gate putc('\n', ofd); 1357*7c478bd9Sstevel@tonic-gate fflush(ofd); 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate static void 1361*7c478bd9Sstevel@tonic-gate xhalt(void) 1362*7c478bd9Sstevel@tonic-gate { 1363*7c478bd9Sstevel@tonic-gate fclose(newo); 1364*7c478bd9Sstevel@tonic-gate fclose(newi); 1365*7c478bd9Sstevel@tonic-gate sigset(SIGINT, savesig); 1366*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, savehup); 1367*7c478bd9Sstevel@tonic-gate if (rcvmode) 1368*7c478bd9Sstevel@tonic-gate stop(0); 1369*7c478bd9Sstevel@tonic-gate exit(1); 1370*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1371*7c478bd9Sstevel@tonic-gate } 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate /* 1374*7c478bd9Sstevel@tonic-gate * Strip the nulls from a buffer of length n 1375*7c478bd9Sstevel@tonic-gate */ 1376*7c478bd9Sstevel@tonic-gate static int 1377*7c478bd9Sstevel@tonic-gate stripnulls(register char *linebuf, register int nread) 1378*7c478bd9Sstevel@tonic-gate { 1379*7c478bd9Sstevel@tonic-gate register int i, j; 1380*7c478bd9Sstevel@tonic-gate 1381*7c478bd9Sstevel@tonic-gate for (i = 0; i < nread; i++) 1382*7c478bd9Sstevel@tonic-gate if (linebuf[i] == '\0') 1383*7c478bd9Sstevel@tonic-gate break; 1384*7c478bd9Sstevel@tonic-gate for (j = i; j < nread; j++) 1385*7c478bd9Sstevel@tonic-gate if (linebuf[j] != '\0') 1386*7c478bd9Sstevel@tonic-gate linebuf[i++] = linebuf[j]; 1387*7c478bd9Sstevel@tonic-gate linebuf[i] = '\0'; 1388*7c478bd9Sstevel@tonic-gate return(i); 1389*7c478bd9Sstevel@tonic-gate } 1390