diff --git a/proc/linux-lib.pl b/proc/linux-lib.pl index 67710aede..98ea8c281 100755 --- a/proc/linux-lib.pl +++ b/proc/linux-lib.pl @@ -158,6 +158,51 @@ $out =~ s/^\s+//g; $out =~ s/\s+$//g; return split(/\s+/, $out); } +# linux_openpty() +# Linux-only, pure-Perl openpty(3)-style helper. +# Returns master fh, slave fh, slave path, and ioctl value on success +sub linux_openpty +{ + +require Fcntl; Fcntl->import(qw(O_RDWR)); +require POSIX; POSIX->import(qw(setsid)); + +# Linux ioctl values +my $TIOCGPTN = 0x80045430; # get pty number +my $TIOCSPTLCK = 0x40045431; # unlock slave +my $TIOCSCTTY = 0x540E; # set controlling tty + +my ($ptmx, $ttyfh); + +# Open PTY master +sysopen($ptmx, "/dev/ptmx", O_RDWR) || return; + +# Unlock the slave +my $lock = pack("i", 0); +ioctl($ptmx, $TIOCSPTLCK, $lock) || do { + close($ptmx); + return; + }; + +# Get slave number +my $buf = pack("i", 0); +ioctl($ptmx, $TIOCGPTN, $buf) || do { + close($ptmx); + return; + }; +my $n = unpack("i", $buf); + +# Open PTY slave +my $tty = "/dev/pts/$n"; +open($ttyfh, "+<", $tty) || do { + close($ptmx); + return; + }; + +# Return master fh, slave fh, slave path, ioctl value +return ($ptmx, $ttyfh, $tty, $TIOCSCTTY); +} + # get_new_pty() # Returns the filehandles and names for a pty and tty sub get_new_pty diff --git a/proc/proc-lib.pl b/proc/proc-lib.pl index f55b23009..41823cdf3 100755 --- a/proc/proc-lib.pl +++ b/proc/proc-lib.pl @@ -249,53 +249,6 @@ do { local $oldexit = $?; } while($xp > 0); } - -# linux_openpty() -# Linux-only, pure-Perl openpty(3)-style helper. -# Returns master fh, slave fh, slave path, and ioctl value on success -sub linux_openpty -{ -return if $^O ne 'linux'; - -require Fcntl; Fcntl->import(qw(O_RDWR)); -require POSIX; POSIX->import(qw(setsid)); - -# Linux ioctl values -my $TIOCGPTN = 0x80045430; # get pty number -my $TIOCSPTLCK = 0x40045431; # unlock slave -my $TIOCSCTTY = 0x540E; # set controlling tty - -my ($ptmx, $ttyfh); - -# Open PTY master -sysopen($ptmx, "/dev/ptmx", O_RDWR) || return; - -# Unlock the slave -my $lock = pack("i", 0); -ioctl($ptmx, $TIOCSPTLCK, $lock) || do { - close($ptmx); - return; - }; - -# Get slave number -my $buf = pack("i", 0); -ioctl($ptmx, $TIOCGPTN, $buf) || do { - close($ptmx); - return; - }; -my $n = unpack("i", $buf); - -# Open PTY slave -my $tty = "/dev/pts/$n"; -open($ttyfh, "+<", $tty) || do { - close($ptmx); - return; - }; - -# Return master fh, slave fh, slave path, ioctl value -return ($ptmx, $ttyfh, $tty, $TIOCSCTTY); -} - # pty_process_exec(command, [uid, gid], [force-binary-name]) # Starts the given command in a new pty and returns the pty filehandle and PID sub pty_process_exec @@ -308,17 +261,19 @@ if (&is_readonly_mode()) { &webmin_debug_log('CMD', "cmd=$cmd uid=$uid gid=$gid") if ($gconfig{'debug_what_cmd'}); +my ($ptyfh, $ttyfh, $pty, $tty, $TIOCSCTTY); + eval "use IO::Pty"; if (!$@) { # Use the IO::Pty perl module if installed - my $ptyfh = new IO::Pty; + $ptyfh = new IO::Pty; if (!$ptyfh) { &error("Failed to create new PTY with IO::Pty"); } local $pid = fork(); if (!$pid) { - local $ttyfh = $ptyfh->slave(); - local $tty = $ptyfh->ttyname(); + $ttyfh = $ptyfh->slave(); + $tty = $ptyfh->ttyname(); if (defined(&close_controlling_pty)) { &close_controlling_pty(); } @@ -358,7 +313,8 @@ if (!$@) { $ptyfh->close_slave(); return ($ptyfh, $pid); } -elsif (my ($ptyfh, $ttyfh, $tty, $TIOCSCTTY) = &linux_openpty()) { +elsif (defined &linux_openpty && + do { ($ptyfh, $ttyfh, $tty, $TIOCSCTTY) = linux_openpty(); $ptyfh }) { # Use pure-Perl Linux fallback my $pid = fork(); if (!$pid) { @@ -407,7 +363,7 @@ elsif (my ($ptyfh, $ttyfh, $tty, $TIOCSCTTY) = &linux_openpty()) { } else { # Need to create a PTY using built-in Webmin code - my ($ptyfh, $ttyfh, $pty, $tty) = &get_new_pty(); + ($ptyfh, $ttyfh, $pty, $tty) = &get_new_pty(); $tty || &error("Failed to create new PTY - try installing the IO::Tty Perl module"); local $pid = fork(); if (!$pid) {