xref: /illumos-gate/usr/src/cmd/csh/sh.err.c (revision 772eca3305893e0fc7b9c13ec6a1a6df72251dbd)
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