|
|
@@ -47,8 +47,8 @@
|
|
|
# define UNUSED(arg) (void) arg
|
|
|
|
|
|
enum err {
|
|
|
+ ERR_GENERAL_ERROR = -1,
|
|
|
ERR_OK = 0,
|
|
|
- ERR_GENERAL_ERROR,
|
|
|
ERR_NOT_INT,
|
|
|
ERR_TOO_BIG,
|
|
|
ERR_NULL_ARG,
|
|
|
@@ -76,8 +76,8 @@ enum err {
|
|
|
};
|
|
|
|
|
|
const char *err_to_name[] = {
|
|
|
- "ERR_OK",
|
|
|
"ERR_GENERAL_ERROR",
|
|
|
+ "ERR_OK",
|
|
|
"ERR_NOT_INT",
|
|
|
"ERR_TOO_BIG",
|
|
|
"ERR_NULL_ARG",
|
|
|
@@ -122,6 +122,8 @@ typedef unsigned char u8;
|
|
|
|
|
|
/* ------------------------------ END INT DEF ------------------------------ */
|
|
|
|
|
|
+extern char **environ;
|
|
|
+
|
|
|
void *malloc(u64 size);
|
|
|
void *realloc(void *ptr, u64 new_size);
|
|
|
void free(void *ptr);
|
|
|
@@ -131,15 +133,19 @@ char *getenv(const char *name);
|
|
|
void abort(void);
|
|
|
void exit(int exit_code);
|
|
|
|
|
|
-int execve(const char *path, char *const argv[],
|
|
|
- char *const envp[]);
|
|
|
-
|
|
|
+int execv(const char *path, char *const argv[]);
|
|
|
+int execve(const char *path, char *const argv[], char *const envp[]);
|
|
|
+int execvpe(const char *path, char *const argv[], char *const envp[]);
|
|
|
|
|
|
int fork(void);
|
|
|
# ifndef WIFEXITED
|
|
|
# error "Must import <sys/wait.h> before lib.h!"
|
|
|
# endif
|
|
|
|
|
|
+# if (! defined(_STDARG_H)) || (! defined(va_start))
|
|
|
+# error "Must import <stdarg.h> before lib.h!"
|
|
|
+# endif
|
|
|
+
|
|
|
/* ----------------------------- START LIB DEF ----------------------------- */
|
|
|
|
|
|
# define TODO(msg) \
|
|
|
@@ -203,9 +209,11 @@ int fork(void);
|
|
|
|
|
|
# define CAST(Type, Var) ((Type) (Var))
|
|
|
|
|
|
-# define LIB_FREE lib_free
|
|
|
+/*# define LIB_FREE lib_free*/
|
|
|
+# define LIB_FREE(Ptr) if ( (Ptr) != NULL ) { free((void *) (Ptr)); }
|
|
|
|
|
|
void lib_free(const void *ptr);
|
|
|
+const char *temp_sprintf(const char *fmt, ...);
|
|
|
|
|
|
# if defined(IMP) || defined(IMP_LIB)
|
|
|
|
|
|
@@ -217,6 +225,22 @@ lib_free(const void *ptr)
|
|
|
free((void *)ptr);
|
|
|
}
|
|
|
|
|
|
+const char *
|
|
|
+temp_sprintf(const char *fmt, ...)
|
|
|
+{
|
|
|
+ static char buf[1024] = {0};
|
|
|
+
|
|
|
+ {
|
|
|
+ va_list ap;
|
|
|
+ va_start(ap, fmt);
|
|
|
+ vsnprintf(buf, 1024, fmt, ap);
|
|
|
+ va_end(ap);
|
|
|
+ }
|
|
|
+ buf[1023] = 0;
|
|
|
+
|
|
|
+ return (const char *) buf;
|
|
|
+}
|
|
|
+
|
|
|
# endif /* defined(IMP) || defined(IMP_LIB) */
|
|
|
|
|
|
/* ------------------------------ END LIB DEF ------------------------------ */
|
|
|
@@ -575,35 +599,25 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
|
|
|
(VarI) < (Da).size; \
|
|
|
++(VarI) )
|
|
|
|
|
|
-# define DA_APPEND(da, val, err_var) \
|
|
|
+# define DA_APPEND(Da, Val, OutErr) \
|
|
|
do { \
|
|
|
- if ( err_var != NULL ) { \
|
|
|
- if ( *err_var != ERR_OK ) { \
|
|
|
- break; \
|
|
|
- } \
|
|
|
- } \
|
|
|
- if ( (da).size + 1 >= (da).cap ) { \
|
|
|
- (da).cap *= 2; \
|
|
|
- (da).data = realloc((da).data, (da).cap); \
|
|
|
- if ( (da).data == NULL ) { \
|
|
|
- LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_REALLOC); \
|
|
|
+ if ( (OutErr) != NULL ) { \
|
|
|
+ if ( *(OutErr) != ERR_OK ) { \
|
|
|
break; \
|
|
|
} \
|
|
|
} \
|
|
|
- if ( (da).data == NULL ) { \
|
|
|
- if ( (da).cap == 0 ) { \
|
|
|
- (da).cap = 32; \
|
|
|
- (da).size = 0; \
|
|
|
- } \
|
|
|
- (da).data = malloc(sizeof(*(da).data) * (da).cap); \
|
|
|
- if ( (da).data == NULL ) { \
|
|
|
- LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_ALLOC); \
|
|
|
+ if ( (Da).size + 1 >= (Da).cap ) { \
|
|
|
+ (Da).cap = (CAST(u64, ((Da).cap == 0) * 32) + (Da).cap) * 2; \
|
|
|
+ (Da).data = realloc((Da).data, sizeof(*(Da).data) * (Da).cap); \
|
|
|
+ if ( (Da).data == NULL ) { \
|
|
|
+ LIB_SET_IF_NOT_NULL((OutErr), ERR_FAILED_REALLOC); \
|
|
|
break; \
|
|
|
} \
|
|
|
- memset((da).data, 0, sizeof(*(da).data) * (da).cap); \
|
|
|
+ memset((Da).data + (Da).size, 0, \
|
|
|
+ sizeof(*(Da).data) * ((Da).cap - (Da).size)); \
|
|
|
} \
|
|
|
- (da).data[(da).size++] = (val); \
|
|
|
- LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
|
|
|
+ (Da).data[(Da).size++] = (Val); \
|
|
|
+ LIB_SET_IF_NOT_NULL((OutErr), ERR_OK); \
|
|
|
} while(0)
|
|
|
|
|
|
# define DA_APPEND_DATA(Da, Val, ItemNum, ErrVar) \
|
|
|
@@ -1211,6 +1225,7 @@ bool path_touch(struct path path, int (*open)(const char *, int),
|
|
|
enum err *out_err);
|
|
|
|
|
|
|
|
|
+
|
|
|
struct file {
|
|
|
u8 *data;
|
|
|
u64 size;
|
|
|
@@ -1220,6 +1235,11 @@ struct file path_file_read_all(const struct path *path, enum err *out_err);
|
|
|
enum err path_file_save(const struct path *path, const struct file *file,
|
|
|
enum err *out_err);
|
|
|
|
|
|
+# if defined(IMP_PATH) || defined(IMP)
|
|
|
+
|
|
|
+
|
|
|
+# endif /* defined(IMP_PATH) || defined(IMP) */
|
|
|
+
|
|
|
# endif /* defined(WANT_PATH) || defined(WANT_ALL) */
|
|
|
|
|
|
/* ----------------------------- END PATH DEF ------------------------------ */
|
|
|
@@ -1938,24 +1958,56 @@ tokenizer_is_str_lit(struct tokenizer *tkn, struct str str)
|
|
|
|
|
|
# if defined(WANT_CMD) || defined(WANT_ALL)
|
|
|
|
|
|
+# ifdef unix
|
|
|
+# define CC "cc"
|
|
|
+# else
|
|
|
+# error "No CC for this platform"
|
|
|
+# endif
|
|
|
+
|
|
|
+struct procs {
|
|
|
+ i32 *data;
|
|
|
+ u64 size;
|
|
|
+ u64 cap;
|
|
|
+};
|
|
|
+
|
|
|
+enum err procs_wait(struct procs *_r_ procs, enum err *_r_ out_err);
|
|
|
+
|
|
|
struct cmd {
|
|
|
- char *exe;
|
|
|
struct {
|
|
|
char **data;
|
|
|
u64 size;
|
|
|
u64 cap;
|
|
|
} args;
|
|
|
+ struct {
|
|
|
+ char **data;
|
|
|
+ u64 size;
|
|
|
+ u64 cap;
|
|
|
+ } envs;
|
|
|
};
|
|
|
|
|
|
-# define cmd_create_ns(Exe, OutErr) \
|
|
|
+struct __cmd_create_args {
|
|
|
+ bool copy_env;
|
|
|
+};
|
|
|
+# define cmd_create(Exe, OutErr, ...) \
|
|
|
+ _cmd_create( \
|
|
|
+ (Exe), \
|
|
|
+ (struct __cmd_create_args) { \
|
|
|
+ .copy_env=true, \
|
|
|
+ __VA_ARGS__ \
|
|
|
+ }, \
|
|
|
+ (OutErr) \
|
|
|
+ )
|
|
|
+# define cmd_create_ns(Exe, OutErr, ...) \
|
|
|
cmd_create( \
|
|
|
- (struct str) { \
|
|
|
+ ((struct str) { \
|
|
|
.data=(Exe), \
|
|
|
.size=cstr_len_max((Exe), STR_SIZE_LIMIT, NULL, (OutErr)) \
|
|
|
- }, \
|
|
|
- (OutErr) \
|
|
|
+ }), \
|
|
|
+ (OutErr), \
|
|
|
+ __VA_ARGS__ \
|
|
|
)
|
|
|
-struct cmd cmd_create(struct str exe, enum err *_r_ out_err);
|
|
|
+struct cmd _cmd_create(struct str exe, struct __cmd_create_args args,
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
|
# define cmd_set_exe_ns(Cmd, Exe, OutErr) \
|
|
|
cmd_set_exe( \
|
|
|
@@ -1981,28 +2033,102 @@ enum err cmd_set_exe(struct cmd *_r_ cmd, struct str exe,
|
|
|
enum err cmd_append_arg(struct cmd *_r_ cmd, struct str arg,
|
|
|
enum err *_r_ out_err);
|
|
|
|
|
|
-enum err cmd_exec(struct cmd *_r_ cmd, enum err *_r_ out_err);
|
|
|
+# define cmd_append_args_cstrs(Cmd, OutErr, Arg, ...) \
|
|
|
+ _cmd_append_args_cstrs( \
|
|
|
+ (Cmd), \
|
|
|
+ (const char *[]){(Arg), __VA_ARGS__, NULL}, \
|
|
|
+ (OutErr) \
|
|
|
+ )
|
|
|
+enum err _cmd_append_args_cstrs(struct cmd *_r_ cmd, const char **args,
|
|
|
+ enum err *_r_ out_err);
|
|
|
+
|
|
|
+# define cmd_append_env_ns(Cmd, Arg, OutErr) \
|
|
|
+ cmd_append_env( \
|
|
|
+ (Cmd), \
|
|
|
+ (struct str) { \
|
|
|
+ .data=(Arg), \
|
|
|
+ .size=cstr_len_max((Arg), STR_SIZE_LIMIT, NULL, (OutErr)) \
|
|
|
+ }, \
|
|
|
+ (OutErr) \
|
|
|
+ )
|
|
|
+enum err cmd_append_env(struct cmd *_r_ cmd, struct str env,
|
|
|
+ enum err *_r_ out_err);
|
|
|
+
|
|
|
+struct __cmd_exec_args {
|
|
|
+ struct procs *procs;
|
|
|
+ bool reset;
|
|
|
+ bool search_path;
|
|
|
+};
|
|
|
+# define cmd_exec(Cmd, OutErr, ...) \
|
|
|
+ _cmd_exec( \
|
|
|
+ (Cmd), \
|
|
|
+ (struct __cmd_exec_args) { \
|
|
|
+ .reset=true, \
|
|
|
+ .search_path=true, \
|
|
|
+ __VA_ARGS__ \
|
|
|
+ }, \
|
|
|
+ (OutErr) \
|
|
|
+ )
|
|
|
+enum err _cmd_exec(struct cmd *_r_ cmd, struct __cmd_exec_args args,
|
|
|
+ enum err *_r_ out_err);
|
|
|
|
|
|
+enum err cmd_clear_args(struct cmd *cmd, enum err *out_err);
|
|
|
enum err cmd_destroy(struct cmd *cmd, enum err *out_err);
|
|
|
|
|
|
+# define GO_REBUILD_YOURSELF() _cmd_go_rebuild_yourself(__FILE__, argv)
|
|
|
+void _cmd_go_rebuild_yourself(const char *src, char **argv);
|
|
|
+
|
|
|
+
|
|
|
# if defined(IMP_CMD) || defined(IMP)
|
|
|
|
|
|
+enum err
|
|
|
+procs_wait(struct procs *_r_ procs, enum err *_r_ out_err)
|
|
|
+{
|
|
|
+ enum err err = ERR_OK;
|
|
|
+ enum err *perr = &err;
|
|
|
+
|
|
|
+ i32 status = 0;
|
|
|
+
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(procs, out_err);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(procs->data, out_err);
|
|
|
+
|
|
|
+ if ( out_err != NULL ) {
|
|
|
+ perr = out_err;
|
|
|
+ }
|
|
|
+
|
|
|
+ DA_FOREACH(*procs, it) {
|
|
|
+ if ( waitpid(*it, &status, 0) < 0 ) {
|
|
|
+ *perr = ERR_FAILED_WAITPID;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( WIFEXITED(status) == true ) {
|
|
|
+ if ( WEXITSTATUS(status) != 0 ) {
|
|
|
+ *perr = ERR_CMD_NON_ZERO_EXIT_CODE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return *perr;
|
|
|
+}
|
|
|
+
|
|
|
struct cmd
|
|
|
-cmd_create(struct str exe, enum err *_r_ out_err)
|
|
|
+_cmd_create(struct str exe, struct __cmd_create_args args,
|
|
|
+ enum err *_r_ out_err)
|
|
|
{
|
|
|
+ enum err err = ERR_OK;
|
|
|
+ enum err *perr = &err;
|
|
|
+
|
|
|
struct cmd empty = {0};
|
|
|
struct cmd cmd = {0};
|
|
|
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
|
LIB_ARG_MUST_NOT_BE_NULL(exe.data, out_err, empty);
|
|
|
|
|
|
- cmd.exe = malloc(exe.size+1);
|
|
|
- if ( cmd.exe == NULL ) {
|
|
|
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
- goto exit_err;
|
|
|
+ if ( out_err != NULL ) {
|
|
|
+ perr = out_err;
|
|
|
}
|
|
|
- cmd.exe[exe.size] = 0;
|
|
|
- memcpy(cmd.exe, exe.data, exe.size);
|
|
|
|
|
|
cmd.args.cap = 32;
|
|
|
cmd.args.data = malloc(sizeof(*cmd.args.data) * cmd.args.cap);
|
|
|
@@ -2010,14 +2136,33 @@ cmd_create(struct str exe, enum err *_r_ out_err)
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
goto exit_err;
|
|
|
}
|
|
|
+ memset(cmd.args.data, 0, sizeof(*cmd.args.data) * cmd.args.cap);
|
|
|
+ cmd_append_arg(&cmd, exe, perr);
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
+ goto exit_err;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd.envs.cap = 32;
|
|
|
+ cmd.envs.data = malloc(sizeof(*cmd.envs.data) * cmd.envs.cap);
|
|
|
+ if ( cmd.envs.data == NULL ) {
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
+ goto exit_err;
|
|
|
+ }
|
|
|
+ memset(cmd.envs.data, 0, sizeof(*cmd.envs.data) * cmd.envs.cap);
|
|
|
|
|
|
- DA_APPEND(cmd.args, cmd.exe, out_err);
|
|
|
+ if ( args.copy_env == true && environ != NULL ) {
|
|
|
+ char **envs = environ;
|
|
|
+ while ( *envs != NULL ) {
|
|
|
+ cmd_append_env_ns(&cmd, *envs, perr);
|
|
|
+ if ( *perr != ERR_OK ) goto exit_err;
|
|
|
+ ++envs;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
return cmd;
|
|
|
exit_err:
|
|
|
- LIB_FREE(cmd.exe);
|
|
|
- LIB_FREE(cmd.args.data);
|
|
|
+ cmd_destroy(&cmd, perr);
|
|
|
return (struct cmd){0};
|
|
|
}
|
|
|
|
|
|
@@ -2028,19 +2173,17 @@ cmd_set_exe(struct cmd *_r_ cmd, struct str exe, enum err *_r_ out_err)
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(exe.data, out_err);
|
|
|
|
|
|
- if ( cmd->exe != NULL ) {
|
|
|
- LIB_FREE(cmd->exe);
|
|
|
+ if ( cmd->args.data[0] != NULL ) {
|
|
|
+ LIB_FREE(cmd->args.data[0]);
|
|
|
}
|
|
|
|
|
|
- cmd->exe = malloc(exe.size+1);
|
|
|
- if ( cmd->exe == NULL ) {
|
|
|
+ cmd->args.data[0] = malloc(exe.size+1);
|
|
|
+ if ( cmd->args.data[0] == NULL ) {
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
return ERR_FAILED_ALLOC;
|
|
|
}
|
|
|
- cmd->exe[exe.size] = 0;
|
|
|
- memcpy(cmd->exe, exe.data, exe.size);
|
|
|
-
|
|
|
- cmd->args.data[0] = cmd->exe;
|
|
|
+ cmd->args.data[0][exe.size] = 0;
|
|
|
+ memcpy(cmd->args.data[0], exe.data, exe.size);
|
|
|
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
return ERR_OK;
|
|
|
@@ -2077,16 +2220,79 @@ cmd_append_arg(struct cmd *_r_ cmd, struct str arg, enum err *_r_ out_err)
|
|
|
}
|
|
|
|
|
|
enum err
|
|
|
-cmd_exec(struct cmd *_r_ cmd, enum err *_r_ out_err)
|
|
|
+_cmd_append_args_cstrs(struct cmd *_r_ cmd, const char **args,
|
|
|
+ enum err *_r_ out_err)
|
|
|
+{
|
|
|
+ enum err err = ERR_OK;
|
|
|
+ enum err *perr = &err;
|
|
|
+
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(args, out_err);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(args[0], out_err);
|
|
|
+
|
|
|
+ if ( out_err != NULL ) {
|
|
|
+ perr = out_err;
|
|
|
+ }
|
|
|
+
|
|
|
+ while ( *args != NULL ) {
|
|
|
+ cmd_append_arg_ns(cmd, *args, perr);
|
|
|
+ if ( *perr != ERR_OK ) return *perr;
|
|
|
+ ++args;
|
|
|
+ }
|
|
|
+
|
|
|
+ return *perr;
|
|
|
+}
|
|
|
+
|
|
|
+enum err
|
|
|
+cmd_append_env(struct cmd *_r_ cmd, struct str env, enum err *_r_ out_err)
|
|
|
+{
|
|
|
+ enum err err = ERR_OK;
|
|
|
+ enum err *perr = &err;
|
|
|
+
|
|
|
+ char *t = NULL;
|
|
|
+
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(env.data, out_err);
|
|
|
+
|
|
|
+ if ( out_err != NULL ) {
|
|
|
+ perr = out_err;
|
|
|
+ }
|
|
|
+
|
|
|
+ t = malloc(env.size + 1);
|
|
|
+ if ( t == NULL ) {
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
+ return ERR_FAILED_ALLOC;
|
|
|
+ }
|
|
|
+ t[env.size] = 0;
|
|
|
+ memcpy(t, env.data, env.size);
|
|
|
+
|
|
|
+ DA_APPEND(cmd->envs, t, perr);
|
|
|
+
|
|
|
+ return *perr;
|
|
|
+}
|
|
|
+
|
|
|
+enum err
|
|
|
+_cmd_exec(struct cmd *_r_ cmd, struct __cmd_exec_args args,
|
|
|
+ enum err *_r_ out_err)
|
|
|
{
|
|
|
+ enum err err = ERR_OK;
|
|
|
+ enum err *perr = &err;
|
|
|
+
|
|
|
i32 pid = -1;
|
|
|
i32 status = 0;
|
|
|
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
|
|
|
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->exe, out_err);
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
|
|
|
|
|
|
+ if ( out_err != NULL ) {
|
|
|
+ perr = out_err;
|
|
|
+ }
|
|
|
+
|
|
|
cmd->args.data[cmd->args.size] = NULL;
|
|
|
|
|
|
pid = fork();
|
|
|
@@ -2096,16 +2302,23 @@ cmd_exec(struct cmd *_r_ cmd, enum err *_r_ out_err)
|
|
|
}
|
|
|
|
|
|
if ( pid == 0 ) {
|
|
|
- /*
|
|
|
- printf("exe=`%s`\n", cmd->exe);
|
|
|
- DA_FOREACH(cmd->args, it) {
|
|
|
- printf("arg=`%s`\n", *it);
|
|
|
- }
|
|
|
- */
|
|
|
- execve(cmd->exe, cmd->args.data, NULL);
|
|
|
+ (
|
|
|
+ (args.search_path == true)
|
|
|
+ ? execvpe
|
|
|
+ : execve
|
|
|
+ ) (cmd->args.data[0], cmd->args.data, cmd->envs.data);
|
|
|
exit(1);
|
|
|
}
|
|
|
|
|
|
+ if ( args.reset == true ) {
|
|
|
+ cmd_clear_args(cmd, NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( args.procs != NULL ) {
|
|
|
+ DA_APPEND(*args.procs, pid, perr);
|
|
|
+ return *perr;
|
|
|
+ }
|
|
|
+
|
|
|
if ( waitpid(pid, &status, 0) < 0 ) {
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_WAITPID);
|
|
|
return ERR_FAILED_WAITPID;
|
|
|
@@ -2123,24 +2336,86 @@ cmd_exec(struct cmd *_r_ cmd, enum err *_r_ out_err)
|
|
|
}
|
|
|
|
|
|
enum err
|
|
|
-cmd_destroy(struct cmd *cmd, enum err *out_err)
|
|
|
+cmd_clear_args(struct cmd *cmd, enum err *out_err)
|
|
|
{
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
|
|
|
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->exe, out_err);
|
|
|
LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
|
|
|
|
|
|
- LIB_FREE(cmd->exe);
|
|
|
DA_FOREACH(cmd->args, it) {
|
|
|
- if ( *it == cmd->exe ) continue;
|
|
|
LIB_FREE(*it);
|
|
|
}
|
|
|
+ cmd->args.size = 0;
|
|
|
+
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
+ return ERR_OK;
|
|
|
+}
|
|
|
+
|
|
|
+enum err
|
|
|
+cmd_destroy(struct cmd *cmd, enum err *out_err)
|
|
|
+{
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
|
|
|
+
|
|
|
+ if ( cmd->args.data != NULL ) {
|
|
|
+ DA_FOREACH(cmd->args, it) {
|
|
|
+ LIB_FREE(*it);
|
|
|
+ }
|
|
|
+ }
|
|
|
LIB_FREE(cmd->args.data);
|
|
|
|
|
|
+ if ( cmd->envs.data != NULL ) {
|
|
|
+ DA_FOREACH(cmd->envs, it) {
|
|
|
+ LIB_FREE(*it);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ LIB_FREE(cmd->envs.data);
|
|
|
+
|
|
|
+ cmd->args.data = NULL;
|
|
|
+ cmd->args.cap = 0;
|
|
|
+ cmd->args.size = 0;
|
|
|
+ cmd->envs.data = NULL;
|
|
|
+ cmd->envs.cap = 0;
|
|
|
+ cmd->envs.size = 0;
|
|
|
+
|
|
|
LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
return ERR_OK;
|
|
|
}
|
|
|
|
|
|
+# ifdef _SYS_STAT_H
|
|
|
+void
|
|
|
+_cmd_go_rebuild_yourself(const char *src, char **argv)
|
|
|
+{
|
|
|
+ enum err err = ERR_OK;
|
|
|
+ struct stat src_stat = {0};
|
|
|
+ struct stat exec_stat = {0};
|
|
|
+
|
|
|
+ if ( err == ERR_OK ) err = stat(src, &src_stat);
|
|
|
+ if ( err == ERR_OK ) err = stat(argv[0] , &exec_stat);
|
|
|
+
|
|
|
+ if ( err == ERR_OK ) do {
|
|
|
+ if ( src_stat.st_mtime > exec_stat.st_mtime ) {
|
|
|
+ err = rename(argv[0], temp_sprintf("%s.old", argv[0]));
|
|
|
+
|
|
|
+ struct cmd cmd = cmd_create_ns(CC, &err);
|
|
|
+ cmd_append_arg_ns(&cmd, src, &err);
|
|
|
+ cmd_append_arg_ns(&cmd, "-o", &err);
|
|
|
+ cmd_append_arg_ns(&cmd, argv[0], &err);
|
|
|
+ cmd_exec(&cmd, &err);
|
|
|
+ cmd_destroy(&cmd, &err);
|
|
|
+
|
|
|
+ if ( err == ERR_OK ) execv(argv[0], argv);
|
|
|
+ if ( err == ERR_OK ) exit(0);
|
|
|
+ }
|
|
|
+ } while(0);
|
|
|
+
|
|
|
+ if ( err != ERR_OK ) {
|
|
|
+ fprintf(stderr, "Failed recompiling myself: %s\n", err_to_name[err]);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+}
|
|
|
+# endif /* _SYS_STAT_H */
|
|
|
+
|
|
|
# endif /* defined(IMP_CMD) || defined(IMP) */
|
|
|
|
|
|
# endif /* defined(WANT_CMD) || defined(WANT_ALL) */
|