diff options
Diffstat (limited to 'ext/pty')
| -rw-r--r-- | ext/pty/depend | 2 | ||||
| -rw-r--r-- | ext/pty/extconf.rb | 2 | ||||
| -rw-r--r-- | ext/pty/pty.c | 58 |
3 files changed, 48 insertions, 14 deletions
diff --git a/ext/pty/depend b/ext/pty/depend index adecfff862..8fa018d084 100644 --- a/ext/pty/depend +++ b/ext/pty/depend @@ -138,6 +138,7 @@ pty.o: $(hdrdir)/ruby/internal/intern/re.h pty.o: $(hdrdir)/ruby/internal/intern/ruby.h pty.o: $(hdrdir)/ruby/internal/intern/select.h pty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +pty.o: $(hdrdir)/ruby/internal/intern/set.h pty.o: $(hdrdir)/ruby/internal/intern/signal.h pty.o: $(hdrdir)/ruby/internal/intern/sprintf.h pty.o: $(hdrdir)/ruby/internal/intern/string.h @@ -172,6 +173,7 @@ pty.o: $(hdrdir)/ruby/ruby.h pty.o: $(hdrdir)/ruby/st.h pty.o: $(hdrdir)/ruby/subst.h pty.o: $(hdrdir)/ruby/util.h +pty.o: $(top_srcdir)/id_table.h pty.o: $(top_srcdir)/internal.h pty.o: $(top_srcdir)/internal/array.h pty.o: $(top_srcdir)/internal/compilers.h diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb index da3655cf4d..ae2cb45d3c 100644 --- a/ext/pty/extconf.rb +++ b/ext/pty/extconf.rb @@ -21,6 +21,8 @@ if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM (util or have_func("openpty")) or have_func("_getpty") or have_func("ioctl") + have_macro("HAVE_FCHMOD") or have_func("fchmod") + have_macro("HAVE_FCHOWN") or have_func("fchown") create_makefile('pty') end end diff --git a/ext/pty/pty.c b/ext/pty/pty.c index 49caa0b79f..3d5977707f 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -94,7 +94,7 @@ static void getDevice(int*, int*, char [DEVICELEN], int); static int start_new_session(char *errbuf, size_t errbuf_len); static int obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len); -static int drop_privilige(char *errbuf, size_t errbuf_len); +static int drop_privilege(char *errbuf, size_t errbuf_len); struct child_info { int master, slave; @@ -117,7 +117,7 @@ chfunc(void *data, char *errbuf, size_t errbuf_len) if (obtain_ctty(master, slave, slavename, errbuf, errbuf_len)) return -1; - if (drop_privilige(errbuf, errbuf_len)) + if (drop_privilege(errbuf, errbuf_len)) return -1; return rb_exec_async_signal_safe(carg->eargp, errbuf, errbuf_len); @@ -180,12 +180,12 @@ obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t e dup2(slave,0); dup2(slave,1); dup2(slave,2); - if (slave < 0 || slave > 2) (void)!close(slave); + if (slave > 2) (void)!close(slave); return 0; } static int -drop_privilige(char *errbuf, size_t errbuf_len) +drop_privilege(char *errbuf, size_t errbuf_len) { #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) if (seteuid(getuid())) ERROR_EXIT("seteuid()"); @@ -274,12 +274,23 @@ ptsname_r(int fd, char *buf, size_t buflen) # define HAVE_PTSNAME_R 1 #endif +#ifdef HAVE_FCHMOD +# define change_mode(name, fd, mode) fchmod(fd, mode) +#else +# define change_mode(name, fd, mode) chmod(name, mode) +#endif +#ifdef HAVE_FCHOWN +# define change_owner(name, fd, uid, gid) fchown(fd, uid, gid) +#else +# define change_owner(name, fd, uid, gid) chown(name, uid, gid) +#endif + #if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME_R) -static int -no_mesg(char *slavedevice, int nomesg) +static inline int +prevent_messages(const char *slavedevice, int fd, int nomesg) { if (nomesg) - return chmod(slavedevice, 0600); + return change_mode(slavedevice, fd, 0600); else return 0; } @@ -340,8 +351,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, if (unlockpt(masterfd) == -1) goto error; if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error; slavedevice = SlaveName; - if (no_mesg(slavedevice, nomesg) == -1) goto error; if ((slavefd = rb_cloexec_open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1) goto error; + if (prevent_messages(slavedevice, slavefd, nomesg) == -1) goto error; rb_update_max_fd(slavefd); #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX) @@ -375,7 +386,9 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, } rb_fd_fix_cloexec(*master); rb_fd_fix_cloexec(*slave); - if (no_mesg(SlaveName, nomesg) == -1) { + if (prevent_messages(SlaveName, *slave, nomesg) == -1) { + close(*master); + close(*slave); if (!fail) return -1; rb_raise(rb_eRuntimeError, "can't chmod slave pty"); } @@ -424,8 +437,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, if(unlockpt(masterfd) == -1) goto error; if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error; slavedevice = SlaveName; - if (no_mesg(slavedevice, nomesg) == -1) goto error; if((slavefd = rb_cloexec_open(slavedevice, O_RDWR, 0)) == -1) goto error; + if (prevent_messages(slavedevice, slavefd, nomesg) == -1) goto error; rb_update_max_fd(slavefd); #if defined(I_PUSH) && !defined(__linux__) && !defined(_AIX) if(ioctl_I_PUSH(slavefd, "ptem") == -1) goto error; @@ -478,8 +491,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, if ((slavefd = rb_cloexec_open(SlaveName,O_RDWR,0)) >= 0) { rb_update_max_fd(slavefd); *slave = slavefd; - if (chown(SlaveName, getuid(), getgid()) != 0) goto error; - if (chmod(SlaveName, nomesg ? 0600 : 0622) != 0) goto error; + if (change_owner(SlaveName, slavefd, getuid(), getgid()) != 0) goto error; + if (change_mode(SlaveName, slavefd, nomesg ? 0600 : 0622) != 0) goto error; return 0; } close(masterfd); @@ -610,9 +623,17 @@ pty_detach_process(VALUE v) * +env+ is an optional hash that provides additional environment variables to the spawned pty. * * # sets FOO to "bar" - * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "bar\r\n" + * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") do |r, w, pid| + * p r.read #=> "bar\r\n" + * ensure + * r.close; w.close; Process.wait(pid) + * end * # unsets FOO - * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "" + * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") do |r, w, pid| + * p r.read #=> "" + * ensure + * r.close; w.close; Process.wait(pid) + * end * * +command+ and +command_line+ are the full commands to run, given a String. * Any additional +arguments+ will be passed to the command. @@ -628,6 +649,15 @@ pty_detach_process(VALUE v) * standard output and standard error * +w+:: A writable IO that is the command's standard input * +pid+:: The process identifier for the command. + * + * === Clean up + * + * This method does not clean up like closing IOs or waiting for child + * process, except that the process is detached in the block form to + * prevent it from becoming a zombie (see Process.detach). Any other + * cleanup is the responsibility of the caller. If waiting for +pid+, + * be sure to close both +r+ and +w+ before doing so; doing it in the + * reverse order may cause deadlock on some OSes. */ static VALUE pty_getpty(int argc, VALUE *argv, VALUE self) |
