/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #include "sh.h" #include #include #include /* * #include * #include */ #include "sh.tconst.h" /* * C Shell */ bool child; bool didfds; bool exiterr; bool errspl; /* Argument to error was spliced by seterr2 */ bool haderr; jmp_buf reslab; tchar one[2] = { '1', 0 }; tchar *onev[2] = { one, NOSTR }; short SHDIAG; int tpgrp; /* * contains DIR * for last opendir_(), its left open if an error * longjmp (reset) occurs before it gets closed via closedir. * if its not null in the error handler, then closedir it. */ DIR *Dirp = NULL; /* * Print error string s with optional argument arg. * This routine always resets or exits. The flag haderr * is set so the routine who catches the unwind can propogate * it if they want. * * Note that any open files at the point of error will eventually * be closed in the routine process in sh.c which is the only * place error unwinds are ever caught. */ /*VARARGS1*/ void error(s, a1, a2) char *s; { tchar **v; char *ep; /* * Must flush before we print as we wish output before the error * to go on (some form of) standard output, while output after * goes on (some form of) diagnostic output. * If didfds then output will go to 1/2 else to FSHOUT/FSHDIAG. * See flush in sh.print.c. */ flush(); haderr = 1; /* Now to diagnostic output */ if (v = pargv) pargv = 0, blkfree(v); if (v = gargv) gargv = 0, blkfree(v); /* * A zero arguments causes no printing, else print * an error diagnostic here. */ if (s) { printf(s, a1, a2), printf("\n"); } didfds = 0; /* Forget about 0,1,2 */ if ((ep = err_msg) && errspl) { errspl = 0; xfree(ep); } errspl = 0; if ( Dirp ){ closedir(Dirp); Dirp = NULL; } /* * Go away if -e or we are a child shell */ if (exiterr || child) { exit(1); } /* * Reset the state of the input. * This buffered seek to end of file will also * clear the while/foreach stack. */ btoeof(); setq(S_status, onev, &shvhed); if (tpgrp > 0) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); reset(); /* Unwind */ } /* * Perror is the shells version of perror which should otherwise * never be called. */ void Perror(tchar *s) { char chbuf[BUFSIZ]; /* * Perror uses unit 2, thus if we didn't set up the fd's * we must set up unit 2 now else the diagnostic will disappear */ if (!didfds) { int oerrno = errno; (void) dcopy(SHDIAG, 2); errno = oerrno; } tstostr(chbuf, s); perror(chbuf); error(NULL); /* To exit or unwind */ } void bferr(char *cp) { flush(); haderr = 1; if( bname) printf("%t: ", bname); error("%s", gettext(cp)); } /* * The parser and scanner set up errors for later by calling seterr, * which sets the variable err as a side effect; later to be tested, * e.g. in process. */ void seterr(char *s) { if (err_msg == NULL) err_msg = s, errspl = 0; } /* Set err to a splice of cp and dp, to be freed later in error() */ void seterr2(tchar *cp, char *dp) { char chbuf[BUFSIZ]; char *gdp; if (err_msg) return; /* Concatinate cp and dp in the allocated space. */ tstostr(chbuf, cp); gdp = gettext(dp); err_msg = (char *)xalloc(strlen(chbuf)+strlen(gdp)+1); strcpy(err_msg, chbuf); strcat(err_msg, gdp); errspl++;/* Remember to xfree(err_msg). */ } /* Set err to a splice of cp with a string form of character d */ void seterrc(char *cp, tchar d) { char chbuf[MB_LEN_MAX+1]; /* don't overwrite an existing error message */ if (err_msg) return; #ifdef MBCHAR { wchar_t wcd=(wchar_t)(d&TRIM); int i; i = wctomb(chbuf, wcd); /* chbuf holds d in multibyte representation. */ chbuf[(i>0)?i:0] = (char) 0; } #else chbuf[0]=(char)(d&TRIM); chbuf[1]=(char)0; #endif /* Concatinate cp and d in the allocated space. */ err_msg = (char *)xalloc(strlen(cp)+strlen(chbuf)+1); strcpy(err_msg, cp); strcat(err_msg, chbuf); errspl++; /* Remember to xfree(err_msg). */ }