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