/[cvs]/joko/TestArea/perl/runtime/POE/jobs-tasks/run.pl
ViewVC logotype

Contents of /joko/TestArea/perl/runtime/POE/jobs-tasks/run.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Sun May 11 21:48:52 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
File MIME type: text/plain
initial commit

1 #!/usr/bin/perl
2 # $Id$
3
4 # This program manages a child process started with POE::Wheel::Run.
5 # Wheel::Run is a lot like IPC::Run but event driven. Because it
6 # doesn't block, though, it can be instantiated several times to drive
7 # many child processes.
8 #
9 # This sample runs a single process, nethack, as its test program. It
10 # adds two "features" to stock nethack:
11 #
12 # 1. It changes all "@" characters to random colors. It's annoying,
13 # but it lets you know the program's working.
14 #
15 # 2. Ctrl+C sends a string of random movement commands to the child
16 # process. This causes your player to go a little berzerk.
17
18 use warnings;
19 use strict;
20
21 sub PROGRAM () { "nethack" }
22
23 use POSIX;
24 use POE qw( Wheel::ReadWrite Wheel::Run Filter::Stream );
25
26 ### Handle the _start event. This sets things in motion.
27
28 sub handle_start {
29 my ( $kernel, $heap ) = @_[ KERNEL, HEAP ];
30
31 # Set a signal handler.
32
33 $kernel->sig( CHLD => "got_sigchld" );
34
35 # Save the original terminal settings so they can be restored later.
36
37 $heap->{stdin_tio} = POSIX::Termios->new();
38 $heap->{stdin_tio}->getattr(0);
39 $heap->{stdout_tio} = POSIX::Termios->new();
40 $heap->{stdout_tio}->getattr(1);
41 $heap->{stderr_tio} = POSIX::Termios->new();
42 $heap->{stderr_tio}->getattr(2);
43
44 # Put the terminal into raw input mode. Otherwise discrete
45 # keystrokes will not be read immediately.
46
47 my $tio = POSIX::Termios->new();
48 $tio->getattr(0);
49 my $lflag = $tio->getlflag;
50 $lflag &= ~( ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG );
51 $tio->setlflag($lflag);
52 my $iflag = $tio->getiflag;
53 $iflag &= ~( BRKINT | INPCK | ISTRIP | IXON );
54 $tio->setiflag($iflag);
55 my $cflag = $tio->getcflag;
56 $cflag &= ~( CSIZE | PARENB );
57 $tio->setcflag($cflag);
58 $tio->setattr( 0, TCSANOW );
59
60 # Start the terminal reader/writer.
61
62 $heap->{stdio} = POE::Wheel::ReadWrite->new
63 ( InputHandle => \*STDIN,
64 OutputHandle => \*STDOUT,
65 InputEvent => "got_terminal_stdin",
66 Filter => POE::Filter::Stream->new(),
67 );
68
69 # Start the asynchronous child process.
70
71 $heap->{program} = POE::Wheel::Run->new
72 ( Program => PROGRAM,
73 Conduit => "pty",
74 StdoutEvent => "got_child_stdout",
75 Filter => POE::Filter::Stream->new(),
76 );
77 }
78
79 ### Handle the _stop event. This restores the original terminal
80 ### settings when we're done. That's very important.
81
82 sub handle_stop {
83 my $heap = $_[HEAP];
84 $heap->{stdin_tio}->setattr( 0, TCSANOW );
85 $heap->{stdout_tio}->setattr( 1, TCSANOW );
86 $heap->{stderr_tio}->setattr( 2, TCSANOW );
87 }
88
89 ### Handle terminal STDIN. Send it to the background program's STDIN.
90 ### If the user presses ^C, then also go berserk a little.
91
92 sub handle_terminal_stdin {
93 my ( $heap, $input ) = @_[ HEAP, ARG0 ];
94
95 while ( $input =~ m/\003/g ) {
96 my $count = int( 5 + rand(10) );
97 my $random_walk = '';
98 $random_walk .= int( rand(9) + 1 ) while $count--;
99 $random_walk =~ tr[5][]d;
100 substr( $input, pos($input) - 1, 1 ) = $random_walk;
101 }
102
103 $heap->{program}->put($input);
104 }
105
106 ### Handle STDOUT from the child program. Send it to the terminal's
107 ### STDOUT. Oh, and do something silly like change the foreground
108 ### color of "@" characters to something random. :)
109
110 sub handle_child_stdout {
111 my ( $heap, $input ) = @_[ HEAP, ARG0 ];
112 my $color = int rand 8;
113 $input =~ s/\@/\e[3${color}m\@\e[0m/g;
114 $heap->{stdio}->put($input);
115 }
116
117 ### Handle SIGCHLD. Shut down if the exiting child process was the
118 ### one we've been managing.
119
120 sub handle_sigchld {
121 my ( $heap, $child_pid ) = @_[ HEAP, ARG1 ];
122 if ( $child_pid == $heap->{program}->PID ) {
123 delete $heap->{program};
124 delete $heap->{stdio};
125 }
126 return 0;
127 }
128
129 ### Start a session to encapsulate the previous features.
130
131 POE::Session->create
132 ( inline_states =>
133 { _start => \&handle_start,
134 _stop => \&handle_stop,
135 got_terminal_stdin => \&handle_terminal_stdin,
136 got_child_stdout => \&handle_child_stdout,
137 got_sigchld => \&handle_sigchld,
138 },
139 );
140
141 ### Start POE's main loop, which runs the session until it's done.
142
143 $poe_kernel->run();
144 exit 0;

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed