Changeset 14430 for misc/runpugs

Show
Ignore:
Timestamp:
10/22/06 01:36:47 (2 years ago)
Author:
andara
Message:

[runpugs]
-improved error handling (try not to die).
-Web::Terminal: new generic version with command history, supports GHCi and
many more. (not live yet)

Location:
misc/runpugs
Files:
3 added
11 modified

Legend:

Unmodified
Added
Removed
  • misc/runpugs/bin/termdispatcher2.pl

    r14366 r14430  
    1414my $cmd=$ARGV[1] || 'my $a='.$id.';say "Hello, $a";'; 
    1515#my $cmd='my $a='.$id.';say "Hello, $a";'; 
    16 my $prompt='pugs> '; 
     16#my $prompt='pugs> '; 
     17my $prompt='Prelude> '; 
    1718print "Sending msg $id: $cmd\n"; 
    1819my $ip="127.0.0.1"; 
    19 my $reply = &Web::Terminal::Dispatcher::send($id,$ip,$prompt.$cmd); 
     20(my $reply,my $histref) = &Web::Terminal::Dispatcher::send($id,$ip,$prompt.$cmd); 
    2021print $reply; 
     22print "\nHistory\n"; 
     23for my $entry (@{$histref}) { 
     24print "\t$entry\n"; 
     25} 
    2126 
  • misc/runpugs/cgi-bin/runpugs

    r14403 r14430  
    102102    #NO UNICODE! 
    103103#    $cmd=tr/\0-\x{10ffff}/\0-\xff_/; 
    104     if ($cmd=~/clear/) {$cmd=''} elsif ($cmd!~/^\p{IsASCII}*$/) { 
    105             $cmd=''; 
    106                 $reply = "Sorry, Unicode is not yet supported.\npugs> "; 
     104    if ($cmd=~/clear/) { 
     105        $cmd=''; 
     106    } elsif ($cmd!~/^\p{IsASCII}*$/) { 
     107        $cmd=''; 
     108        $reply = "Sorry, Unicode is not yet supported.\npugs> "; 
    107109    } else { 
     110    if ($cmd=~/>\s+(\:*help)\b/) { 
     111        $cmd=~s/$1/:h/; 
     112    } elsif ($cmd=~/>\s+(\:*(quit|bye))\b/) { 
     113        $cmd=~s/$1/:q/; 
     114    }  
    108115    $reply = &WebTerminal::Dispatcher::send($sessionid,$ip,$cmd); 
    109116    $reply="\n".$reply; 
  • misc/runpugs/htdocs/runpugs.css

    r14299 r14430  
    1 BODY {width:100%;margin-left:10%;margin-right:10%; margin-top: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 11pt; line-height: normal; background-color:#FFFFFF;} 
     1BODY {width:100%;margin-left:10%;margin-right:10%; margin-top: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 12pt; line-height: normal; background-color:#FFFFFF;} 
    22H1 {font-size: 24pt;  
    33    font-family: Georgia, Serif, Times;  
     
    99H2 { font-weight: bold; font-size: 12pt} 
    1010LABEL {font-weight: bold; } 
    11 EM {font-weight: bold; 
    12     font-style: normal; 
    13     text-decoration:none;} 
    14 TT {color: #204a87; 
    15 font-weight: bold; 
    16 } 
    1711.copyright {font-size: 9pt} 
    1812.warning { 
     
    2216#mainwindow { 
    2317width: 750px  
     18} 
     19#hist { 
     20width: 750px; 
     21border: solid 2px #204a87; 
     22font-family: "Andale Mono", courier, fixed, monospace; 
     23font-size: 10pt; 
     24color: #204a87; 
     25    background-color: #f2f2f0; 
     26    padding-bottom: 5px; 
    2427} 
    2528#cmd { 
  • misc/runpugs/lib/Web/Terminal/Dispatcher.pm

    r14366 r14430  
    2828        my $port = $Web::Terminal::Settings::port; 
    2929        my $cmd=''; 
    30     # we only consider the last line witha prompt 
     30    # we only consider the last line with a prompt 
    3131        my @cmdlines=split("\n",$cmds); 
    3232        for my $cmdline (reverse @cmdlines) { 
     
    7070     my $rid=$rmesgref->{id}; 
    7171      my $reply=$rmesgref->{msg}; 
     72      my $histref=$rmesgref->{recent}; 
    7273    $conn->disconnect(); 
    7374        if ( "$id" ne  "$rid" ) { 
    74                 die "Terminal server returned wrong id: $rid, should be $id"; 
     75#               die "Terminal server returned wrong id: $rid, should be $id"; 
     76        return "Sorry, the pugs session died."; 
    7577        } 
    76         return $reply; 
     78        return ($reply,$histref); 
    7779   } 
    7880} 
  • misc/runpugs/lib/Web/Terminal/Msg.pm

    r14366 r14430  
    249249sub _new_client { 
    250250    my $sock = $main_socket->accept(); 
     251    #returns undef on fail. Calling peerhost on undef makes it die. 
     252    ## so: 
     253    if (defined $sock) { 
     254 
    251255    my $conn = bless { 
    252256        'sock' =>  $sock, 
     
    262266        $conn->disconnect(); 
    263267    } 
     268    } else { 
     269        return undef; 
     270    } 
    264271} 
    265272 
  • misc/runpugs/lib/Web/Terminal/Server.pm

    r14374 r14430  
    3232 
    3333our %terminals=(); 
    34 #our %lastcalled=(); 
    3534our %sessions_per_ip=(); 
    3635 
     
    4241    return "Sorry, I can't run any more sessions.\nPlease try again later."; 
    4342} else { 
    44 #       $lastcalled{$id}=time; 
    4543        if ( exists $terminals{$id} ) { 
     44    print "$id exists\n"; 
     45    if ($terminals{$id}->{pid}) {     
    4646    $terminals{$id}->{called}=time; 
    4747                my $term  = $terminals{$id}; 
     48        push  @{$term->{recent}},$cmd; 
     49        if (scalar @{$term->{recent}}> $Web::Terminal::Settings::nrecent) { 
     50            shift @{$term->{recent}}; 
     51        } 
    4852                my $lines = $term->write($cmd); 
    4953                if ( $cmd eq $Web::Terminal::Settings::quit_command ) { 
     54            my $pid= $terminals{$id}->{pid}; 
     55            print "Quit $id ($pid)\n"; 
    5056                        delete $terminals{$id}; 
     57            if ($pid) { 
     58                kill 9,$pid; 
     59            } 
    5160            $sessions_per_ip{$ip}--; 
    52                 } 
    53         if ($lines=~/Aborted/s) { 
     61#               } 
     62        #if ($lines=~/Aborted/s) { 
     63        } elsif ($terminals{$id}->{error}==1) { 
     64             my $pid= $terminals{$id}->{pid}; 
    5465             delete $terminals{$id}; 
     66            if ($pid) { 
     67                kill 9,$pid; 
     68           } 
    5569            $sessions_per_ip{$ip}--; 
    5670        } 
    5771                return $lines; 
     72        } else { 
     73            return "pugs> "; 
     74        } 
    5875        } else { 
    5976        if ($sessions_per_ip{$ip}>$Web::Terminal::Settings::nsessions_ip) { 
    60          return "Sorry, you can't run more than 
    61          ${Web::Terminal::Settings::nsessions_ip} sessions from one IP 
    62          address.\n";    
     77        print LOG2 "MAX nsessions for $ip reached\n"; 
     78         return "Sorry, you can't run more than ${Web::Terminal::Settings::nsessions_ip} sessions from one IP address.\n";    
    6379        } else { 
     80        print "New $id\n"; 
    6481            $sessions_per_ip{$ip}++; 
    65                 $terminals{$id} = new Web::Terminal::Server::Session(); 
    66     $terminals{$id}->{called}=time; 
    67     $terminals{$id}->{ip}=$ip; 
    68                 my $term = $terminals{$id}; 
    69                 return $term->{'init'}; 
     82                $terminals{$id} = new Web::Terminal::Server::Session(); 
     83            $terminals{$id}->{called}=time; 
     84            $terminals{$id}->{ip}=$ip; 
     85                my $term = $terminals{$id}; 
     86            my $init= $term->{'init'}; 
     87            my $error= $term->{'error'}; 
     88            if ($error==1) { # Failed to create a new terminal 
     89                $sessions_per_ip{$ip}--; 
     90                delete $terminals{$id}; 
     91            } 
     92            return $init; 
    7093        } 
    7194        } 
     
    79102                if ( $len > 0 ) { 
    80103#                       ( my $id, my $ip, my $cmd ) = split( "\n", $msg, 3 ); 
    81             print "MSG:", $msg;                  
    82104                        my $mesgref=YAML::Syck::Load($msg); 
    83                          my $id=$mesgref->{id}; 
    84              my $ip=$mesgref->{ip}; 
    85              my $cmd=$mesgref->{cmd}; 
     105                        my $id=$mesgref->{id}; 
     106            my $ip=$mesgref->{ip}; 
     107            my $cmd=$mesgref->{cmd}; 
    86108#            $cmd=pack("U0C*", unpack("C*",$cmd)); 
    87 #            print "$id($ip): ",$cmd,"\n"; 
     109            my $pid=0; 
     110            if(exists $terminals{$id}) { 
     111                $pid=$terminals{$id}->{pid}; 
     112            } 
     113            my $nsess=scalar keys %terminals; 
     114            print scalar(localtime)," : $nsess : $ip : $id : $pid > ",$cmd,"\n"; 
     115            print LOG2 scalar(localtime)," : $nsess : $ip : $id : $pid > ",$cmd,"\n"; 
    88116                        my $lines = &termhandler( $id, $ip, $cmd ); 
    89             my $replyref=YAML::Syck::Dump({id=>$id,msg=>$lines}); 
    90 #                       $conn->send_now("$id\n$lines"); 
     117            my @history=('--- Recent commands ---'); 
     118            if (defined $terminals{$id}->{recent}) { 
     119             @history=@{$terminals{$id}->{recent}}; 
     120            } 
     121            my 
     122            $replyref=YAML::Syck::Dump({id=>$id,msg=>$lines,recent=>\@history}); 
    91123                        $conn->send_now($replyref); 
    92124 
     
    105137 
    106138$SIG{USR1}=\&timeout; 
    107 #Proc::Daemon::Init; 
    108  
     139if ( $Web::Terminal::Settings::daemon) { 
     140    Proc::Daemon::Init; 
     141} 
    109142# fork/exec by the book: 
    110143use Errno qw(EAGAIN); 
     
    113146if ($pid=fork) { 
    114147    #parent here 
     148    if (-e "/home/andara/apache/data/runpugs2.log") { 
     149        rename "/home/andara/apache/data/runpugs2.log","/home/andara/apache/data/runpugs2.log.".join("",localtime); 
     150    } 
     151    open(LOG2,">/home/andara/apache/data/runpugs2.log"); 
    115152    Web::Terminal::Msg->new_server( $host, $port, \&login_proc ); 
    116153    Web::Terminal::Msg->event_loop(); 
     
    122159        kill 'USR1',getppid(); 
    123160    } 
     161    system("killall $Web::Terminal::Settings::command"); 
     162    chdir $Web::Terminal::Settings::cgi_path; 
     163    exec("$Web::Terminal::Settings::perl ../bin/$Web::Terminal::Settings::server"); 
     164#    chdir "/home/andara/apache/cgi-bin/"; 
     165#    exec('/usr/bin/perl ../bin/termserv.pl'); 
    124166} elsif ($! == EAGAIN) { 
    125167    sleep 5; 
     
    134176    my $now=time(); 
    135177    for my $id (keys %terminals) { 
    136         my $then=$terminals{$id}; 
     178        my $then=$terminals{$id}->{called}; 
    137179        if ($now-$then>$Web::Terminal::Settings::timeout_idle) { 
    138180        if(exists $terminals{$id}) { 
     181          my $pid= $terminals{$id}->{pid}; 
    139182            my $ip=$terminals{$id}->{ip}; 
    140183            $sessions_per_ip{$ip}--; 
    141             $terminals{$id}->write(':q'); 
     184             if ($pid) { 
     185                kill 9,$pid; 
     186            } 
     187#            $terminals{$id}->write(':q'); 
    142188            delete $terminals{$id}; 
     189            print LOG2 "Cleaned up $ip : $id : $pid\n"; 
    143190            } 
    144191        } 
  • misc/runpugs/lib/Web/Terminal/Server/Session.pm

    r14374 r14430  
    1313=cut 
    1414 
     15$SIG{CHLD}='IGNORE'; 
    1516## Constructor 
    1617sub new { 
     
    2021#       my $prompt = '/\>\ /'; 
    2122    my $prompt= '/'.$Web::Terminal::Settings::init_pattern.'/'; 
     23    $self->{'error'}=0; 
     24    $self->{'recent'}=[]; 
    2225        ## Start pugs 
    2326#    $ENV{PUGS_SAFEMODE}=1;# Must be in CGI script! 
    2427        ( $self->{'pty'},$self->{'pid'} ) = 
    2528    &spawn($Web::Terminal::Settings::command);    # spawn() defined below 
    26  
     29    if ( $self->{'pty'}==-1 and  $self->{'pid'}==0) { 
     30        $self->{'init'}= "\nThere was a problem starting pugs. Please try again later."; 
     31        $self->{'error'}=1; 
     32    } else { 
    2733        ## Create a Net::Telnet object to perform I/O on pugs's tty. 
    2834        use Net::Telnet; 
     
    3541        ); 
    3642        #( $self->{'init'}, my $m ) = $self->{'pugs'}->waitfor( 
    37         ( my $p, my $m ) = $self->{'pugs'}->waitfor( 
     43    my $error=''; 
     44    ( my $p, my $m ) = $self->{'pugs'}->waitfor( 
    3845                -match   => $self->{'pugs'}->prompt, 
    3946                -errmode => "return" 
    40           ) or die "starting pugs failed: ", $self->{'pugs'}->lastline; 
    41         $self->{'init'}= $p.$m;#$self->{'pugs'}->prompt; 
     47          ) or do { 
     48          $self->{'error'}=1; 
     49          $error="\nThere was a problem starting pugs. Please try again later."; 
     50          # should close the TTY 
     51          $self->{'pugs'}->close(); 
     52      }; 
     53      #die "starting pugs failed: ", $self->{'pugs'}->lastline; 
     54        $self->{'init'}= $p.$m.$error;#$self->{'pugs'}->prompt; 
     55    } 
    4256        bless($self,$class); 
    4357        return $self; 
     
    5468 
    5569        if ( $cmd eq $Web::Terminal::Settings::quit_command ) { 
     70        $obj->{pugs}->close(); 
    5671                kill 9, $obj->{'pid'};           
    5772                return "\n$Web::Terminal::Settings::quit_message\n"; 
     
    6479 
    6580        $pugs->print($cmd); 
    66         while (1) { 
     81        while ($i<$Web::Terminal::Settings::nlines) { 
    6782                my $line = $pugs->getline; 
    6883        my $msg=$pugs->errmsg; 
     
    7287            $pugs->errmsg([]); 
    7388            $lline="${Web::Terminal::Settings::prompt} Sorry, that took too long! Aborted.\n"; 
     89            $pugs->close(); 
    7490            $ps=$Web::Terminal::Settings::prompt; 
     91            $obj->{'error'}=1; 
    7592            last; 
    7693        } 
     
    84101 
    85102        #$lline .= "\n$ps>"; 
     103   if ($i>=$Web::Terminal::Settings::nlines-1) { 
     104       $obj->{pugs}->close(); 
     105        kill 9, $obj->{'pid'}; 
     106        $lline.="Generated output is limited to $Web::Terminal::Settings::nlines lines. Aborted.\npugs"; 
     107        $obj->{'error'}=1; 
     108    } 
     109 
    86110    chomp $ps; # a hack! 
    87111        $lline .= $ps; 
     
    92116        my (@cmd) = @_; 
    93117        my ( $pid, $pty, $tty, $tty_fd ); 
    94  
     118    my $error=0; 
    95119        ## Create a new pseudo terminal. 
    96120        use IO::Pty (); 
    97121        $pty = new IO::Pty 
    98           or die $!; 
     122          or do { 
     123          return ( -1, 0 ); 
     124      }; 
     125      #die $!; 
    99126    binmode $pty, ":utf8";  
    100127        ## Execute the program in another process. 
    101128        unless ( $pid = fork ) {    # child process 
    102                 die "problem spawning program: $!\n" unless defined $pid; 
    103  
     129        #       die "problem spawning program: $!\n" unless defined $pid; 
     130     if (not defined $pid) { 
     131        $pty->close(); 
     132        $error=1; 
     133    } else { # all is well 
    104134                ## Disassociate process from existing controlling terminal. 
    105135                use POSIX (); 
    106136                POSIX::setsid 
    107                   or die "setsid failed: $!"; 
     137                  or ($error=1);#die "setsid failed: $!"; 
    108138 
    109139                ## Associate process with a new controlling terminal. 
     
    114144 
    115145                ## Make stdio use the new controlling terminal. 
    116                 open STDIN,  "<&$tty_fd" or die $!; 
    117                 open STDOUT, ">&$tty_fd" or die $!; 
    118                 open STDERR, ">&STDOUT"  or die $!; 
     146                open STDIN,  "<&$tty_fd" or ($error=1);#die $!; 
     147                open STDOUT, ">&$tty_fd" or ($error=1);#die $!; 
     148                open STDERR, ">&STDOUT"  or ($error=1);#die $!; 
    119149        binmode STDIN, ":utf8"; 
    120150        binmode STDOUT, ":utf8"; 
     
    124154                ## Execute requested program. 
    125155                exec @cmd 
    126                   or die "problem executing $cmd[0]\n"; 
     156                  or  ($error=1);#die "problem executing $cmd[0]\n"; 
     157          } 
    127158        }    # end child process 
     159 
     160    if($error==1) { 
     161        $pty=-1; 
     162        $pid=0; 
     163    } 
    128164 
    129165        return ( $pty, $pid ); 
  • misc/runpugs/lib/Web/Terminal/Settings.pm

    r14366 r14430  
    2727timeout_idle 
    2828timeout_call 
     29nlines 
     30daemon 
     31perl 
     32server 
     33cgi_path 
     34nrecent 
    2935); 
    3036 
    31 our $command='/usr/bin/pugs'; 
     37our $command='/usr/local/bin/ghci'; 
     38our $prompt='Prelude> '; 
     39our $prompt_pattern='(^(Prelude)>\s+)'; 
     40our $quit_pattern='^Leaving\ GHCi\.'; 
     41our $quit_message='Leaving GHCi.'; 
    3242 
    33 our $prompt='pugs> '; 
     43 
     44#our $command='/usr/bin/nice /usr/bin/pugs'; 
     45our $server='termserv2.pl'; 
     46#our $prompt='pugs> '; 
    3447our $init_pattern='(\>\s+)'; 
    35 our $prompt_pattern='(^(pugs|\.\.\.\.)>\s+)'; 
     48#our $prompt_pattern='(^(pugs|\.\.\.\.)>\s+)'; 
    3649our $quit_command=':q'; 
    37 our $quit_pattern='^Leaving\ pugs\.'; 
    38 our $quit_message='Leaving pugs.'; 
     50#our $quit_pattern='^Leaving\ pugs\.'; 
     51#our $quit_message='Leaving pugs.'; 
    3952 
    4053our $filter=0; 
    4154our $filter_pattern=''; 
    42  
     55our $cgi_path='/home/andara/apache/cgi-bin/'; 
     56our $daemon=0; 
    4357our $port=2057; 
    4458our $host='localhost'; 
     
    5064our $timeout_call=10; 
    5165our $check_interval=300; 
     66our $nlines=250; 
     67our $nrecent=10; 
     68our $perl='/usr/bin/perl'; 
     69 
  • misc/runpugs/lib/WebTerminal/Msg.pm

    r14407 r14430  
    249249sub _new_client { 
    250250    my $sock = $main_socket->accept(); 
    251     #returns undef on fail! 
    252     ## so: 
     251    #returns undef on fail. Calling peerhost on undef makes it die. 
     252    ## so:  
     253    if (defined $sock) { 
    253254    my $conn = bless { 
    254255        'sock' =>  $sock, 
     
    264265        $conn->disconnect(); 
    265266    } 
     267    } else { 
     268    #what? 
     269        return undef; 
     270    } 
    266271} 
    267272 
  • misc/runpugs/lib/WebTerminal/Server.pm

    r14407 r14430  
    4646                my $lines = $term->write($cmd); 
    4747                if ( $cmd eq ':q' ) { 
     48                 my $pid= $terminals{$id}->{pid}; 
    4849                        delete $terminals{$id}; 
    49                  my $pid= $terminals{$id}->{pid}; 
    5050                 if ($pid) { 
    5151                     kill 9,$pid; 
     
    5454                } 
    5555            if ($lines=~/Aborted/s) { 
     56                 my $pid= $terminals{$id}->{pid}; 
    5657                 delete $terminals{$id}; 
    57                  my $pid= $terminals{$id}->{pid}; 
    5858                 if ($pid) { 
    5959                     kill 9,$pid; 
     
    7575                    $terminals{$id}->{ip}=$ip; 
    7676                        my $term = $terminals{$id}; 
    77                 return $term->{'init'}; 
     77                my $init= $term->{'init'}; 
     78                my $error= $term->{'error'}; 
     79                if ($error==1) { # Failed to create a new terminal 
     80                $sessions_per_ip{$ip}--; 
     81                delete $terminals{$id}; 
     82                }  
     83                return $init; 
    7884            } 
    7985            } 
     
    111117    my $port=shift; 
    112118    $SIG{USR1}=\&timeout; 
    113 my $daemon=1; 
     119my $daemon=0; 
    114120if ($daemon) { 
    115121    Proc::Daemon::Init; 
  • misc/runpugs/lib/WebTerminal/Server/Terminal.pm

    r14407 r14430  
    1717        #my $prompt = '/\>\ /'; 
    1818        my $prompt = '/>\ /'; 
     19    $self->{'error'}=0; 
    1920        ## Start pugs 
    2021#    $ENV{PUGS_SAFEMODE}=1;# Must be in CGI script! 
    21         ( $self->{'pty'},$self->{'pid'} ) = &spawn("/usr/bin/pugs");    # spawn() defined below 
    22  
     22        ( $self->{'pty'},$self->{'pid'} ) = &spawn("/usr/bin/nice /usr/bin/pugs");    # spawn() defined below 
     23if ( $self->{'pty'}==-1 and  $self->{'pid'}==0) { 
     24    $self->{'init'}= "\nThere was a problem starting pugs. Please try again later."; 
     25    $self->{'error'}=1; 
     26} else { 
    2327        ## Create a Net::Telnet object to perform I/O on pugs's tty. 
    2428        use Net::Telnet; 
     
    3842#      die "starting pugs failed: ", $self->{'pugs'}->lastline; 
    3943      $error="\nThere was a problem starting pugs. Please try again later."; 
     44      $self->{'error'}=1; 
     45      # should close the TTY 
     46      $self->{'pugs'}->close(); 
    4047      }; 
    4148        $self->{'init'}= $p.$m.$error;#$self->{'pugs'}->prompt; 
     49    } 
    4250        bless($self,$class); 
    4351        return $self; 
     
    6674#           print "L:",$line,":",$msg; 
    6775            if($msg=~/timed/) { 
    68         $msg=''; 
    69         $pugs->errmsg([]); 
    70         $lline="pugs> Sorry, that took too long! Aborted.\n"; 
    71         $ps='pugs'; 
    72         last; 
     76            $msg=''; 
     77            $pugs->errmsg([]); 
     78            $lline="pugs> Sorry, that took too long! Aborted.\n"; 
     79#            $pugs->close(); 
     80            $ps='pugs'; 
     81            $obj->{'error'}=1; 
     82            last; 
    7383        } 
    7484        $msg=''; 
     
    7888        } 
    7989    if ($i>=255) { 
     90#            $pugs->close(); 
    8091     kill 9, $obj->{'pid'}; 
     92            $obj->{'error'}=1; 
    8193     $lline.="Generated output is limited to 100 lines. Aborted.\npugs"; 
    8294    } 
     
    90102        my (@cmd) = @_; 
    91103        my ( $pid, $pty, $tty, $tty_fd ); 
    92  
     104    my $error=0; 
    93105        ## Create a new pseudo terminal.