Nobuyoshi Nakada
8/6/2007 8:38:00 AM
Hi,
At Mon, 6 Aug 2007 02:28:38 +0900,
ronald braswell wrote in [ruby-talk:263410]:
> I noticed that Solaris 10 does not support TIOCSCTTY so in function
> establishShell() the child process closes the slave device and reopens it to
> force it to be the controlling tty. The parent process also closes the
> slave device because it does not need it. I added a call to nanosleep for
> 20 milliseconds just before the parent process closes the slave fd at the
> end of establishShell() and I now both expect and RExpect work reliably. I
> suspect that just keeping a reference to the open file object in the parent
> process while the child process closes and reopens the slave device prevents
> the EOF from occurring -- but I am far from an expert on Solaris internals.
> This may not be the best way to solve the problem and just adding the small
> delay does not ensure that the problem will never happen again but so far,
> so good.
Does this patch work?
Index: ext/pty/expect_sample.rb
===================================================================
--- ext/pty/expect_sample.rb (revision 12878)
+++ ext/pty/expect_sample.rb (working copy)
@@ -16,8 +16,4 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r
$expect_verbose = false
- r_f.expect(/^Name.*: /) do
- w_f.print "ftp\n"
- end
-
if !ENV['USER'].nil?
username = ENV['USER']
@@ -28,9 +24,6 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r
end
- r_f.expect('word:') do
- w_f.print username+"@\n"
- end
- r_f.expect("> ") do
- w_f.print "cd pub/ruby\n"
+ r_f.expect(/^(Name).*: |(word):|> /) do
+ w_f.puts($1 ? "ftp" : $2 ? "#{username}@" : "cd pub/ruby")
end
r_f.expect("> ") do
Index: ext/pty/pty.c
===================================================================
--- ext/pty/pty.c (revision 12878)
+++ ext/pty/pty.c (working copy)
@@ -40,8 +40,8 @@
#if !defined(HAVE_OPENPTY)
#if defined(__hpux)
-static
-char *MasterDevice = "/dev/ptym/pty%s",
- *SlaveDevice = "/dev/pty/tty%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/ptym/pty%s",
+ SlaveDevice[] = "/dev/pty/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
@@ -63,8 +63,8 @@ char *MasterDevice = "/dev/ptym/pty%s",
};
#elif defined(_IBMESA) /* AIX/ESA */
-static
-char *MasterDevice = "/dev/ptyp%s",
- *SlaveDevice = "/dev/ttyp%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/ptyp%s",
+ SlaveDevice[] = "/dev/ttyp%s",
+ *const deviceNo[] = {
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
@@ -85,8 +85,8 @@ char *MasterDevice = "/dev/ptyp%s",
};
#elif !defined(HAVE_PTSNAME)
-static
-char *MasterDevice = "/dev/pty%s",
- *SlaveDevice = "/dev/tty%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/pty%s",
+ SlaveDevice[] = "/dev/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
@@ -102,6 +102,4 @@ char *MasterDevice = "/dev/pty%s",
#endif /* !defined(HAVE_OPENPTY) */
-static char SlaveName[DEVICELEN];
-
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
@@ -156,15 +154,13 @@ pty_syswait(info)
if (cpid == -1) return Qnil;
-#if defined(IF_STOPPED)
- if (IF_STOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
-#elif defined(WIFSTOPPED)
- if (WIFSTOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
+#if defined(WIFSTOPPED)
+#elif defined(IF_STOPPED)
+#define WIFSTOPPED(status) IF_STOPPED(status)
#else
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
#endif /* WIFSTOPPED | IF_STOPPED */
+ if (WIFSTOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
else if (kill(info->child_pid, 0) == 0) {
raise_from_wait("changed", info);
@@ -177,5 +173,5 @@ pty_syswait(info)
}
-static void getDevice _((int*, int*));
+static void getDevice _((int*, int*, char [DEVICELEN]));
struct exec_info {
@@ -195,11 +191,12 @@ pty_exec(v)
static void
-establishShell(argc, argv, info)
+establishShell(argc, argv, info, SlaveName)
int argc;
VALUE *argv;
struct pty_info *info;
+ char SlaveName[DEVICELEN];
{
int i,master,slave;
- char *p,*getenv();
+ char *p, tmp, *getenv();
struct passwd *pwent;
VALUE v;
@@ -224,5 +221,5 @@ establishShell(argc, argv, info)
argv = &v;
}
- getDevice(&master,&slave);
+ getDevice(&master, &slave, SlaveName);
info->thread = rb_thread_current();
@@ -274,4 +271,5 @@ establishShell(argc, argv, info)
close(master);
#endif
+ write(slave, "", 1);
dup2(slave,0);
dup2(slave,1);
@@ -289,4 +287,5 @@ establishShell(argc, argv, info)
}
+ read(master, &tmp, 1);
close(slave);
@@ -306,6 +305,7 @@ pty_finalize_syswait(info)
static int
-get_device_once(master, slave, fail)
+get_device_once(master, slave, SlaveName, fail)
int *master, *slave, fail;
+ char SlaveName[DEVICELEN];
{
#if defined HAVE_OPENPTY
@@ -354,4 +354,5 @@ get_device_once(master, slave, fail)
if(ioctl(j, I_PUSH, "ptem") != -1) {
if(ioctl(j, I_PUSH, "ldterm") != -1) {
+ ioctl(j, I_PUSH, "ttcompat");
#endif
*master = i;
@@ -396,10 +397,11 @@ get_device_once(master, slave, fail)
static void
-getDevice(master, slave)
+getDevice(master, slave, SlaveName)
int *master, *slave;
+ char SlaveName[DEVICELEN];
{
- if (get_device_once(master, slave, 0)) {
+ if (get_device_once(master, slave, SlaveName, 0)) {
rb_gc();
- get_device_once(master, slave, 1);
+ get_device_once(master, slave, SlaveName, 1);
}
}
@@ -418,9 +420,10 @@ pty_getpty(argc, argv, self)
VALUE rport = rb_obj_alloc(rb_cFile);
VALUE wport = rb_obj_alloc(rb_cFile);
+ char SlaveName[DEVICELEN];
MakeOpenFile(rport, rfptr);
MakeOpenFile(wport, wfptr);
- establishShell(argc, argv, &info);
+ establishShell(argc, argv, &info, SlaveName);
rfptr->mode = rb_io_mode_flags("r");
--
Nobu Nakada