mostly KNF; afree() can be called with NULL argument
This commit is contained in:
parent
c19b8b104c
commit
de3d3aa5d2
222
os2.c
222
os2.c
|
@ -38,17 +38,15 @@ static void add_temp(const char *);
|
|||
static void cleanup_temps(void);
|
||||
static void cleanup(void);
|
||||
|
||||
#define RPUT(x) \
|
||||
do { \
|
||||
if (new_argc >= new_alloc) { \
|
||||
new_alloc += 20; \
|
||||
new_argv = (const char **)realloc(new_argv, \
|
||||
new_alloc * sizeof(char *));\
|
||||
if (!new_argv) \
|
||||
goto exit_out_of_memory; \
|
||||
} \
|
||||
new_argv[new_argc++] = x; \
|
||||
} while (0)
|
||||
#define RPUT(x) do { \
|
||||
if (new_argc >= new_alloc) { \
|
||||
new_alloc += 20; \
|
||||
if (!(new_argv = realloc(new_argv, \
|
||||
new_alloc * sizeof(char *)))) \
|
||||
goto exit_out_of_memory; \
|
||||
} \
|
||||
new_argv[new_argc++] = (x); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
#define KLIBC_ARG_RESPONSE_EXCLUDE \
|
||||
(__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL)
|
||||
|
@ -61,8 +59,8 @@ response(int *argcp, const char ***argvp)
|
|||
char *line, *l, *p;
|
||||
FILE *f;
|
||||
|
||||
old_argc = *argcp; old_argv = *argvp;
|
||||
|
||||
old_argc = *argcp;
|
||||
old_argv = *argvp;
|
||||
for (i = 1; i < old_argc; ++i)
|
||||
if (old_argv[i] &&
|
||||
!(old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) &&
|
||||
|
@ -70,9 +68,11 @@ response(int *argcp, const char ***argvp)
|
|||
break;
|
||||
|
||||
if (i >= old_argc)
|
||||
return; /* do nothing */
|
||||
/* do nothing */
|
||||
return;
|
||||
|
||||
new_argv = NULL; new_argc = 0;
|
||||
new_argv = NULL;
|
||||
new_argc = 0;
|
||||
for (i = 0; i < old_argc; ++i) {
|
||||
if (i == 0 || !old_argv[i] ||
|
||||
(old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) ||
|
||||
|
@ -86,23 +86,28 @@ response(int *argcp, const char ***argvp)
|
|||
filesize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
line = malloc(filesize + 1 + 1); /* 1 for type, 1 for NUL */
|
||||
if (!line)
|
||||
goto exit_out_of_memory;
|
||||
line = malloc(filesize + /* type */ 1 + /* NUL */ 1);
|
||||
if (!line) {
|
||||
exit_out_of_memory:
|
||||
fputs("Out of memory while reading response file\n", stderr);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_RESPONSE;
|
||||
l = line + 1;
|
||||
while (fgets(l, (filesize + 1) - (l - (line + 1)), f)) {
|
||||
p = strchr(l, '\n');
|
||||
if (p) {
|
||||
/* if a line ends with '\',
|
||||
* then concatenate a next line
|
||||
/*
|
||||
* if a line ends with a backslash,
|
||||
* concatenate with the next line
|
||||
*/
|
||||
if (p > l && p[-1] == '\\') {
|
||||
char *p1;
|
||||
int count = 0;
|
||||
|
||||
for (p1 = p - 1; p1 >= l && *p1 == '\\'; p1--)
|
||||
for (p1 = p - 1; p1 >= l &&
|
||||
*p1 == '\\'; p1--)
|
||||
count++;
|
||||
|
||||
if (count & 1) {
|
||||
|
@ -134,20 +139,22 @@ response(int *argcp, const char ***argvp)
|
|||
}
|
||||
}
|
||||
|
||||
RPUT(NULL); --new_argc;
|
||||
RPUT(NULL);
|
||||
--new_argc;
|
||||
|
||||
*argcp = new_argc; *argvp = new_argv;
|
||||
return;
|
||||
|
||||
exit_out_of_memory:
|
||||
fputs("Out of memory while reading response file\n", stderr);
|
||||
exit(255);
|
||||
*argcp = new_argc;
|
||||
*argvp = new_argv;
|
||||
}
|
||||
|
||||
static void
|
||||
init_extlibpath(void)
|
||||
{
|
||||
const char *vars[] = {"BEGINLIBPATH", "ENDLIBPATH", "LIBPATHSTRICT", NULL};
|
||||
const char *vars[] = {
|
||||
"BEGINLIBPATH",
|
||||
"ENDLIBPATH",
|
||||
"LIBPATHSTRICT",
|
||||
NULL
|
||||
};
|
||||
char val[512];
|
||||
int flag;
|
||||
|
||||
|
@ -155,24 +162,29 @@ init_extlibpath(void)
|
|||
DosQueryExtLIBPATH(val, flag + 1);
|
||||
if (val[0])
|
||||
setenv(vars[flag], val, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert backslashes of environmental variables to forward slahes.
|
||||
* A backslash may be used as an escaped character when do 'echo'. This leads
|
||||
* to an unexpected behavior.
|
||||
* A backslash may be used as an escaped character when doing 'echo'.
|
||||
* This leads to an unexpected behavior.
|
||||
*/
|
||||
static void
|
||||
env_slashify(void)
|
||||
{
|
||||
/*
|
||||
* PATH and TMPDIR are used by OS/2 as well. That is, they may have
|
||||
* backslashes as a directory separator.
|
||||
* PATH and TMPDIR are used by OS/2 as well. That is, they may
|
||||
* have backslashes as a directory separator.
|
||||
* BEGINLIBPATH and ENDLIBPATH are special variables on OS/2.
|
||||
*/
|
||||
const char *var_list[] = {"PATH", "TMPDIR",
|
||||
"BEGINLIBPATH", "ENDLIBPATH", NULL};
|
||||
const char *var_list[] = {
|
||||
"PATH",
|
||||
"TMPDIR",
|
||||
"BEGINLIBPATH",
|
||||
"ENDLIBPATH",
|
||||
NULL
|
||||
};
|
||||
const char **var;
|
||||
char *value;
|
||||
|
||||
|
@ -184,7 +196,8 @@ env_slashify(void)
|
|||
}
|
||||
}
|
||||
|
||||
void os2_init(int *argcp, const char ***argvp)
|
||||
void
|
||||
os2_init(int *argcp, const char ***argvp)
|
||||
{
|
||||
response(argcp, argvp);
|
||||
|
||||
|
@ -201,10 +214,11 @@ void os2_init(int *argcp, const char ***argvp)
|
|||
atexit(cleanup);
|
||||
}
|
||||
|
||||
void setextlibpath(const char *name, const char *val)
|
||||
void
|
||||
setextlibpath(const char *name, const char *val)
|
||||
{
|
||||
int flag;
|
||||
char *p;
|
||||
char *p, *cp;
|
||||
|
||||
if (!strcmp(name, "BEGINLIBPATH"))
|
||||
flag = BEGIN_LIBPATH;
|
||||
|
@ -215,19 +229,19 @@ void setextlibpath(const char *name, const char *val)
|
|||
else
|
||||
return;
|
||||
|
||||
/* Convert slashes to backslashes. */
|
||||
strdupx(p, val, ATEMP);
|
||||
for (val = p; *p; p++) {
|
||||
/* convert slashes to backslashes */
|
||||
strdupx(cp, val, ATEMP);
|
||||
for (p = cp; *p; p++) {
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
}
|
||||
|
||||
DosSetExtLIBPATH(val, flag);
|
||||
DosSetExtLIBPATH(cp, flag);
|
||||
|
||||
afree((char *)val, ATEMP);
|
||||
afree(cp, ATEMP);
|
||||
}
|
||||
|
||||
/* Remove trailing dots. */
|
||||
/* remove trailing dots */
|
||||
static char *
|
||||
remove_trailing_dots(char *name)
|
||||
{
|
||||
|
@ -239,45 +253,45 @@ remove_trailing_dots(char *name)
|
|||
if (*p != '.' && *p != '/' && *p != '\\' && *p != ':')
|
||||
p[1] = '\0';
|
||||
|
||||
return name;
|
||||
return (name);
|
||||
}
|
||||
|
||||
#define REMOVE_TRAILING_DOTS(name) \
|
||||
remove_trailing_dots(strcpy(alloca(strlen(name) + 1), name))
|
||||
|
||||
/* Alias of stat() */
|
||||
int _std_stat(const char *, struct stat *);
|
||||
/* alias of stat() */
|
||||
extern int _std_stat(const char *, struct stat *);
|
||||
|
||||
/* Replacement for stat() of kLIBC which fails if there are trailing dots */
|
||||
/* replacement for stat() of kLIBC which fails if there are trailing dots */
|
||||
int
|
||||
stat(const char *name, struct stat *buffer)
|
||||
{
|
||||
return _std_stat(REMOVE_TRAILING_DOTS(name), buffer);
|
||||
return (_std_stat(REMOVE_TRAILING_DOTS(name), buffer));
|
||||
}
|
||||
|
||||
/* Alias of access() */
|
||||
int _std_access(const char *, int);
|
||||
/* alias of access() */
|
||||
extern int _std_access(const char *, int);
|
||||
|
||||
/* Replacement for access() of kLIBC which fails if there are trailing dots */
|
||||
/* replacement for access() of kLIBC which fails if there are trailing dots */
|
||||
int
|
||||
access(const char *name, int mode)
|
||||
{
|
||||
/*
|
||||
* On OS/2 kLIBC, X_OK is set only for executable files. This prevent
|
||||
* scripts from being executed.
|
||||
* On OS/2 kLIBC, X_OK is set only for executable files.
|
||||
* This prevents scripts from being executed.
|
||||
*/
|
||||
if (mode & X_OK)
|
||||
mode = (mode & ~X_OK) | R_OK;
|
||||
|
||||
return _std_access(REMOVE_TRAILING_DOTS(name), mode);
|
||||
return (_std_access(REMOVE_TRAILING_DOTS(name), mode));
|
||||
}
|
||||
|
||||
#define MAX_X_SUFFIX_LEN 4
|
||||
|
||||
static const char *x_suffix_list[] =
|
||||
{"", ".ksh", ".exe", ".sh", ".cmd", ".com", ".bat", NULL};
|
||||
{ "", ".ksh", ".exe", ".sh", ".cmd", ".com", ".bat", NULL };
|
||||
|
||||
/* Call fn() by appending executable extensions. */
|
||||
/* call fn() by appending executable extensions */
|
||||
static int
|
||||
access_stat_ex(int (*fn)(), const char *name, void *arg)
|
||||
{
|
||||
|
@ -285,7 +299,7 @@ access_stat_ex(int (*fn)(), const char *name, void *arg)
|
|||
const char **x_suffix;
|
||||
int rc = -1;
|
||||
|
||||
/* Otherwise, try to append executable suffixes */
|
||||
/* otherwise, try to append executable suffixes */
|
||||
x_name = alloc(strlen(name) + MAX_X_SUFFIX_LEN + 1, ATEMP);
|
||||
|
||||
for (x_suffix = x_suffix_list; rc && *x_suffix; x_suffix++) {
|
||||
|
@ -297,21 +311,21 @@ access_stat_ex(int (*fn)(), const char *name, void *arg)
|
|||
|
||||
afree(x_name, ATEMP);
|
||||
|
||||
return rc;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/* access()/search_access() version */
|
||||
int
|
||||
access_ex(int (*fn)(const char *, int), const char *name, int mode)
|
||||
{
|
||||
return access_stat_ex(fn, name, (void *)mode);
|
||||
return (access_stat_ex(fn, name, (void *)mode));
|
||||
}
|
||||
|
||||
/* stat() version */
|
||||
int
|
||||
stat_ex(const char *name, struct stat *buffer)
|
||||
{
|
||||
return access_stat_ex(stat, name, buffer);
|
||||
return (access_stat_ex(stat, name, buffer));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -320,11 +334,11 @@ test_exec_exist(const char *name, char *real_name)
|
|||
struct stat sb;
|
||||
|
||||
if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode))
|
||||
return -1;
|
||||
return (-1);
|
||||
|
||||
strcpy(real_name, name);
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -336,61 +350,60 @@ real_exec_name(const char *name)
|
|||
if (access_stat_ex(test_exec_exist, real_name, x_name) != -1)
|
||||
strdupx(real_name, x_name, ATEMP);
|
||||
|
||||
return real_name;
|
||||
return (real_name);
|
||||
}
|
||||
/* OS/2 can process a command line up to 32K. */
|
||||
|
||||
/* OS/2 can process a command line up to 32 KiB */
|
||||
#define MAX_CMD_LINE_LEN 32768
|
||||
|
||||
/* Make a response file to pass a very long command line. */
|
||||
/* make a response file to pass a very long command line */
|
||||
static char *
|
||||
make_response_file(char * const *argv)
|
||||
{
|
||||
char rsp_name_arg[] = "@mksh-rsp-XXXXXX";
|
||||
char rsp_name_arg[] = "@mksh-rsp-XXXXXX";
|
||||
char *rsp_name = &rsp_name_arg[1];
|
||||
int arg_len = 0;
|
||||
int i;
|
||||
int arg_len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
arg_len += strlen(argv[i]) + 1;
|
||||
|
||||
/*
|
||||
* If a length of command line is longer than MAX_CMD_LINE_LEN, then use
|
||||
* a response file. OS/2 cannot process a command line longer than 32K.
|
||||
* Of course, a response file cannot be recognized by a normal OS/2
|
||||
* program, that is, neither non-EMX or non-kLIBC. But it cannot accept
|
||||
* a command line longer than 32K in itself. So using a response file
|
||||
* in this case, is an acceptable solution.
|
||||
* If a length of command line is longer than MAX_CMD_LINE_LEN, then
|
||||
* use a response file. OS/2 cannot process a command line longer
|
||||
* than 32K. Of course, a response file cannot be recognized by a
|
||||
* normal OS/2 program, that is, neither non-EMX or non-kLIBC. But
|
||||
* it cannot accept a command line longer than 32K in itself. So
|
||||
* using a response file in this case, is an acceptable solution.
|
||||
*/
|
||||
if (arg_len > MAX_CMD_LINE_LEN) {
|
||||
int fd;
|
||||
char *result;
|
||||
|
||||
if ((fd = mkstemp(rsp_name)) == -1)
|
||||
return NULL;
|
||||
return (NULL);
|
||||
|
||||
/* write all the arguments except a 0th program name */
|
||||
for (i = 1; argv[i]; i++) {
|
||||
write(fd, argv[i], strlen(argv[i]));
|
||||
write(fd, "\n", 1 );
|
||||
write(fd, "\n", 1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
add_temp(rsp_name);
|
||||
|
||||
strdupx(result, rsp_name_arg, ATEMP);
|
||||
|
||||
return result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Alias of execve() */
|
||||
int _std_execve(const char *, char * const *, char * const *);
|
||||
/* alias of execve() */
|
||||
extern int _std_execve(const char *, char * const *, char * const *);
|
||||
|
||||
/* Replacement for execve() of kLIBC */
|
||||
int execve(const char *name, char * const *argv, char * const *envp)
|
||||
/* replacement for execve() of kLIBC */
|
||||
int
|
||||
execve(const char *name, char * const *argv, char * const *envp)
|
||||
{
|
||||
const char *exec_name;
|
||||
FILE *fp;
|
||||
|
@ -409,16 +422,16 @@ int execve(const char *name, char * const *argv, char * const *envp)
|
|||
exec_name = search_path(name, path, X_OK, NULL);
|
||||
if (!exec_name) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
/*-
|
||||
* kLIBC execve() has problems when executing scripts.
|
||||
* 1. it fails to execute a script if a directory whose name
|
||||
* is same as an interpreter exists in a current directory.
|
||||
* is same as an interpreter exists in a current directory.
|
||||
* 2. it fails to execute a script not starting with sharpbang.
|
||||
* 3. it fails to execute a batch file if COMSPEC is set to a shell
|
||||
* incompatible with cmd.exe, such as /bin/sh.
|
||||
* incompatible with cmd.exe, such as /bin/sh.
|
||||
* And ksh process scripts more well, so let ksh process scripts.
|
||||
*/
|
||||
errno = 0;
|
||||
|
@ -438,7 +451,7 @@ int execve(const char *name, char * const *argv, char * const *envp)
|
|||
errno = ENOEXEC;
|
||||
|
||||
if (errno == ENOEXEC)
|
||||
return -1;
|
||||
return (-1);
|
||||
|
||||
rsp_name_arg = make_response_file(argv);
|
||||
|
||||
|
@ -452,16 +465,15 @@ int execve(const char *name, char * const *argv, char * const *envp)
|
|||
|
||||
pid = spawnve(P_NOWAIT, exec_name, argv, envp);
|
||||
|
||||
if (rsp_name_arg)
|
||||
afree(rsp_name_arg, ATEMP);
|
||||
afree(rsp_name_arg, ATEMP);
|
||||
|
||||
if (pid == -1) {
|
||||
cleanup_temps();
|
||||
|
||||
return -1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Close all opened handles */
|
||||
/* close all opened handles */
|
||||
for (fd = 0; fd < NUFILE; fd++) {
|
||||
if (fcntl(fd, F_GETFD) == -1)
|
||||
continue;
|
||||
|
@ -470,13 +482,13 @@ int execve(const char *name, char * const *argv, char * const *envp)
|
|||
}
|
||||
|
||||
while ((rc = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
|
||||
/* NOTHING */;
|
||||
/* nothing */;
|
||||
|
||||
cleanup_temps();
|
||||
|
||||
/* Is this possible ? And is this right ? */
|
||||
/* Is this possible? And is this right? */
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
return (-1);
|
||||
|
||||
if (WIFSIGNALED(status))
|
||||
_exit(ksh_sigmask(WTERMSIG(status)));
|
||||
|
@ -486,7 +498,8 @@ int execve(const char *name, char * const *argv, char * const *envp)
|
|||
|
||||
static struct temp *templist = NULL;
|
||||
|
||||
static void add_temp(const char *name)
|
||||
static void
|
||||
add_temp(const char *name)
|
||||
{
|
||||
struct temp *tp;
|
||||
|
||||
|
@ -496,14 +509,15 @@ static void add_temp(const char *name)
|
|||
templist = tp;
|
||||
}
|
||||
|
||||
/* Alias of unlink() */
|
||||
int _std_unlink(const char *);
|
||||
/* alias of unlink() */
|
||||
extern int _std_unlink(const char *);
|
||||
|
||||
/*
|
||||
* Replacement for unlink() of kLIBC not supporting to remove files used by
|
||||
* another processes.
|
||||
*/
|
||||
int unlink(const char *name)
|
||||
int
|
||||
unlink(const char *name)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -511,7 +525,7 @@ int unlink(const char *name)
|
|||
if (rc == -1 && errno != ENOENT)
|
||||
add_temp(name);
|
||||
|
||||
return rc;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue