110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe * CDDL HEADER START
310d63b7dSRichard Lowe *
410d63b7dSRichard Lowe * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe *
810d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe * and limitations under the License.
1210d63b7dSRichard Lowe *
1310d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe *
1910d63b7dSRichard Lowe * CDDL HEADER END
2010d63b7dSRichard Lowe */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe * Use is subject to license terms.
2410d63b7dSRichard Lowe */
2510d63b7dSRichard Lowe
2610d63b7dSRichard Lowe
2710d63b7dSRichard Lowe /*
2810d63b7dSRichard Lowe * misc.cc
2910d63b7dSRichard Lowe *
3010d63b7dSRichard Lowe * This file contains various unclassified routines. Some main groups:
3110d63b7dSRichard Lowe * getname
3210d63b7dSRichard Lowe * Memory allocation
3310d63b7dSRichard Lowe * String handling
3410d63b7dSRichard Lowe * Property handling
3510d63b7dSRichard Lowe * Error message handling
3610d63b7dSRichard Lowe * Make internal state dumping
3710d63b7dSRichard Lowe * main routine support
3810d63b7dSRichard Lowe */
3910d63b7dSRichard Lowe
4010d63b7dSRichard Lowe /*
4110d63b7dSRichard Lowe * Included files
4210d63b7dSRichard Lowe */
4310d63b7dSRichard Lowe #include <bsd/bsd.h> /* bsd_signal() */
4410d63b7dSRichard Lowe #include <mksh/i18n.h> /* get_char_semantics_value() */
4510d63b7dSRichard Lowe #include <mksh/misc.h>
4610d63b7dSRichard Lowe #include <stdarg.h> /* va_list, va_start(), va_end() */
4710d63b7dSRichard Lowe #include <stdlib.h> /* mbstowcs() */
4810d63b7dSRichard Lowe #include <sys/signal.h> /* SIG_DFL */
4910d63b7dSRichard Lowe #include <sys/wait.h> /* wait() */
5010d63b7dSRichard Lowe
5110d63b7dSRichard Lowe #include <string.h> /* strerror() */
5210d63b7dSRichard Lowe #include <libintl.h>
5310d63b7dSRichard Lowe
5410d63b7dSRichard Lowe
5510d63b7dSRichard Lowe /*
5610d63b7dSRichard Lowe * Defined macros
5710d63b7dSRichard Lowe */
5810d63b7dSRichard Lowe
5910d63b7dSRichard Lowe /*
6010d63b7dSRichard Lowe * typedefs & structs
6110d63b7dSRichard Lowe */
6210d63b7dSRichard Lowe
6310d63b7dSRichard Lowe /*
6410d63b7dSRichard Lowe * Static variables
6510d63b7dSRichard Lowe */
6610d63b7dSRichard Lowe extern "C" {
6710d63b7dSRichard Lowe void (*sigivalue)(int) = SIG_DFL;
6810d63b7dSRichard Lowe void (*sigqvalue)(int) = SIG_DFL;
6910d63b7dSRichard Lowe void (*sigtvalue)(int) = SIG_DFL;
7010d63b7dSRichard Lowe void (*sighvalue)(int) = SIG_DFL;
7110d63b7dSRichard Lowe }
7210d63b7dSRichard Lowe
7310d63b7dSRichard Lowe long getname_bytes_count = 0;
7410d63b7dSRichard Lowe long getname_names_count = 0;
7510d63b7dSRichard Lowe long getname_struct_count = 0;
7610d63b7dSRichard Lowe
7710d63b7dSRichard Lowe long freename_bytes_count = 0;
7810d63b7dSRichard Lowe long freename_names_count = 0;
7910d63b7dSRichard Lowe long freename_struct_count = 0;
8010d63b7dSRichard Lowe
8110d63b7dSRichard Lowe long expandstring_count = 0;
8210d63b7dSRichard Lowe long getwstring_count = 0;
8310d63b7dSRichard Lowe
8410d63b7dSRichard Lowe /*
8510d63b7dSRichard Lowe * File table of contents
8610d63b7dSRichard Lowe */
87*e7afc443SToomas Soome static void expand_string(String string, int length);
8810d63b7dSRichard Lowe
8910d63b7dSRichard Lowe #define FATAL_ERROR_MSG_SIZE 200
9010d63b7dSRichard Lowe
9110d63b7dSRichard Lowe /*
9210d63b7dSRichard Lowe * getmem(size)
9310d63b7dSRichard Lowe *
9410d63b7dSRichard Lowe * malloc() version that checks the returned value.
9510d63b7dSRichard Lowe *
9610d63b7dSRichard Lowe * Return value:
9710d63b7dSRichard Lowe * The memory chunk we allocated
9810d63b7dSRichard Lowe *
9910d63b7dSRichard Lowe * Parameters:
10010d63b7dSRichard Lowe * size The size of the chunk we need
10110d63b7dSRichard Lowe *
10210d63b7dSRichard Lowe * Global variables used:
10310d63b7dSRichard Lowe */
10410d63b7dSRichard Lowe char *
getmem(size_t size)105356ba08cSToomas Soome getmem(size_t size)
10610d63b7dSRichard Lowe {
107356ba08cSToomas Soome char *result = (char *)malloc(size);
10810d63b7dSRichard Lowe if (result == NULL) {
109356ba08cSToomas Soome (void) fprintf(stderr, "*** Error: malloc(%d) failed: %s\n%s",
110356ba08cSToomas Soome size, strerror(errno),
111356ba08cSToomas Soome gettext("mksh: Fatal error: Out of memory\n"));
11210d63b7dSRichard Lowe exit(1);
11310d63b7dSRichard Lowe }
114356ba08cSToomas Soome return (result);
11510d63b7dSRichard Lowe }
11610d63b7dSRichard Lowe
11710d63b7dSRichard Lowe /*
11810d63b7dSRichard Lowe * retmem(p)
11910d63b7dSRichard Lowe *
12010d63b7dSRichard Lowe * Cover funtion for free() to make it possible to insert advises.
12110d63b7dSRichard Lowe *
12210d63b7dSRichard Lowe * Parameters:
12310d63b7dSRichard Lowe * p The memory block to free
12410d63b7dSRichard Lowe *
12510d63b7dSRichard Lowe * Global variables used:
12610d63b7dSRichard Lowe */
12710d63b7dSRichard Lowe void
retmem(wchar_t * p)12810d63b7dSRichard Lowe retmem(wchar_t *p)
12910d63b7dSRichard Lowe {
13010d63b7dSRichard Lowe (void) free((char *) p);
13110d63b7dSRichard Lowe }
13210d63b7dSRichard Lowe
13310d63b7dSRichard Lowe void
retmem_mb(caddr_t p)13410d63b7dSRichard Lowe retmem_mb(caddr_t p)
13510d63b7dSRichard Lowe {
13610d63b7dSRichard Lowe (void) free(p);
13710d63b7dSRichard Lowe }
13810d63b7dSRichard Lowe
13910d63b7dSRichard Lowe /*
14010d63b7dSRichard Lowe * getname_fn(name, len, dont_enter)
14110d63b7dSRichard Lowe *
14210d63b7dSRichard Lowe * Hash a name string to the corresponding nameblock.
14310d63b7dSRichard Lowe *
14410d63b7dSRichard Lowe * Return value:
14510d63b7dSRichard Lowe * The Name block for the string
14610d63b7dSRichard Lowe *
14710d63b7dSRichard Lowe * Parameters:
14810d63b7dSRichard Lowe * name The string we want to internalize
14910d63b7dSRichard Lowe * len The length of that string
15010d63b7dSRichard Lowe * dont_enter Don't enter the name if it does not exist
15110d63b7dSRichard Lowe *
15210d63b7dSRichard Lowe * Global variables used:
15310d63b7dSRichard Lowe * funny The vector of semantic tags for characters
15410d63b7dSRichard Lowe * hashtab The hashtable used for the nametable
15510d63b7dSRichard Lowe */
15610d63b7dSRichard Lowe Name
getname_fn(wchar_t * name,int len,Boolean dont_enter,Boolean * foundp)157*e7afc443SToomas Soome getname_fn(wchar_t *name, int len, Boolean dont_enter, Boolean * foundp)
15810d63b7dSRichard Lowe {
159*e7afc443SToomas Soome int length;
160*e7afc443SToomas Soome wchar_t *cap = name;
161*e7afc443SToomas Soome Name np;
16210d63b7dSRichard Lowe static Name_rec empty_Name;
16310d63b7dSRichard Lowe char *tmp_mbs_buffer = NULL;
16410d63b7dSRichard Lowe char *mbs_name = mbs_buffer;
16510d63b7dSRichard Lowe
16610d63b7dSRichard Lowe /*
16710d63b7dSRichard Lowe * First figure out how long the string is.
16810d63b7dSRichard Lowe * If the len argument is -1 we count the chars here.
16910d63b7dSRichard Lowe */
17010d63b7dSRichard Lowe if (len == FIND_LENGTH) {
17110d63b7dSRichard Lowe length = wcslen(name);
17210d63b7dSRichard Lowe } else {
17310d63b7dSRichard Lowe length = len;
17410d63b7dSRichard Lowe }
17510d63b7dSRichard Lowe
17610d63b7dSRichard Lowe Wstring ws;
17710d63b7dSRichard Lowe ws.init(name, length);
17810d63b7dSRichard Lowe if (length >= MAXPATHLEN) {
17910d63b7dSRichard Lowe mbs_name = tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
18010d63b7dSRichard Lowe }
18110d63b7dSRichard Lowe (void) wcstombs(mbs_name, ws.get_string(), (length * MB_LEN_MAX) + 1);
18210d63b7dSRichard Lowe
18310d63b7dSRichard Lowe /* Look for the string */
18410d63b7dSRichard Lowe if (dont_enter || (foundp != 0)) {
18510d63b7dSRichard Lowe np = hashtab.lookup(mbs_name);
18610d63b7dSRichard Lowe if (foundp != 0) {
18710d63b7dSRichard Lowe *foundp = (np != 0) ? true : false;
18810d63b7dSRichard Lowe }
18910d63b7dSRichard Lowe if ((np != 0) || dont_enter) {
19010d63b7dSRichard Lowe if(tmp_mbs_buffer != NULL) {
19110d63b7dSRichard Lowe retmem_mb(tmp_mbs_buffer);
19210d63b7dSRichard Lowe }
19310d63b7dSRichard Lowe return np;
19410d63b7dSRichard Lowe } else {
19510d63b7dSRichard Lowe np = ALLOC(Name);
19610d63b7dSRichard Lowe }
19710d63b7dSRichard Lowe } else {
19810d63b7dSRichard Lowe Boolean found;
19910d63b7dSRichard Lowe np = hashtab.insert(mbs_name, found);
20010d63b7dSRichard Lowe if (found) {
20110d63b7dSRichard Lowe if(tmp_mbs_buffer != NULL) {
20210d63b7dSRichard Lowe retmem_mb(tmp_mbs_buffer);
20310d63b7dSRichard Lowe }
20410d63b7dSRichard Lowe return np;
20510d63b7dSRichard Lowe }
20610d63b7dSRichard Lowe }
20710d63b7dSRichard Lowe getname_struct_count += sizeof(struct _Name);
20810d63b7dSRichard Lowe *np = empty_Name;
20910d63b7dSRichard Lowe
21010d63b7dSRichard Lowe np->string_mb = strdup(mbs_name);
21110d63b7dSRichard Lowe if(tmp_mbs_buffer != NULL) {
21210d63b7dSRichard Lowe retmem_mb(tmp_mbs_buffer);
21310d63b7dSRichard Lowe mbs_name = tmp_mbs_buffer = NULL;
21410d63b7dSRichard Lowe }
21510d63b7dSRichard Lowe getname_bytes_count += strlen(np->string_mb) + 1;
21610d63b7dSRichard Lowe /* Fill in the new Name */
21710d63b7dSRichard Lowe np->stat.time = file_no_time;
21810d63b7dSRichard Lowe np->hash.length = length;
21910d63b7dSRichard Lowe /* Scan the namestring to classify it */
22010d63b7dSRichard Lowe for (cap = name, len = 0; --length >= 0;) {
22110d63b7dSRichard Lowe len |= get_char_semantics_value(*cap++);
22210d63b7dSRichard Lowe }
22310d63b7dSRichard Lowe np->dollar = BOOLEAN((len & (int) dollar_sem) != 0);
22410d63b7dSRichard Lowe np->meta = BOOLEAN((len & (int) meta_sem) != 0);
22510d63b7dSRichard Lowe np->percent = BOOLEAN((len & (int) percent_sem) != 0);
22610d63b7dSRichard Lowe np->wildcard = BOOLEAN((len & (int) wildcard_sem) != 0);
22710d63b7dSRichard Lowe np->colon = BOOLEAN((len & (int) colon_sem) != 0);
22810d63b7dSRichard Lowe np->parenleft = BOOLEAN((len & (int) parenleft_sem) != 0);
22910d63b7dSRichard Lowe getname_names_count++;
23010d63b7dSRichard Lowe return np;
23110d63b7dSRichard Lowe }
23210d63b7dSRichard Lowe
23310d63b7dSRichard Lowe void
store_name(Name name)23410d63b7dSRichard Lowe store_name(Name name)
23510d63b7dSRichard Lowe {
23610d63b7dSRichard Lowe hashtab.insert(name);
23710d63b7dSRichard Lowe }
23810d63b7dSRichard Lowe
23910d63b7dSRichard Lowe void
free_name(Name name)24010d63b7dSRichard Lowe free_name(Name name)
24110d63b7dSRichard Lowe {
24210d63b7dSRichard Lowe freename_names_count++;
24310d63b7dSRichard Lowe freename_struct_count += sizeof(struct _Name);
24410d63b7dSRichard Lowe freename_bytes_count += strlen(name->string_mb) + 1;
24510d63b7dSRichard Lowe retmem_mb(name->string_mb);
24610d63b7dSRichard Lowe for (Property next, p = name->prop; p != NULL; p = next) {
24710d63b7dSRichard Lowe next = p->next;
24810d63b7dSRichard Lowe free(p);
24910d63b7dSRichard Lowe }
25010d63b7dSRichard Lowe free(name);
25110d63b7dSRichard Lowe }
25210d63b7dSRichard Lowe
25310d63b7dSRichard Lowe /*
25410d63b7dSRichard Lowe * enable_interrupt(handler)
25510d63b7dSRichard Lowe *
25610d63b7dSRichard Lowe * This routine sets a new interrupt handler for the signals make
25710d63b7dSRichard Lowe * wants to deal with.
25810d63b7dSRichard Lowe *
25910d63b7dSRichard Lowe * Parameters:
26010d63b7dSRichard Lowe * handler The function installed as interrupt handler
26110d63b7dSRichard Lowe *
26210d63b7dSRichard Lowe * Static variables used:
26310d63b7dSRichard Lowe * sigivalue The original signal handler
26410d63b7dSRichard Lowe * sigqvalue The original signal handler
26510d63b7dSRichard Lowe * sigtvalue The original signal handler
26610d63b7dSRichard Lowe * sighvalue The original signal handler
26710d63b7dSRichard Lowe */
26810d63b7dSRichard Lowe void
enable_interrupt(void (* handler)(int))269*e7afc443SToomas Soome enable_interrupt(void (*handler) (int))
27010d63b7dSRichard Lowe {
27110d63b7dSRichard Lowe if (sigivalue != SIG_IGN) {
27210d63b7dSRichard Lowe (void) bsd_signal(SIGINT, (SIG_PF) handler);
27310d63b7dSRichard Lowe }
27410d63b7dSRichard Lowe if (sigqvalue != SIG_IGN) {
27510d63b7dSRichard Lowe (void) bsd_signal(SIGQUIT, (SIG_PF) handler);
27610d63b7dSRichard Lowe }
27710d63b7dSRichard Lowe if (sigtvalue != SIG_IGN) {
27810d63b7dSRichard Lowe (void) bsd_signal(SIGTERM, (SIG_PF) handler);
27910d63b7dSRichard Lowe }
28010d63b7dSRichard Lowe if (sighvalue != SIG_IGN) {
28110d63b7dSRichard Lowe (void) bsd_signal(SIGHUP, (SIG_PF) handler);
28210d63b7dSRichard Lowe }
28310d63b7dSRichard Lowe }
28410d63b7dSRichard Lowe
28510d63b7dSRichard Lowe /*
28610d63b7dSRichard Lowe * setup_char_semantics()
28710d63b7dSRichard Lowe *
28810d63b7dSRichard Lowe * Load the vector char_semantics[] with lexical markers
28910d63b7dSRichard Lowe *
29010d63b7dSRichard Lowe * Parameters:
29110d63b7dSRichard Lowe *
29210d63b7dSRichard Lowe * Global variables used:
29310d63b7dSRichard Lowe * char_semantics The vector of character semantics that we set
29410d63b7dSRichard Lowe */
29510d63b7dSRichard Lowe void
setup_char_semantics(void)29610d63b7dSRichard Lowe setup_char_semantics(void)
29710d63b7dSRichard Lowe {
29810d63b7dSRichard Lowe const char *s;
29910d63b7dSRichard Lowe wchar_t wc_buffer[1];
30010d63b7dSRichard Lowe int entry;
30110d63b7dSRichard Lowe
30210d63b7dSRichard Lowe if (svr4) {
30310d63b7dSRichard Lowe s = "@-";
30410d63b7dSRichard Lowe } else {
30510d63b7dSRichard Lowe s = "=@-?!+";
30610d63b7dSRichard Lowe }
30710d63b7dSRichard Lowe for (s; MBTOWC(wc_buffer, s); s++) {
30810d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
30910d63b7dSRichard Lowe char_semantics[entry] |= (int) command_prefix_sem;
31010d63b7dSRichard Lowe }
31110d63b7dSRichard Lowe char_semantics[dollar_char_entry] |= (int) dollar_sem;
31210d63b7dSRichard Lowe for (s = "#|=^();&<>*?[]:$`'\"\\\n"; MBTOWC(wc_buffer, s); s++) {
31310d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
31410d63b7dSRichard Lowe char_semantics[entry] |= (int) meta_sem;
31510d63b7dSRichard Lowe }
31610d63b7dSRichard Lowe char_semantics[percent_char_entry] |= (int) percent_sem;
31710d63b7dSRichard Lowe for (s = "@*<%?^"; MBTOWC(wc_buffer, s); s++) {
31810d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
31910d63b7dSRichard Lowe char_semantics[entry] |= (int) special_macro_sem;
32010d63b7dSRichard Lowe }
32110d63b7dSRichard Lowe for (s = "?[*"; MBTOWC(wc_buffer, s); s++) {
32210d63b7dSRichard Lowe entry = get_char_semantics_entry(*wc_buffer);
32310d63b7dSRichard Lowe char_semantics[entry] |= (int) wildcard_sem;
32410d63b7dSRichard Lowe }
32510d63b7dSRichard Lowe char_semantics[colon_char_entry] |= (int) colon_sem;
32610d63b7dSRichard Lowe char_semantics[parenleft_char_entry] |= (int) parenleft_sem;
32710d63b7dSRichard Lowe }
32810d63b7dSRichard Lowe
32910d63b7dSRichard Lowe /*
33010d63b7dSRichard Lowe * errmsg(errnum)
33110d63b7dSRichard Lowe *
33210d63b7dSRichard Lowe * Return the error message for a system call error
33310d63b7dSRichard Lowe *
33410d63b7dSRichard Lowe * Return value:
33510d63b7dSRichard Lowe * An error message string
33610d63b7dSRichard Lowe *
33710d63b7dSRichard Lowe * Parameters:
33810d63b7dSRichard Lowe * errnum The number of the error we want to describe
33910d63b7dSRichard Lowe */
34010d63b7dSRichard Lowe char *
errmsg(int errnum)34110d63b7dSRichard Lowe errmsg(int errnum)
34210d63b7dSRichard Lowe {
343356ba08cSToomas Soome char *msg;
344356ba08cSToomas Soome char *errbuf;
345356ba08cSToomas Soome
346356ba08cSToomas Soome errno = 0;
347356ba08cSToomas Soome msg = strerror(errnum);
348356ba08cSToomas Soome if (errno == EINVAL) {
349356ba08cSToomas Soome size_t size = 6 + 1 + 11 + 1;
350356ba08cSToomas Soome errbuf = getmem(size);
351356ba08cSToomas Soome (void) snprintf(errbuf, size, gettext("Error %d"), errnum);
352356ba08cSToomas Soome return (errbuf);
35310d63b7dSRichard Lowe }
354356ba08cSToomas Soome return (msg);
35510d63b7dSRichard Lowe }
35610d63b7dSRichard Lowe
35710d63b7dSRichard Lowe static char static_buf[MAXPATHLEN*3];
35810d63b7dSRichard Lowe
35910d63b7dSRichard Lowe /*
36010d63b7dSRichard Lowe * fatal_mksh(format, args...)
36110d63b7dSRichard Lowe *
36210d63b7dSRichard Lowe * Print a message and die
36310d63b7dSRichard Lowe *
36410d63b7dSRichard Lowe * Parameters:
36510d63b7dSRichard Lowe * format printf type format string
36610d63b7dSRichard Lowe * args Arguments to match the format
36710d63b7dSRichard Lowe */
36810d63b7dSRichard Lowe /*VARARGS*/
36910d63b7dSRichard Lowe void
fatal_mksh(const char * message,...)37010d63b7dSRichard Lowe fatal_mksh(const char *message, ...)
37110d63b7dSRichard Lowe {
37210d63b7dSRichard Lowe va_list args;
37310d63b7dSRichard Lowe char *buf = static_buf;
37410d63b7dSRichard Lowe char *mksh_fat_err = gettext("mksh: Fatal error: ");
37510d63b7dSRichard Lowe char *cur_wrk_dir = gettext("Current working directory: ");
37610d63b7dSRichard Lowe int mksh_fat_err_len = strlen(mksh_fat_err);
37710d63b7dSRichard Lowe
37810d63b7dSRichard Lowe va_start(args, message);
37910d63b7dSRichard Lowe (void) fflush(stdout);
38010d63b7dSRichard Lowe (void) strcpy(buf, mksh_fat_err);
38110d63b7dSRichard Lowe size_t buf_len = vsnprintf(static_buf + mksh_fat_err_len,
38210d63b7dSRichard Lowe sizeof(static_buf) - mksh_fat_err_len,
38310d63b7dSRichard Lowe message, args)
38410d63b7dSRichard Lowe + mksh_fat_err_len
38510d63b7dSRichard Lowe + strlen(cur_wrk_dir)
38610d63b7dSRichard Lowe + strlen(get_current_path_mksh())
38710d63b7dSRichard Lowe + 3; // "\n\n"
38810d63b7dSRichard Lowe va_end(args);
38910d63b7dSRichard Lowe if (buf_len >= sizeof(static_buf)) {
39010d63b7dSRichard Lowe buf = getmem(buf_len);
39110d63b7dSRichard Lowe (void) strcpy(buf, mksh_fat_err);
39210d63b7dSRichard Lowe va_start(args, message);
39310d63b7dSRichard Lowe (void) vsprintf(buf + mksh_fat_err_len, message, args);
39410d63b7dSRichard Lowe va_end(args);
39510d63b7dSRichard Lowe }
39610d63b7dSRichard Lowe (void) strcat(buf, "\n");
39710d63b7dSRichard Lowe /*
39810d63b7dSRichard Lowe if (report_pwd) {
39910d63b7dSRichard Lowe */
40010d63b7dSRichard Lowe if (1) {
40110d63b7dSRichard Lowe (void) strcat(buf, cur_wrk_dir);
40210d63b7dSRichard Lowe (void) strcat(buf, get_current_path_mksh());
40310d63b7dSRichard Lowe (void) strcat(buf, "\n");
40410d63b7dSRichard Lowe }
40510d63b7dSRichard Lowe (void) fputs(buf, stderr);
40610d63b7dSRichard Lowe (void) fflush(stderr);
40710d63b7dSRichard Lowe if (buf != static_buf) {
40810d63b7dSRichard Lowe retmem_mb(buf);
40910d63b7dSRichard Lowe }
41010d63b7dSRichard Lowe exit_status = 1;
41110d63b7dSRichard Lowe exit(1);
41210d63b7dSRichard Lowe }
41310d63b7dSRichard Lowe
41410d63b7dSRichard Lowe /*
41510d63b7dSRichard Lowe * fatal_reader_mksh(format, args...)
41610d63b7dSRichard Lowe *
41710d63b7dSRichard Lowe * Parameters:
41810d63b7dSRichard Lowe * format printf style format string
41910d63b7dSRichard Lowe * args arguments to match the format
42010d63b7dSRichard Lowe */
42110d63b7dSRichard Lowe /*VARARGS*/
42210d63b7dSRichard Lowe void
fatal_reader_mksh(const char * pattern,...)42310d63b7dSRichard Lowe fatal_reader_mksh(const char * pattern, ...)
42410d63b7dSRichard Lowe {
42510d63b7dSRichard Lowe va_list args;
42610d63b7dSRichard Lowe char message[1000];
42710d63b7dSRichard Lowe
42810d63b7dSRichard Lowe va_start(args, pattern);
42910d63b7dSRichard Lowe /*
43010d63b7dSRichard Lowe if (file_being_read != NULL) {
43110d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, file_being_read);
43210d63b7dSRichard Lowe if (line_number != 0) {
43310d63b7dSRichard Lowe (void) sprintf(message,
43410d63b7dSRichard Lowe gettext("%s, line %d: %s"),
43510d63b7dSRichard Lowe mbs_buffer,
43610d63b7dSRichard Lowe line_number,
43710d63b7dSRichard Lowe pattern);
43810d63b7dSRichard Lowe } else {
43910d63b7dSRichard Lowe (void) sprintf(message,
44010d63b7dSRichard Lowe "%s: %s",
44110d63b7dSRichard Lowe mbs_buffer,
44210d63b7dSRichard Lowe pattern);
44310d63b7dSRichard Lowe }
44410d63b7dSRichard Lowe pattern = message;
44510d63b7dSRichard Lowe }
44610d63b7dSRichard Lowe */
44710d63b7dSRichard Lowe
44810d63b7dSRichard Lowe (void) fflush(stdout);
44910d63b7dSRichard Lowe (void) fprintf(stderr, gettext("mksh: Fatal error in reader: "));
45010d63b7dSRichard Lowe (void) vfprintf(stderr, pattern, args);
45110d63b7dSRichard Lowe (void) fprintf(stderr, "\n");
45210d63b7dSRichard Lowe va_end(args);
45310d63b7dSRichard Lowe
45410d63b7dSRichard Lowe /*
45510d63b7dSRichard Lowe if (temp_file_name != NULL) {
45610d63b7dSRichard Lowe (void) fprintf(stderr,
45710d63b7dSRichard Lowe gettext("mksh: Temp-file %s not removed\n"),
45810d63b7dSRichard Lowe temp_file_name->string_mb);
45910d63b7dSRichard Lowe temp_file_name = NULL;
46010d63b7dSRichard Lowe }
46110d63b7dSRichard Lowe */
46210d63b7dSRichard Lowe
46310d63b7dSRichard Lowe /*
46410d63b7dSRichard Lowe if (report_pwd) {
46510d63b7dSRichard Lowe */
46610d63b7dSRichard Lowe if (1) {
46710d63b7dSRichard Lowe (void) fprintf(stderr,
46810d63b7dSRichard Lowe gettext("Current working directory %s\n"),
46910d63b7dSRichard Lowe get_current_path_mksh());
47010d63b7dSRichard Lowe }
47110d63b7dSRichard Lowe (void) fflush(stderr);
47210d63b7dSRichard Lowe exit_status = 1;
47310d63b7dSRichard Lowe exit(1);
47410d63b7dSRichard Lowe }
47510d63b7dSRichard Lowe
47610d63b7dSRichard Lowe /*
47710d63b7dSRichard Lowe * warning_mksh(format, args...)
47810d63b7dSRichard Lowe *
47910d63b7dSRichard Lowe * Print a message and continue.
48010d63b7dSRichard Lowe *
48110d63b7dSRichard Lowe * Parameters:
48210d63b7dSRichard Lowe * format printf type format string
48310d63b7dSRichard Lowe * args Arguments to match the format
48410d63b7dSRichard Lowe */
48510d63b7dSRichard Lowe /*VARARGS*/
48610d63b7dSRichard Lowe void
warning_mksh(char * message,...)48710d63b7dSRichard Lowe warning_mksh(char * message, ...)
48810d63b7dSRichard Lowe {
48910d63b7dSRichard Lowe va_list args;
49010d63b7dSRichard Lowe
49110d63b7dSRichard Lowe va_start(args, message);
49210d63b7dSRichard Lowe (void) fflush(stdout);
49310d63b7dSRichard Lowe (void) fprintf(stderr, gettext("mksh: Warning: "));
49410d63b7dSRichard Lowe (void) vfprintf(stderr, message, args);
49510d63b7dSRichard Lowe (void) fprintf(stderr, "\n");
49610d63b7dSRichard Lowe va_end(args);
49710d63b7dSRichard Lowe /*
49810d63b7dSRichard Lowe if (report_pwd) {
49910d63b7dSRichard Lowe */
50010d63b7dSRichard Lowe if (1) {
50110d63b7dSRichard Lowe (void) fprintf(stderr,
50210d63b7dSRichard Lowe gettext("Current working directory %s\n"),
50310d63b7dSRichard Lowe get_current_path_mksh());
50410d63b7dSRichard Lowe }
50510d63b7dSRichard Lowe (void) fflush(stderr);
50610d63b7dSRichard Lowe }
50710d63b7dSRichard Lowe
50810d63b7dSRichard Lowe /*
50910d63b7dSRichard Lowe * get_current_path_mksh()
51010d63b7dSRichard Lowe *
51110d63b7dSRichard Lowe * Stuff current_path with the current path if it isnt there already.
51210d63b7dSRichard Lowe *
51310d63b7dSRichard Lowe * Parameters:
51410d63b7dSRichard Lowe *
51510d63b7dSRichard Lowe * Global variables used:
51610d63b7dSRichard Lowe */
51710d63b7dSRichard Lowe char *
get_current_path_mksh(void)51810d63b7dSRichard Lowe get_current_path_mksh(void)
51910d63b7dSRichard Lowe {
52010d63b7dSRichard Lowe char pwd[(MAXPATHLEN * MB_LEN_MAX)];
52110d63b7dSRichard Lowe static char *current_path;
52210d63b7dSRichard Lowe
52310d63b7dSRichard Lowe if (current_path == NULL) {
52410d63b7dSRichard Lowe getcwd(pwd, sizeof(pwd));
52510d63b7dSRichard Lowe if (pwd[0] == (int) nul_char) {
52610d63b7dSRichard Lowe pwd[0] = (int) slash_char;
52710d63b7dSRichard Lowe pwd[1] = (int) nul_char;
52810d63b7dSRichard Lowe }
52910d63b7dSRichard Lowe current_path = strdup(pwd);
53010d63b7dSRichard Lowe }
53110d63b7dSRichard Lowe return current_path;
53210d63b7dSRichard Lowe }
53310d63b7dSRichard Lowe
53410d63b7dSRichard Lowe /*
53510d63b7dSRichard Lowe * append_prop(target, type)
53610d63b7dSRichard Lowe *
53710d63b7dSRichard Lowe * Create a new property and append it to the property list of a Name.
53810d63b7dSRichard Lowe *
53910d63b7dSRichard Lowe * Return value:
54010d63b7dSRichard Lowe * A new property block for the target
54110d63b7dSRichard Lowe *
54210d63b7dSRichard Lowe * Parameters:
54310d63b7dSRichard Lowe * target The target that wants a new property
54410d63b7dSRichard Lowe * type The type of property being requested
54510d63b7dSRichard Lowe *
54610d63b7dSRichard Lowe * Global variables used:
54710d63b7dSRichard Lowe */
54810d63b7dSRichard Lowe Property
append_prop(Name target,Property_id type)549*e7afc443SToomas Soome append_prop(Name target, Property_id type)
55010d63b7dSRichard Lowe {
551*e7afc443SToomas Soome Property *insert = &target->prop;
552*e7afc443SToomas Soome Property prop = *insert;
553*e7afc443SToomas Soome int size;
55410d63b7dSRichard Lowe
55510d63b7dSRichard Lowe switch (type) {
55610d63b7dSRichard Lowe case conditional_prop:
55710d63b7dSRichard Lowe size = sizeof (struct Conditional);
55810d63b7dSRichard Lowe break;
55910d63b7dSRichard Lowe case line_prop:
56010d63b7dSRichard Lowe size = sizeof (struct Line);
56110d63b7dSRichard Lowe break;
56210d63b7dSRichard Lowe case macro_prop:
56310d63b7dSRichard Lowe size = sizeof (struct _Macro);
56410d63b7dSRichard Lowe break;
56510d63b7dSRichard Lowe case makefile_prop:
56610d63b7dSRichard Lowe size = sizeof (struct Makefile);
56710d63b7dSRichard Lowe break;
56810d63b7dSRichard Lowe case member_prop:
56910d63b7dSRichard Lowe size = sizeof (struct Member);
57010d63b7dSRichard Lowe break;
57110d63b7dSRichard Lowe case recursive_prop:
57210d63b7dSRichard Lowe size = sizeof (struct Recursive);
57310d63b7dSRichard Lowe break;
57410d63b7dSRichard Lowe case sccs_prop:
57510d63b7dSRichard Lowe size = sizeof (struct Sccs);
57610d63b7dSRichard Lowe break;
57710d63b7dSRichard Lowe case suffix_prop:
57810d63b7dSRichard Lowe size = sizeof (struct Suffix);
57910d63b7dSRichard Lowe break;
58010d63b7dSRichard Lowe case target_prop:
58110d63b7dSRichard Lowe size = sizeof (struct Target);
58210d63b7dSRichard Lowe break;
58310d63b7dSRichard Lowe case time_prop:
58410d63b7dSRichard Lowe size = sizeof (struct STime);
58510d63b7dSRichard Lowe break;
58610d63b7dSRichard Lowe case vpath_alias_prop:
58710d63b7dSRichard Lowe size = sizeof (struct Vpath_alias);
58810d63b7dSRichard Lowe break;
58910d63b7dSRichard Lowe case long_member_name_prop:
59010d63b7dSRichard Lowe size = sizeof (struct Long_member_name);
59110d63b7dSRichard Lowe break;
59210d63b7dSRichard Lowe case macro_append_prop:
59310d63b7dSRichard Lowe size = sizeof (struct _Macro_appendix);
59410d63b7dSRichard Lowe break;
59510d63b7dSRichard Lowe case env_mem_prop:
59610d63b7dSRichard Lowe size = sizeof (struct _Env_mem);
59710d63b7dSRichard Lowe break;
59810d63b7dSRichard Lowe default:
59910d63b7dSRichard Lowe fatal_mksh(gettext("Internal error. Unknown prop type %d"), type);
60010d63b7dSRichard Lowe }
60110d63b7dSRichard Lowe for (; prop != NULL; insert = &prop->next, prop = *insert);
60210d63b7dSRichard Lowe size += PROPERTY_HEAD_SIZE;
60310d63b7dSRichard Lowe *insert = prop = (Property) getmem(size);
60410d63b7dSRichard Lowe memset((char *) prop, 0, size);
60510d63b7dSRichard Lowe prop->type = type;
60610d63b7dSRichard Lowe prop->next = NULL;
60710d63b7dSRichard Lowe return prop;
60810d63b7dSRichard Lowe }
60910d63b7dSRichard Lowe
61010d63b7dSRichard Lowe /*
61110d63b7dSRichard Lowe * maybe_append_prop(target, type)
61210d63b7dSRichard Lowe *
61310d63b7dSRichard Lowe * Append a property to the Name if none of this type exists
61410d63b7dSRichard Lowe * else return the one already there
61510d63b7dSRichard Lowe *
61610d63b7dSRichard Lowe * Return value:
61710d63b7dSRichard Lowe * A property of the requested type for the target
61810d63b7dSRichard Lowe *
61910d63b7dSRichard Lowe * Parameters:
62010d63b7dSRichard Lowe * target The target that wants a new property
62110d63b7dSRichard Lowe * type The type of property being requested
62210d63b7dSRichard Lowe *
62310d63b7dSRichard Lowe * Global variables used:
62410d63b7dSRichard Lowe */
62510d63b7dSRichard Lowe Property
maybe_append_prop(Name target,Property_id type)626*e7afc443SToomas Soome maybe_append_prop(Name target, Property_id type)
62710d63b7dSRichard Lowe {
628*e7afc443SToomas Soome Property prop;
62910d63b7dSRichard Lowe
63010d63b7dSRichard Lowe if ((prop = get_prop(target->prop, type)) != NULL) {
63110d63b7dSRichard Lowe return prop;
63210d63b7dSRichard Lowe }
63310d63b7dSRichard Lowe return append_prop(target, type);
63410d63b7dSRichard Lowe }
63510d63b7dSRichard Lowe
63610d63b7dSRichard Lowe /*
63710d63b7dSRichard Lowe * get_prop(start, type)
63810d63b7dSRichard Lowe *
63910d63b7dSRichard Lowe * Scan the property list of a Name to find the next property
64010d63b7dSRichard Lowe * of a given type.
64110d63b7dSRichard Lowe *
64210d63b7dSRichard Lowe * Return value:
64310d63b7dSRichard Lowe * The first property of the type, if any left
64410d63b7dSRichard Lowe *
64510d63b7dSRichard Lowe * Parameters:
64610d63b7dSRichard Lowe * start The first property block to check for type
64710d63b7dSRichard Lowe * type The type of property block we need
64810d63b7dSRichard Lowe *
64910d63b7dSRichard Lowe * Global variables used:
65010d63b7dSRichard Lowe */
65110d63b7dSRichard Lowe Property
get_prop(Property start,Property_id type)652*e7afc443SToomas Soome get_prop(Property start, Property_id type)
65310d63b7dSRichard Lowe {
65410d63b7dSRichard Lowe for (; start != NULL; start = start->next) {
65510d63b7dSRichard Lowe if (start->type == type) {
65610d63b7dSRichard Lowe return start;
65710d63b7dSRichard Lowe }
65810d63b7dSRichard Lowe }
65910d63b7dSRichard Lowe return NULL;
66010d63b7dSRichard Lowe }
66110d63b7dSRichard Lowe
66210d63b7dSRichard Lowe /*
66310d63b7dSRichard Lowe * append_string(from, to, length)
66410d63b7dSRichard Lowe *
66510d63b7dSRichard Lowe * Append a C string to a make string expanding it if nessecary
66610d63b7dSRichard Lowe *
66710d63b7dSRichard Lowe * Parameters:
66810d63b7dSRichard Lowe * from The source (C style) string
66910d63b7dSRichard Lowe * to The destination (make style) string
67010d63b7dSRichard Lowe * length The length of the from string
67110d63b7dSRichard Lowe *
67210d63b7dSRichard Lowe * Global variables used:
67310d63b7dSRichard Lowe */
67410d63b7dSRichard Lowe void
append_string(wchar_t * from,String to,int length)675*e7afc443SToomas Soome append_string(wchar_t *from, String to, int length)
67610d63b7dSRichard Lowe {
67710d63b7dSRichard Lowe if (length == FIND_LENGTH) {
67810d63b7dSRichard Lowe length = wcslen(from);
67910d63b7dSRichard Lowe }
68010d63b7dSRichard Lowe if (to->buffer.start == NULL) {
68110d63b7dSRichard Lowe expand_string(to, 32 + length);
68210d63b7dSRichard Lowe }
68310d63b7dSRichard Lowe if (to->buffer.end - to->text.p <= length) {
68410d63b7dSRichard Lowe expand_string(to,
68510d63b7dSRichard Lowe (to->buffer.end - to->buffer.start) * 2 +
68610d63b7dSRichard Lowe length);
68710d63b7dSRichard Lowe }
68810d63b7dSRichard Lowe if (length > 0) {
68910d63b7dSRichard Lowe (void) wcsncpy(to->text.p, from, length);
69010d63b7dSRichard Lowe to->text.p += length;
69110d63b7dSRichard Lowe }
69210d63b7dSRichard Lowe *(to->text.p) = (int) nul_char;
69310d63b7dSRichard Lowe }
69410d63b7dSRichard Lowe
get_wstring(char * from)69510d63b7dSRichard Lowe wchar_t * get_wstring(char *from) {
69610d63b7dSRichard Lowe if(from == NULL) {
69710d63b7dSRichard Lowe return NULL;
69810d63b7dSRichard Lowe }
69910d63b7dSRichard Lowe getwstring_count++;
70010d63b7dSRichard Lowe wchar_t * wcbuf = ALLOC_WC(strlen(from) + 1);
70110d63b7dSRichard Lowe mbstowcs(wcbuf, from, strlen(from)+1);
70210d63b7dSRichard Lowe return wcbuf;
70310d63b7dSRichard Lowe }
70410d63b7dSRichard Lowe
70510d63b7dSRichard Lowe void
append_string(char * from,String to,int length)706*e7afc443SToomas Soome append_string(char *from, String to, int length)
70710d63b7dSRichard Lowe {
70810d63b7dSRichard Lowe if (length == FIND_LENGTH) {
70910d63b7dSRichard Lowe length = strlen(from);
71010d63b7dSRichard Lowe }
71110d63b7dSRichard Lowe if (to->buffer.start == NULL) {
71210d63b7dSRichard Lowe expand_string(to, 32 + length);
71310d63b7dSRichard Lowe }
71410d63b7dSRichard Lowe if (to->buffer.end - to->text.p <= length) {
71510d63b7dSRichard Lowe expand_string(to,
71610d63b7dSRichard Lowe (to->buffer.end - to->buffer.start) * 2 +
71710d63b7dSRichard Lowe length);
71810d63b7dSRichard Lowe }
71910d63b7dSRichard Lowe if (length > 0) {
72010d63b7dSRichard Lowe (void) mbstowcs(to->text.p, from, length);
72110d63b7dSRichard Lowe to->text.p += length;
72210d63b7dSRichard Lowe }
72310d63b7dSRichard Lowe *(to->text.p) = (int) nul_char;
72410d63b7dSRichard Lowe }
72510d63b7dSRichard Lowe
72610d63b7dSRichard Lowe /*
72710d63b7dSRichard Lowe * expand_string(string, length)
72810d63b7dSRichard Lowe *
72910d63b7dSRichard Lowe * Allocate more memory for strings that run out of space.
73010d63b7dSRichard Lowe *
73110d63b7dSRichard Lowe * Parameters:
73210d63b7dSRichard Lowe * string The make style string we want to expand
73310d63b7dSRichard Lowe * length The new length we need
73410d63b7dSRichard Lowe *
73510d63b7dSRichard Lowe * Global variables used:
73610d63b7dSRichard Lowe */
73710d63b7dSRichard Lowe static void
expand_string(String string,int length)738*e7afc443SToomas Soome expand_string(String string, int length)
73910d63b7dSRichard Lowe {
740*e7afc443SToomas Soome wchar_t *p;
74110d63b7dSRichard Lowe
74210d63b7dSRichard Lowe if (string->buffer.start == NULL) {
74310d63b7dSRichard Lowe /* For strings that have no memory allocated */
74410d63b7dSRichard Lowe string->buffer.start =
74510d63b7dSRichard Lowe string->text.p =
74610d63b7dSRichard Lowe string->text.end =
74710d63b7dSRichard Lowe ALLOC_WC(length);
74810d63b7dSRichard Lowe string->buffer.end = string->buffer.start + length;
74910d63b7dSRichard Lowe string->text.p[0] = (int) nul_char;
75010d63b7dSRichard Lowe string->free_after_use = true;
75110d63b7dSRichard Lowe expandstring_count++;
75210d63b7dSRichard Lowe return;
75310d63b7dSRichard Lowe }
75410d63b7dSRichard Lowe if (string->buffer.end - string->buffer.start >= length) {
75510d63b7dSRichard Lowe /* If we really don't need more memory. */
75610d63b7dSRichard Lowe return;
75710d63b7dSRichard Lowe }
75810d63b7dSRichard Lowe /*
75910d63b7dSRichard Lowe * Get more memory, copy the string and free the old buffer if
76010d63b7dSRichard Lowe * it is was malloc()'ed.
76110d63b7dSRichard Lowe */
76210d63b7dSRichard Lowe expandstring_count++;
76310d63b7dSRichard Lowe p = ALLOC_WC(length);
76410d63b7dSRichard Lowe (void) wcscpy(p, string->buffer.start);
76510d63b7dSRichard Lowe string->text.p = p + (string->text.p - string->buffer.start);
76610d63b7dSRichard Lowe string->text.end = p + (string->text.end - string->buffer.start);
76710d63b7dSRichard Lowe string->buffer.end = p + length;
76810d63b7dSRichard Lowe if (string->free_after_use) {
76910d63b7dSRichard Lowe retmem(string->buffer.start);
77010d63b7dSRichard Lowe }
77110d63b7dSRichard Lowe string->buffer.start = p;
77210d63b7dSRichard Lowe string->free_after_use = true;
77310d63b7dSRichard Lowe }
77410d63b7dSRichard Lowe
77510d63b7dSRichard Lowe /*
77610d63b7dSRichard Lowe * append_char(from, to)
77710d63b7dSRichard Lowe *
77810d63b7dSRichard Lowe * Append one char to a make string expanding it if nessecary
77910d63b7dSRichard Lowe *
78010d63b7dSRichard Lowe * Parameters:
78110d63b7dSRichard Lowe * from Single character to append to string
78210d63b7dSRichard Lowe * to The destination (make style) string
78310d63b7dSRichard Lowe *
78410d63b7dSRichard Lowe * Global variables used:
78510d63b7dSRichard Lowe */
78610d63b7dSRichard Lowe void
append_char(wchar_t from,String to)787*e7afc443SToomas Soome append_char(wchar_t from, String to)
78810d63b7dSRichard Lowe {
78910d63b7dSRichard Lowe if (to->buffer.start == NULL) {
79010d63b7dSRichard Lowe expand_string(to, 32);
79110d63b7dSRichard Lowe }
79210d63b7dSRichard Lowe if (to->buffer.end - to->text.p <= 2) {
79310d63b7dSRichard Lowe expand_string(to, to->buffer.end - to->buffer.start + 32);
79410d63b7dSRichard Lowe }
79510d63b7dSRichard Lowe *(to->text.p)++ = from;
79610d63b7dSRichard Lowe *(to->text.p) = (int) nul_char;
79710d63b7dSRichard Lowe }
79810d63b7dSRichard Lowe
79910d63b7dSRichard Lowe /*
80010d63b7dSRichard Lowe * handle_interrupt_mksh()
80110d63b7dSRichard Lowe *
80210d63b7dSRichard Lowe * This is where C-C traps are caught.
80310d63b7dSRichard Lowe */
80410d63b7dSRichard Lowe void
handle_interrupt_mksh(int)80510d63b7dSRichard Lowe handle_interrupt_mksh(int)
80610d63b7dSRichard Lowe {
80710d63b7dSRichard Lowe (void) fflush(stdout);
80810d63b7dSRichard Lowe /* Make sure the processes running under us terminate first. */
80910d63b7dSRichard Lowe if (childPid > 0) {
81010d63b7dSRichard Lowe kill(childPid, SIGTERM);
81110d63b7dSRichard Lowe childPid = -1;
81210d63b7dSRichard Lowe }
81310d63b7dSRichard Lowe while (wait((int *) NULL) != -1);
81410d63b7dSRichard Lowe exit_status = 2;
81510d63b7dSRichard Lowe exit(2);
81610d63b7dSRichard Lowe }
81710d63b7dSRichard Lowe
81810d63b7dSRichard Lowe /*
81910d63b7dSRichard Lowe * setup_interrupt()
82010d63b7dSRichard Lowe *
82110d63b7dSRichard Lowe * This routine saves the original interrupt handler pointers
82210d63b7dSRichard Lowe *
82310d63b7dSRichard Lowe * Parameters:
82410d63b7dSRichard Lowe *
82510d63b7dSRichard Lowe * Static variables used:
82610d63b7dSRichard Lowe * sigivalue The original signal handler
82710d63b7dSRichard Lowe * sigqvalue The original signal handler
82810d63b7dSRichard Lowe * sigtvalue The original signal handler
82910d63b7dSRichard Lowe * sighvalue The original signal handler
83010d63b7dSRichard Lowe */
83110d63b7dSRichard Lowe void
setup_interrupt(void (* handler)(int))832*e7afc443SToomas Soome setup_interrupt(void (*handler) (int))
83310d63b7dSRichard Lowe {
83410d63b7dSRichard Lowe sigivalue = bsd_signal(SIGINT, SIG_IGN);
83510d63b7dSRichard Lowe sigqvalue = bsd_signal(SIGQUIT, SIG_IGN);
83610d63b7dSRichard Lowe sigtvalue = bsd_signal(SIGTERM, SIG_IGN);
83710d63b7dSRichard Lowe sighvalue = bsd_signal(SIGHUP, SIG_IGN);
83810d63b7dSRichard Lowe enable_interrupt(handler);
83910d63b7dSRichard Lowe }
84010d63b7dSRichard Lowe
84110d63b7dSRichard Lowe
84210d63b7dSRichard Lowe void
mbstowcs_with_check(wchar_t * pwcs,const char * s,size_t n)84310d63b7dSRichard Lowe mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n)
84410d63b7dSRichard Lowe {
84510d63b7dSRichard Lowe if(mbstowcs(pwcs, s, n) == -1) {
84610d63b7dSRichard Lowe fatal_mksh(gettext("The string `%s' is not valid in current locale"), s);
84710d63b7dSRichard Lowe }
84810d63b7dSRichard Lowe }
84910d63b7dSRichard Lowe
85010d63b7dSRichard Lowe
85110d63b7dSRichard Lowe
Wstring()85210d63b7dSRichard Lowe Wstring::Wstring()
85310d63b7dSRichard Lowe {
85410d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
85510d63b7dSRichard Lowe }
85610d63b7dSRichard Lowe
Wstring(struct _Name * name)85710d63b7dSRichard Lowe Wstring::Wstring(struct _Name * name)
85810d63b7dSRichard Lowe {
85910d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
86010d63b7dSRichard Lowe append_string(name->string_mb, &string, name->hash.length);
86110d63b7dSRichard Lowe }
86210d63b7dSRichard Lowe
~Wstring()86310d63b7dSRichard Lowe Wstring::~Wstring()
86410d63b7dSRichard Lowe {
86510d63b7dSRichard Lowe if(string.free_after_use) {
86610d63b7dSRichard Lowe retmem(string.buffer.start);
86710d63b7dSRichard Lowe }
86810d63b7dSRichard Lowe }
86910d63b7dSRichard Lowe
87010d63b7dSRichard Lowe void
init(struct _Name * name)87110d63b7dSRichard Lowe Wstring::init(struct _Name * name)
87210d63b7dSRichard Lowe {
87310d63b7dSRichard Lowe if(string.free_after_use) {
87410d63b7dSRichard Lowe retmem(string.buffer.start);
87510d63b7dSRichard Lowe }
87610d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
87710d63b7dSRichard Lowe append_string(name->string_mb, &string, name->hash.length);
87810d63b7dSRichard Lowe }
87910d63b7dSRichard Lowe
88010d63b7dSRichard Lowe void
init(wchar_t * name,unsigned length)88110d63b7dSRichard Lowe Wstring::init(wchar_t * name, unsigned length)
88210d63b7dSRichard Lowe {
88310d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf);
88410d63b7dSRichard Lowe append_string(name, &string, length);
88510d63b7dSRichard Lowe string.buffer.start[length] = 0;
88610d63b7dSRichard Lowe }
88710d63b7dSRichard Lowe
88810d63b7dSRichard Lowe Boolean
equaln(wchar_t * str,unsigned length)88910d63b7dSRichard Lowe Wstring::equaln(wchar_t * str, unsigned length)
89010d63b7dSRichard Lowe {
89110d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start, str, length);
89210d63b7dSRichard Lowe }
89310d63b7dSRichard Lowe
89410d63b7dSRichard Lowe Boolean
equaln(Wstring * str,unsigned length)89510d63b7dSRichard Lowe Wstring::equaln(Wstring * str, unsigned length)
89610d63b7dSRichard Lowe {
89710d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start, str->string.buffer.start, length);
89810d63b7dSRichard Lowe }
89910d63b7dSRichard Lowe
90010d63b7dSRichard Lowe Boolean
equal(wchar_t * str,unsigned off,unsigned length)90110d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off, unsigned length)
90210d63b7dSRichard Lowe {
90310d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start + off, str, length);
90410d63b7dSRichard Lowe }
90510d63b7dSRichard Lowe
90610d63b7dSRichard Lowe Boolean
equal(wchar_t * str,unsigned off)90710d63b7dSRichard Lowe Wstring::equal(wchar_t * str, unsigned off)
90810d63b7dSRichard Lowe {
90910d63b7dSRichard Lowe return (Boolean)IS_WEQUAL(string.buffer.start + off, str);
91010d63b7dSRichard Lowe }
91110d63b7dSRichard Lowe
91210d63b7dSRichard Lowe Boolean
equal(wchar_t * str)91310d63b7dSRichard Lowe Wstring::equal(wchar_t * str)
91410d63b7dSRichard Lowe {
91510d63b7dSRichard Lowe return equal(str, 0);
91610d63b7dSRichard Lowe }
91710d63b7dSRichard Lowe
91810d63b7dSRichard Lowe Boolean
equal(Wstring * str,unsigned off,unsigned length)91910d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off, unsigned length)
92010d63b7dSRichard Lowe {
92110d63b7dSRichard Lowe return (Boolean)IS_WEQUALN(string.buffer.start + off, str->string.buffer.start, length);
92210d63b7dSRichard Lowe }
92310d63b7dSRichard Lowe
92410d63b7dSRichard Lowe Boolean
equal(Wstring * str)92510d63b7dSRichard Lowe Wstring::equal(Wstring * str)
92610d63b7dSRichard Lowe {
92710d63b7dSRichard Lowe return equal(str, 0);
92810d63b7dSRichard Lowe }
92910d63b7dSRichard Lowe
93010d63b7dSRichard Lowe Boolean
equal(Wstring * str,unsigned off)93110d63b7dSRichard Lowe Wstring::equal(Wstring * str, unsigned off)
93210d63b7dSRichard Lowe {
93310d63b7dSRichard Lowe return (Boolean)IS_WEQUAL(string.buffer.start + off, str->string.buffer.start);
93410d63b7dSRichard Lowe }
93510d63b7dSRichard Lowe
93610d63b7dSRichard Lowe void
append_to_str(struct _String * str,unsigned off,unsigned length)93710d63b7dSRichard Lowe Wstring::append_to_str(struct _String * str, unsigned off, unsigned length)
93810d63b7dSRichard Lowe {
93910d63b7dSRichard Lowe append_string(string.buffer.start + off, str, length);
94010d63b7dSRichard Lowe }
94110d63b7dSRichard Lowe
94210d63b7dSRichard Lowe Name
lookup(const char * key)94310d63b7dSRichard Lowe Name_set::lookup(const char *key)
94410d63b7dSRichard Lowe {
94510d63b7dSRichard Lowe for (entry *node = root; node != 0;) {
94610d63b7dSRichard Lowe int res = strcmp(key, node->name->string_mb);
94710d63b7dSRichard Lowe if (res < 0) {
94810d63b7dSRichard Lowe node = node->left;
94910d63b7dSRichard Lowe } else if (res > 0) {
95010d63b7dSRichard Lowe node = node->right;
95110d63b7dSRichard Lowe } else {
95210d63b7dSRichard Lowe return node->name;
95310d63b7dSRichard Lowe }
95410d63b7dSRichard Lowe }
95510d63b7dSRichard Lowe return 0;
95610d63b7dSRichard Lowe }
95710d63b7dSRichard Lowe
95810d63b7dSRichard Lowe Name
insert(const char * key,Boolean & found)95910d63b7dSRichard Lowe Name_set::insert(const char *key, Boolean &found)
96010d63b7dSRichard Lowe {
96110d63b7dSRichard Lowe Name name = 0;
96210d63b7dSRichard Lowe
96310d63b7dSRichard Lowe if (root != 0) {
96410d63b7dSRichard Lowe for (entry *node = root; name == 0;) {
96510d63b7dSRichard Lowe int res = strcmp(key, node->name->string_mb);
96610d63b7dSRichard Lowe if (res < 0) {
96710d63b7dSRichard Lowe if (node->left != 0) {
96810d63b7dSRichard Lowe node = node->left;
96910d63b7dSRichard Lowe } else {
97010d63b7dSRichard Lowe found = false;
97110d63b7dSRichard Lowe name = ALLOC(Name);
97210d63b7dSRichard Lowe
97310d63b7dSRichard Lowe node->left = new entry(name, node);
97410d63b7dSRichard Lowe rebalance(node);
97510d63b7dSRichard Lowe }
97610d63b7dSRichard Lowe } else if (res > 0) {
97710d63b7dSRichard Lowe if (node->right != 0) {
97810d63b7dSRichard Lowe node = node->right;
97910d63b7dSRichard Lowe } else {
98010d63b7dSRichard Lowe found = false;
98110d63b7dSRichard Lowe name = ALLOC(Name);
98210d63b7dSRichard Lowe
98310d63b7dSRichard Lowe node->right = new entry(name, node);
98410d63b7dSRichard Lowe rebalance(node);
98510d63b7dSRichard Lowe }
98610d63b7dSRichard Lowe } else {
98710d63b7dSRichard Lowe found = true;
98810d63b7dSRichard Lowe name = node->name;
98910d63b7dSRichard Lowe }
99010d63b7dSRichard Lowe }
99110d63b7dSRichard Lowe } else {
99210d63b7dSRichard Lowe found = false;
99310d63b7dSRichard Lowe name = ALLOC(Name);
99410d63b7dSRichard Lowe
99510d63b7dSRichard Lowe root = new entry(name, 0);
99610d63b7dSRichard Lowe }
99710d63b7dSRichard Lowe return name;
99810d63b7dSRichard Lowe }
99910d63b7dSRichard Lowe
100010d63b7dSRichard Lowe void
insert(Name name)100110d63b7dSRichard Lowe Name_set::insert(Name name) {
100210d63b7dSRichard Lowe if (root != 0) {
100310d63b7dSRichard Lowe for (entry *node = root;;) {
100410d63b7dSRichard Lowe int res = strcmp(name->string_mb, node->name->string_mb);
100510d63b7dSRichard Lowe if (res < 0) {
100610d63b7dSRichard Lowe if (node->left != 0) {
100710d63b7dSRichard Lowe node = node->left;
100810d63b7dSRichard Lowe } else {
100910d63b7dSRichard Lowe node->left = new entry(name, node);
101010d63b7dSRichard Lowe rebalance(node);
101110d63b7dSRichard Lowe break;
101210d63b7dSRichard Lowe }
101310d63b7dSRichard Lowe } else if (res > 0) {
101410d63b7dSRichard Lowe if (node->right != 0) {
101510d63b7dSRichard Lowe node = node->right;
101610d63b7dSRichard Lowe } else {
101710d63b7dSRichard Lowe node->right = new entry(name, node);
101810d63b7dSRichard Lowe rebalance(node);
101910d63b7dSRichard Lowe break;
102010d63b7dSRichard Lowe }
102110d63b7dSRichard Lowe } else {
102210d63b7dSRichard Lowe // should be an error: inserting already existing name
102310d63b7dSRichard Lowe break;
102410d63b7dSRichard Lowe }
102510d63b7dSRichard Lowe }
102610d63b7dSRichard Lowe } else {
102710d63b7dSRichard Lowe root = new entry(name, 0);
102810d63b7dSRichard Lowe }
102910d63b7dSRichard Lowe }
103010d63b7dSRichard Lowe
103110d63b7dSRichard Lowe void
rebalance(Name_set::entry * node)103210d63b7dSRichard Lowe Name_set::rebalance(Name_set::entry *node) {
103310d63b7dSRichard Lowe for (; node != 0; node = node->parent) {
103410d63b7dSRichard Lowe entry *right = node->right;
103510d63b7dSRichard Lowe entry *left = node->left;
103610d63b7dSRichard Lowe
103710d63b7dSRichard Lowe unsigned rdepth = (right != 0) ? right->depth : 0;
103810d63b7dSRichard Lowe unsigned ldepth = (left != 0) ? left->depth : 0;
103910d63b7dSRichard Lowe
104010d63b7dSRichard Lowe if (ldepth > rdepth + 1) {
104110d63b7dSRichard Lowe if ((node->left = left->right) != 0) {
104210d63b7dSRichard Lowe left->right->parent = node;
104310d63b7dSRichard Lowe }
104410d63b7dSRichard Lowe if ((left->parent = node->parent) != 0) {
104510d63b7dSRichard Lowe if (node == node->parent->right) {
104610d63b7dSRichard Lowe node->parent->right = left;
104710d63b7dSRichard Lowe } else {
104810d63b7dSRichard Lowe node->parent->left = left;
104910d63b7dSRichard Lowe }
105010d63b7dSRichard Lowe } else {
105110d63b7dSRichard Lowe root = left;
105210d63b7dSRichard Lowe }
105310d63b7dSRichard Lowe left->right = node;
105410d63b7dSRichard Lowe node->parent = left;
105510d63b7dSRichard Lowe
105610d63b7dSRichard Lowe node->setup_depth();
105710d63b7dSRichard Lowe node = left;
105810d63b7dSRichard Lowe } else if (rdepth > ldepth + 1) {
105910d63b7dSRichard Lowe if ((node->right = right->left) != 0) {
106010d63b7dSRichard Lowe right->left->parent = node;
106110d63b7dSRichard Lowe }
106210d63b7dSRichard Lowe if ((right->parent = node->parent) != 0) {
106310d63b7dSRichard Lowe if (node == node->parent->right) {
106410d63b7dSRichard Lowe node->parent->right = right;
106510d63b7dSRichard Lowe } else {
106610d63b7dSRichard Lowe node->parent->left = right;
106710d63b7dSRichard Lowe }
106810d63b7dSRichard Lowe } else {
106910d63b7dSRichard Lowe root = right;
107010d63b7dSRichard Lowe }
107110d63b7dSRichard Lowe right->left = node;
107210d63b7dSRichard Lowe node->parent = right;
107310d63b7dSRichard Lowe
107410d63b7dSRichard Lowe node->setup_depth();
107510d63b7dSRichard Lowe node = right;
107610d63b7dSRichard Lowe }
107710d63b7dSRichard Lowe node->setup_depth();
107810d63b7dSRichard Lowe }
107910d63b7dSRichard Lowe }
108010d63b7dSRichard Lowe
108110d63b7dSRichard Lowe Name_set::iterator
begin() const108210d63b7dSRichard Lowe Name_set::begin() const {
108310d63b7dSRichard Lowe for (entry *node = root; node != 0; node = node->left) {
108410d63b7dSRichard Lowe if (node->left == 0) {
108510d63b7dSRichard Lowe return iterator(node);
108610d63b7dSRichard Lowe }
108710d63b7dSRichard Lowe }
108810d63b7dSRichard Lowe return iterator();
108910d63b7dSRichard Lowe }
109010d63b7dSRichard Lowe
109110d63b7dSRichard Lowe Name_set::iterator&
operator ++()109210d63b7dSRichard Lowe Name_set::iterator::operator++() {
109310d63b7dSRichard Lowe if (node != 0) {
109410d63b7dSRichard Lowe if (node->right != 0) {
109510d63b7dSRichard Lowe node = node->right;
109610d63b7dSRichard Lowe while (node->left != 0) {
109710d63b7dSRichard Lowe node = node->left;
109810d63b7dSRichard Lowe }
109910d63b7dSRichard Lowe } else {
110010d63b7dSRichard Lowe while ((node->parent != 0) && (node->parent->right == node)) {
110110d63b7dSRichard Lowe node = node->parent;
110210d63b7dSRichard Lowe }
110310d63b7dSRichard Lowe node = node->parent;
110410d63b7dSRichard Lowe }
110510d63b7dSRichard Lowe }
110610d63b7dSRichard Lowe return *this;
110710d63b7dSRichard Lowe }
1108