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 1995 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 #include "rcv.h" 44*7c478bd9Sstevel@tonic-gate #include <locale.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* 47*7c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 48*7c478bd9Sstevel@tonic-gate * mail program 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * More commands.. 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate static char *stripquotes(char *str); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * pipe messages to cmd. 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate int 60*7c478bd9Sstevel@tonic-gate dopipe(char str[]) 61*7c478bd9Sstevel@tonic-gate { 62*7c478bd9Sstevel@tonic-gate register int *ip, mesg; 63*7c478bd9Sstevel@tonic-gate register struct message *mp; 64*7c478bd9Sstevel@tonic-gate char *cp, *cmd; 65*7c478bd9Sstevel@tonic-gate int f, *msgvec, nowait=0; 66*7c478bd9Sstevel@tonic-gate void (*sigint)(int), (*sigpipe)(int); 67*7c478bd9Sstevel@tonic-gate long lc, cc, t; 68*7c478bd9Sstevel@tonic-gate register pid_t pid; 69*7c478bd9Sstevel@tonic-gate int page, s, pivec[2]; 70*7c478bd9Sstevel@tonic-gate char *Shell; 71*7c478bd9Sstevel@tonic-gate FILE *pio = NULL; 72*7c478bd9Sstevel@tonic-gate extern jmp_buf pipestop; 73*7c478bd9Sstevel@tonic-gate extern void brokpipe(int); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 76*7c478bd9Sstevel@tonic-gate if ((cmd = stripquotes(snarf(str, &f, 0))) == NOSTR) { 77*7c478bd9Sstevel@tonic-gate if (f == -1) { 78*7c478bd9Sstevel@tonic-gate printf(gettext("pipe command error\n")); 79*7c478bd9Sstevel@tonic-gate return(1); 80*7c478bd9Sstevel@tonic-gate } 81*7c478bd9Sstevel@tonic-gate if ( (cmd = value("cmd")) == NOSTR) { 82*7c478bd9Sstevel@tonic-gate printf(gettext("\"cmd\" not set, ignored.\n")); 83*7c478bd9Sstevel@tonic-gate return(1); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate if (!f) { 87*7c478bd9Sstevel@tonic-gate *msgvec = first(0, MMNORM); 88*7c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 89*7c478bd9Sstevel@tonic-gate printf(gettext("No messages to pipe.\n")); 90*7c478bd9Sstevel@tonic-gate return(1); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate msgvec[1] = NULL; 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate if (f && getmsglist(str, msgvec, 0) < 0) 95*7c478bd9Sstevel@tonic-gate return(1); 96*7c478bd9Sstevel@tonic-gate if (*(cp=cmd+strlen(cmd)-1)=='&') { 97*7c478bd9Sstevel@tonic-gate *cp=0; 98*7c478bd9Sstevel@tonic-gate nowait++; 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate printf(gettext("Pipe to: \"%s\"\n"), cmd); 101*7c478bd9Sstevel@tonic-gate flush(); 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate if (setjmp(pipestop)) 104*7c478bd9Sstevel@tonic-gate goto err; 105*7c478bd9Sstevel@tonic-gate /* setup pipe */ 106*7c478bd9Sstevel@tonic-gate if (pipe(pivec) < 0) { 107*7c478bd9Sstevel@tonic-gate perror("pipe"); 108*7c478bd9Sstevel@tonic-gate return(0); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if ((pid = vfork()) == 0) { 112*7c478bd9Sstevel@tonic-gate close(pivec[1]); /* child */ 113*7c478bd9Sstevel@tonic-gate close(0); 114*7c478bd9Sstevel@tonic-gate dup(pivec[0]); 115*7c478bd9Sstevel@tonic-gate close(pivec[0]); 116*7c478bd9Sstevel@tonic-gate if ((Shell = value("SHELL")) == NOSTR || *Shell=='\0') 117*7c478bd9Sstevel@tonic-gate Shell = SHELL; 118*7c478bd9Sstevel@tonic-gate execlp(Shell, Shell, "-c", cmd, 0); 119*7c478bd9Sstevel@tonic-gate perror(Shell); 120*7c478bd9Sstevel@tonic-gate _exit(1); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate if (pid == (pid_t)-1) { /* error */ 123*7c478bd9Sstevel@tonic-gate perror("fork"); 124*7c478bd9Sstevel@tonic-gate close(pivec[0]); 125*7c478bd9Sstevel@tonic-gate close(pivec[1]); 126*7c478bd9Sstevel@tonic-gate return(0); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate close(pivec[0]); /* parent */ 130*7c478bd9Sstevel@tonic-gate pio=fdopen(pivec[1],"w"); 131*7c478bd9Sstevel@tonic-gate sigint = sigset(SIGINT, SIG_IGN); 132*7c478bd9Sstevel@tonic-gate sigpipe = sigset(SIGPIPE, brokpipe); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* send all messages to cmd */ 135*7c478bd9Sstevel@tonic-gate page = (value("page")!=NOSTR); 136*7c478bd9Sstevel@tonic-gate lc = cc = 0; 137*7c478bd9Sstevel@tonic-gate for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 138*7c478bd9Sstevel@tonic-gate mesg = *ip; 139*7c478bd9Sstevel@tonic-gate touch(mesg); 140*7c478bd9Sstevel@tonic-gate mp = &message[mesg-1]; 141*7c478bd9Sstevel@tonic-gate dot = mp; 142*7c478bd9Sstevel@tonic-gate if ((t = msend(mp, pio, 143*7c478bd9Sstevel@tonic-gate (value("alwaysignore") != NOSTR || 144*7c478bd9Sstevel@tonic-gate value("pipeignore") != NOSTR) 145*7c478bd9Sstevel@tonic-gate ? M_IGNORE : 0, fputs)) < 0) { 146*7c478bd9Sstevel@tonic-gate perror(cmd); 147*7c478bd9Sstevel@tonic-gate sigset(SIGPIPE, sigpipe); 148*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 149*7c478bd9Sstevel@tonic-gate fclose(pio); 150*7c478bd9Sstevel@tonic-gate return(1); 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate lc += t; 153*7c478bd9Sstevel@tonic-gate cc += mp->m_size; 154*7c478bd9Sstevel@tonic-gate if (page) putc('\f', pio); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate fflush(pio); 158*7c478bd9Sstevel@tonic-gate if (ferror(pio)) 159*7c478bd9Sstevel@tonic-gate perror(cmd); 160*7c478bd9Sstevel@tonic-gate fclose(pio); 161*7c478bd9Sstevel@tonic-gate pio = NULL; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* wait */ 164*7c478bd9Sstevel@tonic-gate if (!nowait) { 165*7c478bd9Sstevel@tonic-gate while (wait(&s) != pid); 166*7c478bd9Sstevel@tonic-gate s &= 0377; 167*7c478bd9Sstevel@tonic-gate if (s != 0) 168*7c478bd9Sstevel@tonic-gate goto err; 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate printf("\"%s\" %ld/%ld\n", cmd, lc, cc); 172*7c478bd9Sstevel@tonic-gate sigset(SIGPIPE, sigpipe); 173*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 174*7c478bd9Sstevel@tonic-gate return(0); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate err: 177*7c478bd9Sstevel@tonic-gate printf(gettext("Pipe to \"%s\" failed\n"), cmd); 178*7c478bd9Sstevel@tonic-gate if (pio) 179*7c478bd9Sstevel@tonic-gate fclose(pio); 180*7c478bd9Sstevel@tonic-gate sigset(SIGPIPE, sigpipe); 181*7c478bd9Sstevel@tonic-gate sigset(SIGINT, sigint); 182*7c478bd9Sstevel@tonic-gate return(0); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Load the named message from the named file. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate int 189*7c478bd9Sstevel@tonic-gate loadmsg(char str[]) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate char *file; 192*7c478bd9Sstevel@tonic-gate int f, *msgvec; 193*7c478bd9Sstevel@tonic-gate register int c, lastc = '\n'; 194*7c478bd9Sstevel@tonic-gate int blank; 195*7c478bd9Sstevel@tonic-gate int lines; 196*7c478bd9Sstevel@tonic-gate long ms; 197*7c478bd9Sstevel@tonic-gate FILE *ibuf; 198*7c478bd9Sstevel@tonic-gate struct message *mp; 199*7c478bd9Sstevel@tonic-gate off_t size; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 202*7c478bd9Sstevel@tonic-gate if ((file = snarf(str, &f, 1)) == NOSTR) 203*7c478bd9Sstevel@tonic-gate return(1); 204*7c478bd9Sstevel@tonic-gate if (f==-1) 205*7c478bd9Sstevel@tonic-gate return(1); 206*7c478bd9Sstevel@tonic-gate if (!f) { 207*7c478bd9Sstevel@tonic-gate *msgvec = first(0, MMNORM); 208*7c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 209*7c478bd9Sstevel@tonic-gate printf(gettext("No message to load into.\n")); 210*7c478bd9Sstevel@tonic-gate return(1); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate msgvec[1] = NULL; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate if (f && getmsglist(str, msgvec, 0) < 0) 215*7c478bd9Sstevel@tonic-gate return(1); 216*7c478bd9Sstevel@tonic-gate if (msgvec[1] != NULL) { 217*7c478bd9Sstevel@tonic-gate printf(gettext("Can only load into a single message.\n")); 218*7c478bd9Sstevel@tonic-gate return(1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate if ((file = expand(file)) == NOSTR) 221*7c478bd9Sstevel@tonic-gate return(1); 222*7c478bd9Sstevel@tonic-gate printf("\"%s\" ", file); 223*7c478bd9Sstevel@tonic-gate fflush(stdout); 224*7c478bd9Sstevel@tonic-gate if ((ibuf = fopen(file, "r")) == NULL) { 225*7c478bd9Sstevel@tonic-gate perror(""); 226*7c478bd9Sstevel@tonic-gate return(1); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate mp = &message[*msgvec-1]; 229*7c478bd9Sstevel@tonic-gate dot = mp; 230*7c478bd9Sstevel@tonic-gate mp->m_flag |= MODIFY; 231*7c478bd9Sstevel@tonic-gate mp->m_flag &= ~MSAVED; /* should probably turn off more */ 232*7c478bd9Sstevel@tonic-gate fseek(otf, (long) 0, 2); 233*7c478bd9Sstevel@tonic-gate size = fsize(otf); 234*7c478bd9Sstevel@tonic-gate mp->m_offset = size; 235*7c478bd9Sstevel@tonic-gate ms = 0L; 236*7c478bd9Sstevel@tonic-gate lines = 0; 237*7c478bd9Sstevel@tonic-gate while ((c = getc(ibuf)) != EOF) { 238*7c478bd9Sstevel@tonic-gate if (c == '\n') { 239*7c478bd9Sstevel@tonic-gate lines++; 240*7c478bd9Sstevel@tonic-gate blank = lastc == '\n'; 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate lastc = c; 243*7c478bd9Sstevel@tonic-gate putc(c, otf); 244*7c478bd9Sstevel@tonic-gate if (ferror(otf)) 245*7c478bd9Sstevel@tonic-gate break; 246*7c478bd9Sstevel@tonic-gate ms++; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate if (!blank) { 249*7c478bd9Sstevel@tonic-gate putc('\n', otf); 250*7c478bd9Sstevel@tonic-gate ms++; 251*7c478bd9Sstevel@tonic-gate lines++; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate mp->m_size = ms; 254*7c478bd9Sstevel@tonic-gate mp->m_lines = lines; 255*7c478bd9Sstevel@tonic-gate if (fferror(otf)) 256*7c478bd9Sstevel@tonic-gate perror("/tmp"); 257*7c478bd9Sstevel@tonic-gate fclose(ibuf); 258*7c478bd9Sstevel@tonic-gate setclen(mp); 259*7c478bd9Sstevel@tonic-gate printf(gettext("[Loaded] %d/%ld\n"), lines, ms); 260*7c478bd9Sstevel@tonic-gate return(0); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * Display the named field. 265*7c478bd9Sstevel@tonic-gate */ 266*7c478bd9Sstevel@tonic-gate int 267*7c478bd9Sstevel@tonic-gate field(char str[]) 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate register int *ip; 270*7c478bd9Sstevel@tonic-gate register struct message *mp; 271*7c478bd9Sstevel@tonic-gate register char *cp, *fld; 272*7c478bd9Sstevel@tonic-gate int f, *msgvec; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 275*7c478bd9Sstevel@tonic-gate if ((fld = stripquotes(snarf(str, &f, 0))) == NOSTR) { 276*7c478bd9Sstevel@tonic-gate if (f == -1) 277*7c478bd9Sstevel@tonic-gate printf(gettext("Bad field\n")); 278*7c478bd9Sstevel@tonic-gate else 279*7c478bd9Sstevel@tonic-gate printf(gettext("No field specified\n")); 280*7c478bd9Sstevel@tonic-gate return(1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate if (!f) { 283*7c478bd9Sstevel@tonic-gate *msgvec = first(0, MMNORM); 284*7c478bd9Sstevel@tonic-gate if (*msgvec == NULL) { 285*7c478bd9Sstevel@tonic-gate printf(gettext("No messages to display.\n")); 286*7c478bd9Sstevel@tonic-gate return(1); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate msgvec[1] = NULL; 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate if (f && getmsglist(str, msgvec, 0) < 0) 291*7c478bd9Sstevel@tonic-gate return(1); 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 294*7c478bd9Sstevel@tonic-gate mp = &message[*ip - 1]; 295*7c478bd9Sstevel@tonic-gate dot = mp; 296*7c478bd9Sstevel@tonic-gate if ((cp = hfield(fld, mp, addone)) != NULL) 297*7c478bd9Sstevel@tonic-gate printf("%s\n", cp); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate return(0); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate /* 303*7c478bd9Sstevel@tonic-gate * Remove the quotes from around the string passed in (if any). Return 304*7c478bd9Sstevel@tonic-gate * the beginning of the result. 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate static char * 308*7c478bd9Sstevel@tonic-gate stripquotes(char *str) 309*7c478bd9Sstevel@tonic-gate { 310*7c478bd9Sstevel@tonic-gate register int lastch; 311*7c478bd9Sstevel@tonic-gate if (str == NOSTR) { 312*7c478bd9Sstevel@tonic-gate return(NOSTR); 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate lastch = strlen(str)-1; 315*7c478bd9Sstevel@tonic-gate if (any(*str, "\"'") && str[lastch] == *str) { 316*7c478bd9Sstevel@tonic-gate str[lastch] = '\0'; 317*7c478bd9Sstevel@tonic-gate ++str; 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate return(str); 320*7c478bd9Sstevel@tonic-gate } 321