/* 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
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