#!/usr/bin/perl # Start an ssh connection and a pppd running on top of it. # Usage: ssh-ppp [-l user] [-c command] [-b seconds] host # Connect to "host" using the user name "user" and run "command" on the # remote end. (Default is "root" and "/usr/sbin/pppd") # by Olaf Titz, July 1996 require "getopts.pl"; require "sys/syscall.ph"; # Customize if necessary $ssh="/usr/bin/ssh"; $pppd="/usr/sbin/pppd 10.0.2.1:10.0.2.2"; # defaults $opt_l="root"; $opt_c="/usr/sbin/pppd 10.0.2.2:10.0.2.1"; &Getopts("l:c:b:"); ($host=shift) || die "usage: $0 [-l user] [-c command] host"; foreach $maj ("p".."s") { # adjust this to the ptys you have foreach $min ("0".."9", "a".."f") { &tryopen("$maj$min"); } } die "Couldn't alloc master pty\n"; sub tryopen { local($d)=@_; $master=sprintf("/dev/pty%s", $d); $slave=sprintf("/dev/tty%s", $d); if (open(PTY, "+>$master")) { $pid=fork; defined($pid) || die "can't fork"; if (!$pid) { close PTY; (syscall(&SYS_setsid)>0) || die "setsid: $!"; open(STDIN, "+>$slave") || die "open slave: $!"; open(STDOUT, ">&STDIN"); open(STDERR, ">&STDIN"); print STDOUT "\n"; exec $pppd; die "exec $pppd: $!"; } open(STDIN, "<&PTY") || die "reopen stdin"; open(STDOUT, ">&PTY") || die "reopen stout"; close PTY; $opt_l="-l$opt_l"; &bugdaemon($opt_b) if ($opt_b); print STDERR "running on $master; ssh=$$, pppd=$pid\n"; exec $ssh, "-t", $opt_l, $host, $opt_c; die "exec $ssh: $!"; } } sub bugdaemon # This cures a "hang" of the local ssh process { local($secs)=@_; local($p)=fork; if (!defined($p)) { warn "can't fork, no bug daemon"; return; } return if (!$p); # returning the child avoids a zombie sleep $secs; kill "STOP", $p; sleep 1; kill "CONT", $p; exit 0; }