10Sstevel@tonic-gate /*
2*356Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
70Sstevel@tonic-gate /* All Rights Reserved */
80Sstevel@tonic-gate
90Sstevel@tonic-gate /*
100Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
110Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
120Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
130Sstevel@tonic-gate */
140Sstevel@tonic-gate
150Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
160Sstevel@tonic-gate
170Sstevel@tonic-gate #include "sh.h"
180Sstevel@tonic-gate #include <locale.h>
190Sstevel@tonic-gate #include <dirent.h>
20*356Smuffin #include <string.h>
210Sstevel@tonic-gate /*
220Sstevel@tonic-gate * #include <sys/ioctl.h>
230Sstevel@tonic-gate * #include <stdlib.h>
240Sstevel@tonic-gate */
250Sstevel@tonic-gate #include "sh.tconst.h"
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * C Shell
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate
310Sstevel@tonic-gate bool errspl; /* Argument to error was spliced by seterr2 */
320Sstevel@tonic-gate tchar one[2] = { '1', 0 };
330Sstevel@tonic-gate tchar *onev[2] = { one, NOSTR };
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate * contains DIR * for last opendir_(), its left open if an error
360Sstevel@tonic-gate * longjmp (reset) occurs before it gets closed via closedir.
370Sstevel@tonic-gate * if its not null in the error handler, then closedir it.
380Sstevel@tonic-gate */
390Sstevel@tonic-gate DIR *Dirp = NULL;
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * Print error string s with optional argument arg.
430Sstevel@tonic-gate * This routine always resets or exits. The flag haderr
440Sstevel@tonic-gate * is set so the routine who catches the unwind can propogate
450Sstevel@tonic-gate * it if they want.
460Sstevel@tonic-gate *
470Sstevel@tonic-gate * Note that any open files at the point of error will eventually
480Sstevel@tonic-gate * be closed in the routine process in sh.c which is the only
490Sstevel@tonic-gate * place error unwinds are ever caught.
500Sstevel@tonic-gate */
510Sstevel@tonic-gate /*VARARGS1*/
52*356Smuffin void
error(s,a1,a2)530Sstevel@tonic-gate error(s, a1, a2)
540Sstevel@tonic-gate char *s;
550Sstevel@tonic-gate {
56*356Smuffin tchar **v;
57*356Smuffin char *ep;
580Sstevel@tonic-gate
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate * Must flush before we print as we wish output before the error
610Sstevel@tonic-gate * to go on (some form of) standard output, while output after
620Sstevel@tonic-gate * goes on (some form of) diagnostic output.
630Sstevel@tonic-gate * If didfds then output will go to 1/2 else to FSHOUT/FSHDIAG.
640Sstevel@tonic-gate * See flush in sh.print.c.
650Sstevel@tonic-gate */
660Sstevel@tonic-gate flush();
670Sstevel@tonic-gate haderr = 1; /* Now to diagnostic output */
680Sstevel@tonic-gate timflg = 0; /* This isn't otherwise reset */
690Sstevel@tonic-gate if (v = pargv)
700Sstevel@tonic-gate pargv = 0, blkfree(v);
710Sstevel@tonic-gate if (v = gargv)
720Sstevel@tonic-gate gargv = 0, blkfree(v);
730Sstevel@tonic-gate
740Sstevel@tonic-gate /*
750Sstevel@tonic-gate * A zero arguments causes no printing, else print
760Sstevel@tonic-gate * an error diagnostic here.
770Sstevel@tonic-gate */
780Sstevel@tonic-gate if (s) {
790Sstevel@tonic-gate printf(s, a1, a2), printf("\n");
800Sstevel@tonic-gate }
810Sstevel@tonic-gate
820Sstevel@tonic-gate
830Sstevel@tonic-gate didfds = 0; /* Forget about 0,1,2 */
840Sstevel@tonic-gate if ((ep = err) && errspl) {
850Sstevel@tonic-gate errspl = 0;
860Sstevel@tonic-gate xfree(ep);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate errspl = 0;
890Sstevel@tonic-gate
900Sstevel@tonic-gate if ( Dirp ){
910Sstevel@tonic-gate closedir(Dirp);
920Sstevel@tonic-gate Dirp = NULL;
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * Go away if -e or we are a child shell
970Sstevel@tonic-gate */
980Sstevel@tonic-gate if (exiterr || child) {
990Sstevel@tonic-gate exit(1);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate /*
1030Sstevel@tonic-gate * Reset the state of the input.
1040Sstevel@tonic-gate * This buffered seek to end of file will also
1050Sstevel@tonic-gate * clear the while/foreach stack.
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate btoeof();
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate setq(S_status, onev, &shvhed);
1100Sstevel@tonic-gate if (tpgrp > 0)
1110Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp);
1120Sstevel@tonic-gate reset(); /* Unwind */
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate * Perror is the shells version of perror which should otherwise
1170Sstevel@tonic-gate * never be called.
1180Sstevel@tonic-gate */
119*356Smuffin void
Perror(tchar * s)120*356Smuffin Perror(tchar *s)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate char chbuf[BUFSIZ];
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate /*
1250Sstevel@tonic-gate * Perror uses unit 2, thus if we didn't set up the fd's
1260Sstevel@tonic-gate * we must set up unit 2 now else the diagnostic will disappear
1270Sstevel@tonic-gate */
1280Sstevel@tonic-gate if (!didfds) {
129*356Smuffin int oerrno = errno;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate (void) dcopy(SHDIAG, 2);
1320Sstevel@tonic-gate errno = oerrno;
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate tstostr(chbuf, s);
1350Sstevel@tonic-gate perror(chbuf);
1360Sstevel@tonic-gate error(NULL); /* To exit or unwind */
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate
139*356Smuffin void
bferr(char * cp)140*356Smuffin bferr(char *cp)
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate flush();
1440Sstevel@tonic-gate haderr = 1;
1450Sstevel@tonic-gate if( bname) printf("%t: ", bname);
1460Sstevel@tonic-gate error("%s", gettext(cp));
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate * The parser and scanner set up errors for later by calling seterr,
1510Sstevel@tonic-gate * which sets the variable err as a side effect; later to be tested,
1520Sstevel@tonic-gate * e.g. in process.
1530Sstevel@tonic-gate */
154*356Smuffin void
seterr(char * s)155*356Smuffin seterr(char *s)
1560Sstevel@tonic-gate {
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate if (err == 0)
1590Sstevel@tonic-gate err = s, errspl = 0;
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate /* Set err to a splice of cp and dp, to be freed later in error() */
163*356Smuffin void
seterr2(tchar * cp,char * dp)164*356Smuffin seterr2(tchar *cp, char *dp)
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate char chbuf[BUFSIZ];
1670Sstevel@tonic-gate char *gdp;
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate if (err)
1700Sstevel@tonic-gate return;
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /* Concatinate cp and dp in the allocated space. */
1730Sstevel@tonic-gate tstostr(chbuf, cp);
1740Sstevel@tonic-gate gdp = gettext(dp);
1750Sstevel@tonic-gate err = (char *)xalloc(strlen(chbuf)+strlen(gdp)+1);
1760Sstevel@tonic-gate strcpy(err, chbuf);
1770Sstevel@tonic-gate strcat(err, gdp);
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate errspl++;/* Remember to xfree(err). */
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /* Set err to a splice of cp with a string form of character d */
183*356Smuffin void
seterrc(char * cp,tchar d)184*356Smuffin seterrc(char *cp, tchar d)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate char chbuf[MB_LEN_MAX+1];
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /* don't overwrite an existing error message */
1890Sstevel@tonic-gate if (err)
1900Sstevel@tonic-gate return;
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate #ifdef MBCHAR
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate wchar_t wcd=(wchar_t)(d&TRIM);
1950Sstevel@tonic-gate int i;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate i = wctomb(chbuf, wcd); /* chbuf holds d in multibyte representation. */
1980Sstevel@tonic-gate chbuf[(i>0)?i:0] = (char) 0;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate #else
2010Sstevel@tonic-gate chbuf[0]=(char)(d&TRIM); chbuf[1]=(char)0;
2020Sstevel@tonic-gate #endif
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate /* Concatinate cp and d in the allocated space. */
2060Sstevel@tonic-gate err = (char *)xalloc(strlen(cp)+strlen(chbuf)+1);
2070Sstevel@tonic-gate strcpy(err, cp);
2080Sstevel@tonic-gate strcat(err, chbuf);
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate errspl++; /* Remember to xfree(err). */
2110Sstevel@tonic-gate }
212