summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-02-16 06:45:32 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-02-16 06:45:32 +0000
commit03d8c88b8774d40f3ff2596d7658f84938923caa (patch)
treec284a1b3d52c3b37a17591fd6327f2011438653a /win32
parent3bc0f22fcea84f09ba347a0575779f935e044c12 (diff)
* configure.in: check functions, fork spawnv.
* io.c (rb_io_s_popen): accept argv not only single command line. * process.c (rb_proc_exec_n): export. * process.c (rb_check_argv): check if arguments are safe to invoke. * process.c (rb_fork): retry to fork. * process.c (rb_spawn): spawn child process asynchronously. * process.c (rb_f_system): raise an exception if the command could not execute. * win32/win32.c (rb_w32_argv_size): count necessary size for joined arguments. * win32/win32.c (rb_w32_join_argv): join arguments with quoting. * win32/win32.c (rb_w32_pipe_exec, rb_w32_spawn, rb_w32_aspawn): accept program name adding to command line. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5725 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32')
-rw-r--r--win32/win32.c170
-rw-r--r--win32/win32.h8
2 files changed, 85 insertions, 93 deletions
diff --git a/win32/win32.c b/win32/win32.c
index 4436464697..7eea4b76b0 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -589,8 +589,79 @@ rb_w32_get_osfhandle(int fh)
return _get_osfhandle(fh);
}
+int
+rb_w32_argv_size(argv)
+ char **argv;
+{
+ char *p, **t;
+ int len, n, bs, quote;
+
+ for (t = argv, len = 0; *t; t++) {
+ for (p = *t, n = quote = bs = 0; *p; ++p) {
+ switch (*p) {
+ case '\\':
+ ++bs;
+ break;
+ case '"':
+ n += bs + 1; bs = 0;
+ quote = 1;
+ break;
+ case ' ': case '\t':
+ quote = 1;
+ default:
+ bs = 0;
+ p = CharNext(p) - 1;
+ break;
+ }
+ }
+ len += p - *t + n + 1;
+ if (quote) len += 2;
+ }
+ return len;
+}
+
+char *
+rb_w32_join_argv(cmd, argv)
+ char *cmd;
+ char **argv;
+{
+ char *p, *q, *s, **t;
+ int n, bs, quote;
+
+ for (t = argv, q = cmd; p = *t; t++) {
+ quote = 0;
+ s = p;
+ if (!*p || strpbrk(p, " \t\"")) {
+ quote = 1;
+ *q++ = '"';
+ }
+ for (bs = 0; *p; ++p) {
+ switch (*p) {
+ case '\\':
+ ++bs;
+ break;
+ case '"':
+ memcpy(q, s, n = p - s); q += n; s = p;
+ memset(q, '\\', ++bs); q += bs; bs = 0;
+ break;
+ default:
+ bs = 0;
+ p = CharNext(p) - 1;
+ break;
+ }
+ }
+ memcpy(q, s, n = p - s);
+ q += n;
+ if (quote) *q++ = '"';
+ *q++ = ' ';
+ }
+ if (q > cmd) --q;
+ *q = '\0';
+ return cmd;
+}
+
pid_t
-pipe_exec(char *cmd, int mode, FILE **fpr, FILE **fpw)
+rb_w32_pipe_exec(char *cmd, char *prog, int mode, FILE **fpr, FILE **fpw)
{
struct ChildRecord* child;
HANDLE hReadIn, hReadOut;
@@ -667,7 +738,7 @@ pipe_exec(char *cmd, int mode, FILE **fpr, FILE **fpw)
CloseHandle(hCurProc);
/* create child process */
- child = CreateChild(cmd, NULL, &sa, hWriteIn, hReadOut, NULL);
+ child = CreateChild(cmd, prog, &sa, hWriteIn, hReadOut, NULL);
if (!child) {
if (reading) {
CloseHandle(hReadOut);
@@ -729,9 +800,10 @@ pipe_exec(char *cmd, int mode, FILE **fpr, FILE **fpw)
extern VALUE rb_last_status;
int
-do_spawn(mode, cmd)
+rb_w32_spawn(mode, cmd, prog)
int mode;
char *cmd;
+char *prog;
{
struct ChildRecord *child;
DWORD exitcode;
@@ -746,7 +818,7 @@ char *cmd;
return -1;
}
- child = CreateChild(cmd, NULL, NULL, NULL, NULL, NULL);
+ child = CreateChild(cmd, prog, NULL, NULL, NULL, NULL);
if (!child) {
return -1;
}
@@ -768,97 +840,15 @@ char *cmd;
}
int
-do_aspawn(mode, prog, argv)
+rb_w32_aspawn(mode, prog, argv)
int mode;
char *prog;
char **argv;
{
- char *cmd, *p, *q, *s, **t;
- int len, n, bs, quote;
- struct ChildRecord *child;
- DWORD exitcode;
-
- switch (mode) {
- case P_WAIT:
- case P_NOWAIT:
- case P_OVERLAY:
- break;
- default:
- errno = EINVAL;
- return -1;
- }
+ int len = rb_w32_argv_size(argv);
+ char *cmd = ALLOCA_N(char, len);
- for (t = argv, len = 0; *t; t++) {
- for (p = *t, n = quote = bs = 0; *p; ++p) {
- switch (*p) {
- case '\\':
- ++bs;
- break;
- case '"':
- n += bs + 1; bs = 0;
- quote = 1;
- break;
- case ' ': case '\t':
- quote = 1;
- default:
- bs = 0;
- p = CharNext(p) - 1;
- break;
- }
- }
- len += p - *t + n + 1;
- if (quote) len += 2;
- }
- cmd = ALLOCA_N(char, len);
- for (t = argv, q = cmd; p = *t; t++) {
- quote = 0;
- s = p;
- if (!*p || strpbrk(p, " \t\"")) {
- quote = 1;
- *q++ = '"';
- }
- for (bs = 0; *p; ++p) {
- switch (*p) {
- case '\\':
- ++bs;
- break;
- case '"':
- memcpy(q, s, n = p - s); q += n; s = p;
- memset(q, '\\', ++bs); q += bs; bs = 0;
- break;
- default:
- bs = 0;
- p = CharNext(p) - 1;
- break;
- }
- }
- memcpy(q, s, n = p - s);
- q += n;
- if (quote) *q++ = '"';
- *q++ = ' ';
- }
- if (q > cmd) --q;
- *q = '\0';
-
- child = CreateChild(cmd, prog, NULL, NULL, NULL, NULL);
- if (!child) {
- return -1;
- }
-
- switch (mode) {
- case P_WAIT:
- rb_syswait(child->pid);
- return NUM2INT(rb_last_status);
- case P_NOWAIT:
- return child->pid;
- case P_OVERLAY:
- WaitForSingleObject(child->hProcess, INFINITE);
- GetExitCodeProcess(child->hProcess, &exitcode);
- CloseChildHandle(child);
- _exit(exitcode);
- default:
- return -1; /* not reached */
- }
+ return rb_w32_spawn(mode, rb_w32_join_argv(cmd, argv), prog);
}
static struct ChildRecord *
diff --git a/win32/win32.h b/win32/win32.h
index 82bc90ed77..ed930ae6b9 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -120,7 +120,7 @@ extern "C++" {
#undef stat
#define stat(path,st) rb_w32_stat(path,st)
#undef execv
-#define execv(path,argv) do_aspawn(P_OVERLAY,path,argv)
+#define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv)
#ifdef __MINGW32__
struct timezone {
@@ -175,8 +175,10 @@ extern int chown(const char *, int, int);
extern int link(const char *, const char *);
extern int gettimeofday(struct timeval *, struct timezone *);
extern pid_t waitpid (pid_t, int *, int);
-extern int do_spawn(int, char *);
-extern int do_aspawn(int, char *, char **);
+extern int rb_w32_argv_size(char **);
+extern char *rb_w32_join_argv(char *, char **);
+extern int rb_w32_spawn(int, char *, char*);
+extern int rb_w32_aspawn(int, char *, char **);
extern int kill(int, int);
extern pid_t rb_w32_getpid(void);