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