mostly KNF; afree() can be called with NULL argument

This commit is contained in:
mirabilos 2017-03-25 23:56:09 +01:00
parent c19b8b104c
commit de3d3aa5d2

222
os2.c
View File

@ -38,17 +38,15 @@ static void add_temp(const char *);
static void cleanup_temps(void); static void cleanup_temps(void);
static void cleanup(void); static void cleanup(void);
#define RPUT(x) \ #define RPUT(x) do { \
do { \ if (new_argc >= new_alloc) { \
if (new_argc >= new_alloc) { \ new_alloc += 20; \
new_alloc += 20; \ if (!(new_argv = realloc(new_argv, \
new_argv = (const char **)realloc(new_argv, \ new_alloc * sizeof(char *)))) \
new_alloc * sizeof(char *));\ goto exit_out_of_memory; \
if (!new_argv) \ } \
goto exit_out_of_memory; \ new_argv[new_argc++] = (x); \
} \ } while (/* CONSTCOND */ 0)
new_argv[new_argc++] = x; \
} while (0)
#define KLIBC_ARG_RESPONSE_EXCLUDE \ #define KLIBC_ARG_RESPONSE_EXCLUDE \
(__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL) (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL)
@ -61,8 +59,8 @@ response(int *argcp, const char ***argvp)
char *line, *l, *p; char *line, *l, *p;
FILE *f; FILE *f;
old_argc = *argcp; old_argv = *argvp; old_argc = *argcp;
old_argv = *argvp;
for (i = 1; i < old_argc; ++i) for (i = 1; i < old_argc; ++i)
if (old_argv[i] && if (old_argv[i] &&
!(old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) && !(old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) &&
@ -70,9 +68,11 @@ response(int *argcp, const char ***argvp)
break; break;
if (i >= old_argc) 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) { for (i = 0; i < old_argc; ++i) {
if (i == 0 || !old_argv[i] || if (i == 0 || !old_argv[i] ||
(old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) || (old_argv[i][-1] & KLIBC_ARG_RESPONSE_EXCLUDE) ||
@ -86,23 +86,28 @@ response(int *argcp, const char ***argvp)
filesize = ftell(f); filesize = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
line = malloc(filesize + 1 + 1); /* 1 for type, 1 for NUL */ line = malloc(filesize + /* type */ 1 + /* NUL */ 1);
if (!line) if (!line) {
goto exit_out_of_memory; exit_out_of_memory:
fputs("Out of memory while reading response file\n", stderr);
exit(255);
}
line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_RESPONSE; line[0] = __KLIBC_ARG_NONZERO | __KLIBC_ARG_RESPONSE;
l = line + 1; l = line + 1;
while (fgets(l, (filesize + 1) - (l - (line + 1)), f)) { while (fgets(l, (filesize + 1) - (l - (line + 1)), f)) {
p = strchr(l, '\n'); p = strchr(l, '\n');
if (p) { 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] == '\\') { if (p > l && p[-1] == '\\') {
char *p1; char *p1;
int count = 0; int count = 0;
for (p1 = p - 1; p1 >= l && *p1 == '\\'; p1--) for (p1 = p - 1; p1 >= l &&
*p1 == '\\'; p1--)
count++; count++;
if (count & 1) { 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; *argcp = new_argc;
return; *argvp = new_argv;
exit_out_of_memory:
fputs("Out of memory while reading response file\n", stderr);
exit(255);
} }
static void static void
init_extlibpath(void) init_extlibpath(void)
{ {
const char *vars[] = {"BEGINLIBPATH", "ENDLIBPATH", "LIBPATHSTRICT", NULL}; const char *vars[] = {
"BEGINLIBPATH",
"ENDLIBPATH",
"LIBPATHSTRICT",
NULL
};
char val[512]; char val[512];
int flag; int flag;
@ -155,24 +162,29 @@ init_extlibpath(void)
DosQueryExtLIBPATH(val, flag + 1); DosQueryExtLIBPATH(val, flag + 1);
if (val[0]) if (val[0])
setenv(vars[flag], val, 1); setenv(vars[flag], val, 1);
} }
} }
/* /*
* Convert backslashes of environmental variables to forward slahes. * Convert backslashes of environmental variables to forward slahes.
* A backslash may be used as an escaped character when do 'echo'. This leads * A backslash may be used as an escaped character when doing 'echo'.
* to an unexpected behavior. * This leads to an unexpected behavior.
*/ */
static void static void
env_slashify(void) env_slashify(void)
{ {
/* /*
* PATH and TMPDIR are used by OS/2 as well. That is, they may have * PATH and TMPDIR are used by OS/2 as well. That is, they may
* backslashes as a directory separator. * have backslashes as a directory separator.
* BEGINLIBPATH and ENDLIBPATH are special variables on OS/2. * BEGINLIBPATH and ENDLIBPATH are special variables on OS/2.
*/ */
const char *var_list[] = {"PATH", "TMPDIR", const char *var_list[] = {
"BEGINLIBPATH", "ENDLIBPATH", NULL}; "PATH",
"TMPDIR",
"BEGINLIBPATH",
"ENDLIBPATH",
NULL
};
const char **var; const char **var;
char *value; 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); response(argcp, argvp);
@ -201,10 +214,11 @@ void os2_init(int *argcp, const char ***argvp)
atexit(cleanup); atexit(cleanup);
} }
void setextlibpath(const char *name, const char *val) void
setextlibpath(const char *name, const char *val)
{ {
int flag; int flag;
char *p; char *p, *cp;
if (!strcmp(name, "BEGINLIBPATH")) if (!strcmp(name, "BEGINLIBPATH"))
flag = BEGIN_LIBPATH; flag = BEGIN_LIBPATH;
@ -215,19 +229,19 @@ void setextlibpath(const char *name, const char *val)
else else
return; return;
/* Convert slashes to backslashes. */ /* convert slashes to backslashes */
strdupx(p, val, ATEMP); strdupx(cp, val, ATEMP);
for (val = p; *p; p++) { for (p = cp; *p; p++) {
if (*p == '/') if (*p == '/')
*p = '\\'; *p = '\\';
} }
DosSetExtLIBPATH(val, flag); DosSetExtLIBPATH(cp, flag);
afree((char *)val, ATEMP); afree(cp, ATEMP);
} }
/* Remove trailing dots. */ /* remove trailing dots */
static char * static char *
remove_trailing_dots(char *name) remove_trailing_dots(char *name)
{ {
@ -239,45 +253,45 @@ remove_trailing_dots(char *name)
if (*p != '.' && *p != '/' && *p != '\\' && *p != ':') if (*p != '.' && *p != '/' && *p != '\\' && *p != ':')
p[1] = '\0'; p[1] = '\0';
return name; return (name);
} }
#define REMOVE_TRAILING_DOTS(name) \ #define REMOVE_TRAILING_DOTS(name) \
remove_trailing_dots(strcpy(alloca(strlen(name) + 1), name)) remove_trailing_dots(strcpy(alloca(strlen(name) + 1), name))
/* Alias of stat() */ /* alias of stat() */
int _std_stat(const char *, struct 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 int
stat(const char *name, struct stat *buffer) 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() */ /* alias of access() */
int _std_access(const char *, int); 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 int
access(const char *name, int mode) access(const char *name, int mode)
{ {
/* /*
* On OS/2 kLIBC, X_OK is set only for executable files. This prevent * On OS/2 kLIBC, X_OK is set only for executable files.
* scripts from being executed. * This prevents scripts from being executed.
*/ */
if (mode & X_OK) if (mode & X_OK)
mode = (mode & ~X_OK) | R_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 #define MAX_X_SUFFIX_LEN 4
static const char *x_suffix_list[] = 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 static int
access_stat_ex(int (*fn)(), const char *name, void *arg) 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; const char **x_suffix;
int rc = -1; 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); x_name = alloc(strlen(name) + MAX_X_SUFFIX_LEN + 1, ATEMP);
for (x_suffix = x_suffix_list; rc && *x_suffix; x_suffix++) { 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); afree(x_name, ATEMP);
return rc; return (rc);
} }
/* access()/search_access() version */ /* access()/search_access() version */
int int
access_ex(int (*fn)(const char *, int), const char *name, int mode) 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 */ /* stat() version */
int int
stat_ex(const char *name, struct stat *buffer) stat_ex(const char *name, struct stat *buffer)
{ {
return access_stat_ex(stat, name, buffer); return (access_stat_ex(stat, name, buffer));
} }
static int static int
@ -320,11 +334,11 @@ test_exec_exist(const char *name, char *real_name)
struct stat sb; struct stat sb;
if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode)) if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode))
return -1; return (-1);
strcpy(real_name, name); strcpy(real_name, name);
return 0; return (0);
} }
const char * const char *
@ -336,61 +350,60 @@ real_exec_name(const char *name)
if (access_stat_ex(test_exec_exist, real_name, x_name) != -1) if (access_stat_ex(test_exec_exist, real_name, x_name) != -1)
strdupx(real_name, x_name, ATEMP); 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 #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 * static char *
make_response_file(char * const *argv) 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]; char *rsp_name = &rsp_name_arg[1];
int arg_len = 0; int arg_len = 0;
int i; int i;
for (i = 0; argv[i]; i++) for (i = 0; argv[i]; i++)
arg_len += strlen(argv[i]) + 1; arg_len += strlen(argv[i]) + 1;
/* /*
* If a length of command line is longer than MAX_CMD_LINE_LEN, then use * If a length of command line is longer than MAX_CMD_LINE_LEN, then
* a response file. OS/2 cannot process a command line longer than 32K. * use a response file. OS/2 cannot process a command line longer
* Of course, a response file cannot be recognized by a normal OS/2 * than 32K. Of course, a response file cannot be recognized by a
* program, that is, neither non-EMX or non-kLIBC. But it cannot accept * normal OS/2 program, that is, neither non-EMX or non-kLIBC. But
* a command line longer than 32K in itself. So using a response file * it cannot accept a command line longer than 32K in itself. So
* in this case, is an acceptable solution. * using a response file in this case, is an acceptable solution.
*/ */
if (arg_len > MAX_CMD_LINE_LEN) { if (arg_len > MAX_CMD_LINE_LEN) {
int fd; int fd;
char *result; char *result;
if ((fd = mkstemp(rsp_name)) == -1) if ((fd = mkstemp(rsp_name)) == -1)
return NULL; return (NULL);
/* write all the arguments except a 0th program name */ /* write all the arguments except a 0th program name */
for (i = 1; argv[i]; i++) { for (i = 1; argv[i]; i++) {
write(fd, argv[i], strlen(argv[i])); write(fd, argv[i], strlen(argv[i]));
write(fd, "\n", 1 ); write(fd, "\n", 1);
} }
close(fd); close(fd);
add_temp(rsp_name); add_temp(rsp_name);
strdupx(result, rsp_name_arg, ATEMP); strdupx(result, rsp_name_arg, ATEMP);
return (result);
return result;
} }
return NULL; return (NULL);
} }
/* Alias of execve() */ /* alias of execve() */
int _std_execve(const char *, char * const *, char * const *); extern int _std_execve(const char *, char * const *, char * const *);
/* Replacement for execve() of kLIBC */ /* replacement for execve() of kLIBC */
int execve(const char *name, char * const *argv, char * const *envp) int
execve(const char *name, char * const *argv, char * const *envp)
{ {
const char *exec_name; const char *exec_name;
FILE *fp; 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); exec_name = search_path(name, path, X_OK, NULL);
if (!exec_name) { if (!exec_name) {
errno = ENOENT; errno = ENOENT;
return -1; return (-1);
} }
/* /*-
* kLIBC execve() has problems when executing scripts. * kLIBC execve() has problems when executing scripts.
* 1. it fails to execute a script if a directory whose name * 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. * 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 * 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. * And ksh process scripts more well, so let ksh process scripts.
*/ */
errno = 0; errno = 0;
@ -438,7 +451,7 @@ int execve(const char *name, char * const *argv, char * const *envp)
errno = ENOEXEC; errno = ENOEXEC;
if (errno == ENOEXEC) if (errno == ENOEXEC)
return -1; return (-1);
rsp_name_arg = make_response_file(argv); 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); 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) { if (pid == -1) {
cleanup_temps(); cleanup_temps();
return -1; return (-1);
} }
/* Close all opened handles */ /* close all opened handles */
for (fd = 0; fd < NUFILE; fd++) { for (fd = 0; fd < NUFILE; fd++) {
if (fcntl(fd, F_GETFD) == -1) if (fcntl(fd, F_GETFD) == -1)
continue; 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) while ((rc = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
/* NOTHING */; /* nothing */;
cleanup_temps(); cleanup_temps();
/* Is this possible ? And is this right ? */ /* Is this possible? And is this right? */
if (rc == -1) if (rc == -1)
return -1; return (-1);
if (WIFSIGNALED(status)) if (WIFSIGNALED(status))
_exit(ksh_sigmask(WTERMSIG(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 struct temp *templist = NULL;
static void add_temp(const char *name) static void
add_temp(const char *name)
{ {
struct temp *tp; struct temp *tp;
@ -496,14 +509,15 @@ static void add_temp(const char *name)
templist = tp; templist = tp;
} }
/* Alias of unlink() */ /* alias of unlink() */
int _std_unlink(const char *); extern int _std_unlink(const char *);
/* /*
* Replacement for unlink() of kLIBC not supporting to remove files used by * Replacement for unlink() of kLIBC not supporting to remove files used by
* another processes. * another processes.
*/ */
int unlink(const char *name) int
unlink(const char *name)
{ {
int rc; int rc;
@ -511,7 +525,7 @@ int unlink(const char *name)
if (rc == -1 && errno != ENOENT) if (rc == -1 && errno != ENOENT)
add_temp(name); add_temp(name);
return rc; return (rc);
} }
static void static void