xref: /aosp_15_r20/external/mksh/src/os2.c (revision 7c356e860f31eadd15fd599fcfdb9fd21f16a9d4)
1*7c356e86SAndroid Build Coastguard Worker /*-
2*7c356e86SAndroid Build Coastguard Worker  * Copyright (c) 2015, 2017, 2020
3*7c356e86SAndroid Build Coastguard Worker  *	KO Myung-Hun <[email protected]>
4*7c356e86SAndroid Build Coastguard Worker  * Copyright (c) 2017, 2020
5*7c356e86SAndroid Build Coastguard Worker  *	mirabilos <[email protected]>
6*7c356e86SAndroid Build Coastguard Worker  *
7*7c356e86SAndroid Build Coastguard Worker  * Provided that these terms and disclaimer and all copyright notices
8*7c356e86SAndroid Build Coastguard Worker  * are retained or reproduced in an accompanying document, permission
9*7c356e86SAndroid Build Coastguard Worker  * is granted to deal in this work without restriction, including un-
10*7c356e86SAndroid Build Coastguard Worker  * limited rights to use, publicly perform, distribute, sell, modify,
11*7c356e86SAndroid Build Coastguard Worker  * merge, give away, or sublicence.
12*7c356e86SAndroid Build Coastguard Worker  *
13*7c356e86SAndroid Build Coastguard Worker  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
14*7c356e86SAndroid Build Coastguard Worker  * the utmost extent permitted by applicable law, neither express nor
15*7c356e86SAndroid Build Coastguard Worker  * implied; without malicious intent or gross negligence. In no event
16*7c356e86SAndroid Build Coastguard Worker  * may a licensor, author or contributor be held liable for indirect,
17*7c356e86SAndroid Build Coastguard Worker  * direct, other damage, loss, or other issues arising in any way out
18*7c356e86SAndroid Build Coastguard Worker  * of dealing in the work, even if advised of the possibility of such
19*7c356e86SAndroid Build Coastguard Worker  * damage or existence of a defect, except proven that it results out
20*7c356e86SAndroid Build Coastguard Worker  * of said person's immediate fault when using the work as intended.
21*7c356e86SAndroid Build Coastguard Worker  */
22*7c356e86SAndroid Build Coastguard Worker 
23*7c356e86SAndroid Build Coastguard Worker #define INCL_KBD
24*7c356e86SAndroid Build Coastguard Worker #define INCL_DOS
25*7c356e86SAndroid Build Coastguard Worker #include <os2.h>
26*7c356e86SAndroid Build Coastguard Worker 
27*7c356e86SAndroid Build Coastguard Worker #include "sh.h"
28*7c356e86SAndroid Build Coastguard Worker 
29*7c356e86SAndroid Build Coastguard Worker #include <klibc/startup.h>
30*7c356e86SAndroid Build Coastguard Worker #include <errno.h>
31*7c356e86SAndroid Build Coastguard Worker #include <io.h>
32*7c356e86SAndroid Build Coastguard Worker #include <unistd.h>
33*7c356e86SAndroid Build Coastguard Worker #include <process.h>
34*7c356e86SAndroid Build Coastguard Worker 
35*7c356e86SAndroid Build Coastguard Worker __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.11 2020/10/01 21:13:45 tg Exp $");
36*7c356e86SAndroid Build Coastguard Worker 
37*7c356e86SAndroid Build Coastguard Worker struct a_s_arg {
38*7c356e86SAndroid Build Coastguard Worker 	union {
39*7c356e86SAndroid Build Coastguard Worker 		int (*i)(const char *, int);
40*7c356e86SAndroid Build Coastguard Worker 		int (*p)(const char *, void *);
41*7c356e86SAndroid Build Coastguard Worker 	} fn;
42*7c356e86SAndroid Build Coastguard Worker 	union {
43*7c356e86SAndroid Build Coastguard Worker 		int i;
44*7c356e86SAndroid Build Coastguard Worker 		void *p;
45*7c356e86SAndroid Build Coastguard Worker 	} arg;
46*7c356e86SAndroid Build Coastguard Worker 	bool isint;
47*7c356e86SAndroid Build Coastguard Worker };
48*7c356e86SAndroid Build Coastguard Worker 
49*7c356e86SAndroid Build Coastguard Worker static void remove_trailing_dots(char *, size_t);
50*7c356e86SAndroid Build Coastguard Worker static int access_stat_ex(const char *, struct a_s_arg *);
51*7c356e86SAndroid Build Coastguard Worker static int test_exec_exist(const char *, void *);
52*7c356e86SAndroid Build Coastguard Worker static void response(int *, const char ***);
53*7c356e86SAndroid Build Coastguard Worker static char *make_response_file(char * const *);
54*7c356e86SAndroid Build Coastguard Worker static void add_temp(const char *);
55*7c356e86SAndroid Build Coastguard Worker static void cleanup_temps(void);
56*7c356e86SAndroid Build Coastguard Worker static void cleanup(void);
57*7c356e86SAndroid Build Coastguard Worker 
58*7c356e86SAndroid Build Coastguard Worker #define RPUT(x) do {					\
59*7c356e86SAndroid Build Coastguard Worker 	if (new_argc >= new_alloc) {			\
60*7c356e86SAndroid Build Coastguard Worker 		new_alloc += 20;			\
61*7c356e86SAndroid Build Coastguard Worker 		if (!(new_argv = realloc(new_argv,	\
62*7c356e86SAndroid Build Coastguard Worker 		    new_alloc * sizeof(char *))))	\
63*7c356e86SAndroid Build Coastguard Worker 			goto exit_out_of_memory;	\
64*7c356e86SAndroid Build Coastguard Worker 	}						\
65*7c356e86SAndroid Build Coastguard Worker 	new_argv[new_argc++] = (x);			\
66*7c356e86SAndroid Build Coastguard Worker } while (/* CONSTCOND */ 0)
67*7c356e86SAndroid Build Coastguard Worker 
68*7c356e86SAndroid Build Coastguard Worker #define KLIBC_ARG_RESPONSE_EXCLUDE	\
69*7c356e86SAndroid Build Coastguard Worker 	(__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL)
70*7c356e86SAndroid Build Coastguard Worker 
71*7c356e86SAndroid Build Coastguard Worker static void
response(int * argcp,const char *** argvp)72*7c356e86SAndroid Build Coastguard Worker response(int *argcp, const char ***argvp)
73*7c356e86SAndroid Build Coastguard Worker {
74*7c356e86SAndroid Build Coastguard Worker 	int i, old_argc, new_argc, new_alloc = 0;
75*7c356e86SAndroid Build Coastguard Worker 	const char **old_argv, **new_argv;
76*7c356e86SAndroid Build Coastguard Worker 	char *line, *l, *p;
77*7c356e86SAndroid Build Coastguard Worker 	FILE *f;
78*7c356e86SAndroid Build Coastguard Worker 
79*7c356e86SAndroid Build Coastguard Worker 	old_argc = *argcp;
80*7c356e86SAndroid Build Coastguard Worker 	old_argv = *argvp;
81*7c356e86SAndroid Build Coastguard Worker 	for (i = 1; i < old_argc; ++i)
82*7c356e86SAndroid Build Coastguard Worker 		if (old_argv[i] &&
83*7c356e86SAndroid Build Coastguard Worker 		    !(old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) &&
84*7c356e86SAndroid Build Coastguard Worker 		    old_argv[i][0] == '@')
85*7c356e86SAndroid Build Coastguard Worker 			break;
86*7c356e86SAndroid Build Coastguard Worker 
87*7c356e86SAndroid Build Coastguard Worker 	if (i >= old_argc)
88*7c356e86SAndroid Build Coastguard Worker 		/* do nothing */
89*7c356e86SAndroid Build Coastguard Worker 		return;
90*7c356e86SAndroid Build Coastguard Worker 
91*7c356e86SAndroid Build Coastguard Worker 	new_argv = NULL;
92*7c356e86SAndroid Build Coastguard Worker 	new_argc = 0;
93*7c356e86SAndroid Build Coastguard Worker 	for (i = 0; i < old_argc; ++i) {
94*7c356e86SAndroid Build Coastguard Worker 		if (i == 0 || !old_argv[i] ||
95*7c356e86SAndroid Build Coastguard Worker 		    (old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) ||
96*7c356e86SAndroid Build Coastguard Worker 		    old_argv[i][0] != '@' ||
97*7c356e86SAndroid Build Coastguard Worker 		    !(f = fopen(old_argv[i] + 1, "rt")))
98*7c356e86SAndroid Build Coastguard Worker 			RPUT(old_argv[i]);
99*7c356e86SAndroid Build Coastguard Worker 		else {
100*7c356e86SAndroid Build Coastguard Worker 			long filesize;
101*7c356e86SAndroid Build Coastguard Worker 
102*7c356e86SAndroid Build Coastguard Worker 			fseek(f, 0, SEEK_END);
103*7c356e86SAndroid Build Coastguard Worker 			filesize = ftell(f);
104*7c356e86SAndroid Build Coastguard Worker 			fseek(f, 0, SEEK_SET);
105*7c356e86SAndroid Build Coastguard Worker 
106*7c356e86SAndroid Build Coastguard Worker 			line = malloc(filesize + /* type */ 1 + /* NUL */ 1);
107*7c356e86SAndroid Build Coastguard Worker 			if (!line) {
108*7c356e86SAndroid Build Coastguard Worker  exit_out_of_memory:
109*7c356e86SAndroid Build Coastguard Worker 				fputs("Out of memory while reading response file\n", stderr);
110*7c356e86SAndroid Build Coastguard Worker 				exit(255);
111*7c356e86SAndroid Build Coastguard Worker 			}
112*7c356e86SAndroid Build Coastguard Worker 
113*7c356e86SAndroid Build Coastguard Worker 			line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_RESPONSE;
114*7c356e86SAndroid Build Coastguard Worker 			l = line + 1;
115*7c356e86SAndroid Build Coastguard Worker 			while (fgets(l, (filesize + 1) - (l - (line + 1)), f)) {
116*7c356e86SAndroid Build Coastguard Worker 				p = strchr(l, '\n');
117*7c356e86SAndroid Build Coastguard Worker 				if (p) {
118*7c356e86SAndroid Build Coastguard Worker 					/*
119*7c356e86SAndroid Build Coastguard Worker 					 * if a line ends with a backslash,
120*7c356e86SAndroid Build Coastguard Worker 					 * concatenate with the next line
121*7c356e86SAndroid Build Coastguard Worker 					 */
122*7c356e86SAndroid Build Coastguard Worker 					if (p > l && p[-1] == '\\') {
123*7c356e86SAndroid Build Coastguard Worker 						char *p1;
124*7c356e86SAndroid Build Coastguard Worker 						int count = 0;
125*7c356e86SAndroid Build Coastguard Worker 
126*7c356e86SAndroid Build Coastguard Worker 						for (p1 = p - 1; p1 >= l &&
127*7c356e86SAndroid Build Coastguard Worker 						    *p1 == '\\'; p1--)
128*7c356e86SAndroid Build Coastguard Worker 							count++;
129*7c356e86SAndroid Build Coastguard Worker 
130*7c356e86SAndroid Build Coastguard Worker 						if (count & 1) {
131*7c356e86SAndroid Build Coastguard Worker 							l = p + 1;
132*7c356e86SAndroid Build Coastguard Worker 
133*7c356e86SAndroid Build Coastguard Worker 							continue;
134*7c356e86SAndroid Build Coastguard Worker 						}
135*7c356e86SAndroid Build Coastguard Worker 					}
136*7c356e86SAndroid Build Coastguard Worker 
137*7c356e86SAndroid Build Coastguard Worker 					*p = 0;
138*7c356e86SAndroid Build Coastguard Worker 				}
139*7c356e86SAndroid Build Coastguard Worker 				p = strdup(line);
140*7c356e86SAndroid Build Coastguard Worker 				if (!p)
141*7c356e86SAndroid Build Coastguard Worker 					goto exit_out_of_memory;
142*7c356e86SAndroid Build Coastguard Worker 
143*7c356e86SAndroid Build Coastguard Worker 				RPUT(p + 1);
144*7c356e86SAndroid Build Coastguard Worker 
145*7c356e86SAndroid Build Coastguard Worker 				l = line + 1;
146*7c356e86SAndroid Build Coastguard Worker 			}
147*7c356e86SAndroid Build Coastguard Worker 
148*7c356e86SAndroid Build Coastguard Worker 			free(line);
149*7c356e86SAndroid Build Coastguard Worker 
150*7c356e86SAndroid Build Coastguard Worker 			if (ferror(f)) {
151*7c356e86SAndroid Build Coastguard Worker 				fputs("Cannot read response file\n", stderr);
152*7c356e86SAndroid Build Coastguard Worker 				exit(255);
153*7c356e86SAndroid Build Coastguard Worker 			}
154*7c356e86SAndroid Build Coastguard Worker 
155*7c356e86SAndroid Build Coastguard Worker 			fclose(f);
156*7c356e86SAndroid Build Coastguard Worker 		}
157*7c356e86SAndroid Build Coastguard Worker 	}
158*7c356e86SAndroid Build Coastguard Worker 
159*7c356e86SAndroid Build Coastguard Worker 	RPUT(NULL);
160*7c356e86SAndroid Build Coastguard Worker 	--new_argc;
161*7c356e86SAndroid Build Coastguard Worker 
162*7c356e86SAndroid Build Coastguard Worker 	*argcp = new_argc;
163*7c356e86SAndroid Build Coastguard Worker 	*argvp = new_argv;
164*7c356e86SAndroid Build Coastguard Worker }
165*7c356e86SAndroid Build Coastguard Worker 
166*7c356e86SAndroid Build Coastguard Worker static void
init_extlibpath(void)167*7c356e86SAndroid Build Coastguard Worker init_extlibpath(void)
168*7c356e86SAndroid Build Coastguard Worker {
169*7c356e86SAndroid Build Coastguard Worker 	const char *vars[] = {
170*7c356e86SAndroid Build Coastguard Worker 		"BEGINLIBPATH",
171*7c356e86SAndroid Build Coastguard Worker 		"ENDLIBPATH",
172*7c356e86SAndroid Build Coastguard Worker 		"LIBPATHSTRICT",
173*7c356e86SAndroid Build Coastguard Worker 		NULL
174*7c356e86SAndroid Build Coastguard Worker 	};
175*7c356e86SAndroid Build Coastguard Worker 	char val[512];
176*7c356e86SAndroid Build Coastguard Worker 	int flag;
177*7c356e86SAndroid Build Coastguard Worker 
178*7c356e86SAndroid Build Coastguard Worker 	for (flag = 0; vars[flag]; flag++) {
179*7c356e86SAndroid Build Coastguard Worker 		DosQueryExtLIBPATH(val, flag + 1);
180*7c356e86SAndroid Build Coastguard Worker 		if (val[0])
181*7c356e86SAndroid Build Coastguard Worker 			setenv(vars[flag], val, 1);
182*7c356e86SAndroid Build Coastguard Worker 	}
183*7c356e86SAndroid Build Coastguard Worker }
184*7c356e86SAndroid Build Coastguard Worker 
185*7c356e86SAndroid Build Coastguard Worker void
os2_init(int * argcp,const char *** argvp)186*7c356e86SAndroid Build Coastguard Worker os2_init(int *argcp, const char ***argvp)
187*7c356e86SAndroid Build Coastguard Worker {
188*7c356e86SAndroid Build Coastguard Worker 	KBDINFO ki;
189*7c356e86SAndroid Build Coastguard Worker 
190*7c356e86SAndroid Build Coastguard Worker 	response(argcp, argvp);
191*7c356e86SAndroid Build Coastguard Worker 
192*7c356e86SAndroid Build Coastguard Worker 	init_extlibpath();
193*7c356e86SAndroid Build Coastguard Worker 
194*7c356e86SAndroid Build Coastguard Worker 	if (!isatty(STDIN_FILENO))
195*7c356e86SAndroid Build Coastguard Worker 		setmode(STDIN_FILENO, O_BINARY);
196*7c356e86SAndroid Build Coastguard Worker 	if (!isatty(STDOUT_FILENO))
197*7c356e86SAndroid Build Coastguard Worker 		setmode(STDOUT_FILENO, O_BINARY);
198*7c356e86SAndroid Build Coastguard Worker 	if (!isatty(STDERR_FILENO))
199*7c356e86SAndroid Build Coastguard Worker 		setmode(STDERR_FILENO, O_BINARY);
200*7c356e86SAndroid Build Coastguard Worker 
201*7c356e86SAndroid Build Coastguard Worker 	/* ensure ECHO mode is ON so that read command echoes. */
202*7c356e86SAndroid Build Coastguard Worker 	memset(&ki, 0, sizeof(ki));
203*7c356e86SAndroid Build Coastguard Worker 	ki.cb = sizeof(ki);
204*7c356e86SAndroid Build Coastguard Worker 	ki.fsMask |= KEYBOARD_ECHO_ON;
205*7c356e86SAndroid Build Coastguard Worker 	KbdSetStatus(&ki, 0);
206*7c356e86SAndroid Build Coastguard Worker 
207*7c356e86SAndroid Build Coastguard Worker 	atexit(cleanup);
208*7c356e86SAndroid Build Coastguard Worker }
209*7c356e86SAndroid Build Coastguard Worker 
210*7c356e86SAndroid Build Coastguard Worker void
setextlibpath(const char * name,const char * val)211*7c356e86SAndroid Build Coastguard Worker setextlibpath(const char *name, const char *val)
212*7c356e86SAndroid Build Coastguard Worker {
213*7c356e86SAndroid Build Coastguard Worker 	int flag;
214*7c356e86SAndroid Build Coastguard Worker 	char *p, *cp;
215*7c356e86SAndroid Build Coastguard Worker 
216*7c356e86SAndroid Build Coastguard Worker 	if (!strcmp(name, "BEGINLIBPATH"))
217*7c356e86SAndroid Build Coastguard Worker 		flag = BEGIN_LIBPATH;
218*7c356e86SAndroid Build Coastguard Worker 	else if (!strcmp(name, "ENDLIBPATH"))
219*7c356e86SAndroid Build Coastguard Worker 		flag = END_LIBPATH;
220*7c356e86SAndroid Build Coastguard Worker 	else if (!strcmp(name, "LIBPATHSTRICT"))
221*7c356e86SAndroid Build Coastguard Worker 		flag = LIBPATHSTRICT;
222*7c356e86SAndroid Build Coastguard Worker 	else
223*7c356e86SAndroid Build Coastguard Worker 		return;
224*7c356e86SAndroid Build Coastguard Worker 
225*7c356e86SAndroid Build Coastguard Worker 	/* convert slashes to backslashes */
226*7c356e86SAndroid Build Coastguard Worker 	strdupx(cp, val, ATEMP);
227*7c356e86SAndroid Build Coastguard Worker 	for (p = cp; *p; p++) {
228*7c356e86SAndroid Build Coastguard Worker 		if (*p == '/')
229*7c356e86SAndroid Build Coastguard Worker 			*p = '\\';
230*7c356e86SAndroid Build Coastguard Worker 	}
231*7c356e86SAndroid Build Coastguard Worker 
232*7c356e86SAndroid Build Coastguard Worker 	DosSetExtLIBPATH(cp, flag);
233*7c356e86SAndroid Build Coastguard Worker 
234*7c356e86SAndroid Build Coastguard Worker 	afree(cp, ATEMP);
235*7c356e86SAndroid Build Coastguard Worker }
236*7c356e86SAndroid Build Coastguard Worker 
237*7c356e86SAndroid Build Coastguard Worker /* remove trailing dots */
238*7c356e86SAndroid Build Coastguard Worker static void
remove_trailing_dots(char * name,size_t namelen)239*7c356e86SAndroid Build Coastguard Worker remove_trailing_dots(char *name, size_t namelen)
240*7c356e86SAndroid Build Coastguard Worker {
241*7c356e86SAndroid Build Coastguard Worker 	char *p = name + namelen;
242*7c356e86SAndroid Build Coastguard Worker 
243*7c356e86SAndroid Build Coastguard Worker 	while (--p > name && *p == '.')
244*7c356e86SAndroid Build Coastguard Worker 		/* nothing */;
245*7c356e86SAndroid Build Coastguard Worker 
246*7c356e86SAndroid Build Coastguard Worker 	if (*p != '.' && *p != '/' && *p != '\\' && *p != ':')
247*7c356e86SAndroid Build Coastguard Worker 		p[1] = '\0';
248*7c356e86SAndroid Build Coastguard Worker }
249*7c356e86SAndroid Build Coastguard Worker 
250*7c356e86SAndroid Build Coastguard Worker /* alias of stat() */
251*7c356e86SAndroid Build Coastguard Worker extern int _std_stat(const char *, struct stat *);
252*7c356e86SAndroid Build Coastguard Worker 
253*7c356e86SAndroid Build Coastguard Worker /* replacement for stat() of kLIBC which fails if there are trailing dots */
254*7c356e86SAndroid Build Coastguard Worker int
stat(const char * name,struct stat * buffer)255*7c356e86SAndroid Build Coastguard Worker stat(const char *name, struct stat *buffer)
256*7c356e86SAndroid Build Coastguard Worker {
257*7c356e86SAndroid Build Coastguard Worker 	size_t namelen = strlen(name) + 1;
258*7c356e86SAndroid Build Coastguard Worker 	char nodots[namelen];
259*7c356e86SAndroid Build Coastguard Worker 
260*7c356e86SAndroid Build Coastguard Worker 	memcpy(nodots, name, namelen);
261*7c356e86SAndroid Build Coastguard Worker 	remove_trailing_dots(nodots, namelen);
262*7c356e86SAndroid Build Coastguard Worker 	return (_std_stat(nodots, buffer));
263*7c356e86SAndroid Build Coastguard Worker }
264*7c356e86SAndroid Build Coastguard Worker 
265*7c356e86SAndroid Build Coastguard Worker /* alias of access() */
266*7c356e86SAndroid Build Coastguard Worker extern int _std_access(const char *, int);
267*7c356e86SAndroid Build Coastguard Worker 
268*7c356e86SAndroid Build Coastguard Worker /* replacement for access() of kLIBC which fails if there are trailing dots */
269*7c356e86SAndroid Build Coastguard Worker int
access(const char * name,int mode)270*7c356e86SAndroid Build Coastguard Worker access(const char *name, int mode)
271*7c356e86SAndroid Build Coastguard Worker {
272*7c356e86SAndroid Build Coastguard Worker 	size_t namelen = strlen(name) + 1;
273*7c356e86SAndroid Build Coastguard Worker 	char nodots[namelen];
274*7c356e86SAndroid Build Coastguard Worker 
275*7c356e86SAndroid Build Coastguard Worker 	/*
276*7c356e86SAndroid Build Coastguard Worker 	 * On OS/2 kLIBC, X_OK is set only for executable files.
277*7c356e86SAndroid Build Coastguard Worker 	 * This prevents scripts from being executed.
278*7c356e86SAndroid Build Coastguard Worker 	 */
279*7c356e86SAndroid Build Coastguard Worker 	if (mode & X_OK)
280*7c356e86SAndroid Build Coastguard Worker 		mode = (mode & ~X_OK) | R_OK;
281*7c356e86SAndroid Build Coastguard Worker 
282*7c356e86SAndroid Build Coastguard Worker 	memcpy(nodots, name, namelen);
283*7c356e86SAndroid Build Coastguard Worker 	remove_trailing_dots(nodots, namelen);
284*7c356e86SAndroid Build Coastguard Worker 	return (_std_access(nodots, mode));
285*7c356e86SAndroid Build Coastguard Worker }
286*7c356e86SAndroid Build Coastguard Worker 
287*7c356e86SAndroid Build Coastguard Worker #define MAX_X_SUFFIX_LEN	4
288*7c356e86SAndroid Build Coastguard Worker 
289*7c356e86SAndroid Build Coastguard Worker static const char *x_suffix_list[] =
290*7c356e86SAndroid Build Coastguard Worker     { "", ".ksh", ".exe", ".sh", ".cmd", ".com", ".bat", NULL };
291*7c356e86SAndroid Build Coastguard Worker 
292*7c356e86SAndroid Build Coastguard Worker /* call fn() by appending executable extensions */
293*7c356e86SAndroid Build Coastguard Worker static int
access_stat_ex(const char * name,struct a_s_arg * action)294*7c356e86SAndroid Build Coastguard Worker access_stat_ex(const char *name, struct a_s_arg *action)
295*7c356e86SAndroid Build Coastguard Worker {
296*7c356e86SAndroid Build Coastguard Worker 	char *x_name;
297*7c356e86SAndroid Build Coastguard Worker 	const char **x_suffix;
298*7c356e86SAndroid Build Coastguard Worker 	int rc = -1;
299*7c356e86SAndroid Build Coastguard Worker 	size_t x_namelen = strlen(name) + MAX_X_SUFFIX_LEN + 1;
300*7c356e86SAndroid Build Coastguard Worker 
301*7c356e86SAndroid Build Coastguard Worker 	/* otherwise, try to append executable suffixes */
302*7c356e86SAndroid Build Coastguard Worker 	x_name = alloc(x_namelen, ATEMP);
303*7c356e86SAndroid Build Coastguard Worker 
304*7c356e86SAndroid Build Coastguard Worker 	for (x_suffix = x_suffix_list; rc && *x_suffix; x_suffix++) {
305*7c356e86SAndroid Build Coastguard Worker 		strlcpy(x_name, name, x_namelen);
306*7c356e86SAndroid Build Coastguard Worker 		strlcat(x_name, *x_suffix, x_namelen);
307*7c356e86SAndroid Build Coastguard Worker 
308*7c356e86SAndroid Build Coastguard Worker 		rc = action->isint ? action->fn.i(x_name, action->arg.i) :
309*7c356e86SAndroid Build Coastguard Worker 		    action->fn.p(x_name, action->arg.p);
310*7c356e86SAndroid Build Coastguard Worker 	}
311*7c356e86SAndroid Build Coastguard Worker 
312*7c356e86SAndroid Build Coastguard Worker 	afree(x_name, ATEMP);
313*7c356e86SAndroid Build Coastguard Worker 
314*7c356e86SAndroid Build Coastguard Worker 	return (rc);
315*7c356e86SAndroid Build Coastguard Worker }
316*7c356e86SAndroid Build Coastguard Worker 
317*7c356e86SAndroid Build Coastguard Worker /* access()/search_access() version */
318*7c356e86SAndroid Build Coastguard Worker int
access_ex(int (* fn)(const char *,int),const char * name,int mode)319*7c356e86SAndroid Build Coastguard Worker access_ex(int (*fn)(const char *, int), const char *name, int mode)
320*7c356e86SAndroid Build Coastguard Worker {
321*7c356e86SAndroid Build Coastguard Worker 	struct a_s_arg arg;
322*7c356e86SAndroid Build Coastguard Worker 
323*7c356e86SAndroid Build Coastguard Worker 	arg.fn.i = fn;
324*7c356e86SAndroid Build Coastguard Worker 	arg.arg.i = mode;
325*7c356e86SAndroid Build Coastguard Worker 	arg.isint = true;
326*7c356e86SAndroid Build Coastguard Worker 	return (access_stat_ex(name, &arg));
327*7c356e86SAndroid Build Coastguard Worker }
328*7c356e86SAndroid Build Coastguard Worker 
329*7c356e86SAndroid Build Coastguard Worker /* stat()/lstat() version */
330*7c356e86SAndroid Build Coastguard Worker int
stat_ex(int (* fn)(const char *,struct stat *),const char * name,struct stat * buffer)331*7c356e86SAndroid Build Coastguard Worker stat_ex(int (*fn)(const char *, struct stat *),
332*7c356e86SAndroid Build Coastguard Worker     const char *name, struct stat *buffer)
333*7c356e86SAndroid Build Coastguard Worker {
334*7c356e86SAndroid Build Coastguard Worker 	struct a_s_arg arg;
335*7c356e86SAndroid Build Coastguard Worker 
336*7c356e86SAndroid Build Coastguard Worker 	arg.fn.p = fn;
337*7c356e86SAndroid Build Coastguard Worker 	arg.arg.p = buffer;
338*7c356e86SAndroid Build Coastguard Worker 	arg.isint = false;
339*7c356e86SAndroid Build Coastguard Worker 	return (access_stat_ex(name, &arg));
340*7c356e86SAndroid Build Coastguard Worker }
341*7c356e86SAndroid Build Coastguard Worker 
342*7c356e86SAndroid Build Coastguard Worker static int
test_exec_exist(const char * name,void * arg)343*7c356e86SAndroid Build Coastguard Worker test_exec_exist(const char *name, void *arg)
344*7c356e86SAndroid Build Coastguard Worker {
345*7c356e86SAndroid Build Coastguard Worker 	struct stat sb;
346*7c356e86SAndroid Build Coastguard Worker 	char *real_name;
347*7c356e86SAndroid Build Coastguard Worker 
348*7c356e86SAndroid Build Coastguard Worker 	if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode))
349*7c356e86SAndroid Build Coastguard Worker 		return (-1);
350*7c356e86SAndroid Build Coastguard Worker 
351*7c356e86SAndroid Build Coastguard Worker 	/*XXX memory leak */
352*7c356e86SAndroid Build Coastguard Worker 	strdupx(real_name, name, ATEMP);
353*7c356e86SAndroid Build Coastguard Worker 	*((char **)arg) = real_name;
354*7c356e86SAndroid Build Coastguard Worker 	return (0);
355*7c356e86SAndroid Build Coastguard Worker }
356*7c356e86SAndroid Build Coastguard Worker 
357*7c356e86SAndroid Build Coastguard Worker const char *
real_exec_name(const char * name)358*7c356e86SAndroid Build Coastguard Worker real_exec_name(const char *name)
359*7c356e86SAndroid Build Coastguard Worker {
360*7c356e86SAndroid Build Coastguard Worker 	struct a_s_arg arg;
361*7c356e86SAndroid Build Coastguard Worker 	char *real_name;
362*7c356e86SAndroid Build Coastguard Worker 
363*7c356e86SAndroid Build Coastguard Worker 	arg.fn.p = &test_exec_exist;
364*7c356e86SAndroid Build Coastguard Worker 	arg.arg.p = (void *)(&real_name);
365*7c356e86SAndroid Build Coastguard Worker 	arg.isint = false;
366*7c356e86SAndroid Build Coastguard Worker 	return (access_stat_ex(name, &arg) ? name : real_name);
367*7c356e86SAndroid Build Coastguard Worker }
368*7c356e86SAndroid Build Coastguard Worker 
369*7c356e86SAndroid Build Coastguard Worker /* make a response file to pass a very long command line */
370*7c356e86SAndroid Build Coastguard Worker static char *
make_response_file(char * const * argv)371*7c356e86SAndroid Build Coastguard Worker make_response_file(char * const *argv)
372*7c356e86SAndroid Build Coastguard Worker {
373*7c356e86SAndroid Build Coastguard Worker 	char rsp_name_arg[] = "@mksh-rsp-XXXXXX";
374*7c356e86SAndroid Build Coastguard Worker 	char *rsp_name = &rsp_name_arg[1];
375*7c356e86SAndroid Build Coastguard Worker 	int i;
376*7c356e86SAndroid Build Coastguard Worker 	int fd;
377*7c356e86SAndroid Build Coastguard Worker 	char *result;
378*7c356e86SAndroid Build Coastguard Worker 
379*7c356e86SAndroid Build Coastguard Worker 	if ((fd = mkstemp(rsp_name)) == -1)
380*7c356e86SAndroid Build Coastguard Worker 		return (NULL);
381*7c356e86SAndroid Build Coastguard Worker 
382*7c356e86SAndroid Build Coastguard Worker 	/* write all the arguments except a 0th program name */
383*7c356e86SAndroid Build Coastguard Worker 	for (i = 1; argv[i]; i++) {
384*7c356e86SAndroid Build Coastguard Worker 		write(fd, argv[i], strlen(argv[i]));
385*7c356e86SAndroid Build Coastguard Worker 		write(fd, "\n", 1);
386*7c356e86SAndroid Build Coastguard Worker 	}
387*7c356e86SAndroid Build Coastguard Worker 
388*7c356e86SAndroid Build Coastguard Worker 	close(fd);
389*7c356e86SAndroid Build Coastguard Worker 	add_temp(rsp_name);
390*7c356e86SAndroid Build Coastguard Worker 	strdupx(result, rsp_name_arg, ATEMP);
391*7c356e86SAndroid Build Coastguard Worker 
392*7c356e86SAndroid Build Coastguard Worker 	return (result);
393*7c356e86SAndroid Build Coastguard Worker }
394*7c356e86SAndroid Build Coastguard Worker 
395*7c356e86SAndroid Build Coastguard Worker /* alias of execve() */
396*7c356e86SAndroid Build Coastguard Worker extern int _std_execve(const char *, char * const *, char * const *);
397*7c356e86SAndroid Build Coastguard Worker 
398*7c356e86SAndroid Build Coastguard Worker /* replacement for execve() of kLIBC */
399*7c356e86SAndroid Build Coastguard Worker int
execve(const char * name,char * const * argv,char * const * envp)400*7c356e86SAndroid Build Coastguard Worker execve(const char *name, char * const *argv, char * const *envp)
401*7c356e86SAndroid Build Coastguard Worker {
402*7c356e86SAndroid Build Coastguard Worker 	const char *exec_name;
403*7c356e86SAndroid Build Coastguard Worker 	FILE *fp;
404*7c356e86SAndroid Build Coastguard Worker 	char sign[2];
405*7c356e86SAndroid Build Coastguard Worker 	int pid;
406*7c356e86SAndroid Build Coastguard Worker 	int status;
407*7c356e86SAndroid Build Coastguard Worker 	int fd;
408*7c356e86SAndroid Build Coastguard Worker 	int rc;
409*7c356e86SAndroid Build Coastguard Worker 	int saved_mode;
410*7c356e86SAndroid Build Coastguard Worker 	int saved_errno;
411*7c356e86SAndroid Build Coastguard Worker 
412*7c356e86SAndroid Build Coastguard Worker 	/*
413*7c356e86SAndroid Build Coastguard Worker 	 * #! /bin/sh : append .exe
414*7c356e86SAndroid Build Coastguard Worker 	 * extproc sh : search sh.exe in PATH
415*7c356e86SAndroid Build Coastguard Worker 	 */
416*7c356e86SAndroid Build Coastguard Worker 	exec_name = search_path(name, path, X_OK, NULL);
417*7c356e86SAndroid Build Coastguard Worker 	if (!exec_name) {
418*7c356e86SAndroid Build Coastguard Worker 		errno = ENOENT;
419*7c356e86SAndroid Build Coastguard Worker 		return (-1);
420*7c356e86SAndroid Build Coastguard Worker 	}
421*7c356e86SAndroid Build Coastguard Worker 
422*7c356e86SAndroid Build Coastguard Worker 	/*-
423*7c356e86SAndroid Build Coastguard Worker 	 * kLIBC execve() has problems when executing scripts.
424*7c356e86SAndroid Build Coastguard Worker 	 * 1. it fails to execute a script if a directory whose name
425*7c356e86SAndroid Build Coastguard Worker 	 *    is same as an interpreter exists in a current directory.
426*7c356e86SAndroid Build Coastguard Worker 	 * 2. it fails to execute a script not starting with sharpbang.
427*7c356e86SAndroid Build Coastguard Worker 	 * 3. it fails to execute a batch file if COMSPEC is set to a shell
428*7c356e86SAndroid Build Coastguard Worker 	 *    incompatible with cmd.exe, such as /bin/sh.
429*7c356e86SAndroid Build Coastguard Worker 	 * And ksh process scripts more well, so let ksh process scripts.
430*7c356e86SAndroid Build Coastguard Worker 	 */
431*7c356e86SAndroid Build Coastguard Worker 	errno = 0;
432*7c356e86SAndroid Build Coastguard Worker 	if (!(fp = fopen(exec_name, "rb")))
433*7c356e86SAndroid Build Coastguard Worker 		errno = ENOEXEC;
434*7c356e86SAndroid Build Coastguard Worker 
435*7c356e86SAndroid Build Coastguard Worker 	if (!errno && fread(sign, 1, sizeof(sign), fp) != sizeof(sign))
436*7c356e86SAndroid Build Coastguard Worker 		errno = ENOEXEC;
437*7c356e86SAndroid Build Coastguard Worker 
438*7c356e86SAndroid Build Coastguard Worker 	if (fp && fclose(fp))
439*7c356e86SAndroid Build Coastguard Worker 		errno = ENOEXEC;
440*7c356e86SAndroid Build Coastguard Worker 
441*7c356e86SAndroid Build Coastguard Worker 	if (!errno &&
442*7c356e86SAndroid Build Coastguard Worker 	    !((sign[0] == 'M' && sign[1] == 'Z') ||
443*7c356e86SAndroid Build Coastguard Worker 	      (sign[0] == 'N' && sign[1] == 'E') ||
444*7c356e86SAndroid Build Coastguard Worker 	      (sign[0] == 'L' && sign[1] == 'X')))
445*7c356e86SAndroid Build Coastguard Worker 		errno = ENOEXEC;
446*7c356e86SAndroid Build Coastguard Worker 
447*7c356e86SAndroid Build Coastguard Worker 	if (errno == ENOEXEC)
448*7c356e86SAndroid Build Coastguard Worker 		return (-1);
449*7c356e86SAndroid Build Coastguard Worker 
450*7c356e86SAndroid Build Coastguard Worker 	/*
451*7c356e86SAndroid Build Coastguard Worker 	 * Normal OS/2 programs expect that standard IOs, especially stdin,
452*7c356e86SAndroid Build Coastguard Worker 	 * are opened in text mode at the startup. By the way, on OS/2 kLIBC
453*7c356e86SAndroid Build Coastguard Worker 	 * child processes inherit a translation mode of a parent process.
454*7c356e86SAndroid Build Coastguard Worker 	 * As a result, if stdin is set to binary mode in a parent process,
455*7c356e86SAndroid Build Coastguard Worker 	 * stdin of child processes is opened in binary mode as well at the
456*7c356e86SAndroid Build Coastguard Worker 	 * startup. In this case, some programs such as sed suffer from CR.
457*7c356e86SAndroid Build Coastguard Worker 	 */
458*7c356e86SAndroid Build Coastguard Worker 	saved_mode = setmode(STDIN_FILENO, O_TEXT);
459*7c356e86SAndroid Build Coastguard Worker 
460*7c356e86SAndroid Build Coastguard Worker 	pid = spawnve(P_NOWAIT, exec_name, argv, envp);
461*7c356e86SAndroid Build Coastguard Worker 	saved_errno = errno;
462*7c356e86SAndroid Build Coastguard Worker 
463*7c356e86SAndroid Build Coastguard Worker 	/* arguments too long? */
464*7c356e86SAndroid Build Coastguard Worker 	if (pid == -1 && saved_errno == EINVAL) {
465*7c356e86SAndroid Build Coastguard Worker 		/* retry with a response file */
466*7c356e86SAndroid Build Coastguard Worker 		char *rsp_name_arg = make_response_file(argv);
467*7c356e86SAndroid Build Coastguard Worker 
468*7c356e86SAndroid Build Coastguard Worker 		if (rsp_name_arg) {
469*7c356e86SAndroid Build Coastguard Worker 			char *rsp_argv[3] = { argv[0], rsp_name_arg, NULL };
470*7c356e86SAndroid Build Coastguard Worker 
471*7c356e86SAndroid Build Coastguard Worker 			pid = spawnve(P_NOWAIT, exec_name, rsp_argv, envp);
472*7c356e86SAndroid Build Coastguard Worker 			saved_errno = errno;
473*7c356e86SAndroid Build Coastguard Worker 
474*7c356e86SAndroid Build Coastguard Worker 			afree(rsp_name_arg, ATEMP);
475*7c356e86SAndroid Build Coastguard Worker 		}
476*7c356e86SAndroid Build Coastguard Worker 	}
477*7c356e86SAndroid Build Coastguard Worker 
478*7c356e86SAndroid Build Coastguard Worker 	/* restore translation mode of stdin */
479*7c356e86SAndroid Build Coastguard Worker 	setmode(STDIN_FILENO, saved_mode);
480*7c356e86SAndroid Build Coastguard Worker 
481*7c356e86SAndroid Build Coastguard Worker 	if (pid == -1) {
482*7c356e86SAndroid Build Coastguard Worker 		cleanup_temps();
483*7c356e86SAndroid Build Coastguard Worker 
484*7c356e86SAndroid Build Coastguard Worker 		errno = saved_errno;
485*7c356e86SAndroid Build Coastguard Worker 		return (-1);
486*7c356e86SAndroid Build Coastguard Worker 	}
487*7c356e86SAndroid Build Coastguard Worker 
488*7c356e86SAndroid Build Coastguard Worker 	/* close all opened handles */
489*7c356e86SAndroid Build Coastguard Worker 	for (fd = 0; fd < NUFILE; fd++) {
490*7c356e86SAndroid Build Coastguard Worker 		if (fcntl(fd, F_GETFD) == -1)
491*7c356e86SAndroid Build Coastguard Worker 			continue;
492*7c356e86SAndroid Build Coastguard Worker 
493*7c356e86SAndroid Build Coastguard Worker 		close(fd);
494*7c356e86SAndroid Build Coastguard Worker 	}
495*7c356e86SAndroid Build Coastguard Worker 
496*7c356e86SAndroid Build Coastguard Worker 	while ((rc = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
497*7c356e86SAndroid Build Coastguard Worker 		/* nothing */;
498*7c356e86SAndroid Build Coastguard Worker 
499*7c356e86SAndroid Build Coastguard Worker 	cleanup_temps();
500*7c356e86SAndroid Build Coastguard Worker 
501*7c356e86SAndroid Build Coastguard Worker 	/* Is this possible? And is this right? */
502*7c356e86SAndroid Build Coastguard Worker 	if (rc == -1)
503*7c356e86SAndroid Build Coastguard Worker 		return (-1);
504*7c356e86SAndroid Build Coastguard Worker 
505*7c356e86SAndroid Build Coastguard Worker 	if (WIFSIGNALED(status))
506*7c356e86SAndroid Build Coastguard Worker 		_exit(ksh_sigmask(WTERMSIG(status)));
507*7c356e86SAndroid Build Coastguard Worker 
508*7c356e86SAndroid Build Coastguard Worker 	_exit(WEXITSTATUS(status));
509*7c356e86SAndroid Build Coastguard Worker }
510*7c356e86SAndroid Build Coastguard Worker 
511*7c356e86SAndroid Build Coastguard Worker static struct temp *templist = NULL;
512*7c356e86SAndroid Build Coastguard Worker 
513*7c356e86SAndroid Build Coastguard Worker static void
add_temp(const char * name)514*7c356e86SAndroid Build Coastguard Worker add_temp(const char *name)
515*7c356e86SAndroid Build Coastguard Worker {
516*7c356e86SAndroid Build Coastguard Worker 	struct temp *tp;
517*7c356e86SAndroid Build Coastguard Worker 
518*7c356e86SAndroid Build Coastguard Worker 	tp = alloc(offsetof(struct temp, tffn[0]) + strlen(name) + 1, APERM);
519*7c356e86SAndroid Build Coastguard Worker 	memcpy(tp->tffn, name, strlen(name) + 1);
520*7c356e86SAndroid Build Coastguard Worker 	tp->next = templist;
521*7c356e86SAndroid Build Coastguard Worker 	templist = tp;
522*7c356e86SAndroid Build Coastguard Worker }
523*7c356e86SAndroid Build Coastguard Worker 
524*7c356e86SAndroid Build Coastguard Worker /* alias of unlink() */
525*7c356e86SAndroid Build Coastguard Worker extern int _std_unlink(const char *);
526*7c356e86SAndroid Build Coastguard Worker 
527*7c356e86SAndroid Build Coastguard Worker /*
528*7c356e86SAndroid Build Coastguard Worker  * Replacement for unlink() of kLIBC not supporting to remove files used by
529*7c356e86SAndroid Build Coastguard Worker  * another processes.
530*7c356e86SAndroid Build Coastguard Worker  */
531*7c356e86SAndroid Build Coastguard Worker int
unlink(const char * name)532*7c356e86SAndroid Build Coastguard Worker unlink(const char *name)
533*7c356e86SAndroid Build Coastguard Worker {
534*7c356e86SAndroid Build Coastguard Worker 	int rc;
535*7c356e86SAndroid Build Coastguard Worker 
536*7c356e86SAndroid Build Coastguard Worker 	rc = _std_unlink(name);
537*7c356e86SAndroid Build Coastguard Worker 	if (rc == -1 && errno != ENOENT)
538*7c356e86SAndroid Build Coastguard Worker 		add_temp(name);
539*7c356e86SAndroid Build Coastguard Worker 
540*7c356e86SAndroid Build Coastguard Worker 	return (rc);
541*7c356e86SAndroid Build Coastguard Worker }
542*7c356e86SAndroid Build Coastguard Worker 
543*7c356e86SAndroid Build Coastguard Worker static void
cleanup_temps(void)544*7c356e86SAndroid Build Coastguard Worker cleanup_temps(void)
545*7c356e86SAndroid Build Coastguard Worker {
546*7c356e86SAndroid Build Coastguard Worker 	struct temp *tp;
547*7c356e86SAndroid Build Coastguard Worker 	struct temp **tpnext;
548*7c356e86SAndroid Build Coastguard Worker 
549*7c356e86SAndroid Build Coastguard Worker 	for (tpnext = &templist, tp = templist; tp; tp = *tpnext) {
550*7c356e86SAndroid Build Coastguard Worker 		if (_std_unlink(tp->tffn) == 0 || errno == ENOENT) {
551*7c356e86SAndroid Build Coastguard Worker 			*tpnext = tp->next;
552*7c356e86SAndroid Build Coastguard Worker 			afree(tp, APERM);
553*7c356e86SAndroid Build Coastguard Worker 		} else {
554*7c356e86SAndroid Build Coastguard Worker 			tpnext = &tp->next;
555*7c356e86SAndroid Build Coastguard Worker 		}
556*7c356e86SAndroid Build Coastguard Worker 	}
557*7c356e86SAndroid Build Coastguard Worker }
558*7c356e86SAndroid Build Coastguard Worker 
559*7c356e86SAndroid Build Coastguard Worker static void
cleanup(void)560*7c356e86SAndroid Build Coastguard Worker cleanup(void)
561*7c356e86SAndroid Build Coastguard Worker {
562*7c356e86SAndroid Build Coastguard Worker 	cleanup_temps();
563*7c356e86SAndroid Build Coastguard Worker }
564*7c356e86SAndroid Build Coastguard Worker 
565*7c356e86SAndroid Build Coastguard Worker int
getdrvwd(char ** cpp,unsigned int drvltr)566*7c356e86SAndroid Build Coastguard Worker getdrvwd(char **cpp, unsigned int drvltr)
567*7c356e86SAndroid Build Coastguard Worker {
568*7c356e86SAndroid Build Coastguard Worker 	PBYTE cp;
569*7c356e86SAndroid Build Coastguard Worker 	ULONG sz;
570*7c356e86SAndroid Build Coastguard Worker 	APIRET rc;
571*7c356e86SAndroid Build Coastguard Worker 	ULONG drvno;
572*7c356e86SAndroid Build Coastguard Worker 
573*7c356e86SAndroid Build Coastguard Worker 	if (DosQuerySysInfo(QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH,
574*7c356e86SAndroid Build Coastguard Worker 	    &sz, sizeof(sz)) != 0) {
575*7c356e86SAndroid Build Coastguard Worker 		errno = EDOOFUS;
576*7c356e86SAndroid Build Coastguard Worker 		return (-1);
577*7c356e86SAndroid Build Coastguard Worker 	}
578*7c356e86SAndroid Build Coastguard Worker 
579*7c356e86SAndroid Build Coastguard Worker 	/* allocate 'X:/' plus sz plus NUL */
580*7c356e86SAndroid Build Coastguard Worker 	checkoktoadd((size_t)sz, (size_t)4);
581*7c356e86SAndroid Build Coastguard Worker 	cp = aresize(*cpp, (size_t)sz + (size_t)4, ATEMP);
582*7c356e86SAndroid Build Coastguard Worker 	cp[0] = ksh_toupper(drvltr);
583*7c356e86SAndroid Build Coastguard Worker 	cp[1] = ':';
584*7c356e86SAndroid Build Coastguard Worker 	cp[2] = '/';
585*7c356e86SAndroid Build Coastguard Worker 	drvno = ksh_numuc(cp[0]) + 1;
586*7c356e86SAndroid Build Coastguard Worker 	/* NUL is part of space within buffer passed */
587*7c356e86SAndroid Build Coastguard Worker 	++sz;
588*7c356e86SAndroid Build Coastguard Worker 	if ((rc = DosQueryCurrentDir(drvno, cp + 3, &sz)) == 0) {
589*7c356e86SAndroid Build Coastguard Worker 		/* success! */
590*7c356e86SAndroid Build Coastguard Worker 		*cpp = cp;
591*7c356e86SAndroid Build Coastguard Worker 		return (0);
592*7c356e86SAndroid Build Coastguard Worker 	}
593*7c356e86SAndroid Build Coastguard Worker 	afree(cp, ATEMP);
594*7c356e86SAndroid Build Coastguard Worker 	*cpp = NULL;
595*7c356e86SAndroid Build Coastguard Worker 	switch (rc) {
596*7c356e86SAndroid Build Coastguard Worker 	case 15: /* invalid drive */
597*7c356e86SAndroid Build Coastguard Worker 		errno = ENOTBLK;
598*7c356e86SAndroid Build Coastguard Worker 		break;
599*7c356e86SAndroid Build Coastguard Worker 	case 26: /* not dos disk */
600*7c356e86SAndroid Build Coastguard Worker 		errno = ENODEV;
601*7c356e86SAndroid Build Coastguard Worker 		break;
602*7c356e86SAndroid Build Coastguard Worker 	case 108: /* drive locked */
603*7c356e86SAndroid Build Coastguard Worker 		errno = EDEADLK;
604*7c356e86SAndroid Build Coastguard Worker 		break;
605*7c356e86SAndroid Build Coastguard Worker 	case 111: /* buffer overflow */
606*7c356e86SAndroid Build Coastguard Worker 		errno = ENAMETOOLONG;
607*7c356e86SAndroid Build Coastguard Worker 		break;
608*7c356e86SAndroid Build Coastguard Worker 	default:
609*7c356e86SAndroid Build Coastguard Worker 		errno = EINVAL;
610*7c356e86SAndroid Build Coastguard Worker 	}
611*7c356e86SAndroid Build Coastguard Worker 	return (-1);
612*7c356e86SAndroid Build Coastguard Worker }
613