aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--ext/pty/extconf.rb3
-rw-r--r--ext/pty/pty.c46
-rw-r--r--test/test_pty.rb19
4 files changed, 68 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 1d89d1ea71..471e0e7261 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Tue Dec 16 19:48:18 2008 Tanaka Akira <akr@fsij.org>
+
+ * ext/pty/extconf.rb: check posix_openpt.
+
+ * ext/pty/pty.c (get_device_once): use posix_openpt if available.
+
Tue Dec 16 19:43:53 2008 Tanaka Akira <akr@fsij.org>
* re.c: use strlcpy for error messages.
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
index 87fbdc6024..b26600ab34 100644
--- a/ext/pty/extconf.rb
+++ b/ext/pty/extconf.rb
@@ -6,7 +6,8 @@ if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM
have_header("libutil.h")
have_header("pty.h")
have_library("util", "openpty")
- if have_func("openpty") or
+ if have_func("posix_openpt") or
+ have_func("openpty") or
have_func("_getpty") or
have_func("ptsname") or
have_func("ioctl")
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index d190aba94f..a8a02d8769 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -2,6 +2,7 @@
#ifdef RUBY_EXTCONF_H
#include RUBY_EXTCONF_H
#endif
+#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -272,7 +273,44 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
static int
get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int fail)
{
-#if defined HAVE_OPENPTY
+#if defined(HAVE_POSIX_OPENPT)
+ int masterfd,slavefd;
+ char *slavedevice;
+ struct sigaction dfl, old;
+
+ dfl.sa_handler = SIG_DFL;
+ dfl.sa_flags = 0;
+ sigemptyset(&dfl.sa_mask);
+
+ if((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) != -1) {
+ sigaction(SIGCHLD, &dfl, &old);
+ if(grantpt(masterfd) != -1) {
+ sigaction(SIGCHLD, &old, NULL);
+ if(unlockpt(masterfd) != -1) {
+ if((slavedevice = ptsname(masterfd)) != NULL) {
+ if((slavefd = open(slavedevice, O_RDWR|O_NOCTTY, 0)) != -1) {
+#if defined I_PUSH && !defined linux
+ if(ioctl(slavefd, I_PUSH, "ptem") != -1) {
+ if(ioctl(slavefd, I_PUSH, "ldterm") != -1) {
+ ioctl(slavefd, I_PUSH, "ttcompat");
+#endif
+ *master = masterfd;
+ *slave = slavefd;
+ strlcpy(SlaveName, slavedevice, DEVICELEN);
+ return 0;
+#if defined I_PUSH && !defined linux
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ close(masterfd);
+ }
+ if (!fail) rb_raise(rb_eRuntimeError, "can't get Master/Slave device");
+ return -1;
+#elif defined HAVE_OPENPTY
/*
* Use openpty(3) of 4.3BSD Reno and later,
* or the same interface function.
@@ -296,10 +334,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int fail)
strlcpy(SlaveName, name, DEVICELEN);
return 0;
-#else /* HAVE__GETPTY */
+#elif defined(HAVE_PTSNAME)
int i,j;
-
-#ifdef HAVE_PTSNAME
char *pn;
void (*s)();
@@ -336,6 +372,7 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int fail)
if (!fail) rb_raise(rb_eRuntimeError, "can't get Master/Slave device");
return -1;
#else
+ int i,j;
const char *const *p;
char MasterName[DEVICELEN];
@@ -356,7 +393,6 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int fail)
if (fail) rb_raise(rb_eRuntimeError, "can't get %s", SlaveName);
return -1;
#endif
-#endif
}
static void
diff --git a/test/test_pty.rb b/test/test_pty.rb
index 684ab2c01b..704861dd3c 100644
--- a/test/test_pty.rb
+++ b/test/test_pty.rb
@@ -98,5 +98,24 @@ class TestPTY < Test::Unit::TestCase
}
end
+ def test_stat_slave
+ # If grantpt is used, the slave device is changed as follows.
+ # owner: real UID
+ # group: an unspecified value (e.g. tty)
+ # mode: 0620 (rw--w----)
+ #
+ # The group is not testable because unspecified.
+ #
+ # The mode is testable but the condition is relaxed because other
+ # pty functions (openpty, _getpty, etc.) may not use 0620.
+ # But no one can read from the tty, I hope (for security reason).
+ #
+ PTY.open {|master, slave|
+ s = File.stat(slave.path)
+ assert_equal(Process.uid, s.uid)
+ assert_equal(0600, s.mode & 0755)
+ }
+ end
+
end if defined? PTY