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