File Coverage

blib/lib/IO/Stty.pm
Criterion Covered Total %
statement 79 317 24.9
branch 51 270 18.8
condition 13 24 54.1
subroutine 7 8 87.5
pod 2 2 100.0
total 152 621 24.4


line stmt bran cond sub pod time code
1             package IO::Stty;
2              
3 8     8   1146922 use strict;
  8         16  
  8         297  
4 8     8   69 use warnings;
  8         13  
  8         673  
5              
6 8     8   2486 use POSIX;
  8         33380  
  8         52  
7              
8             our $VERSION = '0.05';
9              
10             # Baud rate constants: standard POSIX rates plus modern rates.
11             # Modern rates (B57600, B115200, B230400) are not available on all platforms,
12             # so we use eval guards to include only what the current system supports.
13             my %BAUD_RATES;
14             my %BAUD_SPEEDS;
15             BEGIN {
16 8     8   19216 my @standard = qw(0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 9600 19200 38400);
17 8         26 my @modern = qw(57600 115200 230400);
18 8         25 for my $rate (@standard, @modern) {
19 152         169 my $val = eval { POSIX->can("B$rate") };
  152         732  
20 152 100 66     26033 next unless $val && ref($val) eq 'CODE';
21 128         144 $val = eval { $val->() };
  128         179  
22 128 50       212 if (defined $val) {
23 128         249 $BAUD_RATES{$rate} = $val;
24 128         298 $BAUD_SPEEDS{$val} = $rate;
25             }
26             }
27             }
28              
29             =for markdown [![testsuite](https://github.com/cpan-authors/IO-Stty/actions/workflows/testsuite.yml/badge.svg)](https://github.com/cpan-authors/IO-Stty/actions/workflows/testsuite.yml)
30              
31             =head1 NAME
32              
33             IO::Stty - Change and print terminal line settings
34              
35             =head1 SYNOPSIS
36              
37             # calling the script directly
38             stty.pl [setting...]
39             stty.pl {-a,-g,-v,--version}
40            
41             # Calling Stty module
42             use IO::Stty;
43             IO::Stty::stty(\*TTYHANDLE, @modes);
44              
45             use IO::Stty;
46             $old_mode=IO::Stty::stty(\*STDIN,'-g');
47              
48             # Turn off echoing.
49             IO::Stty::stty(\*STDIN,'-echo');
50              
51             # Do whatever.. grab input maybe?
52             $read_password = <>;
53              
54             # Now restore the old mode.
55             IO::Stty::stty(\*STDIN,$old_mode);
56              
57             # What settings do we have anyway?
58             print IO::Stty::stty(\*STDIN,'-a');
59              
60             =head1 DESCRIPTION
61              
62             This is the PERL POSIX compliant stty.
63              
64             =head1 INTRO
65              
66             This has not been tailored to the IO::File stuff but will work with it as
67             indicated. Before you go futzing with term parameters it's a good idea to grab
68             the current settings and restore them when you finish.
69              
70             stty accepts the following non-option arguments that change aspects of the
71             terminal line operation. A `[-]' before a capability means that it can be
72             turned off by preceding it with a `-'.
73              
74             =head1 stty parameters
75              
76             =head2 Control settings
77              
78             =over 4
79              
80             =item [-]parenb
81              
82             Generate parity bit in output and expect parity bit in input.
83              
84             =item [-]parodd
85              
86             Set odd parity (even with `-').
87              
88             =item cs5 cs6 cs7 cs8
89              
90             Set character size to 5, 6, 7, or 8 bits.
91              
92             =item [-]hupcl [-]hup
93              
94             Send a hangup signal when the last process closes the tty.
95              
96             =item [-]cstopb
97              
98             Use two stop bits per character (one with `-').
99              
100             =item [-]cread
101              
102             Allow input to be received.
103              
104             =item [-]clocal
105              
106             Disable modem control signals.
107              
108             =back
109              
110             =head2 Input settings
111              
112             =over 4
113              
114             =item [-]ignbrk
115              
116             Ignore break characters.
117              
118             =item [-]brkint
119              
120             Breaks cause an interrupt signal.
121              
122             =item [-]ignpar
123              
124             Ignore characters with parity errors.
125              
126             =item [-]parmrk
127              
128             Mark parity errors (with a 255-0-character sequence).
129              
130             =item [-]inpck
131              
132             Enable input parity checking.
133              
134             =item [-]istrip
135              
136             Clear high (8th) bit of input characters.
137              
138             =item [-]inlcr
139              
140             Translate newline to carriage return.
141              
142             =item [-]igncr
143              
144             Ignore carriage return.
145              
146             =item [-]icrnl
147              
148             Translate carriage return to newline.
149              
150             =item [-]ixon
151              
152             Enable XON/XOFF flow control.
153              
154             =item [-]ixoff
155              
156             Enable sending of stop character when the system
157             input buffer is almost full, and start character
158             when it becomes almost empty again.
159              
160             =back
161              
162             =head2 Output settings
163              
164             =over 4
165              
166             =item [-]opost
167              
168             Postprocess output.
169              
170             =back
171              
172             =head2 Local settings
173              
174             =over 4
175              
176             =item [-]isig
177              
178             Enable interrupt, quit, and suspend special characters.
179              
180             =item [-]icanon
181              
182             Enable erase, kill, werase, and rprnt special characters.
183              
184             =item [-]echo
185              
186             Echo input characters.
187              
188             =item [-]echoe, [-]crterase
189              
190             Echo erase characters as backspace-space-backspace.
191              
192             =item [-]echok
193              
194             Echo a newline after a kill character.
195              
196             =item [-]echonl
197              
198             Echo newline even if not echoing other characters.
199              
200             =item [-]noflsh
201              
202             Disable flushing after interrupt and quit special characters.
203              
204             * Though this claims non-posixhood it is supported by the perl POSIX.pm.
205              
206             =item [-]tostop (np)
207              
208             Stop background jobs that try to write to the terminal.
209              
210             =back
211              
212             =head2 Combination settings
213              
214             =over 4
215              
216             =item ek
217              
218             Reset the erase and kill special characters to their default values.
219              
220             =item sane
221              
222             Same as:
223              
224             cread -ignbrk brkint -inlcr -igncr icrnl -ixoff opost
225             isig icanon echo echoe echok -echonl -noflsh -tostop
226              
227             also sets all special characters to their default
228             values.
229              
230             =item [-]cooked
231              
232             Same as:
233              
234             brkint ignpar istrip icrnl ixon opost isig icanon
235              
236             plus sets the eof and eol characters to their default values
237             if they are the same as the min and time characters.
238             With `-', same as raw.
239              
240             =item [-]raw
241              
242             Same as:
243              
244             -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr
245             -icrnl -ixon -ixoff -opost -isig -icanon min 1 time 0
246              
247             With `-', same as cooked.
248              
249             =item [-]pass8
250              
251             Same as:
252              
253             -parenb -istrip cs8
254              
255             With `-', same as parenb istrip cs7.
256              
257             =item dec
258              
259             Same as:
260              
261             echoe echoctl echoke -ixany
262              
263             Also sets the interrupt special character to Ctrl-C, erase to
264             Del, and kill to Ctrl-U.
265              
266             =back
267              
268             =head2 Special characters
269              
270             The special characters' default values vary from system to
271             system. They are set with the syntax `name value', where
272             the names are listed below and the value can be given
273             either literally, in hat notation (`^c'), or as an integer
274             which may start with `0x' to indicate hexadecimal, `0' to
275             indicate octal, or any other digit to indicate decimal.
276             Giving a value of `^-' or `undef' disables that special
277             character.
278              
279             =over 4
280              
281             =item intr
282              
283             Send an interrupt signal.
284              
285             =item quit
286              
287             Send a quit signal.
288              
289             =item erase
290              
291             Erase the last character typed.
292              
293             =item kill
294              
295             Erase the current line.
296              
297             =item eof
298              
299             Send an end of file (terminate the input).
300              
301             =item eol
302              
303             End the line.
304              
305             =item start
306              
307             Restart the output after stopping it.
308              
309             =item stop
310              
311             Stop the output.
312              
313             =item susp
314              
315             Send a terminal stop signal.
316              
317             =back
318              
319             =head2 Special settings
320              
321             =over 4
322              
323             =item min N
324              
325             Set the minimum number of characters that will satisfy a read
326             until the time value has expired, when -icanon is set.
327              
328             =item time N
329              
330             Set the number of tenths of a second before reads
331             time out if the min number of characters have not
332             been read, when -icanon is set.
333              
334             =item N
335              
336             Set the input and output speeds to N. N can be one
337             of: 0 50 75 110 134 134.5 150 200 300 600 1200 1800
338             2400 4800 9600 19200 38400 exta extb. exta is the
339             same as 19200; extb is the same as 38400. 0 hangs
340             up the line if -clocal is set.
341              
342             =back
343              
344             =head2 OPTIONS
345              
346             =over 4
347              
348             =item -a
349              
350             Print all current settings in human-readable form.
351              
352             =item -g
353              
354             Print all current settings in a form that can be
355             used as an argument to another stty command to
356             restore the current settings.
357              
358             =item -v,--version
359              
360             Print version info.
361              
362             =back
363              
364             =head1 Direct Subroutines
365              
366             =over 4
367              
368             =item B<_parse_char_value()>
369              
370             my $numeric = IO::Stty::_parse_char_value($value);
371              
372             Parse a special character value from any of the supported notations:
373             literal integers, hat notation (C<^c>), hexadecimal (C<0x...>),
374             octal (C<0...>), or C/C<^-> to disable.
375              
376             =cut
377              
378             sub _parse_char_value {
379 24     24   264932 my ($val) = @_;
380              
381             # undef or ^- means disable the character
382 24 100 100     161 if ( $val eq 'undef' || $val eq '^-' ) {
383 2         8 return 0;
384             }
385              
386             # Hat notation: ^c means Ctrl-C (0x03), ^? means DEL (0x7F)
387 22 100       91 if ( $val =~ /^\^(.)$/ ) {
388 8         25 my $ch = $1;
389 8 100       21 if ( $ch eq '?' ) {
390 1         4 return 0x7F;
391             }
392 7         29 return ord( uc($ch) ) & 0x1F;
393             }
394              
395             # Hexadecimal: 0x...
396 14 100       83 if ( $val =~ /^0x([0-9a-fA-F]+)$/ ) {
397 6         30 return hex($1);
398             }
399              
400             # Octal: 0 followed by digits (but not plain "0" which is decimal zero)
401 8 100       53 if ( $val =~ /^0(\d+)$/ ) {
402 4         22 return oct($1);
403             }
404              
405             # Decimal integer (including plain 0)
406 4 50       24 if ( $val =~ /^\d+$/ ) {
407 4         18 return $val + 0;
408             }
409              
410             # Single literal character
411 0 0       0 if ( length($val) == 1 ) {
412 0         0 return ord($val);
413             }
414              
415 0         0 warn "IO::Stty: unrecognized character value '$val'\n";
416 0         0 return 0;
417             }
418              
419             =item B
420              
421             IO::Stty::stty(\*STDIN, @params);
422              
423             From comments:
424              
425             I'm not feeling very inspired about this. Terminal parameters are obscure
426             and boring. Basically what this will do is get the current setting,
427             take the parameters, modify the setting and write it back. Zzzz.
428             This is not especially efficent and probably not too fast. Assuming the POSIX
429             spec has been implemented properly it should mostly work.
430              
431             =cut
432              
433             sub stty {
434 0     0 1 0 my $tty_handle = shift; # This should be a \*HANDLE
435              
436 0 0       0 @_ or die("No parameters passed to stty");
437              
438             # Notice fileno() instead of handle->fileno(). I want it to work with
439             # normal fhs.
440 0         0 my ($file_num) = fileno($tty_handle);
441              
442             # Is it a terminal?
443 0 0       0 return undef unless isatty($file_num);
444 0         0 my ($tty_name) = ttyname($file_num);
445              
446             # make a terminal object.
447 0         0 my ($termios) = POSIX::Termios->new();
448 0 0       0 $termios->getattr($file_num) || warn "Couldn't get terminal parameters for '$tty_name', file num ($file_num)";
449 0         0 my ($c_cflag) = $termios->getcflag;
450 0         0 my ($c_iflag) = $termios->getiflag;
451 0         0 my ($ispeed) = $termios->getispeed;
452 0         0 my ($c_lflag) = $termios->getlflag;
453 0         0 my ($c_oflag) = $termios->getoflag;
454 0         0 my ($ospeed) = $termios->getospeed;
455 0         0 my (%control_chars);
456 0         0 $control_chars{'INTR'} = $termios->getcc(VINTR);
457 0         0 $control_chars{'QUIT'} = $termios->getcc(VQUIT);
458 0         0 $control_chars{'ERASE'} = $termios->getcc(VERASE);
459 0         0 $control_chars{'KILL'} = $termios->getcc(VKILL);
460 0         0 $control_chars{'EOF'} = $termios->getcc(VEOF);
461 0         0 $control_chars{'TIME'} = $termios->getcc(VTIME);
462 0         0 $control_chars{'MIN'} = $termios->getcc(VMIN);
463 0         0 $control_chars{'START'} = $termios->getcc(VSTART);
464 0         0 $control_chars{'STOP'} = $termios->getcc(VSTOP);
465 0         0 $control_chars{'SUSP'} = $termios->getcc(VSUSP);
466 0         0 $control_chars{'EOL'} = $termios->getcc(VEOL);
467              
468             # OK.. we have our crap.
469              
470 0         0 my @parameters;
471              
472 0 0       0 if ( @_ == 1 ) {
473              
474             # handle the one-arg cases specifically
475             # Version info
476 0 0       0 if ( $_[0] =~ /^(-v|version)$/ ) {
    0          
    0          
    0          
477 0         0 return $IO::Stty::VERSION . "\n";
478             }
479             elsif ( $_[0] =~ /^\d+$/ ) {
480 0         0 push( @parameters, 'ispeed', $_[0], 'ospeed', $_[0] );
481             }
482              
483             # Do we want to know what the crap is?
484             elsif ( $_[0] eq '-a' ) {
485 0         0 return show_me_the_crap(
486             $c_cflag, $c_iflag, $ispeed, $c_lflag, $c_oflag,
487             $ospeed, \%control_chars
488             );
489             }
490              
491             # did we get the '-g' flag?
492             elsif ( $_[0] eq '-g' ) {
493             return
494             "$c_cflag:$c_iflag:$ispeed:$c_lflag:$c_oflag:$ospeed:"
495             . $control_chars{'INTR'} . ":"
496             . $control_chars{'QUIT'} . ":"
497             . $control_chars{'ERASE'} . ":"
498             . $control_chars{'KILL'} . ":"
499             . $control_chars{'EOF'} . ":"
500             . $control_chars{'TIME'} . ":"
501             . $control_chars{'MIN'} . ":"
502             . $control_chars{'START'} . ":"
503             . $control_chars{'STOP'} . ":"
504             . $control_chars{'SUSP'} . ":"
505 0         0 . $control_chars{'EOL'};
506             }
507             else {
508             # Or the converse.. -g used before and we're getting the return.
509             # Note that this uses the functionality of stty -g, not any specific
510             # method. Don't take the output here and feed it to the OS stty.
511              
512             # This will make perl -w happy.
513 0         0 my (@g_params) = split( ':', $_[0] );
514 0 0       0 if ( @g_params == 17 ) {
515              
516             # print "Feeding back...\n";
517 0         0 ( $c_cflag, $c_iflag, $ispeed, $c_lflag, $c_oflag, $ospeed ) = (@g_params);
518 0         0 $control_chars{'INTR'} = $g_params[6];
519 0         0 $control_chars{'QUIT'} = $g_params[7];
520 0         0 $control_chars{'ERASE'} = $g_params[8];
521 0         0 $control_chars{'KILL'} = $g_params[9];
522 0         0 $control_chars{'EOF'} = $g_params[10];
523 0         0 $control_chars{'TIME'} = $g_params[11];
524 0         0 $control_chars{'MIN'} = $g_params[12];
525 0         0 $control_chars{'START'} = $g_params[13];
526 0         0 $control_chars{'STOP'} = $g_params[14];
527 0         0 $control_chars{'SUSP'} = $g_params[15];
528 0         0 $control_chars{'EOL'} = $g_params[16];
529              
530             # leave parameters empty
531             }
532             else {
533             # a simple single option
534 0         0 @parameters = @_;
535             }
536             }
537             }
538             else {
539 0         0 @parameters = @_;
540             }
541              
542             # So.. what shall we set?
543 0         0 my ($set_value);
544 0         0 local ($_);
545 0         0 while ( defined( $_ = shift(@parameters) ) ) {
546              
547             # print "Param:$_:\n";
548             # Build the 'this really means this' cases.
549 0 0       0 if ( $_ eq 'ek' ) {
550 0         0 unshift( @parameters, 'erase', 8, 'kill', 21 );
551 0         0 next;
552             }
553 0 0       0 if ( $_ eq 'sane' ) {
554 0         0 unshift(
555             @parameters, 'cread', '-ignbrk', 'brkint', '-inlcr', '-igncr', 'icrnl',
556             '-ixoff', 'opost', 'isig', 'icanon', 'iexten', 'echo', 'echoe', 'echok',
557             '-echonl', '-noflsh', '-tostop', 'echok', 'intr', 3, 'quit', 28, 'erase',
558             8, 'kill', 21, 'eof', 4, 'eol', 0, 'stop', 19, 'start', 17, 'susp', 26,
559             'time', 0, 'min', 0
560             );
561 0         0 next;
562              
563             # Ugh.
564             }
565 0 0 0     0 if ( $_ eq 'cooked' || $_ eq '-raw' ) {
566              
567             # Is this right?
568 0         0 unshift(
569             @parameters, 'brkint', 'ignpar', 'istrip', 'icrnl', 'ixon', 'opost',
570             'isig', 'icanon',
571             'intr', 3, 'quit', 28, 'erase', 8, 'kill', 21, 'eof',
572             4, 'eol', 0, 'stop', 19, 'start', 17, 'susp', 26, 'time', 0, 'min', 0
573             );
574 0         0 next;
575             }
576 0 0 0     0 if ( $_ eq 'raw' || $_ eq '-cooked' ) {
577 0         0 unshift(
578             @parameters, '-ignbrk', '-brkint', '-ignpar', '-parmrk', '-inpck',
579             '-istrip', '-inlcr', '-igncr', '-icrnl', '-ixon', '-ixoff',
580             '-opost', '-isig', '-icanon', 'min', 1, 'time', 0
581             );
582 0         0 next;
583             }
584 0 0       0 if ( $_ eq 'pass8' ) {
585 0         0 unshift( @parameters, '-parenb', '-istrip', 'cs8' );
586 0         0 next;
587             }
588 0 0       0 if ( $_ eq '-pass8' ) {
589 0         0 unshift( @parameters, 'parenb', 'istrip', 'cs7' );
590 0         0 next;
591             }
592 0 0       0 if ( $_ eq 'crt' ) {
593 0         0 unshift( @parameters, 'echoe', 'echok' );
594 0         0 next;
595             }
596 0 0       0 if ( $_ eq 'dec' ) {
597              
598             # 127 == delete, no?
599 0         0 unshift( @parameters, 'echoe', 'echok', 'intr', 3, 'erase', 127, 'kill', 21 );
600 0         0 next;
601             }
602 0         0 $set_value = 1; # On by default...
603             # unset if starts w/ -, as in -crtscts
604 0 0       0 $set_value = 0 if s/^\-//;
605              
606             # Now the fun part.
607              
608             # c_cc field crap.
609 0 0       0 if ( $_ eq 'intr' ) { $control_chars{'INTR'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
610 0 0       0 if ( $_ eq 'quit' ) { $control_chars{'QUIT'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
611 0 0       0 if ( $_ eq 'erase' ) { $control_chars{'ERASE'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
612 0 0       0 if ( $_ eq 'kill' ) { $control_chars{'KILL'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
613 0 0       0 if ( $_ eq 'eof' ) { $control_chars{'EOF'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
614 0 0       0 if ( $_ eq 'eol' ) { $control_chars{'EOL'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
615 0 0       0 if ( $_ eq 'start' ) { $control_chars{'START'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
616 0 0       0 if ( $_ eq 'stop' ) { $control_chars{'STOP'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
617 0 0       0 if ( $_ eq 'susp' ) { $control_chars{'SUSP'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
618 0 0       0 if ( $_ eq 'min' ) { $control_chars{'MIN'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
619 0 0       0 if ( $_ eq 'time' ) { $control_chars{'TIME'} = _parse_char_value( shift @parameters ); next; }
  0         0  
  0         0  
620              
621             # c_cflag crap
622 0 0       0 if ( $_ eq 'clocal' ) { $c_cflag = ( $set_value ? ( $c_cflag | CLOCAL ) : ( $c_cflag & ( ~CLOCAL ) ) ); next; }
  0 0       0  
  0         0  
623 0 0       0 if ( $_ eq 'cread' ) { $c_cflag = ( $set_value ? ( $c_cflag | CREAD ) : ( $c_cflag & ( ~CREAD ) ) ); next; }
  0 0       0  
  0         0  
624              
625             # As best I can tell, doing |~CS8 will clear the bits.. under solaris
626             # anyway, where CS5 = 0, CS6 = 0x20, CS7= 0x40, CS8=0x60
627 0 0       0 if ( $_ eq 'cs5' ) { $c_cflag = ( ( $c_cflag & ~CS8 ) | CS5 ); next; }
  0         0  
  0         0  
628 0 0       0 if ( $_ eq 'cs6' ) { $c_cflag = ( ( $c_cflag & ~CS8 ) | CS6 ); next; }
  0         0  
  0         0  
629 0 0       0 if ( $_ eq 'cs7' ) { $c_cflag = ( ( $c_cflag & ~CS8 ) | CS7 ); next; }
  0         0  
  0         0  
630 0 0       0 if ( $_ eq 'cs8' ) { $c_cflag = ( $c_cflag | CS8 ); next; }
  0         0  
  0         0  
631 0 0       0 if ( $_ eq 'cstopb' ) { $c_cflag = ( $set_value ? ( $c_cflag | CSTOPB ) : ( $c_cflag & ( ~CSTOPB ) ) ); next; }
  0 0       0  
  0         0  
632 0 0 0     0 if ( $_ eq 'hupcl' || $_ eq 'hup' ) { $c_cflag = ( $set_value ? ( $c_cflag | HUPCL ) : ( $c_cflag & ( ~HUPCL ) ) ); next; }
  0 0       0  
  0         0  
633 0 0       0 if ( $_ eq 'parenb' ) { $c_cflag = ( $set_value ? ( $c_cflag | PARENB ) : ( $c_cflag & ( ~PARENB ) ) ); next; }
  0 0       0  
  0         0  
634 0 0       0 if ( $_ eq 'parodd' ) { $c_cflag = ( $set_value ? ( $c_cflag | PARODD ) : ( $c_cflag & ( ~PARODD ) ) ); next; }
  0 0       0  
  0         0  
635              
636             # That was fun. Still awake? c_iflag time.
637 0 0       0 if ( $_ eq 'brkint' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | BRKINT ) : ( $c_iflag & ( ~BRKINT ) ) ) ); next; }
  0 0       0  
  0         0  
638 0 0       0 if ( $_ eq 'icrnl' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | ICRNL ) : ( $c_iflag & ( ~ICRNL ) ) ) ); next; }
  0 0       0  
  0         0  
639 0 0       0 if ( $_ eq 'ignbrk' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | IGNBRK ) : ( $c_iflag & ( ~IGNBRK ) ) ) ); next; }
  0 0       0  
  0         0  
640 0 0       0 if ( $_ eq 'igncr' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | IGNCR ) : ( $c_iflag & ( ~IGNCR ) ) ) ); next; }
  0 0       0  
  0         0  
641 0 0       0 if ( $_ eq 'ignpar' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | IGNPAR ) : ( $c_iflag & ( ~IGNPAR ) ) ) ); next; }
  0 0       0  
  0         0  
642 0 0       0 if ( $_ eq 'inlcr' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | INLCR ) : ( $c_iflag & ( ~INLCR ) ) ) ); next; }
  0 0       0  
  0         0  
643 0 0       0 if ( $_ eq 'inpck' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | INPCK ) : ( $c_iflag & ( ~INPCK ) ) ) ); next; }
  0 0       0  
  0         0  
644 0 0       0 if ( $_ eq 'istrip' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | ISTRIP ) : ( $c_iflag & ( ~ISTRIP ) ) ) ); next; }
  0 0       0  
  0         0  
645 0 0       0 if ( $_ eq 'ixoff' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | IXOFF ) : ( $c_iflag & ( ~IXOFF ) ) ) ); next; }
  0 0       0  
  0         0  
646 0 0       0 if ( $_ eq 'ixon' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | IXON ) : ( $c_iflag & ( ~IXON ) ) ) ); next; }
  0 0       0  
  0         0  
647 0 0       0 if ( $_ eq 'parmrk' ) { $c_iflag = ( ( $set_value ? ( $c_iflag | PARMRK ) : ( $c_iflag & ( ~PARMRK ) ) ) ); next; }
  0 0       0  
  0         0  
648              
649             # Are we there yet? No. Are we there yet? No. Are we there yet...
650             # print "Values: $c_lflag,".($c_lflag | ECHO)." ".($c_lflag & (~ECHO))."\n";
651 0 0       0 if ( $_ eq 'echo' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | ECHO ) : ( $c_lflag & ( ~ECHO ) ) ) ); next; }
  0 0       0  
  0         0  
652 0 0       0 if ( $_ eq 'echoe' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | ECHOE ) : ( $c_lflag & ( ~ECHOE ) ) ) ); next; }
  0 0       0  
  0         0  
653 0 0       0 if ( $_ eq 'echok' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | ECHOK ) : ( $c_lflag & ( ~ECHOK ) ) ) ); next; }
  0 0       0  
  0         0  
654 0 0       0 if ( $_ eq 'echonl' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | ECHONL ) : ( $c_lflag & ( ~ECHONL ) ) ) ); next; }
  0 0       0  
  0         0  
655 0 0       0 if ( $_ eq 'icanon' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | ICANON ) : ( $c_lflag & ( ~ICANON ) ) ) ); next; }
  0 0       0  
  0         0  
656 0 0       0 if ( $_ eq 'iexten' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | IEXTEN ) : ( $c_lflag & ( ~IEXTEN ) ) ) ); next; }
  0 0       0  
  0         0  
657 0 0       0 if ( $_ eq 'isig' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | ISIG ) : ( $c_lflag & ( ~ISIG ) ) ) ); next; }
  0 0       0  
  0         0  
658 0 0       0 if ( $_ eq 'noflsh' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | NOFLSH ) : ( $c_lflag & ( ~NOFLSH ) ) ) ); next; }
  0 0       0  
  0         0  
659 0 0       0 if ( $_ eq 'tostop' ) { $c_lflag = ( ( $set_value ? ( $c_lflag | TOSTOP ) : ( $c_lflag & ( ~TOSTOP ) ) ) ); next; }
  0 0       0  
  0         0  
660              
661             # Make it stop! Make it stop!
662             # c_oflag crap.
663 0 0       0 if ( $_ eq 'opost' ) { $c_oflag = ( ( $set_value ? ( $c_oflag | OPOST ) : ( $c_oflag & ( ~OPOST ) ) ) ); next; }
  0 0       0  
  0         0  
664              
665             # Speed?
666 0 0       0 if ( $_ eq 'ospeed' ) {
667 0         0 my $rate = shift(@parameters);
668 0 0       0 exists $BAUD_RATES{$rate} or warn "IO::Stty::stty: unknown baud rate '$rate'\n";
669 0 0       0 $ospeed = $BAUD_RATES{$rate} if exists $BAUD_RATES{$rate};
670 0         0 next;
671             }
672 0 0       0 if ( $_ eq 'ispeed' ) {
673 0         0 my $rate = shift(@parameters);
674 0 0       0 exists $BAUD_RATES{$rate} or warn "IO::Stty::stty: unknown baud rate '$rate'\n";
675 0 0       0 $ispeed = $BAUD_RATES{$rate} if exists $BAUD_RATES{$rate};
676 0         0 next;
677             }
678              
679             # Default.. parameter hasn't matched anything
680             # print "char:".sprintf("%lo",ord($_))."\n";
681 0         0 warn "IO::Stty::stty passed invalid parameter '$_'\n";
682             }
683              
684             # What a pain in the ass! Ok.. let's write the crap back.
685 0         0 $termios->setcflag($c_cflag);
686 0         0 $termios->setiflag($c_iflag);
687 0         0 $termios->setispeed($ispeed);
688 0         0 $termios->setlflag($c_lflag);
689 0         0 $termios->setoflag($c_oflag);
690 0         0 $termios->setospeed($ospeed);
691 0         0 $termios->setcc( VINTR, $control_chars{'INTR'} );
692 0         0 $termios->setcc( VQUIT, $control_chars{'QUIT'} );
693 0         0 $termios->setcc( VERASE, $control_chars{'ERASE'} );
694 0         0 $termios->setcc( VKILL, $control_chars{'KILL'} );
695 0         0 $termios->setcc( VEOF, $control_chars{'EOF'} );
696 0         0 $termios->setcc( VTIME, $control_chars{'TIME'} );
697 0         0 $termios->setcc( VMIN, $control_chars{'MIN'} );
698 0         0 $termios->setcc( VSTART, $control_chars{'START'} );
699 0         0 $termios->setcc( VSTOP, $control_chars{'STOP'} );
700 0         0 $termios->setcc( VSUSP, $control_chars{'SUSP'} );
701 0         0 $termios->setcc( VEOL, $control_chars{'EOL'} );
702 0         0 $termios->setattr( $file_num, TCSANOW ); # TCSANOW = do immediately. don't unbuffer first.
703             # OK.. that sucked.
704             }
705              
706             =item B
707              
708             Needs documentation
709              
710             =cut
711              
712             sub _cc_to_hat {
713 166     166   245633 my ($val) = @_;
714 166 100 100     590 return '' if !defined $val || $val == 0 || $val == 255;
      100        
715 146 100       216 return '^?' if $val == 127;
716 128 100 66     482 return '^' . chr( ord('@') + $val ) if $val >= 0 && $val < 32;
717 2         14 return chr($val);
718             }
719              
720             sub show_me_the_crap {
721             my (
722 17     17 1 194964 $c_cflag, $c_iflag, $ispeed, $c_lflag, $c_oflag,
723             $ospeed, $control_chars
724             ) = @_;
725 17         94 my (%cc) = %$control_chars;
726              
727             # rs = return string
728 17         37 my ($rs) = '';
729 17         27 $rs .= 'speed ';
730 17 50       50 if ( exists $BAUD_SPEEDS{$ospeed} ) {
731 17         33 $rs .= $BAUD_SPEEDS{$ospeed};
732             }
733 17         23 $rs .= " baud\n";
734 17         32 $rs .= 'intr = ' . _cc_to_hat($cc{'INTR'}) . '; quit = ' . _cc_to_hat($cc{'QUIT'}) . '; erase = ' . _cc_to_hat($cc{'ERASE'}) . '; kill = ' . _cc_to_hat($cc{'KILL'}) . ";\n";
735 17         34 $rs .= 'eof = ' . _cc_to_hat($cc{'EOF'}) . '; eol = ' . _cc_to_hat($cc{'EOL'}) . '; start = ' . _cc_to_hat($cc{'START'}) . '; stop = ' . _cc_to_hat($cc{'STOP'}) . '; susp = ' . _cc_to_hat($cc{'SUSP'}) . ";\n";
736              
737             # c flags.
738 17 50       45 $rs .= ( ( $c_cflag & CLOCAL ) ? '' : '-' ) . 'clocal ';
739 17 50       27 $rs .= ( ( $c_cflag & CREAD ) ? '' : '-' ) . 'cread ';
740 17 50       25 $rs .= ( ( $c_cflag & CSTOPB ) ? '' : '-' ) . 'cstopb ';
741 17 50       25 $rs .= ( ( $c_cflag & HUPCL ) ? '' : '-' ) . 'hupcl ';
742 17 50       37 $rs .= ( ( $c_cflag & PARENB ) ? '' : '-' ) . 'parenb ';
743 17 50       25 $rs .= ( ( $c_cflag & PARODD ) ? '' : '-' ) . 'parodd ';
744 17         31 $c_cflag = $c_cflag & CS8;
745              
746 17 100       41 if ( $c_cflag == CS8 ) {
    50          
    50          
747 1         2 $rs .= "cs8\n";
748             }
749             elsif ( $c_cflag == CS7 ) {
750 0         0 $rs .= "cs7\n";
751             }
752             elsif ( $c_cflag == CS6 ) {
753 0         0 $rs .= "cs6\n";
754             }
755             else {
756 16         23 $rs .= "cs5\n";
757             }
758              
759             # l flags.
760 17 50       25 $rs .= ( ( $c_lflag & ECHO ) ? '' : '-' ) . 'echo ';
761 17 50       24 $rs .= ( ( $c_lflag & ECHOE ) ? '' : '-' ) . 'echoe ';
762 17 50       23 $rs .= ( ( $c_lflag & ECHOK ) ? '' : '-' ) . 'echok ';
763 17 50       26 $rs .= ( ( $c_lflag & ECHONL ) ? '' : '-' ) . 'echonl ';
764 17 50       35 $rs .= ( ( $c_lflag & ICANON ) ? '' : '-' ) . 'icanon ';
765 17 50       24 $rs .= ( ( $c_lflag & ISIG ) ? '' : '-' ) . 'isig ';
766 17 50       23 $rs .= ( ( $c_lflag & NOFLSH ) ? '' : '-' ) . 'noflsh ';
767 17 50       28 $rs .= ( ( $c_lflag & TOSTOP ) ? '' : '-' ) . 'tostop ';
768 17 50       24 $rs .= ( ( $c_lflag & IEXTEN ) ? '' : '-' ) . 'iexten ';
769              
770             # o flag. jam it after the l flags so it looks more compact.
771 17 50       42 $rs .= ( ( $c_oflag & OPOST ) ? '' : '-' ) . "opost\n";
772              
773             # i flags.
774 17 50       22 $rs .= ( ( $c_iflag & BRKINT ) ? '' : '-' ) . 'brkint ';
775 17 50       26 $rs .= ( ( $c_iflag & IGNBRK ) ? '' : '-' ) . 'ignbrk ';
776 17 50       25 $rs .= ( ( $c_iflag & IGNPAR ) ? '' : '-' ) . 'ignpar ';
777 17 50       24 $rs .= ( ( $c_iflag & PARMRK ) ? '' : '-' ) . 'parmrk ';
778 17 50       22 $rs .= ( ( $c_iflag & INPCK ) ? '' : '-' ) . 'inpck ';
779 17 50       24 $rs .= ( ( $c_iflag & ISTRIP ) ? '' : '-' ) . 'istrip ';
780 17 50       23 $rs .= ( ( $c_iflag & INLCR ) ? '' : '-' ) . 'inlcr ';
781 17 50       27 $rs .= ( ( $c_iflag & ICRNL ) ? '' : '-' ) . 'icrnl ';
782 17 50       26 $rs .= ( ( $c_iflag & IXON ) ? '' : '-' ) . 'ixon ';
783 17 50       23 $rs .= ( ( $c_iflag & IXOFF ) ? '' : '-' ) . "ixoff\n";
784 17         58 return $rs;
785             }
786              
787             =back
788              
789             =head1 AUTHOR
790              
791             Austin Schutz (Initial version and maintenance)
792              
793             Todd Rinaldo (Maintenance)
794              
795             =head1 BUGS
796              
797             This is use at your own risk software. Do anything you want with it except
798             blame me for it blowing up your machine because it's full of bugs.
799              
800             See above for what functions are supported. It's mostly standard POSIX
801             stuff. If any of the settings are wrong and you actually know what some of
802             these extremely arcane settings (like what 'sane' should be in POSIX land)
803             really should be, please open an RT ticket.
804              
805             =head1 ACKNOWLEDGEMENTS
806              
807             None
808              
809             =head1 COPYRIGHT & LICENSE
810              
811             Copyright 1997 Austin Schutz, all rights reserved.
812              
813             This program is free software; you can redistribute it and/or modify it
814             under the same terms as Perl itself.
815              
816             =cut
817              
818             1;