summaryrefslogtreecommitdiff
path: root/ext/pty
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pty')
-rw-r--r--ext/pty/depend2
-rw-r--r--ext/pty/extconf.rb2
-rw-r--r--ext/pty/pty.c58
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)