1*10d63b7dSRichard Lowe /*
2*10d63b7dSRichard Lowe * CDDL HEADER START
3*10d63b7dSRichard Lowe *
4*10d63b7dSRichard Lowe * The contents of this file are subject to the terms of the
5*10d63b7dSRichard Lowe * Common Development and Distribution License (the "License").
6*10d63b7dSRichard Lowe * You may not use this file except in compliance with the License.
7*10d63b7dSRichard Lowe *
8*10d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*10d63b7dSRichard Lowe * See the License for the specific language governing permissions
11*10d63b7dSRichard Lowe * and limitations under the License.
12*10d63b7dSRichard Lowe *
13*10d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*10d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*10d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*10d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*10d63b7dSRichard Lowe *
19*10d63b7dSRichard Lowe * CDDL HEADER END
20*10d63b7dSRichard Lowe */
21*10d63b7dSRichard Lowe /*
22*10d63b7dSRichard Lowe * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23*10d63b7dSRichard Lowe * Use is subject to license terms.
24*10d63b7dSRichard Lowe */
25*10d63b7dSRichard Lowe
26*10d63b7dSRichard Lowe
27*10d63b7dSRichard Lowe /*
28*10d63b7dSRichard Lowe * misc.cc
29*10d63b7dSRichard Lowe *
30*10d63b7dSRichard Lowe * This file contains various unclassified routines. Some main groups:
31*10d63b7dSRichard Lowe * getname
32*10d63b7dSRichard Lowe * Memory allocation
33*10d63b7dSRichard Lowe * String handling
34*10d63b7dSRichard Lowe * Property handling
35*10d63b7dSRichard Lowe * Error message handling
36*10d63b7dSRichard Lowe * Make internal state dumping
37*10d63b7dSRichard Lowe * main routine support
38*10d63b7dSRichard Lowe */
39*10d63b7dSRichard Lowe
40*10d63b7dSRichard Lowe /*
41*10d63b7dSRichard Lowe * Included files
42*10d63b7dSRichard Lowe */
43*10d63b7dSRichard Lowe #include <bsd/bsd.h> /* bsd_signal() */
44*10d63b7dSRichard Lowe #include <mksh/i18n.h> /* get_char_semantics_value() */
45*10d63b7dSRichard Lowe #include <mksh/misc.h>
46*10d63b7dSRichard Lowe #include <stdarg.h> /* va_list, va_start(), va_end() */
47*10d63b7dSRichard Lowe #include <stdlib.h> /* mbstowcs() */
48*10d63b7dSRichard Lowe #include <sys/signal.h> /* SIG_DFL */
49*10d63b7dSRichard Lowe #include <sys/wait.h> /* wait() */
50*10d63b7dSRichard Lowe
51*10d63b7dSRichard Lowe #include <string.h> /* strerror() */
52*10d63b7dSRichard Lowe #include <libintl.h>
53*10d63b7dSRichard Lowe
54*10d63b7dSRichard Lowe
55*10d63b7dSRichard Lowe /*
56*10d63b7dSRichard Lowe * Defined macros
57*10d63b7dSRichard Lowe */
58*10d63b7dSRichard Lowe
59*10d63b7dSRichard Lowe /*
60*10d63b7dSRichard Lowe * typedefs & structs
61*10d63b7dSRichard Lowe */
62*10d63b7dSRichard Lowe
63*10d63b7dSRichard Lowe /*
64*10d63b7dSRichard Lowe * Static variables
65*10d63b7dSRichard Lowe */
66*10d63b7dSRichard Lowe extern "C" {
67*10d63b7dSRichard Lowe void (*sigivalue)(int) = SIG_DFL;
68*10d63b7dSRichard Lowe void (*sigqvalue)(int) = SIG_DFL;
69*10d63b7dSRichard Lowe void (*sigtvalue)(int) = SIG_DFL;
70*10d63b7dSRichard Lowe void (*sighvalue)(int) = SIG_DFL;
71*10d63b7dSRichard Lowe }
72*10d63b7dSRichard Lowe
73*10d63b7dSRichard Lowe long getname_bytes_count = 0;
74*10d63b7dSRichard Lowe long getname_names_count = 0;
75*10d63b7dSRichard Lowe long getname_struct_count = 0;
76*10d63b7dSRichard Lowe
77*10d63b7dSRichard Lowe long freename_bytes_count = 0;
78*10d63b7dSRichard Lowe long freename_names_count = 0;
79*10d63b7dSRichard Lowe long freename_struct_count = 0;
80*10d63b7dSRichard Lowe
81*10d63b7dSRichard Lowe long expandstring_count = 0;
82*10d63b7dSRichard Lowe long getwstring_count = 0;
83*10d63b7dSRichard Lowe
84*10d63b7dSRichard Lowe /*
85*10d63b7dSRichard Lowe * File table of contents
86*10d63b7dSRichard Lowe */
87*10d63b7dSRichard Lowe static void expand_string(register String string, register int length);
88*10d63b7dSRichard Lowe
89*10d63b7dSRichard Lowe #define FATAL_ERROR_MSG_SIZE 200
90*10d63b7dSRichard Lowe
91*10d63b7dSRichard Lowe /*
92*10d63b7dSRichard Lowe * getmem(size)
93*10d63b7dSRichard Lowe *
94*10d63b7dSRichard Lowe * malloc() version that checks the returned value.
95*10d63b7dSRichard Lowe *
96*10d63b7dSRichard Lowe * Return value:
97*10d63b7dSRichard Lowe * The memory chunk we allocated
98*10d63b7dSRichard Lowe *
99*10d63b7dSRichard Lowe * Parameters:
100*10d63b7dSRichard Lowe * size The size of the chunk we need
101*10d63b7dSRichard Lowe *
102*10d63b7dSRichard Lowe * Global variables used:
103*10d63b7dSRichard Lowe */
104*10d63b7dSRichard Lowe char *
getmem(register int size)105*10d63b7dSRichard Lowe getmem(register int size)
106*10d63b7dSRichard Lowe {
107*10d63b7dSRichard Lowe register char *result = (char *) malloc((unsigned) size);
108*10d63b7dSRichard Lowe if (result == NULL) {
109*10d63b7dSRichard Lowe char buf[FATAL_ERROR_MSG_SIZE];
110*10d63b7dSRichard Lowe sprintf(buf, "*** Error: malloc(%d) failed: %s\n", size, strerror(errno));
111*10d63b7dSRichard Lowe strcat(buf, gettext("mksh: Fatal error: Out of memory\n"));
112*10d63b7dSRichard Lowe fputs(buf, stderr);
113*10d63b7dSRichard Lowe exit_status = 1;
114*10d63b7dSRichard Lowe exit(1);
115*10d63b7dSRichard Lowe }
116*10d63b7dSRichard Lowe return result;
117*10d63b7dSRichard Lowe }
118*10d63b7dSRichard Lowe
119*10d63b7dSRichard Lowe /*
120*10d63b7dSRichard Lowe * retmem(p)
121*10d63b7dSRichard Lowe *
122*10d63b7dSRichard Lowe * Cover funtion for free() to make it possible to insert advises.
123*10d63b7dSRichard Lowe *
124*10d63b7dSRichard Lowe * Parameters:
125*10d63b7dSRichard Lowe * p The memory block to free
126*10d63b7dSRichard Lowe *
127*10d63b7dSRichard Lowe * Global variables used:
128*10d63b7dSRichard Lowe */
129*10d63b7dSRichard Lowe void
retmem(wchar_t * p)130*10d63b7dSRichard Lowe retmem(wchar_t *p)
131*10d63b7dSRichard Lowe {
132*10d63b7dSRichard Lowe (void) free((char *) p);
133*10d63b7dSRichard Lowe }
134*10d63b7dSRichard Lowe
135*10d63b7dSRichard Lowe void
retmem_mb(caddr_t p)136*10d63b7dSRichard Lowe retmem_mb(caddr_t p)
137*10d63b7dSRichard Lowe {
138*10d63b7dSRichard Lowe (void) free(p);
139*10d63b7dSRichard Lowe }
140*10d63b7dSRichard Lowe
141*10d63b7dSRichard Lowe /*
142*10d63b7dSRichard Lowe * getname_fn(name, len, dont_enter)
143*10d63b7dSRichard Lowe *
144*10d63b7dSRichard Lowe * Hash a name string to the corresponding nameblock.
145*10d63b7dSRichard Lowe *
146*10d63b7dSRichard Lowe * Return value:
147*10d63b7dSRichard Lowe * The Name block for the string
148*10d63b7dSRichard Lowe *
149*10d63b7dSRichard Lowe * Parameters:
150*10d63b7dSRichard Lowe * name The string we want to internalize
151*10d63b7dSRichard Lowe * len The length of that string
152*10d63b7dSRichard Lowe * dont_enter Don't enter the name if it does not exist
153*10d63b7dSRichard Lowe *
154*10d63b7dSRichard Lowe * Global variables used:
155*10d63b7dSRichard Lowe * funny The vector of semantic tags for characters
156*10d63b7dSRichard Lowe * hashtab The hashtable used for the nametable
157*10d63b7dSRichard Lowe */
158*10d63b7dSRichard Lowe Name
getname_fn(wchar_t * name,register int len,register Boolean dont_enter,register Boolean * foundp)159*10d63b7dSRichard Lowe getname_fn(wchar_t *name, register int len, register Boolean dont_enter, register Boolean * foundp)
160*10d63b7dSRichard Lowe {
161*10d63b7dSRichard Lowe register int length;
162*10d63b7dSRichard Lowe register wchar_t *cap = name;
163*10d63b7dSRichard Lowe register Name np;
164*10d63b7dSRichard Lowe static Name_rec empty_Name;
165*10d63b7dSRichard Lowe char *tmp_mbs_buffer = NULL;
166*10d63b7dSRichard Lowe char *mbs_name = mbs_buffer;
167*10d63b7dSRichard Lowe
168*10d63b7dSRichard Lowe /*
169*10d63b7dSRichard Lowe * First figure out how long the string is.
170*10d63b7dSRichard Lowe * If the len argument is -1 we count the chars here.
171*10d63b7dSRichard Lowe */
172*10d63b7dSRichard Lowe if (len == FIND_LENGTH) {
173*10d63b7dSRichard Lowe length = wcslen(name);
174*10d63b7dSRichard Lowe } else {
175*10d63b7dSRichard Lowe length = len;
176*10d63b7dSRichard Lowe }
177*10d63b7dSRichard Lowe
178*10d63b7dSRichard Lowe Wstring ws;
179*10d63b7dSRichard Lowe ws.init(name, length);
180*10d63b7dSRichard Lowe if (length >= MAXPATHLEN) {
181*10d63b7dSRichard Lowe mbs_name = tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
182*10d63b7dSRichard Lowe }
183*10d63b7dSRichard Lowe (void) wcstombs(mbs_name, ws.get_string(), (length * MB_LEN_MAX) + 1);
184*10d63b7dSRichard Lowe
185*10d63b7dSRichard Lowe /* Look for the string */
186*10d63b7dSRichard Lowe if (dont_enter || (foundp != 0)) {
187*10d63b7dSRichard Lowe np = hashtab.lookup(mbs_name);
188*10d63b7dSRichard Lowe if (foundp != 0) {
189*10d63b7dSRichard Lowe *foundp = (np != 0) ? true : false;
190*10d63b7dSRichard Lowe }
191*10d63b7dSRichard Lowe if ((np != 0) || dont_enter) {
192*10d63b7dSRichard Lowe if(tmp_mbs_buffer != NULL) {
193*10d63b7dSRichard Lowe retmem_mb(tmp_mbs_buffer);
194*10d63b7dSRichard Lowe }
195*10d63b7dSRichard Lowe return np;
196*10d63b7dSRichard Lowe } else {
197*10d63b7dSRichard Lowe np = ALLOC(Name);
198*10d63b7dSRichard Lowe }
199*10d63b7dSRichard Lowe } else {
200*10d63b7dSRichard Lowe Boolean found;
201*10d63b7dSRichard Lowe np = hashtab.insert(mbs_name, found);
202*10d63b7dSRichard Lowe if (found) {
203*10d63b7dSRichard Lowe if(tmp_mbs_buffer != NULL) {
204*10d63b7dSRichard Lowe retmem_mb(tmp_mbs_buffer);
205*10d63b7dSRichard Lowe }
206*10d63b7dSRichard Lowe return np;
207*10d63b7dSRichard Lowe }
208*10d63b7dSRichard Lowe }
209*10d63b7dSRichard Lowe getname_struct_count += sizeof(struct _Name);
210*10d63b7dSRichard Lowe *np = empty_Name;
211*10d63b7dSRichard Lowe
212*10d63b7dSRichard Lowe np->string_mb = strdup(mbs_name);
213*10d63b7dSRichard Lowe if(tmp_mbs_buffer != NULL) {
214*10d63b7dSRichard Lowe retmem_mb(tmp_mbs_buffer);
215*10d63b7dSRichard Lowe mbs_name = tmp_mbs_buffer = NULL;
216*10d63b7dSRichard Lowe }
217*10d63b7dSRichard Lowe getname_bytes_count += strlen(np->string_mb) + 1;
218*10d63b7dSRichard Lowe /* Fill in the new Name */
219*10d63b7dSRichard Lowe np->stat.time = file_no_time;
220*10d63b7dSRichard Lowe np->hash.length = length;
221*10d63b7dSRichard Lowe /* Scan the namestring to classify it */
222*10d63b7dSRichard Lowe for (cap = name, len = 0; --length >= 0;) {
223*10d63b7dSRichard Lowe len |= get_char_semantics_value(*cap++);
224*10d63b7dSRichard Lowe }
225*10d63b7dSRichard Lowe np->dollar = BOOLEAN((len & (int) dollar_sem) != 0);
226*10d63b7dSRichard Lowe np->meta = BOOLEAN((len & (int) meta_sem) != 0);
227*10d63b7dSRichard Lowe np->percent = BOOLEAN((len & (int) percent_sem) != 0);
228*10d63b7dSRichard Lowe np->wildcard = BOOLEAN((len & (int) wildcard_sem) != 0);
229*10d63b7dSRichard Lowe np->colon = BOOLEAN((len & (int) colon_sem) != 0);
230*10d63b7dSRichard Lowe np->parenleft = BOOLEAN((len & (int) parenleft_sem) != 0);
231*10d63b7dSRichard Lowe getname_names_count++;
232*10d63b7dSRichard Lowe return np;
233*10d63b7dSRichard Lowe }
234*10d63b7dSRichard Lowe
235*10d63b7dSRichard Lowe void
store_name(Name name)236*10d63b7dSRichard Lowe store_name(Name name)
237*10d63b7dSRichard Lowe {
238*10d63b7dSRichard Lowe hashtab.insert(name);
239*10d63b7dSRichard Lowe }
240*10d63b7dSRichard Lowe
241*10d63b7dSRichard Lowe void
free_name(Name name)242*10d63b7dSRichard Lowe free_name(Name name)
243*10d63b7dSRichard Lowe {
244*10d63b7dSRichard Lowe freename_names_count++;
245*10d63b7dSRichard Lowe freename_struct_count += sizeof(struct _Name);
246*10d63b7dSRichard Lowe freename_bytes_count += strlen(name->string_mb) + 1;
247*10d63b7dSRichard Lowe retmem_mb(name->string_mb);
248*10d63b7dSRichard Lowe for (Property next, p = name->prop; p != NULL; p = next) {
249*10d63b7dSRichard Lowe next = p->next;
250*10d63b7dSRichard Lowe free(p);
251*10d63b7dSRichard Lowe }
252*10d63b7dSRichard Lowe free(name);
253*10d63b7dSRichard Lowe }
254*10d63b7dSRichard Lowe
255*10d63b7dSRichard Lowe /*
256*10d63b7dSRichard Lowe * enable_interrupt(handler)
257*10d63b7dSRichard Lowe *
258*10d63b7dSRichard Lowe * This routine sets a new interrupt handler for the signals make
259*10d63b7dSRichard Lowe * wants to deal with.
260*10d63b7dSRichard Lowe *
261*10d63b7dSRichard Lowe * Parameters:
262*10d63b7dSRichard Lowe * handler The function installed as interrupt handler
263*10d63b7dSRichard Lowe *
264*10d63b7dSRichard Lowe * Static variables used:
265*10d63b7dSRichard Lowe * sigivalue The original signal handler
266*10d63b7dSRichard Lowe * sigqvalue The original signal handler
267*10d63b7dSRichard Lowe * sigtvalue The original signal handler
268*10d63b7dSRichard Lowe * sighvalue The original signal handler
269*10d63b7dSRichard Lowe */
270*10d63b7dSRichard Lowe void
enable_interrupt(register void (* handler)(int))271*10d63b7dSRichard Lowe enable_interrupt(register void (*handler) (int))
272*10d63b7dSRichard Lowe {
273*10d63b7dSRichard Lowe if (sigivalue != SIG_IGN) {
274*10d63b7dSRichard Lowe (void) bsd_signal(SIGINT, (SIG_PF) handler);
275*10d63b7dSRichard Lowe }
276*10d63b7dSRichard Lowe if (sigqvalue != SIG_IGN) {
277*10d63b7dSRichard Lowe (void) bsd_signal(SIGQUIT, (SIG_PF) handler);
278*10d63b7dSRichard Lowe }
279*10d63b7dSRichard Lowe if (sigtvalue != SIG_IGN) {
280*10d63b7dSRichard Lowe (void) bsd_signal(SIGTERM, (SIG_PF) handler);
281*10d63b7dSRichard Lowe }
282*10d63b7dSRichard Lowe if (sighvalue != SIG_IGN) {
283*10d63b7dSRichard Lowe (void) bsd_signal(SIGHUP, (SIG_PF) handler);
284*10d63b7dSRichard Lowe }
285*10d63b7dSRichard Lowe }
286*10d63b7dSRichard Lowe
287*10d63b7dSRichard Lowe /*
288*10d63b7dSRichard Lowe * setup_char_semantics()
289*10d63b7dSRichard Lowe *
290*10d63b7dSRichard Lowe * Load the vector char_semantics[] with lexical markers
291*10d63b7dSRichard Lowe *
292*10d63b7dSRichard Lowe * Parameters:
293*10d63b7dSRichard Lowe *
294*10d63b7dSRichard Lowe * Global variables used:
295*10d63b7dSRichard Lowe * char_semantics The vector of character semantics that we set
296*10d63b7dSRichard Lowe */
297*10d63b7dSRichard Lowe void
setup_char_semantics(void)298*10d63b7dSRichard Lowe setup_char_semantics(void)
299*10d63b7dSRichard Lowe {
300*10d63b7dSRichard Lowe const char *s;
301*10d63b7dSRichard Lowe wchar_t wc_buffer[1];
302*10d63b7dSRichard Lowe int entry;
303*10d63b7dSRichard Lowe
304*10d63b7dSRichard Lowe if (svr4) {
305*10d63b7dSRichard Lowe s = "@-";
306*10d63b7dSRichard Lowe } else {
307*10d63b7dSRichard Lowe s = "=@-?!+";
308*10d63b7dSRichard Lowe }
309*10d63b7dSRichard Lowe for (s; MBTOWC(wc_buffer, s); s++) {
310*10d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
311*10d63b7dSRichard Lowe char_semantics[entry] |= (int) command_prefix_sem;
312*10d63b7dSRichard Lowe }
313*10d63b7dSRichard Lowe char_semantics[dollar_char_entry] |= (int) dollar_sem;
314*10d63b7dSRichard Lowe for (s = "#|=^();&<>*?[]:$`'\"\\\n"; MBTOWC(wc_buffer, s); s++) {
315*10d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
316*10d63b7dSRichard Lowe char_semantics[entry] |= (int) meta_sem;
317*10d63b7dSRichard Lowe }
318*10d63b7dSRichard Lowe char_semantics[percent_char_entry] |= (int) percent_sem;
319*10d63b7dSRichard Lowe for (s = "@*<%?^"; MBTOWC(wc_buffer, s); s++) {
320*10d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
321*10d63b7dSRichard Lowe char_semantics[entry] |= (int) special_macro_sem;
322*10d63b7dSRichard Lowe }
323*10d63b7dSRichard Lowe for (s = "?[*"; MBTOWC(wc_buffer, s); s++) {
324*10d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
325*10d63b7dSRichard Lowe char_semantics[entry] |= (int) wildcard_sem;
326*10d63b7dSRichard Lowe }
327*10d63b7dSRichard Lowe char_semantics[colon_char_entry] |= (int) colon_sem;
328*10d63b7dSRichard Lowe char_semantics[parenleft_char_entry] |= (int) parenleft_sem;
329*10d63b7dSRichard Lowe }
330*10d63b7dSRichard Lowe
331*10d63b7dSRichard Lowe /*
332*10d63b7dSRichard Lowe * errmsg(errnum)
333*10d63b7dSRichard Lowe *
334*10d63b7dSRichard Lowe * Return the error message for a system call error
335*10d63b7dSRichard Lowe *
336*10d63b7dSRichard Lowe * Return value:
337*10d63b7dSRichard Lowe * An error message string
338*10d63b7dSRichard Lowe *
339*10d63b7dSRichard Lowe * Parameters:
340*10d63b7dSRichard Lowe * errnum The number of the error we want to describe
341*10d63b7dSRichard Lowe *
342*10d63b7dSRichard Lowe * Global variables used:
343*10d63b7dSRichard Lowe * sys_errlist A vector of error messages
344*10d63b7dSRichard Lowe * sys_nerr The size of sys_errlist
345*10d63b7dSRichard Lowe */
346*10d63b7dSRichard Lowe char *
errmsg(int errnum)347*10d63b7dSRichard Lowe errmsg(int errnum)
348*10d63b7dSRichard Lowe {
349*10d63b7dSRichard Lowe
350*10d63b7dSRichard Lowe extern int sys_nerr;
351*10d63b7dSRichard Lowe char *errbuf;
352*10d63b7dSRichard Lowe
353*10d63b7dSRichard Lowe if ((errnum < 0) || (errnum > sys_nerr)) {
354*10d63b7dSRichard Lowe errbuf = getmem(6+1+11+1);
355*10d63b7dSRichard Lowe (void) sprintf(errbuf, gettext("Error %d"), errnum);
356*10d63b7dSRichard Lowe return errbuf;
357*10d63b7dSRichard Lowe } else {
358*10d63b7dSRichard Lowe return strerror(errnum);
359*10d63b7dSRichard Lowe
360*10d63b7dSRichard Lowe }
361*10d63b7dSRichard Lowe }
362*10d63b7dSRichard Lowe
363*10d63b7dSRichard Lowe static char static_buf[MAXPATHLEN*3];
364*10d63b7dSRichard Lowe
365*10d63b7dSRichard Lowe /*
366*10d63b7dSRichard Lowe * fatal_mksh(format, args...)
367*10d63b7dSRichard Lowe *
368*10d63b7dSRichard Lowe * Print a message and die
369*10d63b7dSRichard Lowe *
370*10d63b7dSRichard Lowe * Parameters:
371*10d63b7dSRichard Lowe * format printf type format string
372*10d63b7dSRichard Lowe * args Arguments to match the format
373*10d63b7dSRichard Lowe */
374*10d63b7dSRichard Lowe /*VARARGS*/
375*10d63b7dSRichard Lowe void
fatal_mksh(const char * message,...)376*10d63b7dSRichard Lowe fatal_mksh(const char *message, ...)
377*10d63b7dSRichard Lowe {
378*10d63b7dSRichard Lowe va_list args;
379*10d63b7dSRichard Lowe char *buf = static_buf;
380*10d63b7dSRichard Lowe char *mksh_fat_err = gettext("mksh: Fatal error: ");
381*10d63b7dSRichard Lowe char *cur_wrk_dir = gettext("Current working directory: ");
382*10d63b7dSRichard Lowe int mksh_fat_err_len = strlen(mksh_fat_err);
383*10d63b7dSRichard Lowe
384*10d63b7dSRichard Lowe va_start(args, message);
385*10d63b7dSRichard Lowe (void) fflush(stdout);
386*10d63b7dSRichard Lowe (void) strcpy(buf, mksh_fat_err);
387*10d63b7dSRichard Lowe size_t buf_len = vsnprintf(static_buf + mksh_fat_err_len,
388*10d63b7dSRichard Lowe sizeof(static_buf) - mksh_fat_err_len,
389*10d63b7dSRichard Lowe message, args)
390*10d63b7dSRichard Lowe + mksh_fat_err_len
391*10d63b7dSRichard Lowe + strlen(cur_wrk_dir)
392*10d63b7dSRichard Lowe + strlen(get_current_path_mksh())
393*10d63b7dSRichard Lowe + 3; // "\n\n"
394*10d63b7dSRichard Lowe va_end(args);
395*10d63b7dSRichard Lowe if (buf_len >= sizeof(static_buf)) {
396*10d63b7dSRichard Lowe buf = getmem(buf_len);
397*10d63b7dSRichard Lowe (void) strcpy(buf, mksh_fat_err);
398*10d63b7dSRichard Lowe va_start(args, message);
399*10d63b7dSRichard Lowe (void) vsprintf(buf + mksh_fat_err_len, message, args);
400*10d63b7dSRichard Lowe va_end(args);
401*10d63b7dSRichard Lowe }
402*10d63b7dSRichard Lowe (void) strcat(buf, "\n");
403*10d63b7dSRichard Lowe /*
404*10d63b7dSRichard Lowe if (report_pwd) {
405*10d63b7dSRichard Lowe */
406*10d63b7dSRichard Lowe if (1) {
407*10d63b7dSRichard Lowe (void) strcat(buf, cur_wrk_dir);
408*10d63b7dSRichard Lowe (void) strcat(buf, get_current_path_mksh());
409*10d63b7dSRichard Lowe (void) strcat(buf, "\n");
410*10d63b7dSRichard Lowe }
411*10d63b7dSRichard Lowe (void) fputs(buf, stderr);
412*10d63b7dSRichard Lowe (void) fflush(stderr);
413*10d63b7dSRichard Lowe if (buf != static_buf) {
414*10d63b7dSRichard Lowe retmem_mb(buf);
415*10d63b7dSRichard Lowe }
416*10d63b7dSRichard Lowe exit_status = 1;
417*10d63b7dSRichard Lowe exit(1);
418*10d63b7dSRichard Lowe }
419*10d63b7dSRichard Lowe
420*10d63b7dSRichard Lowe /*
421*10d63b7dSRichard Lowe * fatal_reader_mksh(format, args...)
422*10d63b7dSRichard Lowe *
423*10d63b7dSRichard Lowe * Parameters:
424*10d63b7dSRichard Lowe * format printf style format string
425*10d63b7dSRichard Lowe * args arguments to match the format
426*10d63b7dSRichard Lowe */
427*10d63b7dSRichard Lowe /*VARARGS*/
428*10d63b7dSRichard Lowe void
fatal_reader_mksh(const char * pattern,...)429*10d63b7dSRichard Lowe fatal_reader_mksh(const char * pattern, ...)
430*10d63b7dSRichard Lowe {
431*10d63b7dSRichard Lowe va_list args;
432*10d63b7dSRichard Lowe char message[1000];
433*10d63b7dSRichard Lowe
434*10d63b7dSRichard Lowe va_start(args, pattern);
435*10d63b7dSRichard Lowe /*
436*10d63b7dSRichard Lowe if (file_being_read != NULL) {
437*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, file_being_read);
438*10d63b7dSRichard Lowe if (line_number != 0) {
439*10d63b7dSRichard Lowe (void) sprintf(message,
440*10d63b7dSRichard Lowe gettext("%s, line %d: %s"),
441*10d63b7dSRichard Lowe mbs_buffer,
442*10d63b7dSRichard Lowe line_number,
443*10d63b7dSRichard Lowe pattern);
444*10d63b7dSRichard Lowe } else {
445*10d63b7dSRichard Lowe (void) sprintf(message,
446*10d63b7dSRichard Lowe "%s: %s",
447*10d63b7dSRichard Lowe mbs_buffer,
448*10d63b7dSRichard Lowe pattern);
449*10d63b7dSRichard Lowe }
450*10d63b7dSRichard Lowe pattern = message;
451*10d63b7dSRichard Lowe }
452*10d63b7dSRichard Lowe */
453*10d63b7dSRichard Lowe
454*10d63b7dSRichard Lowe (void) fflush(stdout);
455*10d63b7dSRichard Lowe (void) fprintf(stderr, gettext("mksh: Fatal error in reader: "));
456*10d63b7dSRichard Lowe (void) vfprintf(stderr, pattern, args);
457*10d63b7dSRichard Lowe (void) fprintf(stderr, "\n");
458*10d63b7dSRichard Lowe va_end(args);
459*10d63b7dSRichard Lowe
460*10d63b7dSRichard Lowe /*
461*10d63b7dSRichard Lowe if (temp_file_name != NULL) {
462*10d63b7dSRichard Lowe (void) fprintf(stderr,
463*10d63b7dSRichard Lowe gettext("mksh: Temp-file %s not removed\n"),
464*10d63b7dSRichard Lowe temp_file_name->string_mb);
465*10d63b7dSRichard Lowe temp_file_name = NULL;
466*10d63b7dSRichard Lowe }
467*10d63b7dSRichard Lowe */
468*10d63b7dSRichard Lowe
469*10d63b7dSRichard Lowe /*
470*10d63b7dSRichard Lowe if (report_pwd) {
471*10d63b7dSRichard Lowe */
472*10d63b7dSRichard Lowe if (1) {
473*10d63b7dSRichard Lowe (void) fprintf(stderr,
474*10d63b7dSRichard Lowe gettext("Current working directory %s\n"),
475*10d63b7dSRichard Lowe get_current_path_mksh());
476*10d63b7dSRichard Lowe }
477*10d63b7dSRichard Lowe (void) fflush(stderr);
478*10d63b7dSRichard Lowe exit_status = 1;
479*10d63b7dSRichard Lowe exit(1);
480*10d63b7dSRichard Lowe }
481*10d63b7dSRichard Lowe
482*10d63b7dSRichard Lowe /*
483*10d63b7dSRichard Lowe * warning_mksh(format, args...)
484*10d63b7dSRichard Lowe *
485*10d63b7dSRichard Lowe * Print a message and continue.
486*10d63b7dSRichard Lowe *
487*10d63b7dSRichard Lowe * Parameters:
488*10d63b7dSRichard Lowe * format printf type format string
489*10d63b7dSRichard Lowe * args Arguments to match the format
490*10d63b7dSRichard Lowe */
491*10d63b7dSRichard Lowe /*VARARGS*/
492*10d63b7dSRichard Lowe void
warning_mksh(char * message,...)493*10d63b7dSRichard Lowe warning_mksh(char * message, ...)
494*10d63b7dSRichard Lowe {
495*10d63b7dSRichard Lowe va_list args;
496*10d63b7dSRichard Lowe
497*10d63b7dSRichard Lowe va_start(args, message);
498*10d63b7dSRichard Lowe (void) fflush(stdout);
499*10d63b7dSRichard Lowe (void) fprintf(stderr, gettext("mksh: Warning: "));
500*10d63b7dSRichard Lowe (void) vfprintf(stderr, message, args);
501*10d63b7dSRichard Lowe (void) fprintf(stderr, "\n");
502*10d63b7dSRichard Lowe va_end(args);
503*10d63b7dSRichard Lowe /*
504*10d63b7dSRichard Lowe if (report_pwd) {
505*10d63b7dSRichard Lowe */
506*10d63b7dSRichard Lowe if (1) {
507*10d63b7dSRichard Lowe (void) fprintf(stderr,
508*10d63b7dSRichard Lowe gettext("Current working directory %s\n"),
509*10d63b7dSRichard Lowe get_current_path_mksh());
510*10d63b7dSRichard Lowe }
511*10d63b7dSRichard Lowe (void) fflush(stderr);
512*10d63b7dSRichard Lowe }
513*10d63b7dSRichard Lowe
514*10d63b7dSRichard Lowe /*
515*10d63b7dSRichard Lowe * get_current_path_mksh()
516*10d63b7dSRichard Lowe *
517*10d63b7dSRichard Lowe * Stuff current_path with the current path if it isnt there already.
518*10d63b7dSRichard Lowe *
519*10d63b7dSRichard Lowe * Parameters:
520*10d63b7dSRichard Lowe *
521*10d63b7dSRichard Lowe * Global variables used:
522*10d63b7dSRichard Lowe */
523*10d63b7dSRichard Lowe char *
get_current_path_mksh(void)524*10d63b7dSRichard Lowe get_current_path_mksh(void)
525*10d63b7dSRichard Lowe {
526*10d63b7dSRichard Lowe char pwd[(MAXPATHLEN * MB_LEN_MAX)];
527*10d63b7dSRichard Lowe static char *current_path;
528*10d63b7dSRichard Lowe
529*10d63b7dSRichard Lowe if (current_path == NULL) {
530*10d63b7dSRichard Lowe getcwd(pwd, sizeof(pwd));
531*10d63b7dSRichard Lowe if (pwd[0] == (int) nul_char) {
532*10d63b7dSRichard Lowe pwd[0] = (int) slash_char;
533*10d63b7dSRichard Lowe pwd[1] = (int) nul_char;
534*10d63b7dSRichard Lowe }
535*10d63b7dSRichard Lowe current_path = strdup(pwd);
536*10d63b7dSRichard Lowe }
537*10d63b7dSRichard Lowe return current_path;
538*10d63b7dSRichard Lowe }
539*10d63b7dSRichard Lowe
540*10d63b7dSRichard Lowe /*
541*10d63b7dSRichard Lowe * append_prop(target, type)
542*10d63b7dSRichard Lowe *
543*10d63b7dSRichard Lowe * Create a new property and append it to the property list of a Name.
544*10d63b7dSRichard Lowe *
545*10d63b7dSRichard Lowe * Return value:
546*10d63b7dSRichard Lowe * A new property block for the target
547*10d63b7dSRichard Lowe *
548*10d63b7dSRichard Lowe * Parameters:
549*10d63b7dSRichard Lowe * target The target that wants a new property
550*10d63b7dSRichard Lowe * type The type of property being requested
551*10d63b7dSRichard Lowe *
552*10d63b7dSRichard Lowe * Global variables used:
553*10d63b7dSRichard Lowe */
554*10d63b7dSRichard Lowe Property
append_prop(register Name target,register Property_id type)555*10d63b7dSRichard Lowe append_prop(register Name target, register Property_id type)
556*10d63b7dSRichard Lowe {
557*10d63b7dSRichard Lowe register Property *insert = &target->prop;
558*10d63b7dSRichard Lowe register Property prop = *insert;
559*10d63b7dSRichard Lowe register int size;
560*10d63b7dSRichard Lowe
561*10d63b7dSRichard Lowe switch (type) {
562*10d63b7dSRichard Lowe case conditional_prop:
563*10d63b7dSRichard Lowe size = sizeof (struct Conditional);
564*10d63b7dSRichard Lowe break;
565*10d63b7dSRichard Lowe case line_prop:
566*10d63b7dSRichard Lowe size = sizeof (struct Line);
567*10d63b7dSRichard Lowe break;
568*10d63b7dSRichard Lowe case macro_prop:
569*10d63b7dSRichard Lowe size = sizeof (struct _Macro);
570*10d63b7dSRichard Lowe break;
571*10d63b7dSRichard Lowe case makefile_prop:
572*10d63b7dSRichard Lowe size = sizeof (struct Makefile);
573*10d63b7dSRichard Lowe break;
574*10d63b7dSRichard Lowe case member_prop:
575*10d63b7dSRichard Lowe size = sizeof (struct Member);
576*10d63b7dSRichard Lowe break;
577*10d63b7dSRichard Lowe case recursive_prop:
578*10d63b7dSRichard Lowe size = sizeof (struct Recursive);
579*10d63b7dSRichard Lowe break;
580*10d63b7dSRichard Lowe case sccs_prop:
581*10d63b7dSRichard Lowe size = sizeof (struct Sccs);
582*10d63b7dSRichard Lowe break;
583*10d63b7dSRichard Lowe case suffix_prop:
584*10d63b7dSRichard Lowe size = sizeof (struct Suffix);
585*10d63b7dSRichard Lowe break;
586*10d63b7dSRichard Lowe case target_prop:
587*10d63b7dSRichard Lowe size = sizeof (struct Target);
588*10d63b7dSRichard Lowe break;
589*10d63b7dSRichard Lowe case time_prop:
590*10d63b7dSRichard Lowe size = sizeof (struct STime);
591*10d63b7dSRichard Lowe break;
592*10d63b7dSRichard Lowe case vpath_alias_prop:
593*10d63b7dSRichard Lowe size = sizeof (struct Vpath_alias);
594*10d63b7dSRichard Lowe break;
595*10d63b7dSRichard Lowe case long_member_name_prop:
596*10d63b7dSRichard Lowe size = sizeof (struct Long_member_name);
597*10d63b7dSRichard Lowe break;
598*10d63b7dSRichard Lowe case macro_append_prop:
599*10d63b7dSRichard Lowe size = sizeof (struct _Macro_appendix);
600*10d63b7dSRichard Lowe break;
601*10d63b7dSRichard Lowe case env_mem_prop:
602*10d63b7dSRichard Lowe size = sizeof (struct _Env_mem);
603*10d63b7dSRichard Lowe break;
604*10d63b7dSRichard Lowe default:
605*10d63b7dSRichard Lowe fatal_mksh(gettext("Internal error. Unknown prop type %d"), type);
606*10d63b7dSRichard Lowe }
607*10d63b7dSRichard Lowe for (; prop != NULL; insert = &prop->next, prop = *insert);
608*10d63b7dSRichard Lowe size += PROPERTY_HEAD_SIZE;
609*10d63b7dSRichard Lowe *insert = prop = (Property) getmem(size);
610*10d63b7dSRichard Lowe memset((char *) prop, 0, size);
611*10d63b7dSRichard Lowe prop->type = type;
612*10d63b7dSRichard Lowe prop->next = NULL;
613*10d63b7dSRichard Lowe return prop;
614*10d63b7dSRichard Lowe }
615*10d63b7dSRichard Lowe
616*10d63b7dSRichard Lowe /*
617*10d63b7dSRichard Lowe * maybe_append_prop(target, type)
618*10d63b7dSRichard Lowe *
619*10d63b7dSRichard Lowe * Append a property to the Name if none of this type exists
620*10d63b7dSRichard Lowe * else return the one already there
621*10d63b7dSRichard Lowe *
622*10d63b7dSRichard Lowe * Return value:
623*10d63b7dSRichard Lowe * A property of the requested type for the target
624*10d63b7dSRichard Lowe *
625*10d63b7dSRichard Lowe * Parameters:
626*10d63b7dSRichard Lowe * target The target that wants a new property
627*10d63b7dSRichard Lowe * type The type of property being requested
628*10d63b7dSRichard Lowe *
629*10d63b7dSRichard Lowe * Global variables used:
630*10d63b7dSRichard Lowe */
631*10d63b7dSRichard Lowe Property
maybe_append_prop(register Name target,register Property_id type)632*10d63b7dSRichard Lowe maybe_append_prop(register Name target, register Property_id type)
633*10d63b7dSRichard Lowe {
634*10d63b7dSRichard Lowe register Property prop;
635*10d63b7dSRichard Lowe
636*10d63b7dSRichard Lowe if ((prop = get_prop(target->prop, type)) != NULL) {
637*10d63b7dSRichard Lowe return prop;
638*10d63b7dSRichard Lowe }
639*10d63b7dSRichard Lowe return append_prop(target, type);
640*10d63b7dSRichard Lowe }
641*10d63b7dSRichard Lowe
642*10d63b7dSRichard Lowe /*
643*10d63b7dSRichard Lowe * get_prop(start, type)
644*10d63b7dSRichard Lowe *
645*10d63b7dSRichard Lowe * Scan the property list of a Name to find the next property
646*10d63b7dSRichard Lowe * of a given type.
647*10d63b7dSRichard Lowe *
648*10d63b7dSRichard Lowe * Return value:
649*10d63b7dSRichard Lowe * The first property of the type, if any left
650*10d63b7dSRichard Lowe *
651*10d63b7dSRichard Lowe * Parameters:
652*10d63b7dSRichard Lowe * start The first property block to check for type
653*10d63b7dSRichard Lowe * type The type of property block we need
654*10d63b7dSRichard Lowe *
655*10d63b7dSRichard Lowe * Global variables used:
656*10d63b7dSRichard Lowe */
657*10d63b7dSRichard Lowe Property
get_prop(register Property start,register Property_id type)658*10d63b7dSRichard Lowe get_prop(register Property start, register Property_id type)
659*10d63b7dSRichard Lowe {
660*10d63b7dSRichard Lowe for (; start != NULL; start = start->next) {
661*10d63b7dSRichard Lowe if (start->type == type) {
662*10d63b7dSRichard Lowe return start;
663*10d63b7dSRichard Lowe }
664*10d63b7dSRichard Lowe }
665*10d63b7dSRichard Lowe return NULL;
666*10d63b7dSRichard Lowe }
667*10d63b7dSRichard Lowe
668*10d63b7dSRichard Lowe /*
669*10d63b7dSRichard Lowe * append_string(from, to, length)
670*10d63b7dSRichard Lowe *
671*10d63b7dSRichard Lowe * Append a C string to a make string expanding it if nessecary
672*10d63b7dSRichard Lowe *
673*10d63b7dSRichard Lowe * Parameters:
674*10d63b7dSRichard Lowe * from The source (C style) string
675*10d63b7dSRichard Lowe * to The destination (make style) string
676*10d63b7dSRichard Lowe * length The length of the from string
677*10d63b7dSRichard Lowe *
678*10d63b7dSRichard Lowe * Global variables used:
679*10d63b7dSRichard Lowe */
680*10d63b7dSRichard Lowe void
append_string(register wchar_t * from,register String to,register int length)681*10d63b7dSRichard Lowe append_string(register wchar_t *from, register String to, register int length)
682*10d63b7dSRichard Lowe {
683*10d63b7dSRichard Lowe if (length == FIND_LENGTH) {
684*10d63b7dSRichard Lowe length = wcslen(from);
685*10d63b7dSRichard Lowe }
686*10d63b7dSRichard Lowe if (to->buffer.start == NULL) {
687*10d63b7dSRichard Lowe expand_string(to, 32 + length);
688*10d63b7dSRichard Lowe }
689*10d63b7dSRichard Lowe if (to->buffer.end - to->text.p <= length) {
690*10d63b7dSRichard Lowe expand_string(to,
691*10d63b7dSRichard Lowe (to->buffer.end - to->buffer.start) * 2 +
692*10d63b7dSRichard Lowe length);
693*10d63b7dSRichard Lowe }
694*10d63b7dSRichard Lowe if (length > 0) {
695*10d63b7dSRichard Lowe (void) wcsncpy(to->text.p, from, length);
696*10d63b7dSRichard Lowe to->text.p += length;
697*10d63b7dSRichard Lowe }
698*10d63b7dSRichard Lowe *(to->text.p) = (int) nul_char;
699*10d63b7dSRichard Lowe }
700*10d63b7dSRichard Lowe
get_wstring(char * from)701*10d63b7dSRichard Lowe wchar_t * get_wstring(char *from) {
702*10d63b7dSRichard Lowe if(from == NULL) {
703*10d63b7dSRichard Lowe return NULL;
704*10d63b7dSRichard Lowe }
705*10d63b7dSRichard Lowe getwstring_count++;
706*10d63b7dSRichard Lowe wchar_t * wcbuf = ALLOC_WC(strlen(from) + 1);
707*10d63b7dSRichard Lowe mbstowcs(wcbuf, from, strlen(from)+1);
708*10d63b7dSRichard Lowe return wcbuf;
709*10d63b7dSRichard Lowe }
710*10d63b7dSRichard Lowe
711*10d63b7dSRichard Lowe void
append_string(register char * from,register String to,register int length)712*10d63b7dSRichard Lowe append_string(register char *from, register String to, register int length)
713*10d63b7dSRichard Lowe {
714*10d63b7dSRichard Lowe if (length == FIND_LENGTH) {
715*10d63b7dSRichard Lowe length = strlen(from);
716*10d63b7dSRichard Lowe }
717*10d63b7dSRichard Lowe if (to->buffer.start == NULL) {
718*10d63b7dSRichard Lowe expand_string(to, 32 + length);
719*10d63b7dSRichard Lowe }
720*10d63b7dSRichard Lowe if (to->buffer.end - to->text.p <= length) {
721*10d63b7dSRichard Lowe expand_string(to,
722*10d63b7dSRichard Lowe (to->buffer.end - to->buffer.start) * 2 +
723*10d63b7dSRichard Lowe length);
724*10d63b7dSRichard Lowe }
725*10d63b7dSRichard Lowe if (length > 0) {
726*10d63b7dSRichard Lowe (void) mbstowcs(to->text.p, from, length);
727*10d63b7dSRichard Lowe to->text.p += length;
728*10d63b7dSRichard Lowe }
729*10d63b7dSRichard Lowe *(to->text.p) = (int) nul_char;
730*10d63b7dSRichard Lowe }
731*10d63b7dSRichard Lowe
732*10d63b7dSRichard Lowe /*
733*10d63b7dSRichard Lowe * expand_string(string, length)
734*10d63b7dSRichard Lowe *
735*10d63b7dSRichard Lowe * Allocate more memory for strings that run out of space.
736*10d63b7dSRichard Lowe *
737*10d63b7dSRichard Lowe * Parameters:
738*10d63b7dSRichard Lowe * string The make style string we want to expand
739*10d63b7dSRichard Lowe * length The new length we need
740*10d63b7dSRichard Lowe *
741*10d63b7dSRichard Lowe * Global variables used:
742*10d63b7dSRichard Lowe */
743*10d63b7dSRichard Lowe static void
expand_string(register String string,register int length)744*10d63b7dSRichard Lowe expand_string(register String string, register int length)
745*10d63b7dSRichard Lowe {
746*10d63b7dSRichard Lowe register wchar_t *p;
747*10d63b7dSRichard Lowe
748*10d63b7dSRichard Lowe if (string->buffer.start == NULL) {
749*10d63b7dSRichard Lowe /* For strings that have no memory allocated */
750*10d63b7dSRichard Lowe string->buffer.start =
751*10d63b7dSRichard Lowe string->text.p =
752*10d63b7dSRichard Lowe string->text.end =
753*10d63b7dSRichard Lowe ALLOC_WC(length);
754*10d63b7dSRichard Lowe string->buffer.end = string->buffer.start + length;
755*10d63b7dSRichard Lowe string->text.p[0] = (int) nul_char;
756*10d63b7dSRichard Lowe string->free_after_use = true;
757*10d63b7dSRichard Lowe expandstring_count++;
758*10d63b7dSRichard Lowe return;
759*10d63b7dSRichard Lowe }
760*10d63b7dSRichard Lowe if (string->buffer.end - string->buffer.start >= length) {
761*10d63b7dSRichard Lowe /* If we really don't need more memory. */
762*10d63b7dSRichard Lowe return;
763*10d63b7dSRichard Lowe }
764*10d63b7dSRichard Lowe /*
765*10d63b7dSRichard Lowe * Get more memory, copy the string and free the old buffer if
766*10d63b7dSRichard Lowe * it is was malloc()'ed.
767*10d63b7dSRichard Lowe */
768*10d63b7dSRichard Lowe expandstring_count++;
769*10d63b7dSRichard Lowe p = ALLOC_WC(length);
770*10d63b7dSRichard Lowe (void) wcscpy(p, string->buffer.start);
771*10d63b7dSRichard Lowe string->text.p = p + (string->text.p - string->buffer.start);
772*10d63b7dSRichard Lowe string->text.end = p + (string->text.end - string->buffer.start);
773*10d63b7dSRichard Lowe string->buffer.end = p + length;
774*10d63b7dSRichard Lowe if (string->free_after_use) {
775*10d63b7dSRichard Lowe retmem(string->buffer.start);
776*10d63b7dSRichard Lowe }
777*10d63b7dSRichard Lowe string->buffer.start = p;
778*10d63b7dSRichard Lowe string->free_after_use = true;
779*10d63b7dSRichard Lowe }
780*10d63b7dSRichard Lowe
781*10d63b7dSRichard Lowe /*
782*10d63b7dSRichard Lowe * append_char(from, to)
783*10d63b7dSRichard Lowe *
784*10d63b7dSRichard Lowe * Append one char to a make string expanding it if nessecary
785*10d63b7dSRichard Lowe *
786*10d63b7dSRichard Lowe * Parameters:
787*10d63b7dSRichard Lowe * from Single character to append to string
788*10d63b7dSRichard Lowe * to The destination (make style) string
789*10d63b7dSRichard Lowe *
790*10d63b7dSRichard Lowe * Global variables used:
791*10d63b7dSRichard Lowe */
792*10d63b7dSRichard Lowe void
append_char(wchar_t from,register String to)793*10d63b7dSRichard Lowe append_char(wchar_t from, register String to)
794*10d63b7dSRichard Lowe {
795*10d63b7dSRichard Lowe if (to->buffer.start == NULL) {
796*10d63b7dSRichard Lowe expand_string(to, 32);
797*10d63b7dSRichard Lowe }
798*10d63b7dSRichard Lowe if (to->buffer.end - to->text.p <= 2) {
799*10d63b7dSRichard Lowe expand_string(to, to->buffer.end - to->buffer.start + 32);
800*10d63b7dSRichard Lowe }
801*10d63b7dSRichard Lowe *(to->text.p)++ = from;
802*10d63b7dSRichard Lowe *(to->text.p) = (int) nul_char;
803*10d63b7dSRichard Lowe }
804*10d63b7dSRichard Lowe
805*10d63b7dSRichard Lowe /*
806*10d63b7dSRichard Lowe * handle_interrupt_mksh()
807*10d63b7dSRichard Lowe *
808*10d63b7dSRichard Lowe * This is where C-C traps are caught.
809*10d63b7dSRichard Lowe */
810*10d63b7dSRichard Lowe void
handle_interrupt_mksh(int)811*10d63b7dSRichard Lowe handle_interrupt_mksh(int)
812*10d63b7dSRichard Lowe {
813*10d63b7dSRichard Lowe (void) fflush(stdout);
814*10d63b7dSRichard Lowe /* Make sure the processes running under us terminate first. */
815*10d63b7dSRichard Lowe if (childPid > 0) {
816*10d63b7dSRichard Lowe kill(childPid, SIGTERM);
817*10d63b7dSRichard Lowe childPid = -1;
818*10d63b7dSRichard Lowe }
819*10d63b7dSRichard Lowe while (wait((int *) NULL) != -1);
820*10d63b7dSRichard Lowe exit_status = 2;
821*10d63b7dSRichard Lowe exit(2);
822*10d63b7dSRichard Lowe }
823*10d63b7dSRichard Lowe
824*10d63b7dSRichard Lowe /*
825*10d63b7dSRichard Lowe * setup_interrupt()
826*10d63b7dSRichard Lowe *
827*10d63b7dSRichard Lowe * This routine saves the original interrupt handler pointers
828*10d63b7dSRichard Lowe *
829*10d63b7dSRichard Lowe * Parameters:
830*10d63b7dSRichard Lowe *
831*10d63b7dSRichard Lowe * Static variables used:
832*10d63b7dSRichard Lowe * sigivalue The original signal handler
833*10d63b7dSRichard Lowe * sigqvalue The original signal handler
834*10d63b7dSRichard Lowe * sigtvalue The original signal handler
835*10d63b7dSRichard Lowe * sighvalue The original signal handler
836*10d63b7dSRichard Lowe */
837*10d63b7dSRichard Lowe void
setup_interrupt(register void (* handler)(int))838*10d63b7dSRichard Lowe setup_interrupt(register void (*handler) (int))
839*10d63b7dSRichard Lowe {
840*10d63b7dSRichard Lowe sigivalue = bsd_signal(SIGINT, SIG_IGN);
841*10d63b7dSRichard Lowe sigqvalue = bsd_signal(SIGQUIT, SIG_IGN);
842*10d63b7dSRichard Lowe sigtvalue = bsd_signal(SIGTERM, SIG_IGN);
843*10d63b7dSRichard Lowe sighvalue = bsd_signal(SIGHUP, SIG_IGN);
844*10d63b7dSRichard Lowe enable_interrupt(handler);
845*10d63b7dSRichard Lowe }
846*10d63b7dSRichard Lowe
847*10d63b7dSRichard Lowe
848*10d63b7dSRichard Lowe void
mbstowcs_with_check(wchar_t * pwcs,const char * s,size_t n)849*10d63b7dSRichard Lowe mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n)
850*10d63b7dSRichard Lowe {
851*10d63b7dSRichard Lowe if(mbstowcs(pwcs, s, n) == -1) {
852*10d63b7dSRichard Lowe fatal_mksh(gettext("The string `%s' is not valid in current locale"), s);
853*10d63b7dSRichard Lowe }
854*10d63b7dSRichard Lowe }
855*10d63b7dSRichard Lowe
856*10d63b7dSRichard Lowe
857*10d63b7dSRichard Lowe
Wstring()858*10d63b7dSRichard Lowe Wstring::Wstring()
859*10d63b7dSRichard Lowe {
860*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
861*10d63b7dSRichard Lowe }
862*10d63b7dSRichard Lowe
Wstring(struct _Name * name)863*10d63b7dSRichard Lowe Wstring::Wstring(struct _Name * name)
864*10d63b7dSRichard Lowe {
865*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
866*10d63b7dSRichard Lowe append_string(name->string_mb, &string, name->hash.length);
867*10d63b7dSRichard Lowe }
868*10d63b7dSRichard Lowe
~Wstring()869*10d63b7dSRichard Lowe Wstring::~Wstring()
870*10d63b7dSRichard Lowe {
871*10d63b7dSRichard Lowe if(string.free_after_use) {
872*10d63b7dSRichard Lowe retmem(string.buffer.start);
873*10d63b7dSRichard Lowe }
874*10d63b7dSRichard Lowe }
875*10d63b7dSRichard Lowe
876*10d63b7dSRichard Lowe void
init(struct _Name * name)877*10d63b7dSRichard Lowe Wstring::init(struct _Name * name)
878*10d63b7dSRichard Lowe {
879*10d63b7dSRichard Lowe if(string.free_after_use) {
880*10d63b7dSRichard Lowe retmem(string.buffer.start);
881*10d63b7dSRichard Lowe }
882*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
883*10d63b7dSRichard Lowe append_string(name->string_mb, &string, name->hash.length);
884*10d63b7dSRichard Lowe }
885*10d63b7dSRichard Lowe
886*10d63b7dSRichard Lowe void
init(wchar_t * name,unsigned length)887*10d63b7dSRichard Lowe Wstring::init(wchar_t * name, unsigned length)
888*10d63b7dSRichard Lowe {
889*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
890*10d63b7dSRichard Lowe append_string(name, &string, length);
891*10d63b7dSRichard Lowe string.buffer.start[length] = 0;
892*10d63b7dSRichard Lowe }
893*10d63b7dSRichard Lowe
894*10d63b7dSRichard Lowe Boolean
equaln(wchar_t * str,unsigned length)895*10d63b7dSRichard Lowe Wstring::equaln(wchar_t * str, unsigned length)
896*10d63b7dSRichard Lowe {
897*10d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start, str, length);
898*10d63b7dSRichard Lowe }
899*10d63b7dSRichard Lowe
900*10d63b7dSRichard Lowe Boolean
equaln(Wstring * str,unsigned length)901*10d63b7dSRichard Lowe Wstring::equaln(Wstring * str, unsigned length)
902*10d63b7dSRichard Lowe {
903*10d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start, str->string.buffer.start, length);
904*10d63b7dSRichard Lowe }
905*10d63b7dSRichard Lowe
906*10d63b7dSRichard Lowe Boolean
equal(wchar_t * str,unsigned off,unsigned length)907*10d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off, unsigned length)
908*10d63b7dSRichard Lowe {
909*10d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start + off, str, length);
910*10d63b7dSRichard Lowe }
911*10d63b7dSRichard Lowe
912*10d63b7dSRichard Lowe Boolean
equal(wchar_t * str,unsigned off)913*10d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off)
914*10d63b7dSRichard Lowe {
915*10d63b7dSRichard Lowe return (Boolean)IS_WEQUAL(string.buffer.start + off, str);
916*10d63b7dSRichard Lowe }
917*10d63b7dSRichard Lowe
918*10d63b7dSRichard Lowe Boolean
equal(wchar_t * str)919*10d63b7dSRichard Lowe Wstring::equal(wchar_t * str)
920*10d63b7dSRichard Lowe {
921*10d63b7dSRichard Lowe return equal(str, 0);
922*10d63b7dSRichard Lowe }
923*10d63b7dSRichard Lowe
924*10d63b7dSRichard Lowe Boolean
equal(Wstring * str,unsigned off,unsigned length)925*10d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off, unsigned length)
926*10d63b7dSRichard Lowe {
927*10d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start + off, str->string.buffer.start, length);
928*10d63b7dSRichard Lowe }
929*10d63b7dSRichard Lowe
930*10d63b7dSRichard Lowe Boolean
equal(Wstring * str)931*10d63b7dSRichard Lowe Wstring::equal(Wstring * str)
932*10d63b7dSRichard Lowe {
933*10d63b7dSRichard Lowe return equal(str, 0);
934*10d63b7dSRichard Lowe }
935*10d63b7dSRichard Lowe
936*10d63b7dSRichard Lowe Boolean
equal(Wstring * str,unsigned off)937*10d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off)
938*10d63b7dSRichard Lowe {
939*10d63b7dSRichard Lowe return (Boolean)IS_WEQUAL(string.buffer.start + off, str->string.buffer.start);
940*10d63b7dSRichard Lowe }
941*10d63b7dSRichard Lowe
942*10d63b7dSRichard Lowe void
append_to_str(struct _String * str,unsigned off,unsigned length)943*10d63b7dSRichard Lowe Wstring::append_to_str(struct _String * str, unsigned off, unsigned length)
944*10d63b7dSRichard Lowe {
945*10d63b7dSRichard Lowe append_string(string.buffer.start + off, str, length);
946*10d63b7dSRichard Lowe }
947*10d63b7dSRichard Lowe
948*10d63b7dSRichard Lowe Name
lookup(const char * key)949*10d63b7dSRichard Lowe Name_set::lookup(const char *key)
950*10d63b7dSRichard Lowe {
951*10d63b7dSRichard Lowe for (entry *node = root; node != 0;) {
952*10d63b7dSRichard Lowe int res = strcmp(key, node->name->string_mb);
953*10d63b7dSRichard Lowe if (res < 0) {
954*10d63b7dSRichard Lowe node = node->left;
955*10d63b7dSRichard Lowe } else if (res > 0) {
956*10d63b7dSRichard Lowe node = node->right;
957*10d63b7dSRichard Lowe } else {
958*10d63b7dSRichard Lowe return node->name;
959*10d63b7dSRichard Lowe }
960*10d63b7dSRichard Lowe }
961*10d63b7dSRichard Lowe return 0;
962*10d63b7dSRichard Lowe }
963*10d63b7dSRichard Lowe
964*10d63b7dSRichard Lowe Name
insert(const char * key,Boolean & found)965*10d63b7dSRichard Lowe Name_set::insert(const char *key, Boolean &found)
966*10d63b7dSRichard Lowe {
967*10d63b7dSRichard Lowe Name name = 0;
968*10d63b7dSRichard Lowe
969*10d63b7dSRichard Lowe if (root != 0) {
970*10d63b7dSRichard Lowe for (entry *node = root; name == 0;) {
971*10d63b7dSRichard Lowe int res = strcmp(key, node->name->string_mb);
972*10d63b7dSRichard Lowe if (res < 0) {
973*10d63b7dSRichard Lowe if (node->left != 0) {
974*10d63b7dSRichard Lowe node = node->left;
975*10d63b7dSRichard Lowe } else {
976*10d63b7dSRichard Lowe found = false;
977*10d63b7dSRichard Lowe name = ALLOC(Name);
978*10d63b7dSRichard Lowe
979*10d63b7dSRichard Lowe node->left = new entry(name, node);
980*10d63b7dSRichard Lowe rebalance(node);
981*10d63b7dSRichard Lowe }
982*10d63b7dSRichard Lowe } else if (res > 0) {
983*10d63b7dSRichard Lowe if (node->right != 0) {
984*10d63b7dSRichard Lowe node = node->right;
985*10d63b7dSRichard Lowe } else {
986*10d63b7dSRichard Lowe found = false;
987*10d63b7dSRichard Lowe name = ALLOC(Name);
988*10d63b7dSRichard Lowe
989*10d63b7dSRichard Lowe node->right = new entry(name, node);
990*10d63b7dSRichard Lowe rebalance(node);
991*10d63b7dSRichard Lowe }
992*10d63b7dSRichard Lowe } else {
993*10d63b7dSRichard Lowe found = true;
994*10d63b7dSRichard Lowe name = node->name;
995*10d63b7dSRichard Lowe }
996*10d63b7dSRichard Lowe }
997*10d63b7dSRichard Lowe } else {
998*10d63b7dSRichard Lowe found = false;
999*10d63b7dSRichard Lowe name = ALLOC(Name);
1000*10d63b7dSRichard Lowe
1001*10d63b7dSRichard Lowe root = new entry(name, 0);
1002*10d63b7dSRichard Lowe }
1003*10d63b7dSRichard Lowe return name;
1004*10d63b7dSRichard Lowe }
1005*10d63b7dSRichard Lowe
1006*10d63b7dSRichard Lowe void
insert(Name name)1007*10d63b7dSRichard Lowe Name_set::insert(Name name) {
1008*10d63b7dSRichard Lowe if (root != 0) {
1009*10d63b7dSRichard Lowe for (entry *node = root;;) {
1010*10d63b7dSRichard Lowe int res = strcmp(name->string_mb, node->name->string_mb);
1011*10d63b7dSRichard Lowe if (res < 0) {
1012*10d63b7dSRichard Lowe if (node->left != 0) {
1013*10d63b7dSRichard Lowe node = node->left;
1014*10d63b7dSRichard Lowe } else {
1015*10d63b7dSRichard Lowe node->left = new entry(name, node);
1016*10d63b7dSRichard Lowe rebalance(node);
1017*10d63b7dSRichard Lowe break;
1018*10d63b7dSRichard Lowe }
1019*10d63b7dSRichard Lowe } else if (res > 0) {
1020*10d63b7dSRichard Lowe if (node->right != 0) {
1021*10d63b7dSRichard Lowe node = node->right;
1022*10d63b7dSRichard Lowe } else {
1023*10d63b7dSRichard Lowe node->right = new entry(name, node);
1024*10d63b7dSRichard Lowe rebalance(node);
1025*10d63b7dSRichard Lowe break;
1026*10d63b7dSRichard Lowe }
1027*10d63b7dSRichard Lowe } else {
1028*10d63b7dSRichard Lowe // should be an error: inserting already existing name
1029*10d63b7dSRichard Lowe break;
1030*10d63b7dSRichard Lowe }
1031*10d63b7dSRichard Lowe }
1032*10d63b7dSRichard Lowe } else {
1033*10d63b7dSRichard Lowe root = new entry(name, 0);
1034*10d63b7dSRichard Lowe }
1035*10d63b7dSRichard Lowe }
1036*10d63b7dSRichard Lowe
1037*10d63b7dSRichard Lowe void
rebalance(Name_set::entry * node)1038*10d63b7dSRichard Lowe Name_set::rebalance(Name_set::entry *node) {
1039*10d63b7dSRichard Lowe for (; node != 0; node = node->parent) {
1040*10d63b7dSRichard Lowe entry *right = node->right;
1041*10d63b7dSRichard Lowe entry *left = node->left;
1042*10d63b7dSRichard Lowe
1043*10d63b7dSRichard Lowe unsigned rdepth = (right != 0) ? right->depth : 0;
1044*10d63b7dSRichard Lowe unsigned ldepth = (left != 0) ? left->depth : 0;
1045*10d63b7dSRichard Lowe
1046*10d63b7dSRichard Lowe if (ldepth > rdepth + 1) {
1047*10d63b7dSRichard Lowe if ((node->left = left->right) != 0) {
1048*10d63b7dSRichard Lowe left->right->parent = node;
1049*10d63b7dSRichard Lowe }
1050*10d63b7dSRichard Lowe if ((left->parent = node->parent) != 0) {
1051*10d63b7dSRichard Lowe if (node == node->parent->right) {
1052*10d63b7dSRichard Lowe node->parent->right = left;
1053*10d63b7dSRichard Lowe } else {
1054*10d63b7dSRichard Lowe node->parent->left = left;
1055*10d63b7dSRichard Lowe }
1056*10d63b7dSRichard Lowe } else {
1057*10d63b7dSRichard Lowe root = left;
1058*10d63b7dSRichard Lowe }
1059*10d63b7dSRichard Lowe left->right = node;
1060*10d63b7dSRichard Lowe node->parent = left;
1061*10d63b7dSRichard Lowe
1062*10d63b7dSRichard Lowe node->setup_depth();
1063*10d63b7dSRichard Lowe node = left;
1064*10d63b7dSRichard Lowe } else if (rdepth > ldepth + 1) {
1065*10d63b7dSRichard Lowe if ((node->right = right->left) != 0) {
1066*10d63b7dSRichard Lowe right->left->parent = node;
1067*10d63b7dSRichard Lowe }
1068*10d63b7dSRichard Lowe if ((right->parent = node->parent) != 0) {
1069*10d63b7dSRichard Lowe if (node == node->parent->right) {
1070*10d63b7dSRichard Lowe node->parent->right = right;
1071*10d63b7dSRichard Lowe } else {
1072*10d63b7dSRichard Lowe node->parent->left = right;
1073*10d63b7dSRichard Lowe }
1074*10d63b7dSRichard Lowe } else {
1075*10d63b7dSRichard Lowe root = right;
1076*10d63b7dSRichard Lowe }
1077*10d63b7dSRichard Lowe right->left = node;
1078*10d63b7dSRichard Lowe node->parent = right;
1079*10d63b7dSRichard Lowe
1080*10d63b7dSRichard Lowe node->setup_depth();
1081*10d63b7dSRichard Lowe node = right;
1082*10d63b7dSRichard Lowe }
1083*10d63b7dSRichard Lowe node->setup_depth();
1084*10d63b7dSRichard Lowe }
1085*10d63b7dSRichard Lowe }
1086*10d63b7dSRichard Lowe
1087*10d63b7dSRichard Lowe Name_set::iterator
begin() const1088*10d63b7dSRichard Lowe Name_set::begin() const {
1089*10d63b7dSRichard Lowe for (entry *node = root; node != 0; node = node->left) {
1090*10d63b7dSRichard Lowe if (node->left == 0) {
1091*10d63b7dSRichard Lowe return iterator(node);
1092*10d63b7dSRichard Lowe }
1093*10d63b7dSRichard Lowe }
1094*10d63b7dSRichard Lowe return iterator();
1095*10d63b7dSRichard Lowe }
1096*10d63b7dSRichard Lowe
1097*10d63b7dSRichard Lowe Name_set::iterator&
operator ++()1098*10d63b7dSRichard Lowe Name_set::iterator::operator++() {
1099*10d63b7dSRichard Lowe if (node != 0) {
1100*10d63b7dSRichard Lowe if (node->right != 0) {
1101*10d63b7dSRichard Lowe node = node->right;
1102*10d63b7dSRichard Lowe while (node->left != 0) {
1103*10d63b7dSRichard Lowe node = node->left;
1104*10d63b7dSRichard Lowe }
1105*10d63b7dSRichard Lowe } else {
1106*10d63b7dSRichard Lowe while ((node->parent != 0) && (node->parent->right == node)) {
1107*10d63b7dSRichard Lowe node = node->parent;
1108*10d63b7dSRichard Lowe }
1109*10d63b7dSRichard Lowe node = node->parent;
1110*10d63b7dSRichard Lowe }
1111*10d63b7dSRichard Lowe }
1112*10d63b7dSRichard Lowe return *this;
1113*10d63b7dSRichard Lowe }
1114