line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Documentation at the __END__ |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package IO::Pty; |
4
|
|
|
|
|
|
|
|
5
|
4
|
|
|
4
|
|
279876
|
use strict; |
|
4
|
|
|
|
|
41
|
|
|
4
|
|
|
|
|
133
|
|
6
|
4
|
|
|
4
|
|
20
|
use Carp; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
239
|
|
7
|
4
|
|
|
4
|
|
2463
|
use IO::Tty qw(TIOCSCTTY TCSETCTTY TIOCNOTTY); |
|
4
|
|
|
|
|
15
|
|
|
4
|
|
|
|
|
19
|
|
8
|
4
|
|
|
4
|
|
31
|
use IO::File; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
502
|
|
9
|
|
|
|
|
|
|
require POSIX; |
10
|
|
|
|
|
|
|
|
11
|
4
|
|
|
4
|
|
25
|
use vars qw(@ISA $VERSION); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
4291
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
$VERSION = '1.15'; # keep same as in Tty.pm |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
@ISA = qw(IO::Handle); |
16
|
|
|
|
|
|
|
eval { local $^W = 0; undef local $SIG{__DIE__}; require IO::Stty }; |
17
|
|
|
|
|
|
|
push @ISA, "IO::Stty" if (not $@); # if IO::Stty is installed |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
6
|
|
50
|
6
|
1
|
2737927
|
my ($class) = $_[0] || "IO::Pty"; |
21
|
6
|
50
|
|
|
|
71
|
$class = ref($class) if ref($class); |
22
|
6
|
50
|
|
|
|
72
|
@_ <= 1 or croak 'usage: new $class'; |
23
|
|
|
|
|
|
|
|
24
|
6
|
|
|
|
|
5024
|
my ($ptyfd, $ttyfd, $ttyname) = pty_allocate(); |
25
|
|
|
|
|
|
|
|
26
|
6
|
50
|
|
|
|
52
|
croak "Cannot open a pty" if not defined $ptyfd; |
27
|
|
|
|
|
|
|
|
28
|
6
|
|
|
|
|
310
|
my $pty = $class->SUPER::new_from_fd($ptyfd, "r+"); |
29
|
6
|
50
|
|
|
|
1454
|
croak "Cannot create a new $class from fd $ptyfd: $!" if not $pty; |
30
|
6
|
|
|
|
|
183
|
$pty->autoflush(1); |
31
|
6
|
|
|
|
|
560
|
bless $pty => $class; |
32
|
|
|
|
|
|
|
|
33
|
6
|
|
|
|
|
163
|
my $slave = IO::Tty->new_from_fd($ttyfd, "r+"); |
34
|
6
|
50
|
|
|
|
513
|
croak "Cannot create a new IO::Tty from fd $ttyfd: $!" if not $slave; |
35
|
6
|
|
|
|
|
65
|
$slave->autoflush(1); |
36
|
|
|
|
|
|
|
|
37
|
6
|
|
|
|
|
240
|
${*$pty}{'io_pty_slave'} = $slave; |
|
6
|
|
|
|
|
57
|
|
38
|
6
|
|
|
|
|
17
|
${*$pty}{'io_pty_ttyname'} = $ttyname; |
|
6
|
|
|
|
|
32
|
|
39
|
6
|
|
|
|
|
18
|
${*$slave}{'io_tty_ttyname'} = $ttyname; |
|
6
|
|
|
|
|
32
|
|
40
|
|
|
|
|
|
|
|
41
|
6
|
|
|
|
|
44
|
return $pty; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub ttyname { |
45
|
0
|
0
|
|
0
|
1
|
0
|
@_ == 1 or croak 'usage: $pty->ttyname();'; |
46
|
0
|
|
|
|
|
0
|
my $pty = shift; |
47
|
0
|
|
|
|
|
0
|
${*$pty}{'io_pty_ttyname'}; |
|
0
|
|
|
|
|
0
|
|
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub close_slave { |
52
|
3
|
50
|
|
3
|
1
|
2374
|
@_ == 1 or croak 'usage: $pty->close_slave();'; |
53
|
|
|
|
|
|
|
|
54
|
3
|
|
|
|
|
42
|
my $master = shift; |
55
|
|
|
|
|
|
|
|
56
|
3
|
50
|
|
|
|
24
|
if (exists ${*$master}{'io_pty_slave'}) { |
|
3
|
|
|
|
|
147
|
|
57
|
3
|
|
|
|
|
35
|
close ${*$master}{'io_pty_slave'}; |
|
3
|
|
|
|
|
79
|
|
58
|
3
|
|
|
|
|
46
|
delete ${*$master}{'io_pty_slave'}; |
|
3
|
|
|
|
|
176
|
|
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub slave { |
63
|
2
|
50
|
|
2
|
1
|
872
|
@_ == 1 or croak 'usage: $pty->slave();'; |
64
|
|
|
|
|
|
|
|
65
|
2
|
|
|
|
|
25
|
my $master = shift; |
66
|
|
|
|
|
|
|
|
67
|
2
|
50
|
|
|
|
19
|
if (exists ${*$master}{'io_pty_slave'}) { |
|
2
|
|
|
|
|
58
|
|
68
|
2
|
|
|
|
|
25
|
return ${*$master}{'io_pty_slave'}; |
|
2
|
|
|
|
|
44
|
|
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
0
|
|
|
|
|
|
my $tty = ${*$master}{'io_pty_ttyname'}; |
|
0
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
0
|
|
|
|
|
|
my $slave = new IO::Tty; |
74
|
|
|
|
|
|
|
|
75
|
0
|
0
|
|
|
|
|
$slave->open($tty, O_RDWR | O_NOCTTY) || |
76
|
|
|
|
|
|
|
croak "Cannot open slave $tty: $!"; |
77
|
|
|
|
|
|
|
|
78
|
0
|
|
|
|
|
|
return $slave; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub make_slave_controlling_terminal { |
82
|
0
|
0
|
|
0
|
1
|
|
@_ == 1 or croak 'usage: $pty->make_slave_controlling_terminal();'; |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
my $self = shift; |
85
|
0
|
|
|
|
|
|
local(*DEVTTY); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# loose controlling terminal explicitly |
88
|
0
|
0
|
|
|
|
|
if (defined TIOCNOTTY) { |
89
|
0
|
0
|
|
|
|
|
if (open (\*DEVTTY, "/dev/tty")) { |
90
|
0
|
|
|
|
|
|
ioctl( \*DEVTTY, TIOCNOTTY, 0 ); |
91
|
0
|
|
|
|
|
|
close \*DEVTTY; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Create a new 'session', lose controlling terminal. |
96
|
0
|
0
|
|
|
|
|
if (POSIX::setsid() == -1) { |
97
|
0
|
0
|
|
|
|
|
warn "setsid() failed, strange behavior may result: $!\r\n" if $^W; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
0
|
0
|
|
|
|
|
if (open(\*DEVTTY, "/dev/tty")) { |
101
|
0
|
0
|
|
|
|
|
warn "Could not disconnect from controlling terminal?!\n" if $^W; |
102
|
0
|
|
|
|
|
|
close \*DEVTTY; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# now open slave, this should set it as controlling tty on some systems |
106
|
0
|
|
|
|
|
|
my $ttyname = ${*$self}{'io_pty_ttyname'}; |
|
0
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
my $slv = new IO::Tty; |
108
|
0
|
0
|
|
|
|
|
$slv->open($ttyname, O_RDWR) |
109
|
|
|
|
|
|
|
or croak "Cannot open slave $ttyname: $!"; |
110
|
|
|
|
|
|
|
|
111
|
0
|
0
|
|
|
|
|
if (not exists ${*$self}{'io_pty_slave'}) { |
|
0
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
${*$self}{'io_pty_slave'} = $slv; |
|
0
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
} else { |
114
|
0
|
|
|
|
|
|
$slv->close; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# Acquire a controlling terminal if this doesn't happen automatically |
118
|
0
|
0
|
|
|
|
|
if (not open(\*DEVTTY, "/dev/tty")) { |
119
|
0
|
0
|
|
|
|
|
if (defined TIOCSCTTY) { |
|
|
0
|
|
|
|
|
|
120
|
0
|
0
|
|
|
|
|
if (not defined ioctl( ${*$self}{'io_pty_slave'}, TIOCSCTTY, 0 )) { |
|
0
|
|
|
|
|
|
|
121
|
0
|
0
|
|
|
|
|
warn "warning: TIOCSCTTY failed, slave might not be set as controlling terminal: $!" if $^W; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
} elsif (defined TCSETCTTY) { |
124
|
0
|
0
|
|
|
|
|
if (not defined ioctl( ${*$self}{'io_pty_slave'}, TCSETCTTY, 0 )) { |
|
0
|
|
|
|
|
|
|
125
|
0
|
0
|
|
|
|
|
warn "warning: TCSETCTTY failed, slave might not be set as controlling terminal: $!" if $^W; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} else { |
128
|
0
|
0
|
|
|
|
|
warn "warning: You have neither TIOCSCTTY nor TCSETCTTY on your system\n" if $^W; |
129
|
0
|
|
|
|
|
|
return 0; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
0
|
0
|
|
|
|
|
if (not open(\*DEVTTY, "/dev/tty")) { |
134
|
0
|
|
|
|
|
|
warn "Error: could not connect pty as controlling terminal!\n"; |
135
|
0
|
|
|
|
|
|
return undef; |
136
|
|
|
|
|
|
|
} else { |
137
|
0
|
|
|
|
|
|
close \*DEVTTY; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
|
return 1; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
*clone_winsize_from = \&IO::Tty::clone_winsize_from; |
144
|
|
|
|
|
|
|
*get_winsize = \&IO::Tty::get_winsize; |
145
|
|
|
|
|
|
|
*set_winsize = \&IO::Tty::set_winsize; |
146
|
|
|
|
|
|
|
*set_raw = \&IO::Tty::set_raw; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
1; |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
__END__ |