ext/rubysl/pty/pty.c in rubysl-pty-2.0.2 vs ext/rubysl/pty/pty.c in rubysl-pty-2.0.3

- old
+ new

@@ -313,10 +313,13 @@ if (ioctl(slavefd, I_PUSH, "ptem") == -1) goto error; if (ioctl(slavefd, I_PUSH, "ldterm") == -1) goto error; if (ioctl(slavefd, I_PUSH, "ttcompat") == -1) goto error; #endif + rb_fd_fix_cloexec(masterfd); + rb_fd_fix_cloexec(slavefd); + *master = masterfd; *slave = slavefd; strlcpy(SlaveName, slavedevice, DEVICELEN); return 0; @@ -337,10 +340,14 @@ if (openpty(master, slave, SlaveName, (struct termios *)0, (struct winsize *)0) == -1) { if (!fail) return -1; rb_raise(rb_eRuntimeError, "openpty() failed"); } + + rb_fd_fix_cloexec(*master); + rb_fd_fix_cloexec(*slave); + if (no_mesg(SlaveName, nomesg) == -1) { if (!fail) return -1; rb_raise(rb_eRuntimeError, "can't chmod slave pty"); } @@ -354,10 +361,14 @@ if (!fail) return -1; rb_raise(rb_eRuntimeError, "_getpty() failed"); } *slave = open(name, O_RDWR); + + rb_fd_fix_cloexec(*master); + rb_fd_fix_cloexec(*slave); + /* error check? */ strlcpy(SlaveName, name, DEVICELEN); return 0; #elif defined(HAVE_PTSNAME) @@ -380,10 +391,14 @@ #if defined I_PUSH && !defined linux if(ioctl(slavefd, I_PUSH, "ptem") == -1) goto error; if(ioctl(slavefd, I_PUSH, "ldterm") == -1) goto error; ioctl(slavefd, I_PUSH, "ttcompat"); #endif + + rb_fd_fix_cloexec(masterfd); + rb_fd_fix_cloexec(slavefd); + *master = masterfd; *slave = slavefd; strlcpy(SlaveName, slavedevice, DEVICELEN); return 0; @@ -399,13 +414,15 @@ for (p = deviceNo; *p != NULL; p++) { snprintf(MasterName, sizeof MasterName, MasterDevice, *p); if ((masterfd = open(MasterName,O_RDWR,0)) >= 0) { *master = masterfd; + rb_fd_fix_cloexec(*master); snprintf(SlaveName, DEVICELEN, SlaveDevice, *p); if ((slavefd = open(SlaveName,O_RDWR,0)) >= 0) { *slave = slavefd; + rb_fd_fix_cloexec(*slave); if (chown(SlaveName, getuid(), getgid()) != 0) goto error; if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0) goto error; return 0; } close(masterfd); @@ -487,11 +504,11 @@ rb_str_new2("r")); rb_ivar_set(rport, rb_intern("@path"), rb_str_new2(SlaveName)); wport = rb_funcall(rb_cFile, rb_intern("new"), 2, INT2FIX(dup(info.fd)), - rb_str_new2("r")); + rb_str_new2("w")); rb_ivar_set(wport, rb_intern("@path"), rb_str_new2(SlaveName)); rb_funcall(wport, rb_intern("sync="), 1, Qtrue); res = rb_ary_new3(3, (VALUE)rport, (VALUE)wport, INT2FIX(info.child_pid)); @@ -501,10 +518,55 @@ return Qnil; } return res; } +static VALUE +pty_close_pty(VALUE assoc) +{ + VALUE io; + int i; + + for (i = 0; i < 2; i++) { + io = rb_ary_entry(assoc, i); + if (RB_TYPE_P(io, T_FILE) && 0 <= RFILE(io)->fptr->fd) { + rb_io_close(io); + } + } + return Qnil; +} + +static VALUE +pty_open(VALUE klass) { + int master_fd, slave_fd; + char slavename[DEVICELEN]; + VALUE master_io, slave_file; + rb_io_t *master_fptr, *slave_fptr; + VALUE assoc; + + getDevice(&master_fd, &slave_fd, slavename, 1); + + master_io = rb_funcall(rb_cIO, rb_intern("new"), 2, INT2FIX(master_fd), + rb_str_new2("r+")); + + rb_funcall(master_io, rb_intern("sync="), 1, Qtrue); + + slave_file = rb_funcall(rb_cFile, rb_intern("new"), 2, INT2FIX(slave_fd), + rb_str_new2("r+")); + + rb_ivar_set(slave_file, rb_intern("@path"), + rb_obj_freeze(rb_str_new2(slavename))); + rb_funcall(slave_file, rb_intern("sync="), 1, Qtrue); + + assoc = rb_assoc_new(master_io, slave_file); + + if (rb_block_given_p()) { + return rb_ensure(rb_yield, assoc, pty_close_pty, assoc); + } + return assoc; +} + /* * Document-class: PTY::ChildExited * * Thrown when PTY#check is called for a pid that represents a process that * has exited. @@ -521,9 +583,10 @@ Init_pty() { VALUE cPTY = rb_define_module("PTY"); rb_define_module_function(cPTY, "getpty", pty_getpty, -1); rb_define_module_function(cPTY, "spawn", pty_getpty, -1); + rb_define_singleton_method(cPTY, "open", pty_open, 0); rb_define_singleton_method(cPTY, "__get_device__", pty_get_device, 0); eChildExited = rb_define_class_under(cPTY, "ChildExited", rb_eRuntimeError); rb_define_method(eChildExited, "status", echild_status, 0); }