зеркало из https://github.com/github/ruby.git
* hash.c (envix): use GET_ENVIRON and FREE_ENVIRON to get environment
variables list. * hash.c (env_keys): ditto. * hash.c (env_each_key): ditto. * hash.c (env_values): ditto. * hash.c (env_keys): ditto. * hash.c (env_each_value): ditto. * hash.c (env_each): ditto. * hash.c (env_inspect): ditto. * hash.c (env_to_a): ditto. * hash.c (env_size): ditto. * hash.c (env_empty_p): ditto. * hash.c (env_has_value): ditto. * hash.c (env_index): ditto. * hash.c (env_to_hash): ditto. * win32/win32.c (win32_getenv): use static buffer. * win32/win32.c, win32/win32.h (win32_get_environ): get environment variables list. [new] * win32/win32.c, win32/win32.h (win32_free_environ): free environment variables list. [new] * win32/win32.c (do_spawn): use CreateChild() instead of calling CreateProcess() directly. Original patches comes from Patrick Cheng. * win32/win32.c (mypopen): ditto. * win32/win32.c (mypclose): use rb_syswait() instead of waiting in this function. * win32/win32.c (waitpid): use wait_child() instead of _cwait(). * win32/win32.c (CreateChild): added. [new] * win32/win32.c (wait_child): added. [new] * win32/win32.c (FindFirstChildSlot): added. [new] * win32/win32.c (FindChildSlot): added. [new] * win32/win32.c (FindPipedChildSlot): added. [new] * win32/win32.c (CloseChildHandle): added. [new] * win32/win32.c (FindFreeChildSlot): added. [new] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1823 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
8fed738ffa
Коммит
c5ca1bc929
65
ChangeLog
65
ChangeLog
|
@ -1,3 +1,68 @@
|
||||||
|
Tue Nov 13 12:55:59 2001 Usaku Nakamura <usa@ruby-lang.org>
|
||||||
|
|
||||||
|
* win32/win32.c (do_spawn): use CreateChild() instead of calling
|
||||||
|
CreateProcess() directly. Original patches comes from Patrick Cheng.
|
||||||
|
|
||||||
|
* win32/win32.c (mypopen): ditto.
|
||||||
|
|
||||||
|
* win32/win32.c (mypclose): use rb_syswait() instead of waiting in this
|
||||||
|
function.
|
||||||
|
|
||||||
|
* win32/win32.c (waitpid): use wait_child() instead of _cwait().
|
||||||
|
|
||||||
|
* win32/win32.c (CreateChild): added. [new]
|
||||||
|
|
||||||
|
* win32/win32.c (wait_child): added. [new]
|
||||||
|
|
||||||
|
* win32/win32.c (FindFirstChildSlot): added. [new]
|
||||||
|
|
||||||
|
* win32/win32.c (FindChildSlot): added. [new]
|
||||||
|
|
||||||
|
* win32/win32.c (FindPipedChildSlot): added. [new]
|
||||||
|
|
||||||
|
* win32/win32.c (CloseChildHandle): added. [new]
|
||||||
|
|
||||||
|
* win32/win32.c (FindFreeChildSlot): added. [new]
|
||||||
|
|
||||||
|
Tue Nov 13 12:38:12 2001 Usaku Nakamura <usa@ruby-lang.org>
|
||||||
|
|
||||||
|
* hash.c (envix): use GET_ENVIRON and FREE_ENVIRON to get environment
|
||||||
|
variables list.
|
||||||
|
|
||||||
|
* hash.c (env_keys): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_each_key): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_values): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_keys): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_each_value): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_each): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_inspect): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_to_a): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_size): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_empty_p): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_has_value): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_index): ditto.
|
||||||
|
|
||||||
|
* hash.c (env_to_hash): ditto.
|
||||||
|
|
||||||
|
* win32/win32.c (win32_getenv): use static buffer.
|
||||||
|
|
||||||
|
* win32/win32.c, win32/win32.h (win32_get_environ): get environment
|
||||||
|
variables list. [new]
|
||||||
|
|
||||||
|
* win32/win32.c, win32/win32.h (win32_free_environ): free environment
|
||||||
|
variables list. [new]
|
||||||
|
|
||||||
Fri Nov 9 13:50:06 2001 Usaku Nakamura <usa@ruby-lang.org>
|
Fri Nov 9 13:50:06 2001 Usaku Nakamura <usa@ruby-lang.org>
|
||||||
|
|
||||||
* win32/config.status.in: make CFLAGS same as Makefile's one.
|
* win32/config.status.in: make CFLAGS same as Makefile's one.
|
||||||
|
|
78
hash.c
78
hash.c
|
@ -843,10 +843,18 @@ rb_hash_update(hash1, hash2)
|
||||||
|
|
||||||
static int path_tainted = -1;
|
static int path_tainted = -1;
|
||||||
|
|
||||||
#ifndef NT
|
|
||||||
extern char **environ;
|
|
||||||
#endif
|
|
||||||
static char **origenviron;
|
static char **origenviron;
|
||||||
|
#ifdef NT
|
||||||
|
#define GET_ENVIRON(e) (e = win32_get_environ())
|
||||||
|
#define FREE_ENVIRON(e) win32_free_environ(e)
|
||||||
|
static char **my_environ;
|
||||||
|
#undef environ
|
||||||
|
#define environ my_environ
|
||||||
|
#else
|
||||||
|
extern char **environ;
|
||||||
|
#define GET_ENVIRON(e) (e)
|
||||||
|
#define FREE_ENVIRON(e)
|
||||||
|
#endif
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
env_delete(obj, name)
|
env_delete(obj, name)
|
||||||
|
@ -955,17 +963,20 @@ envix(nam)
|
||||||
char *nam;
|
char *nam;
|
||||||
{
|
{
|
||||||
register int i, len = strlen(nam);
|
register int i, len = strlen(nam);
|
||||||
|
char **env;
|
||||||
|
|
||||||
for (i = 0; environ[i]; i++) {
|
env = GET_ENVIRON(environ);
|
||||||
|
for (i = 0; env[i]; i++) {
|
||||||
if (
|
if (
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
strnicmp(environ[i],nam,len) == 0
|
strnicmp(env[i],nam,len) == 0
|
||||||
#else
|
#else
|
||||||
memcmp(environ[i],nam,len) == 0
|
memcmp(env[i],nam,len) == 0
|
||||||
#endif
|
#endif
|
||||||
&& environ[i][len] == '=')
|
&& env[i][len] == '=')
|
||||||
break; /* memcmp must come first to avoid */
|
break; /* memcmp must come first to avoid */
|
||||||
} /* potential SEGV's */
|
} /* potential SEGV's */
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,7 +1152,7 @@ env_keys()
|
||||||
char **env;
|
char **env;
|
||||||
VALUE ary = rb_ary_new();
|
VALUE ary = rb_ary_new();
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1149,6 +1160,7 @@ env_keys()
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,7 +1170,7 @@ env_each_key(hash)
|
||||||
{
|
{
|
||||||
char **env;
|
char **env;
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1166,6 +1178,7 @@ env_each_key(hash)
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1175,7 +1188,7 @@ env_values()
|
||||||
char **env;
|
char **env;
|
||||||
VALUE ary = rb_ary_new();
|
VALUE ary = rb_ary_new();
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1183,6 +1196,7 @@ env_values()
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,7 +1206,7 @@ env_each_value(hash)
|
||||||
{
|
{
|
||||||
char **env;
|
char **env;
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1200,6 +1214,7 @@ env_each_value(hash)
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1209,7 +1224,7 @@ env_each(hash)
|
||||||
{
|
{
|
||||||
char **env;
|
char **env;
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1218,6 +1233,7 @@ env_each(hash)
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,7 +1283,7 @@ env_inspect()
|
||||||
VALUE str = rb_str_buf_new2("{");
|
VALUE str = rb_str_buf_new2("{");
|
||||||
VALUE i;
|
VALUE i;
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
|
|
||||||
|
@ -1283,6 +1299,7 @@ env_inspect()
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
rb_str_buf_cat2(str, "}");
|
rb_str_buf_cat2(str, "}");
|
||||||
OBJ_TAINT(str);
|
OBJ_TAINT(str);
|
||||||
|
|
||||||
|
@ -1295,7 +1312,7 @@ env_to_a()
|
||||||
char **env;
|
char **env;
|
||||||
VALUE ary = rb_ary_new();
|
VALUE ary = rb_ary_new();
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1304,6 +1321,7 @@ env_to_a()
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1317,16 +1335,26 @@ static VALUE
|
||||||
env_size()
|
env_size()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
char **env;
|
||||||
|
|
||||||
for(i=0; environ[i]; i++)
|
env = GET_ENVIRON(environ);
|
||||||
|
for(i=0; env[i]; i++)
|
||||||
;
|
;
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return INT2FIX(i);
|
return INT2FIX(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
env_empty_p()
|
env_empty_p()
|
||||||
{
|
{
|
||||||
if (environ[0] == 0) return Qtrue;
|
char **env;
|
||||||
|
|
||||||
|
env = GET_ENVIRON(environ);
|
||||||
|
if (env[0] == 0) {
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1350,15 +1378,18 @@ env_has_value(dmy, value)
|
||||||
char **env;
|
char **env;
|
||||||
|
|
||||||
if (TYPE(value) != T_STRING) return Qfalse;
|
if (TYPE(value) != T_STRING) return Qfalse;
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=')+1;
|
char *s = strchr(*env, '=')+1;
|
||||||
if (s) {
|
if (s) {
|
||||||
if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0)
|
if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,18 +1398,22 @@ env_index(dmy, value)
|
||||||
VALUE dmy, value;
|
VALUE dmy, value;
|
||||||
{
|
{
|
||||||
char **env;
|
char **env;
|
||||||
|
VALUE str;
|
||||||
|
|
||||||
if (TYPE(value) != T_STRING) return Qnil;
|
if (TYPE(value) != T_STRING) return Qnil;
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=')+1;
|
char *s = strchr(*env, '=')+1;
|
||||||
if (s) {
|
if (s) {
|
||||||
if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
|
if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
|
||||||
return rb_tainted_str_new(*env, s-*env-1);
|
str = rb_tainted_str_new(*env, s-*env-1);
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1413,7 +1448,7 @@ env_to_hash()
|
||||||
char **env;
|
char **env;
|
||||||
VALUE hash = rb_hash_new();
|
VALUE hash = rb_hash_new();
|
||||||
|
|
||||||
env = environ;
|
env = GET_ENVIRON(environ);
|
||||||
while (*env) {
|
while (*env) {
|
||||||
char *s = strchr(*env, '=');
|
char *s = strchr(*env, '=');
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1422,6 +1457,7 @@ env_to_hash()
|
||||||
}
|
}
|
||||||
env++;
|
env++;
|
||||||
}
|
}
|
||||||
|
FREE_ENVIRON(environ);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
774
win32/win32.c
774
win32/win32.c
|
@ -72,6 +72,7 @@ extern char **environ;
|
||||||
#define environ _environ
|
#define environ _environ
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static struct ChildRecord *CreateChild(char *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE);
|
||||||
static bool NtHasRedirection (char *);
|
static bool NtHasRedirection (char *);
|
||||||
static int valid_filename(char *s);
|
static int valid_filename(char *s);
|
||||||
static void StartSockets ();
|
static void StartSockets ();
|
||||||
|
@ -294,24 +295,74 @@ char *getlogin()
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// popen stuff
|
#define MAXCHILDNUM 256 /* max num of child processes */
|
||||||
|
|
||||||
//
|
struct ChildRecord {
|
||||||
// use these so I can remember which index is which
|
HANDLE hProcess; /* process handle */
|
||||||
//
|
pid_t pid; /* process id */
|
||||||
|
FILE* pipe; /* pipe */
|
||||||
|
} ChildRecord[MAXCHILDNUM];
|
||||||
|
|
||||||
#define NtPipeRead 0 // index of pipe read descriptor
|
#define FOREACH_CHILD(v) do { \
|
||||||
#define NtPipeWrite 1 // index of pipe write descriptor
|
struct ChildRecord* v; \
|
||||||
|
for (v = ChildRecord; v < ChildRecord + sizeof(ChildRecord) / sizeof(ChildRecord[0]); ++v)
|
||||||
|
#define END_FOREACH_CHILD } while (0)
|
||||||
|
|
||||||
#define NtPipeSize 1024 // size of pipe buffer
|
static struct ChildRecord *
|
||||||
|
FindFirstChildSlot(void)
|
||||||
|
{
|
||||||
|
FOREACH_CHILD(child) {
|
||||||
|
if (child->pid) return child;
|
||||||
|
} END_FOREACH_CHILD;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#define MYPOPENSIZE 256 // size of book keeping structure
|
static struct ChildRecord *
|
||||||
|
FindChildSlot(pid_t pid)
|
||||||
|
{
|
||||||
|
|
||||||
|
FOREACH_CHILD(child) {
|
||||||
|
if (child->pid == pid) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
} END_FOREACH_CHILD;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ChildRecord *
|
||||||
|
FindPipedChildSlot(FILE *fp)
|
||||||
|
{
|
||||||
|
FOREACH_CHILD(child) {
|
||||||
|
if (child->pid && child->pipe == fp) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
} END_FOREACH_CHILD;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
CloseChildHandle(struct ChildRecord *child)
|
||||||
|
{
|
||||||
|
HANDLE h = child->hProcess;
|
||||||
|
child->hProcess = NULL;
|
||||||
|
child->pid = 0;
|
||||||
|
CloseHandle(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ChildRecord *
|
||||||
|
FindFreeChildSlot(void)
|
||||||
|
{
|
||||||
|
FOREACH_CHILD(child) {
|
||||||
|
if (!child->pid) {
|
||||||
|
child->pid = -1; /* lock the slot */
|
||||||
|
child->hProcess = NULL;
|
||||||
|
child->pipe = NULL;
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
} END_FOREACH_CHILD;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct {
|
|
||||||
int inuse;
|
|
||||||
int pid;
|
|
||||||
FILE *pipe;
|
|
||||||
} MyPopenRecord[MYPOPENSIZE];
|
|
||||||
|
|
||||||
int SafeFree(char **vec, int vecc)
|
int SafeFree(char **vec, int vecc)
|
||||||
{
|
{
|
||||||
|
@ -398,34 +449,13 @@ FILE *
|
||||||
mypopen (char *cmd, char *mode)
|
mypopen (char *cmd, char *mode)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int saved, reading;
|
int reading;
|
||||||
int pipemode;
|
int pipemode;
|
||||||
int pipes[2];
|
struct ChildRecord* child;
|
||||||
int pid;
|
BOOL fRet;
|
||||||
int slot;
|
HANDLE hInFile, hOutFile;
|
||||||
static initialized = 0;
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
int fd;
|
||||||
//
|
|
||||||
// if first time through, intialize our book keeping structure
|
|
||||||
//
|
|
||||||
|
|
||||||
if (!initialized++) {
|
|
||||||
for (slot = 0; slot < MYPOPENSIZE; slot++)
|
|
||||||
MyPopenRecord[slot].inuse = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("mypopen %s\n", cmd);
|
|
||||||
|
|
||||||
//
|
|
||||||
// find a free popen slot
|
|
||||||
//
|
|
||||||
|
|
||||||
for (slot = 0; slot < MYPOPENSIZE && MyPopenRecord[slot].inuse; slot++)
|
|
||||||
;
|
|
||||||
|
|
||||||
if (slot > MYPOPENSIZE) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Figure out what we\'re doing...
|
// Figure out what we\'re doing...
|
||||||
|
@ -437,410 +467,183 @@ mypopen (char *cmd, char *mode)
|
||||||
//
|
//
|
||||||
// Now get a pipe
|
// Now get a pipe
|
||||||
//
|
//
|
||||||
|
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
|
sa.bInheritHandle = TRUE;
|
||||||
|
|
||||||
#if 0
|
fRet = CreatePipe(&hInFile, &hOutFile, &sa, 2048L);
|
||||||
if (_pipe(pipes, NtPipeSize, pipemode) == -1) {
|
if (!fRet) {
|
||||||
return NULL;
|
errno = GetLastError();
|
||||||
|
rb_sys_fail("mypopen: CreatePipe");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reading) {
|
if (reading) {
|
||||||
|
child = CreateChild(cmd, &sa, NULL, hOutFile, NULL);
|
||||||
//
|
|
||||||
// we\'re reading from the pipe, so we must hook up the
|
|
||||||
// write end of the pipe to the new processes stdout.
|
|
||||||
// To do this we must save our file handle from stdout
|
|
||||||
// by _dup\'ing it, then setting our stdout to be the pipe\'s
|
|
||||||
// write descriptor. We must also make the write handle
|
|
||||||
// inheritable so the new process can use it.
|
|
||||||
|
|
||||||
if ((saved = _dup(fileno(stdout))) == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_dup2 (pipes[NtPipeWrite], fileno(stdout)) == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//
|
child = CreateChild(cmd, &sa, hInFile, NULL, NULL);
|
||||||
// must be writing to the new process. Do the opposite of
|
|
||||||
// the above, i.e. hook up the processes stdin to the read
|
|
||||||
// end of the pipe.
|
|
||||||
//
|
|
||||||
|
|
||||||
if ((saved = _dup(fileno(stdin))) == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_dup2(pipes[NtPipeRead], fileno(stdin)) == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
if (!child) {
|
||||||
// Start the new process. Must set _fileinfo to non-zero value
|
CloseHandle(hInFile);
|
||||||
// for file descriptors to be inherited. Reset after the process
|
CloseHandle(hOutFile);
|
||||||
// is started.
|
rb_sys_fail("mypopen: CreateChild");
|
||||||
//
|
|
||||||
|
|
||||||
if (NtHasRedirection(cmd)) {
|
|
||||||
docmd:
|
|
||||||
pid = spawnlpe(_P_NOWAIT, "cmd.exe", "/c", cmd, 0, environ);
|
|
||||||
if (pid == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
char **vec;
|
|
||||||
int vecc = NtMakeCmdVector(cmd, &vec, FALSE);
|
|
||||||
|
|
||||||
//pid = spawnvpe (_P_NOWAIT, vec[0], vec, environ);
|
|
||||||
pid = spawnvpe (_P_WAIT, vec[0], vec, environ);
|
|
||||||
if (pid == -1) {
|
|
||||||
goto docmd;
|
|
||||||
}
|
|
||||||
Safefree (vec, vecc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reading) {
|
if (reading) {
|
||||||
|
fd = _open_osfhandle((long)hInFile, (_O_RDONLY | pipemode));
|
||||||
//
|
CloseHandle(hOutFile);
|
||||||
// We need to close our instance of the inherited pipe write
|
|
||||||
// handle now that it's been inherited so that it will actually close
|
|
||||||
// when the child process ends.
|
|
||||||
//
|
|
||||||
|
|
||||||
if (_close(pipes[NtPipeWrite]) == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_dup2 (saved, fileno(stdout)) == -1) {
|
|
||||||
_close(pipes[NtPipeRead]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
_close(saved);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Now get a stream pointer to return to the calling program.
|
|
||||||
//
|
|
||||||
|
|
||||||
if ((fp = (FILE *) fdopen(pipes[NtPipeRead], mode)) == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
fd = _open_osfhandle((long)hOutFile, (_O_WRONLY | pipemode));
|
||||||
//
|
CloseHandle(hInFile);
|
||||||
// need to close our read end of the pipe so that it will go
|
|
||||||
// away when the write end is closed.
|
|
||||||
//
|
|
||||||
|
|
||||||
if (_close(pipes[NtPipeRead]) == -1) {
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_dup2 (saved, fileno(stdin)) == -1) {
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
_close(saved);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Now get a stream pointer to return to the calling program.
|
|
||||||
//
|
|
||||||
|
|
||||||
if ((fp = (FILE *) fdopen(pipes[NtPipeWrite], mode)) == NULL) {
|
|
||||||
_close(pipes[NtPipeWrite]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
if (fd == -1) {
|
||||||
// do the book keeping
|
CloseHandle(reading ? hInFile : hOutFile);
|
||||||
//
|
CloseChildHandle(child);
|
||||||
|
rb_sys_fail("mypopen: _open_osfhandle");
|
||||||
|
}
|
||||||
|
|
||||||
MyPopenRecord[slot].inuse = TRUE;
|
if ((fp = (FILE *) fdopen(fd, mode)) == NULL) {
|
||||||
MyPopenRecord[slot].pipe = fp;
|
_close(fd);
|
||||||
MyPopenRecord[slot].pid = pid;
|
CloseChildHandle(child);
|
||||||
|
rb_sys_fail("mypopen: fdopen");
|
||||||
|
}
|
||||||
|
|
||||||
|
child->pipe = fp;
|
||||||
|
|
||||||
return fp;
|
return fp;
|
||||||
#else
|
|
||||||
{
|
|
||||||
int p[2];
|
|
||||||
|
|
||||||
BOOL fRet;
|
|
||||||
HANDLE hInFile, hOutFile;
|
|
||||||
LPCSTR lpApplicationName = NULL;
|
|
||||||
LPTSTR lpCommandLine;
|
|
||||||
LPTSTR lpCmd2 = NULL;
|
|
||||||
DWORD dwCreationFlags;
|
|
||||||
STARTUPINFO aStartupInfo;
|
|
||||||
PROCESS_INFORMATION aProcessInformation;
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
|
||||||
sa.lpSecurityDescriptor = NULL;
|
|
||||||
sa.bInheritHandle = TRUE;
|
|
||||||
|
|
||||||
fRet = CreatePipe(&hInFile, &hOutFile, &sa, 2048L);
|
|
||||||
if (!fRet) {
|
|
||||||
errno = GetLastError();
|
|
||||||
rb_sys_fail("mypopen: CreatePipe");
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&aStartupInfo, 0, sizeof (STARTUPINFO));
|
|
||||||
memset(&aProcessInformation, 0, sizeof (PROCESS_INFORMATION));
|
|
||||||
aStartupInfo.cb = sizeof (STARTUPINFO);
|
|
||||||
aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
|
||||||
|
|
||||||
if (reading) {
|
|
||||||
aStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
aStartupInfo.hStdOutput = hOutFile;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aStartupInfo.hStdInput = hInFile;
|
|
||||||
aStartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
}
|
|
||||||
aStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
|
||||||
|
|
||||||
dwCreationFlags = (NORMAL_PRIORITY_CLASS);
|
|
||||||
|
|
||||||
lpCommandLine = cmd;
|
|
||||||
if (NtHasRedirection(cmd) || isInternalCmd(cmd)) {
|
|
||||||
lpApplicationName = getenv("COMSPEC");
|
|
||||||
lpCmd2 = xmalloc(strlen(lpApplicationName) + 1 + strlen(cmd) + sizeof (" /c "));
|
|
||||||
sprintf(lpCmd2, "%s %s%s", lpApplicationName, " /c ", cmd);
|
|
||||||
lpCommandLine = lpCmd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
fRet = CreateProcess(lpApplicationName, lpCommandLine, &sa, &sa,
|
|
||||||
sa.bInheritHandle, dwCreationFlags, NULL, NULL, &aStartupInfo, &aProcessInformation);
|
|
||||||
errno = GetLastError();
|
|
||||||
|
|
||||||
if (lpCmd2)
|
|
||||||
free(lpCmd2);
|
|
||||||
|
|
||||||
if (!fRet) {
|
|
||||||
CloseHandle(hInFile);
|
|
||||||
CloseHandle(hOutFile);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(aProcessInformation.hThread);
|
|
||||||
|
|
||||||
if (reading) {
|
|
||||||
fd = _open_osfhandle((long)hInFile, (_O_RDONLY | pipemode));
|
|
||||||
CloseHandle(hOutFile);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fd = _open_osfhandle((long)hOutFile, (_O_WRONLY | pipemode));
|
|
||||||
CloseHandle(hInFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == -1) {
|
|
||||||
CloseHandle(reading ? hInFile : hOutFile);
|
|
||||||
CloseHandle(aProcessInformation.hProcess);
|
|
||||||
rb_sys_fail("mypopen: _open_osfhandle");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fp = (FILE *) fdopen(fd, mode)) == NULL) {
|
|
||||||
_close(fd);
|
|
||||||
CloseHandle(aProcessInformation.hProcess);
|
|
||||||
rb_sys_fail("mypopen: fdopen");
|
|
||||||
}
|
|
||||||
|
|
||||||
MyPopenRecord[slot].inuse = TRUE;
|
|
||||||
MyPopenRecord[slot].pipe = fp;
|
|
||||||
MyPopenRecord[slot].pid = (int)aProcessInformation.hProcess;
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern VALUE rb_last_status;
|
||||||
|
|
||||||
int
|
int
|
||||||
mypclose(FILE *fp)
|
mypclose(FILE *fp)
|
||||||
{
|
{
|
||||||
int i;
|
struct ChildRecord *child = FindPipedChildSlot(fp);
|
||||||
DWORD exitcode;
|
|
||||||
|
|
||||||
Sleep(100);
|
if (!child) {
|
||||||
for (i = 0; i < MYPOPENSIZE; i++) {
|
return -1; /* may closed in waitpid() */
|
||||||
if (MyPopenRecord[i].inuse && MyPopenRecord[i].pipe == fp)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (i >= MYPOPENSIZE) {
|
|
||||||
rb_fatal("Invalid file pointer passed to mypclose!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// get the return status of the process
|
|
||||||
//
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (_cwait(&exitcode, MyPopenRecord[i].pid, WAIT_CHILD) == -1) {
|
|
||||||
if (errno == ECHILD) {
|
|
||||||
fprintf(stderr, "mypclose: nosuch child as pid %x\n",
|
|
||||||
MyPopenRecord[i].pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
for (;;) {
|
|
||||||
if (GetExitCodeProcess((HANDLE)MyPopenRecord[i].pid, &exitcode)) {
|
|
||||||
if (exitcode == STILL_ACTIVE) {
|
|
||||||
//printf("Process is Active.\n");
|
|
||||||
Sleep(100);
|
|
||||||
TerminateProcess((HANDLE)MyPopenRecord[i].pid, 0); // ugly...
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (exitcode == 0) {
|
|
||||||
//printf("done.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//printf("never.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle((HANDLE)MyPopenRecord[i].pid);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// close the pipe
|
// close the pipe
|
||||||
//
|
//
|
||||||
|
child->pipe = NULL;
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
//
|
//
|
||||||
// free this slot
|
// get the return status of the process
|
||||||
//
|
//
|
||||||
|
rb_syswait(child->pid);
|
||||||
MyPopenRecord[i].inuse = FALSE;
|
return NUM2INT(rb_last_status);
|
||||||
MyPopenRecord[i].pipe = NULL;
|
|
||||||
MyPopenRecord[i].pid = 0;
|
|
||||||
|
|
||||||
return (int)((exitcode & 0xff) << 8);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
|
|
||||||
typedef char* CHARP;
|
|
||||||
/*
|
|
||||||
* The following code is based on the do_exec and do_aexec functions
|
|
||||||
* in file doio.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
int
|
||||||
do_spawn(cmd)
|
do_spawn(cmd)
|
||||||
char *cmd;
|
char *cmd;
|
||||||
{
|
{
|
||||||
register char **a;
|
struct ChildRecord *child = CreateChild(cmd, NULL, NULL, NULL, NULL);
|
||||||
register char *s;
|
if (!child) {
|
||||||
char **argv;
|
rb_sys_fail("do_spawn: CreateChild");
|
||||||
int status = -1;
|
|
||||||
char *shell, *cmd2;
|
|
||||||
int mode = NtSyncProcess ? P_WAIT : P_NOWAIT;
|
|
||||||
char quote;
|
|
||||||
char *exec;
|
|
||||||
|
|
||||||
/* save an extra exec if possible */
|
|
||||||
if ((shell = getenv("RUBYSHELL")) != 0) {
|
|
||||||
if (NtHasRedirection(cmd)) {
|
|
||||||
int i;
|
|
||||||
char *p;
|
|
||||||
char *argv[4];
|
|
||||||
char *cmdline = ALLOC_N(char, (strlen(cmd) * 2 + 1));
|
|
||||||
|
|
||||||
p=cmdline;
|
|
||||||
*p++ = '"';
|
|
||||||
for (s=cmd; *s;) {
|
|
||||||
if (*s == '"')
|
|
||||||
*p++ = '\\'; /* Escape d-quote */
|
|
||||||
*p++ = *s++;
|
|
||||||
}
|
|
||||||
*p++ = '"';
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
/* fprintf(stderr, "do_spawn: %s %s\n", shell, cmdline); */
|
|
||||||
argv[0] = shell;
|
|
||||||
argv[1] = "-c";
|
|
||||||
argv[2] = cmdline;
|
|
||||||
argv[4] = NULL;
|
|
||||||
status = spawnvpe(mode, argv[0], argv, environ);
|
|
||||||
/* return spawnle(mode, shell, shell, "-c", cmd, (char*)0, environ); */
|
|
||||||
free(cmdline);
|
|
||||||
return (int)((status & 0xff) << 8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ((shell = getenv("COMSPEC")) != 0) {
|
rb_syswait(child->pid);
|
||||||
if (NtHasRedirection(cmd) /* || isInternalCmd(cmd) */) {
|
return NUM2INT(rb_last_status);
|
||||||
status = spawnle(mode, shell, shell, "/c", cmd, (char*)0, environ);
|
}
|
||||||
return (int)((status & 0xff) << 8);
|
|
||||||
}
|
static struct ChildRecord *
|
||||||
|
CreateChild(char *cmd, SECURITY_ATTRIBUTES *psa, HANDLE hInput, HANDLE hOutput, HANDLE hError)
|
||||||
|
{
|
||||||
|
BOOL fRet;
|
||||||
|
DWORD dwCreationFlags;
|
||||||
|
STARTUPINFO aStartupInfo;
|
||||||
|
PROCESS_INFORMATION aProcessInformation;
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
char *shell;
|
||||||
|
struct ChildRecord *child;
|
||||||
|
|
||||||
|
child = FindFreeChildSlot();
|
||||||
|
if (!child) {
|
||||||
|
errno = EAGAIN;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv = ALLOC_N(CHARP, (strlen(cmd) / 2 + 2));
|
if (!psa) {
|
||||||
cmd2 = ALLOC_N(char, (strlen(cmd) + 1));
|
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
|
||||||
strcpy(cmd2, cmd);
|
sa.lpSecurityDescriptor = NULL;
|
||||||
a = argv;
|
sa.bInheritHandle = TRUE;
|
||||||
for (s = cmd2; *s;) {
|
psa = &sa;
|
||||||
while (*s && ISSPACE(*s)) s++;
|
|
||||||
if (*s == '"') {
|
|
||||||
quote = *s;
|
|
||||||
*(a++) = s++;
|
|
||||||
while (*s) {
|
|
||||||
if (*s == '\\' && *(s + 1) == quote) {
|
|
||||||
memmove(s, s + 1, strlen(s) + 1);
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
else if (*s == quote) {
|
|
||||||
s++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (*s) {
|
|
||||||
*(a++) = s;
|
|
||||||
while (*s && !ISSPACE(*s)) s++;
|
|
||||||
}
|
|
||||||
if (*s)
|
|
||||||
*s++ = '\0';
|
|
||||||
}
|
}
|
||||||
*a = NULL;
|
|
||||||
exec = NULL;
|
memset(&aStartupInfo, 0, sizeof (STARTUPINFO));
|
||||||
if (argv[0]) {
|
memset(&aProcessInformation, 0, sizeof (PROCESS_INFORMATION));
|
||||||
exec = ALLOC_N(char, (strlen(argv[0]) + 1));
|
aStartupInfo.cb = sizeof (STARTUPINFO);
|
||||||
if (argv[0][0] == '"' && argv[0][strlen(argv[0]) - 1] == '"') {
|
aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||||
strcpy(exec, &argv[0][1]);
|
if (hInput) {
|
||||||
exec[strlen(exec) - 1] = '\0';
|
aStartupInfo.hStdInput = hInput;
|
||||||
}
|
|
||||||
else {
|
|
||||||
strcpy(exec, argv[0]);
|
|
||||||
}
|
|
||||||
if ((status = spawnvpe(mode, exec, argv, environ)) == -1) {
|
|
||||||
free(exec);
|
|
||||||
free(argv);
|
|
||||||
free(cmd2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(exec);
|
else {
|
||||||
free(cmd2);
|
aStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
free(argv);
|
}
|
||||||
return (int)((status & 0xff) << 8);
|
if (hOutput) {
|
||||||
|
aStartupInfo.hStdOutput = hOutput;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aStartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
}
|
||||||
|
if (hError) {
|
||||||
|
aStartupInfo.hStdError = hError;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
aStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
dwCreationFlags = (NORMAL_PRIORITY_CLASS);
|
||||||
|
|
||||||
|
if ((shell = getenv("RUBYSHELL")) && NtHasRedirection(cmd)) {
|
||||||
|
char *tmp = ALLOCA_N(char, strlen(shell) + strlen(cmd) + sizeof (" -c "));
|
||||||
|
sprintf(tmp, "%s -c %s", shell, cmd);
|
||||||
|
cmd = tmp;
|
||||||
|
}
|
||||||
|
else if ((shell = getenv("COMSPEC")) &&
|
||||||
|
(NtHasRedirection(cmd) || isInternalCmd(cmd))) {
|
||||||
|
char *tmp = ALLOCA_N(char, strlen(shell) + strlen(cmd) + sizeof (" /c "));
|
||||||
|
sprintf(tmp, "%s /c %s", shell, cmd);
|
||||||
|
cmd = tmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shell = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUBY_CRITICAL({
|
||||||
|
fRet = CreateProcess(shell, cmd, psa, psa,
|
||||||
|
psa->bInheritHandle, dwCreationFlags, NULL, NULL,
|
||||||
|
&aStartupInfo, &aProcessInformation);
|
||||||
|
errno = GetLastError();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fRet) {
|
||||||
|
child->pid = 0; /* release the slot */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(aProcessInformation.hThread);
|
||||||
|
|
||||||
|
child->hProcess = aProcessInformation.hProcess;
|
||||||
|
child->pid = (pid_t)aProcessInformation.dwProcessId;
|
||||||
|
|
||||||
|
if (!IsWinNT()) {
|
||||||
|
/* On Win9x, make pid positive similarly to cygwin and perl */
|
||||||
|
child->pid = -child->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1062,6 +865,7 @@ NtHasRedirection (char *cmd)
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
case '<':
|
case '<':
|
||||||
|
case '|':
|
||||||
|
|
||||||
if (!inquote)
|
if (!inquote)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -2465,6 +2269,30 @@ void setservent (int stayopen) {}
|
||||||
#define WNOHANG -1
|
#define WNOHANG -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static pid_t
|
||||||
|
wait_child(struct ChildRecord *child, int *stat_loc, DWORD timeout)
|
||||||
|
{
|
||||||
|
DWORD exitcode;
|
||||||
|
|
||||||
|
if (!GetExitCodeProcess(child->hProcess, &exitcode)) {
|
||||||
|
/* If an error occured, return immediatly. */
|
||||||
|
errno = GetLastError();
|
||||||
|
if (errno == ERROR_INVALID_PARAMETER) {
|
||||||
|
errno = ECHILD;
|
||||||
|
}
|
||||||
|
CloseChildHandle(child);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (exitcode != STILL_ACTIVE) {
|
||||||
|
/* If already died, return immediatly. */
|
||||||
|
pid_t pid = child->pid;
|
||||||
|
CloseChildHandle(child);
|
||||||
|
if (stat_loc) *stat_loc = exitcode << 8;
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pid_t
|
pid_t
|
||||||
waitpid (pid_t pid, int *stat_loc, int options)
|
waitpid (pid_t pid, int *stat_loc, int options)
|
||||||
{
|
{
|
||||||
|
@ -2475,17 +2303,54 @@ waitpid (pid_t pid, int *stat_loc, int options)
|
||||||
} else {
|
} else {
|
||||||
timeout = INFINITE;
|
timeout = INFINITE;
|
||||||
}
|
}
|
||||||
RUBY_CRITICAL({
|
|
||||||
if (wait_events((HANDLE)pid, timeout) == WAIT_OBJECT_0) {
|
if (pid == -1) {
|
||||||
pid = _cwait(stat_loc, pid, 0);
|
int count = 0;
|
||||||
|
DWORD ret;
|
||||||
|
HANDLE events[MAXCHILDNUM + 1];
|
||||||
|
|
||||||
|
FOREACH_CHILD(child) {
|
||||||
|
if (!child->pid || child->pid < 0) continue;
|
||||||
|
if ((pid = wait_child(child, stat_loc, 0))) return pid;
|
||||||
|
events[count++] = child->hProcess;
|
||||||
|
} END_FOREACH_CHILD;
|
||||||
|
if (!count) {
|
||||||
|
errno = ECHILD;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
events[count] = interrupted_event;
|
||||||
pid = 0;
|
|
||||||
|
ret = WaitForMultipleEvents(count, events, FALSE, timeout, TRUE);
|
||||||
|
if (ret == WAIT_TIMEOUT) return 0;
|
||||||
|
if ((ret -= WAIT_OBJECT_0) == count) {
|
||||||
|
ResetSignal(interrupted_event);
|
||||||
|
errno = EINTR;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
});
|
if (ret > count) {
|
||||||
#if !defined __BORLANDC__
|
errno = GetLastError();
|
||||||
if (pid) *stat_loc <<= 8;
|
return -1;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
return wait_child(ChildRecord + ret, stat_loc, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct ChildRecord* child = FindChildSlot(pid);
|
||||||
|
if (!child) {
|
||||||
|
errno = ECHILD;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(pid = wait_child(child, stat_loc, timeout))) {
|
||||||
|
/* wait... */
|
||||||
|
if (wait_events(child->hProcess, timeout) != WAIT_OBJECT_0) {
|
||||||
|
/* still active */
|
||||||
|
pid = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2493,7 +2358,7 @@ waitpid (pid_t pid, int *stat_loc, int options)
|
||||||
|
|
||||||
int _cdecl
|
int _cdecl
|
||||||
gettimeofday(struct timeval *tv, struct timezone *tz)
|
gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||||
{
|
{
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
time_t t;
|
time_t t;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
@ -2559,39 +2424,56 @@ chown(const char *path, int owner, int group)
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#ifndef SIGINT
|
||||||
|
#define SIGINT 2
|
||||||
|
#endif
|
||||||
|
#ifndef SIGKILL
|
||||||
|
#define SIGKILL 9
|
||||||
|
#endif
|
||||||
int
|
int
|
||||||
kill(int pid, int sig)
|
kill(int pid, int sig)
|
||||||
{
|
{
|
||||||
if ((unsigned int)pid == GetCurrentProcessId())
|
int ret = 0;
|
||||||
|
|
||||||
|
if ((unsigned int)pid == GetCurrentProcessId() && sig != SIGKILL)
|
||||||
return raise(sig);
|
return raise(sig);
|
||||||
|
|
||||||
if (sig == 2 && pid > 0) {
|
if (sig == SIGINT && pid > 0) {
|
||||||
if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, (DWORD)pid)) {
|
RUBY_CRITICAL({
|
||||||
errno = GetLastError();
|
if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, (DWORD)pid)) {
|
||||||
return -1;
|
errno = GetLastError();
|
||||||
}
|
ret = -1;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (sig == 9 && pid > 0) {
|
else if (sig == SIGKILL && pid > 0) {
|
||||||
HANDLE hProc;
|
HANDLE hProc;
|
||||||
|
|
||||||
hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
|
RUBY_CRITICAL({
|
||||||
if (hProc == NULL || hProc == INVALID_HANDLE_VALUE) {
|
hProc = OpenProcess(PROCESS_TERMINATE, FALSE,
|
||||||
errno = GetLastError();
|
IsWin95() ? -pid : pid);
|
||||||
return -1;
|
if (hProc == NULL || hProc == INVALID_HANDLE_VALUE) {
|
||||||
}
|
if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
||||||
if (!TerminateProcess(hProc, 0)) {
|
errno = ESRCH;
|
||||||
errno = GetLastError();
|
}
|
||||||
|
else {
|
||||||
|
errno = EPERM;
|
||||||
|
}
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else if (!TerminateProcess(hProc, 0)) {
|
||||||
|
errno = EPERM;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
CloseHandle(hProc);
|
CloseHandle(hProc);
|
||||||
return -1;
|
});
|
||||||
}
|
|
||||||
CloseHandle(hProc);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2609,14 +2491,16 @@ wait()
|
||||||
char *
|
char *
|
||||||
win32_getenv(const char *name)
|
win32_getenv(const char *name)
|
||||||
{
|
{
|
||||||
char *curitem = NULL; /* XXX threadead */
|
static char *curitem = NULL;
|
||||||
DWORD curlen = 0; /* XXX threadead */
|
static DWORD curlen = 0;
|
||||||
DWORD needlen;
|
DWORD needlen;
|
||||||
|
|
||||||
curlen = 512;
|
if (curitem == NULL || curlen == 0) {
|
||||||
curitem = ALLOC_N(char, curlen);
|
curlen = 512;
|
||||||
|
curitem = ALLOC_N(char, curlen);
|
||||||
|
}
|
||||||
|
|
||||||
needlen = GetEnvironmentVariable(name,curitem,curlen);
|
needlen = GetEnvironmentVariable(name, curitem, curlen);
|
||||||
if (needlen != 0) {
|
if (needlen != 0) {
|
||||||
while (needlen > curlen) {
|
while (needlen > curlen) {
|
||||||
REALLOC_N(curitem, char, needlen);
|
REALLOC_N(curitem, char, needlen);
|
||||||
|
@ -3070,3 +2954,35 @@ VALUE win32_asynchronize(asynchronous_func_t func,
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char **win32_get_environ(void)
|
||||||
|
{
|
||||||
|
char *envtop, *env;
|
||||||
|
char **myenvtop, **myenv;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
envtop = GetEnvironmentStrings();
|
||||||
|
for (env = envtop, num = 0; *env; env += strlen(env) + 1)
|
||||||
|
if (*env != '=') num++;
|
||||||
|
|
||||||
|
myenvtop = ALLOC_N(char*, num + 1);
|
||||||
|
for (env = envtop, myenv = myenvtop; *env; env += strlen(env) + 1) {
|
||||||
|
if (*env != '=') {
|
||||||
|
*myenv = ALLOC_N(char, strlen(env) + 1);
|
||||||
|
strcpy(*myenv, env);
|
||||||
|
myenv++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*myenv = NULL;
|
||||||
|
FreeEnvironmentStrings(envtop);
|
||||||
|
|
||||||
|
return myenvtop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void win32_free_environ(char **env)
|
||||||
|
{
|
||||||
|
char **t = env;
|
||||||
|
|
||||||
|
while (*t) free(*t++);
|
||||||
|
free(env);
|
||||||
|
}
|
||||||
|
|
|
@ -232,6 +232,8 @@ extern struct servent * mygetservbyname(char *, char *);
|
||||||
extern struct servent * mygetservbyport(int, char *);
|
extern struct servent * mygetservbyport(int, char *);
|
||||||
extern char *win32_getenv(const char *);
|
extern char *win32_getenv(const char *);
|
||||||
extern int myrename(const char *, const char *);
|
extern int myrename(const char *, const char *);
|
||||||
|
extern char **win32_get_environ(void);
|
||||||
|
extern void win32_free_environ(char **);
|
||||||
|
|
||||||
extern int chown(const char *, int, int);
|
extern int chown(const char *, int, int);
|
||||||
extern int link(char *, char *);
|
extern int link(char *, char *);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче