1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include "sh.h" 18*7c478bd9Sstevel@tonic-gate #include <locale.h> 19*7c478bd9Sstevel@tonic-gate #include <dirent.h> 20*7c478bd9Sstevel@tonic-gate /* 21*7c478bd9Sstevel@tonic-gate * #include <sys/ioctl.h> 22*7c478bd9Sstevel@tonic-gate * #include <stdlib.h> 23*7c478bd9Sstevel@tonic-gate */ 24*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * C Shell 27*7c478bd9Sstevel@tonic-gate */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate bool errspl; /* Argument to error was spliced by seterr2 */ 31*7c478bd9Sstevel@tonic-gate tchar one[2] = { '1', 0 }; 32*7c478bd9Sstevel@tonic-gate tchar *onev[2] = { one, NOSTR }; 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * contains DIR * for last opendir_(), its left open if an error 35*7c478bd9Sstevel@tonic-gate * longjmp (reset) occurs before it gets closed via closedir. 36*7c478bd9Sstevel@tonic-gate * if its not null in the error handler, then closedir it. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate DIR *Dirp = NULL; 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate /* 41*7c478bd9Sstevel@tonic-gate * Print error string s with optional argument arg. 42*7c478bd9Sstevel@tonic-gate * This routine always resets or exits. The flag haderr 43*7c478bd9Sstevel@tonic-gate * is set so the routine who catches the unwind can propogate 44*7c478bd9Sstevel@tonic-gate * it if they want. 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * Note that any open files at the point of error will eventually 47*7c478bd9Sstevel@tonic-gate * be closed in the routine process in sh.c which is the only 48*7c478bd9Sstevel@tonic-gate * place error unwinds are ever caught. 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate /*VARARGS1*/ 51*7c478bd9Sstevel@tonic-gate error(s, a1, a2) 52*7c478bd9Sstevel@tonic-gate char *s; 53*7c478bd9Sstevel@tonic-gate { 54*7c478bd9Sstevel@tonic-gate register tchar **v; 55*7c478bd9Sstevel@tonic-gate register char *ep; 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate /* 58*7c478bd9Sstevel@tonic-gate * Must flush before we print as we wish output before the error 59*7c478bd9Sstevel@tonic-gate * to go on (some form of) standard output, while output after 60*7c478bd9Sstevel@tonic-gate * goes on (some form of) diagnostic output. 61*7c478bd9Sstevel@tonic-gate * If didfds then output will go to 1/2 else to FSHOUT/FSHDIAG. 62*7c478bd9Sstevel@tonic-gate * See flush in sh.print.c. 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate flush(); 65*7c478bd9Sstevel@tonic-gate haderr = 1; /* Now to diagnostic output */ 66*7c478bd9Sstevel@tonic-gate timflg = 0; /* This isn't otherwise reset */ 67*7c478bd9Sstevel@tonic-gate if (v = pargv) 68*7c478bd9Sstevel@tonic-gate pargv = 0, blkfree(v); 69*7c478bd9Sstevel@tonic-gate if (v = gargv) 70*7c478bd9Sstevel@tonic-gate gargv = 0, blkfree(v); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* 73*7c478bd9Sstevel@tonic-gate * A zero arguments causes no printing, else print 74*7c478bd9Sstevel@tonic-gate * an error diagnostic here. 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate if (s) { 77*7c478bd9Sstevel@tonic-gate printf(s, a1, a2), printf("\n"); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate didfds = 0; /* Forget about 0,1,2 */ 82*7c478bd9Sstevel@tonic-gate if ((ep = err) && errspl) { 83*7c478bd9Sstevel@tonic-gate errspl = 0; 84*7c478bd9Sstevel@tonic-gate xfree(ep); 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate errspl = 0; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate if ( Dirp ){ 89*7c478bd9Sstevel@tonic-gate closedir(Dirp); 90*7c478bd9Sstevel@tonic-gate Dirp = NULL; 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * Go away if -e or we are a child shell 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate if (exiterr || child) { 97*7c478bd9Sstevel@tonic-gate exit(1); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * Reset the state of the input. 102*7c478bd9Sstevel@tonic-gate * This buffered seek to end of file will also 103*7c478bd9Sstevel@tonic-gate * clear the while/foreach stack. 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate btoeof(); 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate setq(S_status, onev, &shvhed); 108*7c478bd9Sstevel@tonic-gate if (tpgrp > 0) 109*7c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); 110*7c478bd9Sstevel@tonic-gate reset(); /* Unwind */ 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * Perror is the shells version of perror which should otherwise 115*7c478bd9Sstevel@tonic-gate * never be called. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate Perror(s) 118*7c478bd9Sstevel@tonic-gate tchar *s; 119*7c478bd9Sstevel@tonic-gate { 120*7c478bd9Sstevel@tonic-gate char chbuf[BUFSIZ]; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * Perror uses unit 2, thus if we didn't set up the fd's 124*7c478bd9Sstevel@tonic-gate * we must set up unit 2 now else the diagnostic will disappear 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate if (!didfds) { 127*7c478bd9Sstevel@tonic-gate register int oerrno = errno; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate (void) dcopy(SHDIAG, 2); 130*7c478bd9Sstevel@tonic-gate errno = oerrno; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate tstostr(chbuf, s); 133*7c478bd9Sstevel@tonic-gate perror(chbuf); 134*7c478bd9Sstevel@tonic-gate error(NULL); /* To exit or unwind */ 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate bferr(cp) 138*7c478bd9Sstevel@tonic-gate char *cp; 139*7c478bd9Sstevel@tonic-gate { 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate flush(); 142*7c478bd9Sstevel@tonic-gate haderr = 1; 143*7c478bd9Sstevel@tonic-gate if( bname) printf("%t: ", bname); 144*7c478bd9Sstevel@tonic-gate error("%s", gettext(cp)); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * The parser and scanner set up errors for later by calling seterr, 149*7c478bd9Sstevel@tonic-gate * which sets the variable err as a side effect; later to be tested, 150*7c478bd9Sstevel@tonic-gate * e.g. in process. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate seterr(s) 153*7c478bd9Sstevel@tonic-gate char *s; 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate if (err == 0) 157*7c478bd9Sstevel@tonic-gate err = s, errspl = 0; 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* Set err to a splice of cp and dp, to be freed later in error() */ 161*7c478bd9Sstevel@tonic-gate seterr2(cp, dp) 162*7c478bd9Sstevel@tonic-gate tchar *cp; 163*7c478bd9Sstevel@tonic-gate char *dp; 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate char chbuf[BUFSIZ]; 166*7c478bd9Sstevel@tonic-gate char *gdp; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate if (err) 169*7c478bd9Sstevel@tonic-gate return; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* Concatinate cp and dp in the allocated space. */ 172*7c478bd9Sstevel@tonic-gate tstostr(chbuf, cp); 173*7c478bd9Sstevel@tonic-gate gdp = gettext(dp); 174*7c478bd9Sstevel@tonic-gate err = (char *)xalloc(strlen(chbuf)+strlen(gdp)+1); 175*7c478bd9Sstevel@tonic-gate strcpy(err, chbuf); 176*7c478bd9Sstevel@tonic-gate strcat(err, gdp); 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate errspl++;/* Remember to xfree(err). */ 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* Set err to a splice of cp with a string form of character d */ 182*7c478bd9Sstevel@tonic-gate seterrc(cp, d) 183*7c478bd9Sstevel@tonic-gate char *cp; 184*7c478bd9Sstevel@tonic-gate tchar d; 185*7c478bd9Sstevel@tonic-gate { 186*7c478bd9Sstevel@tonic-gate char chbuf[MB_LEN_MAX+1]; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* don't overwrite an existing error message */ 189*7c478bd9Sstevel@tonic-gate if (err) 190*7c478bd9Sstevel@tonic-gate return; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate wchar_t wcd=(wchar_t)(d&TRIM); 195*7c478bd9Sstevel@tonic-gate int i; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate i = wctomb(chbuf, wcd); /* chbuf holds d in multibyte representation. */ 198*7c478bd9Sstevel@tonic-gate chbuf[(i>0)?i:0] = (char) 0; 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate #else 201*7c478bd9Sstevel@tonic-gate chbuf[0]=(char)(d&TRIM); chbuf[1]=(char)0; 202*7c478bd9Sstevel@tonic-gate #endif 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* Concatinate cp and d in the allocated space. */ 206*7c478bd9Sstevel@tonic-gate err = (char *)xalloc(strlen(cp)+strlen(chbuf)+1); 207*7c478bd9Sstevel@tonic-gate strcpy(err, cp); 208*7c478bd9Sstevel@tonic-gate strcat(err, chbuf); 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate errspl++; /* Remember to xfree(err). */ 211*7c478bd9Sstevel@tonic-gate } 212