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);
}