>From a4d348abfcb88bc5d6c26f6f92458a9043829b64 Mon Sep 17 00:00:00 2001 From: Petr Skocik Date: Sun, 31 Jul 2016 22:07:10 +0200 Subject: [PATCH] passing scripts via fds --- shell.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/shell.c b/shell.c index 2fd8179..62e20a3 100644 --- a/shell.c +++ b/shell.c @@ -108,6 +108,9 @@ extern int gnu_error_format; extern char *primary_prompt, *secondary_prompt; extern char *this_command_name; +//readlink into mallocated memory +char* readlink_dyn(const char* path); + /* Non-zero means that this shell has already been run; i.e. you should call shell_reinitialize () if you need to start afresh. */ int shell_initialized = 0; @@ -1416,6 +1419,7 @@ open_shell_script (script_name) char sample[80]; int sample_len; struct stat sb; + int rawfd = 0; #if defined (ARRAY_VARS) SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v; ARRAY *funcname_a, *bash_source_a, *bash_lineno_a; @@ -1423,29 +1427,59 @@ open_shell_script (script_name) filename = savestring (script_name); - fd = open (filename, O_RDONLY); - if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0)) - { - e = errno; - /* If it's not in the current directory, try looking through PATH - for it. */ - path_filename = find_path_file (script_name); - if (path_filename) - { - free (filename); - filename = path_filename; - fd = open (filename, O_RDONLY); - } - else - errno = e; - } +#define DEV_FD "/dev/fd/" +#define PROC_FD "/proc/self/fd/" + if (0 == strncmp(filename, DEV_FD, sizeof(DEV_FD)-1)){ + const char* ptr = filename + sizeof(DEV_FD)-1; + char* endptr; + rawfd = 1; + fd = strtoul(ptr, &endptr, 10); + if (*endptr){ + errno = ENOENT; + file_error (filename); + } + }else if (0 == strncmp(filename, PROC_FD, sizeof(PROC_FD)-1)){ + const char* ptr = filename + sizeof(PROC_FD)-1; + char* endptr; + rawfd = 1; + fd = strtoul(ptr, &endptr, 10); + if (*endptr){ + errno = ENOENT; + file_error (filename); + } +#undef DEV_FD +#undef PROC_FD + }else { + fd = open (filename, O_RDONLY); + if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0)) + { + e = errno; + /* If it's not in the current directory, try looking through PATH + for it. */ + path_filename = find_path_file (script_name); + if (path_filename) + { + free (filename); + filename = path_filename; + fd = open (filename, O_RDONLY); + } + else + errno = e; + } + + if (fd < 0) + { + e = errno; + file_error (filename); + exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT); + } + } + + if (rawfd){ + free(exec_argv0); + exec_argv0 = readlink_dyn(script_name); + } - if (fd < 0) - { - e = errno; - file_error (filename); - exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT); - } free (dollar_vars[0]); dollar_vars[0] = exec_argv0 ? savestring (exec_argv0) : savestring (script_name); @@ -1477,7 +1511,7 @@ open_shell_script (script_name) #endif /* Only do this with non-tty file descriptors we can seek on. */ - if (fd_is_tty == 0 && (lseek (fd, 0L, 1) != -1)) + if (fd_is_tty == 0 && !rawfd && (lseek (fd, 0L, 1) != -1)) { /* Check to see if the `file' in `bash file' is a binary file according to the same tests done by execute_simple_command (), @@ -1895,3 +1929,24 @@ run_shopt_alist () shopt_alist = 0; shopt_ind = shopt_len = 0; } + +char* readlink_dyn(const char* path){ + struct stat sb; + char *data; + ssize_t r; + + if ( 0 > lstat(path, &sb) ) + return NULL; + if (NULL == (data = malloc(sb.st_size + 1))) + return NULL; + if (0>(r = readlink(path, data, sb.st_size + 1))) + goto err_out; + if (r > sb.st_size) + goto err_out; + data[r] = '\0'; + return data; +err_out: + free(data); + return NULL; +} + -- 2.9.2