aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/elua/io.c
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2014-05-29 15:21:50 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2014-06-10 15:48:52 +0100
commit489b5fac1173fe7f199751c78b1e583e8cbc152a (patch)
tree0ce0d0e1e7609b35839729dc57f7c02b531481bd /src/bin/elua/io.c
parentelua: if ugly, then at least portable (we already assume presence of bourne s... (diff)
downloadefl-489b5fac1173fe7f199751c78b1e583e8cbc152a.tar.gz
elua: do not use fork in our "array popen" impl; instead serialize args in a platform specific way
Diffstat (limited to 'src/bin/elua/io.c')
-rw-r--r--src/bin/elua/io.c108
1 files changed, 63 insertions, 45 deletions
diff --git a/src/bin/elua/io.c b/src/bin/elua/io.c
index c303683d8e..6f2e0e28df 100644
--- a/src/bin/elua/io.c
+++ b/src/bin/elua/io.c
@@ -1,50 +1,71 @@
/* elua io extras, largely taken from lua io lib source */
+#include "main.h"
+
+/* expand fname to full path name (so that PATH is ignored) plus turn
+ * stuff into a command, and also verify whether the path exists */
+static char *
+get_cmdline_from_argv(const char *fname, const char **argv)
+{
+ Eina_Strbuf *buf;
+ char *ret;
+ char pbuf[PATH_MAX];
+
+ FILE *testf = fopen(fname, "r");
+ if (!testf)
+ return NULL;
+
+ /* for windows, we have realpath in evil, no need for GetFullPathName */
+ if (!realpath(fname, pbuf))
+ return NULL;
+
+ fclose(testf);
+
+ buf = eina_strbuf_new();
+ eina_strbuf_append_char(buf, '"');
+ eina_strbuf_append(buf, pbuf);
+ eina_strbuf_append_char(buf, '"');
+
+ while (*argv)
+ {
+ const char *arg = *(argv++);
+ char c;
+ eina_strbuf_append_char(buf, ' ');
+ eina_strbuf_append_char(buf, '"');
+
+ while ((c = *(arg++)))
+ {
#ifndef _WIN32
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#define pipe(x, mode) pipe(x)
+ if (c == '"' || c == '$') eina_strbuf_append_char(buf, '\\');
+ eina_strbuf_append_char(buf, c);
#else
-#include <io.h>
-#define fdopen _fdopen
-#define execv _execv
-#define close _close
-#define dup2 _dup2
-#define pipe(x, mode) _pipe(x, 4096, ((mode && mode[0] && mode[1] == 'b') \
- ? _O_BINARY : _O_TEXT) | _NO_NOINHERIT)
+ if (c == '"') eina_strbuf_append_char(buf, '\\');
+ else if (c == '%') eina_strbuf_append_char(buf, '"');
+ eina_strbuf_append_char(buf, c);
+ if (c == '%') eina_strbuf_append_char(buf, '"');
#endif
+ }
-#include "main.h"
+ eina_strbuf_append_char(buf, '"');
+ }
+
+ ret = strdup(eina_strbuf_string_get(buf));
+ eina_strbuf_free(buf);
+ return ret;
+}
static FILE *
-elua_popen_c(const char *path, const char *argv[], const char *mode)
+elua_popen_c(const char *path, const char *md, const char *argv[])
{
- int read = (!mode || mode[0] == 'r');
- int binary = mode && mode[0] && mode[1] == 'b';
- pid_t pid;
+ FILE *ret;
- int des[2];
- if (pipe(des, mode)) return NULL;
+ char *cmdline = get_cmdline_from_argv(path, argv);
+ if (!cmdline) return NULL;
- pid = fork();
- if (!pid)
- {
- /* if read, stdout (1) is still open here
- * (parent can read, child can write) */
- close(des[!read]);
- dup2(des[read], read ? STDOUT_FILENO : STDIN_FILENO);
- execv(path, (char * const *)argv);
- return NULL;
- }
- else
- {
- /* if read, stdin (0) is still open here
- * (child can read, parent can write) */
- close(des[read]);
- return fdopen(des[!read], read ? (binary ? "rb" : "r")
- : (binary ? "wb" : "w"));
- }
+ ret = popen(cmdline, md);
+ if (!ret) return NULL;
+
+ return ret;
}
static int
@@ -322,21 +343,18 @@ elua_popen(lua_State *L)
FILE **pf = elua_newfile(L);
if (nargs > 0)
{
- const char **argv = (const char**)alloca((nargs + 2) * sizeof(char*));
- memset(argv, 0, (nargs + 2) * sizeof(char*));
+ const char **argv = (const char**)alloca((nargs + 1) * sizeof(char*));
+ memset(argv, 0, (nargs + 1) * sizeof(char*));
for (; nargs; --nargs)
{
- argv[nargs] = lua_tostring(L, nargs + 2);
+ argv[nargs - 1] = lua_tostring(L, nargs + 2);
}
- argv[0] = fname;
- *pf = elua_popen_c(fname, argv, mode);
+ *pf = elua_popen_c(fname, mode, argv);
}
else
{
- const char **argv = (const char**)alloca(2 * sizeof(char*));
- argv[0] = fname;
- argv[1] = NULL;
- *pf = elua_popen_c(fname, argv, mode);
+ const char **argv = { NULL };
+ *pf = elua_popen_c(fname, mode, argv);
}
return (!*pf) ? push_ret(L, 0, fname) : 1;
} \ No newline at end of file