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