Пример #1
0
VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE result = Qnil;	/* OK */
    struct METHOD *data;
    int state;
    volatile int safe = -1;

    Data_Get_Struct(method, struct METHOD, data);
    if (data->recv == Qundef) {
	rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    PUSH_TAG(PROT_NONE);
    if (OBJ_TAINTED(method)) {
	safe = rb_safe_level();
	if (rb_safe_level() < 4) {
	    rb_set_safe_level_force(4);
	}
    }
    if ((state = EXEC_TAG()) == 0) {
	PASS_PASSED_BLOCK();
	result = th_call0(GET_THREAD(),
			  data->klass, data->recv, data->id, data->oid,
			  argc, argv, data->body, 0);
    }
    POP_TAG();
    if (safe >= 0)
	rb_set_safe_level_force(safe);
    if (state)
	JUMP_TAG(state);
    return result;
}
Пример #2
0
VALUE
rb_method_call(int argc, VALUE *argv, VALUE method)
{
    VALUE result = Qnil;	/* OK */
    struct METHOD *data;
    int state;
    volatile int safe = -1;

    Data_Get_Struct(method, struct METHOD, data);
    if (data->recv == Qundef) {
	rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    PUSH_TAG();
    if (OBJ_TAINTED(method)) {
	safe = rb_safe_level();
	if (rb_safe_level() < 4) {
	    rb_set_safe_level_force(4);
	}
    }
    if ((state = EXEC_TAG()) == 0) {
	rb_thread_t *th = GET_THREAD();
	VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
			 int argc, const VALUE *argv, const NODE *body, int nosuper);

	PASS_PASSED_BLOCK_TH(th);
	result = rb_vm_call(th, data->oclass, data->recv, data->id, data->oid,
			    argc, argv, data->body, 0);
    }
    POP_TAG();
    if (safe >= 0)
	rb_set_safe_level_force(safe);
    if (state)
	JUMP_TAG(state);
    return result;
}
Пример #3
0
VALUE
rb_method_call(VALUE method, SEL sel, int argc, VALUE *argv)
{
    rb_vm_method_t *data;

    Data_Get_Struct(method, rb_vm_method_t, data);
    if (data->recv == Qundef) {
	rb_raise(rb_eTypeError, "can't call unbound method; bind first");
    }
    
    int safe = -1;
    if (OBJ_TAINTED(method)) {
	safe = rb_safe_level();
	if (rb_safe_level() < 4) {
	    rb_set_safe_level_force(4);
	}
    }

    VALUE result = rb_vm_method_call(data, rb_vm_current_block(), argc, argv);

    if (safe >= 0) {
	rb_set_safe_level_force(safe);
    }

    return result;
}
Пример #4
0
void
rb_secure(int level)
{
    if (level <= rb_safe_level()) {
	if (rb_frame_callee()) {
	    rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
		     rb_id2name(rb_frame_callee()), rb_safe_level());
	}
	else {
	    rb_raise(rb_eSecurityError, "Insecure operation at level %d",
		     rb_safe_level());
	}
    }
}
Пример #5
0
VALUE
rb_require_safe(VALUE fname, int safe)
{
    volatile VALUE result = Qnil;
    rb_thread_t *th = GET_THREAD();
    volatile VALUE errinfo = th->errinfo;
    int state;
    struct {
	int safe;
    } volatile saved;
    char *volatile ftptr = 0;

    PUSH_TAG();
    saved.safe = rb_safe_level();
    if ((state = EXEC_TAG()) == 0) {
	VALUE path;
	long handle;
	int found;

	rb_set_safe_level_force(safe);
	FilePathValue(fname);
	rb_set_safe_level_force(0);
	found = search_required(fname, &path, safe);
	if (found) {
	    if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
		result = Qfalse;
	    }
	    else {
		switch (found) {
		  case 'r':
		    rb_load_internal(path, 0);
		    break;

		  case 's':
		    handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
						    path, 0, path);
		    rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
		    break;
		}
		rb_provide_feature(path);
		result = Qtrue;
	    }
	}
    }
    POP_TAG();
    load_unlock(ftptr, !state);

    rb_set_safe_level_force(saved.safe);
    if (state) {
	JUMP_TAG(state);
    }

    if (NIL_P(result)) {
	load_failed(fname);
    }

    th->errinfo = errinfo;

    return result;
}
Пример #6
0
static VALUE
trap(int sig, sighandler_t func, VALUE command)
{
    sighandler_t oldfunc;
    VALUE oldcmd;
    rb_vm_t *vm = GET_VM();

    /*
     * Be careful. ruby_signal() and trap_list[sig].cmd must be changed
     * atomically. In current implementation, we only need to don't call
     * RUBY_VM_CHECK_INTS().
     */
    oldfunc = ruby_signal(sig, func);
    oldcmd = vm->trap_list[sig].cmd;
    switch (oldcmd) {
      case 0:
      case Qtrue:
	if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
	else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
	else oldcmd = Qnil;
	break;
      case Qnil:
	break;
      case Qundef:
	oldcmd = rb_str_new2("EXIT");
	break;
    }

    vm->trap_list[sig].cmd = command;
    vm->trap_list[sig].safe = rb_safe_level();

    return oldcmd;
}
Пример #7
0
static int
load_encoding(const char *name)
{
    VALUE enclib = rb_sprintf("enc/%s.so", name);
    VALUE verbose = ruby_verbose;
    VALUE debug = ruby_debug;
    VALUE errinfo;
    char *s = RSTRING_PTR(enclib) + 4, *e = RSTRING_END(enclib) - 3;
    int loaded;
    int idx;

    while (s < e) {
	if (!ISALNUM(*s)) *s = '_';
	else if (ISUPPER(*s)) *s = (char)TOLOWER(*s);
	++s;
    }
    FL_UNSET(enclib, FL_TAINT);
    enclib = rb_fstring(enclib);
    ruby_verbose = Qfalse;
    ruby_debug = Qfalse;
    errinfo = rb_errinfo();
    loaded = rb_require_internal(enclib, rb_safe_level());
    ruby_verbose = verbose;
    ruby_debug = debug;
    rb_set_errinfo(errinfo);
    if (loaded < 0 || 1 < loaded) return -1;
    if ((idx = rb_enc_registered(name)) < 0) return -1;
    if (enc_autoload_p(enc_table.list[idx].enc)) return -1;
    return idx;
}
Пример #8
0
/* call-seq:
 *   unfreeze -> self
 * 
 * Unfreezes the given object.  Will raise a +SecurityError+ if
 * <tt>$SAFE</tt> > 0.  Has no effect if the object is not yet frozen. */
static VALUE evilr_unfreeze(VALUE self) {
  if (rb_safe_level() > 0) {
    rb_raise(rb_eSecurityError, "can't unfreeze objects when $SAFE > 0");
  }
  FL_UNSET(self, FL_FREEZE);
  return self;
}
static void
remove_method(VALUE klass, ID mid)
{
    st_data_t key, data;
    rb_method_entry_t *me = 0;

    if (klass == rb_cObject) {
	rb_secure(4);
    }
    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
	rb_raise(rb_eSecurityError, "Insecure: can't remove method");
    }
    rb_check_frozen(klass);
    if (mid == object_id || mid == id__send__ || mid == idInitialize) {
	rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
    }

    if (!st_lookup(RCLASS_M_TBL(klass), mid, &data) ||
	!(me = (rb_method_entry_t *)data) ||
	(!me->def || me->def->type == VM_METHOD_TYPE_UNDEF)) {
	rb_name_error(mid, "method `%s' not defined in %s",
		      rb_id2name(mid), rb_class2name(klass));
    }
    key = (st_data_t)mid;
    st_delete(RCLASS_M_TBL(klass), &key, &data);

    rb_vm_check_redefinition_opt_method(me, klass);
    rb_clear_cache_for_undef(klass, mid);
    rb_unlink_method_entry(me);

    CALL_METHOD_HOOK(klass, removed, mid);
}
Пример #10
0
VALUE
rb_f_eval(int argc, VALUE *argv, VALUE self)
{
    VALUE src, scope, vfile, vline;
    const char *file = "(eval)";
    int line = 1;

    rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
    if (rb_safe_level() >= 4) {
	StringValue(src);
	if (!NIL_P(scope) && !OBJ_TAINTED(scope)) {
	    rb_raise(rb_eSecurityError,
		     "Insecure: can't modify trusted binding");
	}
    }
    else {
	SafeStringValue(src);
    }
    if (argc >= 3) {
	StringValue(vfile);
    }
    if (argc >= 4) {
	line = NUM2INT(vline);
    }

    if (!NIL_P(vfile))
	file = RSTRING_PTR(vfile);
    return eval_string(self, src, scope, file, line);
}
Пример #11
0
static VALUE
trap(struct trap_arg *arg)
{
    sighandler_t oldfunc;
    sighandler_t func = arg->func;
    VALUE oldcmd;
    VALUE command = arg->cmd;
    int sig = arg->sig;

    oldfunc = ruby_signal(sig, func);
    oldcmd = rb_vm_trap_cmd_for_signal(sig);
    if (oldcmd == 0) {
	if (oldfunc == SIG_IGN)
	    oldcmd = rb_str_new2("IGNORE");
	else if (oldfunc == sighandler)
	    oldcmd = rb_str_new2("DEFAULT");
	else
	    oldcmd = Qnil;
    }
    else if (oldcmd == Qundef)
	oldcmd = rb_str_new2("EXIT");

    // Assign trap to signal
    rb_vm_set_trap_for_signal(command, rb_safe_level(), sig);

    return oldcmd;
}
Пример #12
0
static inline void*
getPointer(VALUE value, int type)
{
    if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_AbstractMemoryClass)) {

        return ((AbstractMemory *) DATA_PTR(value))->address;

    } else if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_StructClass)) {

        AbstractMemory* memory = ((Struct *) DATA_PTR(value))->pointer;
        return memory != NULL ? memory->address : NULL;

    } else if (type == T_STRING) {

        if (rb_safe_level() >= 1 && OBJ_TAINTED(value)) {
            rb_raise(rb_eSecurityError, "Unsafe string parameter");
        }
        return StringValuePtr(value);

    } else if (type == T_NIL) {

        return NULL;

    } else if (rb_respond_to(value, id_to_ptr)) {

        VALUE ptr = rb_funcall2(value, id_to_ptr, 0, NULL);
        if (rb_obj_is_kind_of(ptr, rbffi_AbstractMemoryClass) && TYPE(ptr) == T_DATA) {
            return ((AbstractMemory *) DATA_PTR(ptr))->address;
        }
        rb_raise(rb_eArgError, "to_ptr returned an invalid pointer");
    }

    rb_raise(rb_eArgError, ":pointer argument is not a valid pointer");
    return NULL;
}
Пример #13
0
static VALUE
trap(struct trap_arg *arg)
{
    sighandler_t oldfunc, func = arg->func;
    VALUE oldcmd, command = arg->cmd;
    int sig = arg->sig;
    rb_vm_t *vm = GET_VM();

    oldfunc = ruby_signal(sig, func);
    oldcmd = vm->trap_list[sig].cmd;
    switch (oldcmd) {
      case 0:
	if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
	else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
	else oldcmd = Qnil;
	break;
      case Qundef:
	oldcmd = rb_str_new2("EXIT");
	break;
    }

    vm->trap_list[sig].cmd = command;
    vm->trap_list[sig].safe = rb_safe_level();
    /* enable at least specified signal. */
#if USE_TRAP_MASK
#ifdef HAVE_SIGPROCMASK
    sigdelset(&arg->mask, sig);
#else
    arg->mask &= ~sigmask(sig);
#endif
#endif
    return oldcmd;
}
Пример #14
0
static VALUE
env_aset(VALUE obj, SEL sel, VALUE nm, VALUE val)
{
    if (rb_safe_level() >= 4) {
	rb_raise(rb_eSecurityError, "can't change environment variable");
    }

    if (NIL_P(val)) {
	env_delete(obj, nm);
	return Qnil;
    }
    StringValue(nm);
    StringValue(val);
    const char *name = RSTRING_PTR(nm);
    const char *value = RSTRING_PTR(val);
    if (strlen(name) != RSTRING_LEN(nm)) {
	rb_raise(rb_eArgError, "bad environment variable name");
    }
    if (strlen(value) != RSTRING_LEN(val)) {
	rb_raise(rb_eArgError, "bad environment variable value");
    }

    ruby_setenv(name, value);
    if (strcmp(name, PATH_ENV) == 0) {
	if (OBJ_TAINTED(val)) {
	    /* already tainted, no check */
	    path_tainted = 1;
	    return val;
	}
	else {
	    path_tainted_p(value);
	}
    }
    return val;
}
Пример #15
0
/*
 * call-seq:
 *   basicsocket.shutdown([how]) => 0
 *
 * Calls shutdown(2) system call.
 *
 * s.shutdown(Socket::SHUT_RD) disallows further read.
 *
 * s.shutdown(Socket::SHUT_WR) disallows further write.
 *
 * s.shutdown(Socket::SHUT_RDWR) disallows further read and write.
 *
 * _how_ can be symbol or string:
 * - :RD, :SHUT_RD, "RD" and "SHUT_RD" are accepted as Socket::SHUT_RD.
 * - :WR, :SHUT_WR, "WR" and "SHUT_WR" are accepted as Socket::SHUT_WR.
 * - :RDWR, :SHUT_RDWR, "RDWR" and "SHUT_RDWR" are accepted as Socket::SHUT_RDWR.
 *
 *   UNIXSocket.pair {|s1, s2|
 *     s1.puts "ping"
 *     s1.shutdown(:WR)
 *     p s2.read          #=> "ping\n"
 *     s2.puts "pong"
 *     s2.close
 *     p s1.read          #=> "pong\n"
 *   }
 *
 */
static VALUE
bsock_shutdown(int argc, VALUE *argv, VALUE sock)
{
UNRUBBY_SOCKET_HACK;
    VALUE howto;
    int how;
    rb_io_t *fptr;

    if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
	rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
    }
    rb_scan_args(argc, argv, "01", &howto);
    if (howto == Qnil)
	how = SHUT_RDWR;
    else {
	how = rsock_shutdown_how_arg(howto);
        if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
	    rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
	}
    }
    GetOpenFile(sock, fptr);
    if (shutdown(fptr->fd, how) == -1)
	rb_sys_fail(0);

    return INT2FIX(0);
}
Пример #16
0
static VALUE fcgi_stream_gets(VALUE self) {
  FCGX_Stream *stream;
  char buff[BUFSIZ];
  VALUE str = rb_str_new(0,0);
  OBJ_TAINT(str);

  if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
    rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
  }

  Data_Get_Struct(self, FCGX_Stream, stream);

  for (;;) {
    if (FCGX_GetLine(buff, BUFSIZ, stream) == NULL) {
      CHECK_STREAM_ERROR(stream);
      break;
    }
    rb_str_cat(str, buff, strlen(buff));
    if (strchr(buff, '\n')) break;
  }
  if (RSTRING_LEN(str) > 0)
    return str;
  else
    return Qnil;
}
Пример #17
0
VALUE
rb_require(const char *fname)
{
    VALUE fn = rb_str_new2(fname);
    OBJ_FREEZE(fn);
    return rb_require_safe(fn, rb_safe_level());
}
Пример #18
0
static VALUE
memory_put_bytes(int argc, VALUE* argv, VALUE self)
{
    AbstractMemory* ptr = MEMORY(self);
    VALUE offset = Qnil, str = Qnil, rbIndex = Qnil, rbLength = Qnil;
    long off, len, idx;
    int nargs = rb_scan_args(argc, argv, "22", &offset, &str, &rbIndex, &rbLength);

    Check_Type(str, T_STRING);

    off = NUM2LONG(offset);
    idx = nargs > 2 ? NUM2LONG(rbIndex) : 0;
    if (idx < 0) {
        rb_raise(rb_eRangeError, "index canot be less than zero");
        return Qnil;
    }
    len = nargs > 3 ? NUM2LONG(rbLength) : (RSTRING_LEN(str) - idx);
    if ((idx + len) > RSTRING_LEN(str)) {
        rb_raise(rb_eRangeError, "index+length is greater than size of string");
        return Qnil;
    }

    checkWrite(ptr);
    checkBounds(ptr, off, len);

    if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
        rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
        return Qnil;
    }
    memcpy(ptr->address + off, RSTRING_PTR(str) + idx, len);

    return self;
}
Пример #19
0
static void
rb_struct_modify(VALUE s)
{
    if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
    if (!OBJ_TAINTED(s) && rb_safe_level() >= 4)
       rb_raise(rb_eSecurityError, "Insecure: can't modify Struct");
}
Пример #20
0
static VALUE
define_final(VALUE os, SEL sel, int argc, VALUE *argv)
{
    VALUE obj, block;

    rb_scan_args(argc, argv, "11", &obj, &block);
    if (argc == 1) {
	block = rb_block_proc();
    }
    else if (!rb_respond_to(block, rb_intern("call"))) {
	rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
		rb_obj_classname(block));
    }

    if (SPECIAL_CONST_P(obj)) {
	rb_raise(rb_eArgError, "immediate types are not finalizable");
    }

    rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
	    &finalizer_key);
    if (finalizer == NULL) {
	finalizer = (rb_vm_finalizer_t *)
	    rb_objc_newobj(sizeof(rb_vm_finalizer_t *));
	finalizer->klass = rb_cFinalizer;
	finalizer->objid = rb_obj_id(obj, 0);
	GC_WB(&finalizer->finalizers, rb_ary_new());
	rb_objc_set_associative_ref((void *)obj, &finalizer_key, finalizer);
	rb_vm_register_finalizer(finalizer); 
    }

    rb_ary_push(finalizer->finalizers, block);
    
    // For RubySpec conformance.
    return rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
}
Пример #21
0
static VALUE
fenix_coerce_to_path(VALUE obj)
{
	VALUE tmp;
	ID to_path;
	rb_encoding *enc;
	int level = rb_safe_level();

	if (insecure_obj_p(obj, level)) {
		rb_insecure_operation();
	}

	CONST_ID(to_path, "to_path");
	tmp = rb_check_funcall(obj, to_path, 0, 0);
	if (tmp == Qundef)
		tmp = obj;

	StringValue(tmp);

	tmp = file_path_convert(tmp);
	if (obj != tmp && insecure_obj_p(tmp, level)) {
		rb_insecure_operation();
	}
	enc = rb_enc_get(tmp);
	if (!rb_enc_asciicompat(enc)) {
		tmp = rb_str_inspect(tmp);
		rb_raise(rb_eEncCompatError, "path name must be ASCII-compatible (%s): %s",
			 rb_enc_name(enc), RSTRING_PTR(tmp));
	}
	return rb_str_new4(tmp);
}
Пример #22
0
/*
 * call-seq:
 *   proc.dump(limit) => String
 *
 * Dump a Proc to a String.
 */
static VALUE proc_dump(VALUE self, VALUE limit)
{
  if(rb_safe_level() >= 4)
  {
    /* no access to potentially sensitive data from the sandbox */
    rb_raise(rb_eSecurityError, "Insecure: can't dump proc");
  }

  {
#ifdef RUBY_VM
    rb_proc_t * p;
    VALUE iseq, str;
    rb_iseq_t * iseqdat;
    GetProcPtr(self, p);
    iseq = p->block.iseq->self;
    iseqdat = iseq_check(iseq);
    iseqdat->type = ISEQ_TYPE_TOP; /* TODO: is this right? */
    str = marshal_dump(iseq, limit);
    return str;
#else
    struct BLOCK * b;
    VALUE body, var, arr;

    Data_Get_Struct(self, struct BLOCK, b);
    body = wrap_node(b->body);
    var = wrap_node(b->var);
    arr = rb_assoc_new(body, var);
    return marshal_dump(arr, limit);
#endif
  }
}
Пример #23
0
static void
dir_check(VALUE dir)
{
    if (!OBJ_TAINTED(dir) && rb_safe_level() >= 4)
	rb_raise(rb_eSecurityError, "Insecure: operation on untainted Dir");
    rb_check_frozen(dir);
}
Пример #24
0
void
rb_error_untrusted(VALUE obj)
{
    if (rb_safe_level() >= 4) {
	rb_raise(rb_eSecurityError, "Insecure: can't modify %s",
		 rb_obj_classname(obj));
    }
}
Пример #25
0
static void
secure_visibility(VALUE self)
{
    if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
	rb_raise(rb_eSecurityError,
		 "Insecure: can't change method visibility");
    }
}
Пример #26
0
VALUE
rb_format_exception_message(VALUE exc)
{
    const int old_level = rb_safe_level();
    rb_set_safe_level_force(0);

    return rb_ensure(format_message, exc, restore_level, (VALUE)old_level);
}
Пример #27
0
void
rb_check_safe_obj(VALUE x)
{
    if (rb_safe_level() > 0 && OBJ_TAINTED(x)) {
	rb_insecure_operation();
    }
    rb_secure(4);
}
Пример #28
0
void
rb_undef(VALUE klass, ID id)
{
    // TODO
#if 0
    VALUE origin;
    NODE *body;

#if 0 // TODO
    if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
	rb_secure(4);
    }
#endif
    if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
		 rb_id2name(id));
    }
    rb_frozen_class_p(klass);
    if (id == object_id || id == __send__ || id == idInitialize) {
	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
    }
    /* TODO: warn if a very important method of NSObject is undefined 
     * by default, pure objc methods are not exposed by introspections API 
     */
    body = search_method(klass, id, &origin);
    if (!body || !body->nd_body) {
	const char *s0 = " class";
	VALUE c = klass;

	if (RCLASS_SINGLETON(c)) {
	    VALUE obj = rb_iv_get(klass, "__attached__");

	    switch (TYPE(obj)) {
	      case T_MODULE:
	      case T_CLASS:
		c = obj;
		s0 = "";
	    }
	}
	else if (TYPE(c) == T_MODULE) {
	    s0 = " module";
	}
	rb_name_error(id, "undefined method `%s' for%s `%s'",
		      rb_id2name(id), s0, rb_class2name(c));
    }

    rb_add_method(klass, id, 0, NOEX_PUBLIC);

    if (RCLASS_SINGLETON(klass)) {
	rb_funcall(rb_iv_get(klass, "__attached__"),
		   singleton_undefined, 1, ID2SYM(id));
    }
    else {
	rb_funcall(klass, undefined, 1, ID2SYM(id));
    }
#endif
}
Пример #29
0
/*
 * call-seq:
 *   require_relative(string) -> true or false
 *
 * Ruby tries to load the library named _string_ relative to the requiring
 * file's path.  If the file's path cannot be determined a LoadError is raised.
 * If a file is loaded +true+ is returned and false otherwise.
 */
VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
	rb_loaderror("cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}
Пример #30
0
static void
init_sigchld(int sig)
{
    sighandler_t oldfunc;

    oldfunc = ruby_signal(sig, SIG_DFL);
    if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
	ruby_signal(sig, oldfunc);
    } else {
	rb_vm_set_trap_for_signal((VALUE)0, rb_safe_level(), sig);
    }
}