static VALUE rhash_create(VALUE klass, SEL sel, int argc, VALUE *argv) { if (argc == 1) { VALUE tmp = rhash_try_convert(Qnil, 0, argv[0]); if (!NIL_P(tmp)) { VALUE hash = rhash_alloc(klass, 0); if (IS_RHASH(tmp)) { GC_WB(&RHASH(hash)->tbl, st_copy(RHASH(tmp)->tbl)); } else { VALUE keys = rb_hash_keys(tmp); for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) { VALUE key = RARRAY_AT(keys, i); VALUE val = rb_hash_lookup(tmp, key); rhash_aset(hash, 0, key, val); } } return hash; } tmp = rb_check_array_type(argv[0]); if (!NIL_P(tmp)) { VALUE hash = rhash_alloc(klass, 0); for (int i = 0; i < RARRAY_LEN(tmp); ++i) { VALUE v = rb_check_array_type(RARRAY_AT(tmp, i)); if (NIL_P(v)) { continue; } const long len = RARRAY_LEN(v); if (len < 1 || 2 < len) { continue; } rhash_aset(hash, 0, RARRAY_AT(v, 0), RARRAY_AT(v, 1)); } return hash; } } if (argc % 2 != 0) { rb_raise(rb_eArgError, "odd number of arguments for Hash"); } VALUE hash = rhash_alloc(klass, 0); for (int i = 0; i < argc; i += 2) { rb_hash_aset(hash, argv[i], argv[i + 1]); } return hash; }
/* Export an argv that does sane, reasonable things instead of doing weird * shit. * * Return value is largely irrelevant */ VALUE posix_execve(VALUE self, VALUE _binary, VALUE _argv, VALUE _envp) { /* Iterators */ int i; VALUE akey, keys, envk; /* Binary to load in the new process */ char* binary = StringValueCStr(_binary); /* Construct our new process' argv. Onus is on * the programmer to set ARGV[0] to something * reasonable. */ char** argv = malloc(sizeof(char*)*RARRAY_LEN(_argv) + 1); argv[0] = NULL; for (i = 0; i < RARRAY_LEN(_argv); i++) { argv[i] = StringValuePtr(RARRAY_PTR(_argv)[i]); argv[i+1] = NULL; /* Ensure that we're null terminated */ } /* Construct our environment. Note that this totally ignores the precedent * set by Process#spawn, Kernel#exec and fiends */ char **envp; if (RHASH(_envp)->ntbl) { envp = malloc(sizeof(char**)*RHASH(_envp)->ntbl->num_entries + 1); keys = rb_hash_keys(_envp); for (i = 0; i < RARRAY_LEN(keys); i++) { akey = RARRAY_PTR(keys)[i]; envk = rb_hash_aref(_envp, akey); asprintf(&envp[i], "%s=%s", StringValuePtr(akey), StringValuePtr(envk)); envp[i+1] = NULL; /* Ensure that we're null terminated */ } } else { envp = malloc(sizeof(char**)); envp[0] = NULL; } execve(binary, argv, envp); fprintf(stderr, "Error: %s", strerror(errno)); }
static VALUE rb_thread_keys(VALUE self, SEL sel) { VALUE h = rb_vm_thread_locals(self, false); return h == Qnil ? rb_ary_new() : rb_hash_keys(h); }