1 //===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Utility/PseudoTerminal.h"
11
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 #if defined(TIOCSCTTY)
17 #include <sys/ioctl.h>
18 #endif
19
20 using namespace lldb_utility;
21
22 //----------------------------------------------------------------------
23 // PseudoTerminal constructor
24 //----------------------------------------------------------------------
PseudoTerminal()25 PseudoTerminal::PseudoTerminal () :
26 m_master_fd(invalid_fd),
27 m_slave_fd(invalid_fd)
28 {
29 }
30
31 //----------------------------------------------------------------------
32 // Destructor
33 //
34 // The destructor will close the master and slave file descriptors
35 // if they are valid and ownwership has not been released using the
36 // ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor()
37 // member functions.
38 //----------------------------------------------------------------------
~PseudoTerminal()39 PseudoTerminal::~PseudoTerminal ()
40 {
41 CloseMasterFileDescriptor();
42 CloseSlaveFileDescriptor();
43 }
44
45 //----------------------------------------------------------------------
46 // Close the master file descriptor if it is valid.
47 //----------------------------------------------------------------------
48 void
CloseMasterFileDescriptor()49 PseudoTerminal::CloseMasterFileDescriptor ()
50 {
51 if (m_master_fd >= 0)
52 {
53 ::close (m_master_fd);
54 m_master_fd = invalid_fd;
55 }
56 }
57
58 //----------------------------------------------------------------------
59 // Close the slave file descriptor if it is valid.
60 //----------------------------------------------------------------------
61 void
CloseSlaveFileDescriptor()62 PseudoTerminal::CloseSlaveFileDescriptor ()
63 {
64 if (m_slave_fd >= 0)
65 {
66 ::close (m_slave_fd);
67 m_slave_fd = invalid_fd;
68 }
69 }
70
71 //----------------------------------------------------------------------
72 // Open the first available pseudo terminal with OFLAG as the
73 // permissions. The file descriptor is stored in this object and can
74 // be accessed with the MasterFileDescriptor() accessor. The
75 // ownership of the master file descriptor can be released using
76 // the ReleaseMasterFileDescriptor() accessor. If this object has
77 // a valid master files descriptor when its destructor is called, it
78 // will close the master file descriptor, therefore clients must
79 // call ReleaseMasterFileDescriptor() if they wish to use the master
80 // file descriptor after this object is out of scope or destroyed.
81 //
82 // RETURNS:
83 // Zero when successful, non-zero indicating an error occurred.
84 //----------------------------------------------------------------------
85 bool
OpenFirstAvailableMaster(int oflag,char * error_str,size_t error_len)86 PseudoTerminal::OpenFirstAvailableMaster (int oflag, char *error_str, size_t error_len)
87 {
88 if (error_str)
89 error_str[0] = '\0';
90
91 // Open the master side of a pseudo terminal
92 m_master_fd = ::posix_openpt (oflag);
93 if (m_master_fd < 0)
94 {
95 if (error_str)
96 ::strerror_r (errno, error_str, error_len);
97 return false;
98 }
99
100 // Grant access to the slave pseudo terminal
101 if (::grantpt (m_master_fd) < 0)
102 {
103 if (error_str)
104 ::strerror_r (errno, error_str, error_len);
105 CloseMasterFileDescriptor ();
106 return false;
107 }
108
109 // Clear the lock flag on the slave pseudo terminal
110 if (::unlockpt (m_master_fd) < 0)
111 {
112 if (error_str)
113 ::strerror_r (errno, error_str, error_len);
114 CloseMasterFileDescriptor ();
115 return false;
116 }
117
118 return true;
119 }
120
121 //----------------------------------------------------------------------
122 // Open the slave pseudo terminal for the current master pseudo
123 // terminal. A master pseudo terminal should already be valid prior to
124 // calling this function (see OpenFirstAvailableMaster()).
125 // The file descriptor is stored this object's member variables and can
126 // be accessed via the GetSlaveFileDescriptor(), or released using the
127 // ReleaseSlaveFileDescriptor() member function.
128 //
129 // RETURNS:
130 // Zero when successful, non-zero indicating an error occurred.
131 //----------------------------------------------------------------------
132 bool
OpenSlave(int oflag,char * error_str,size_t error_len)133 PseudoTerminal::OpenSlave (int oflag, char *error_str, size_t error_len)
134 {
135 if (error_str)
136 error_str[0] = '\0';
137
138 CloseSlaveFileDescriptor();
139
140 // Open the master side of a pseudo terminal
141 const char *slave_name = GetSlaveName (error_str, error_len);
142
143 if (slave_name == NULL)
144 return false;
145
146 m_slave_fd = ::open (slave_name, oflag);
147
148 if (m_slave_fd < 0)
149 {
150 if (error_str)
151 ::strerror_r (errno, error_str, error_len);
152 return false;
153 }
154
155 return true;
156 }
157
158
159
160 //----------------------------------------------------------------------
161 // Get the name of the slave pseudo terminal. A master pseudo terminal
162 // should already be valid prior to calling this function (see
163 // OpenFirstAvailableMaster()).
164 //
165 // RETURNS:
166 // NULL if no valid master pseudo terminal or if ptsname() fails.
167 // The name of the slave pseudo terminal as a NULL terminated C string
168 // that comes from static memory, so a copy of the string should be
169 // made as subsequent calls can change this value.
170 //----------------------------------------------------------------------
171 const char*
GetSlaveName(char * error_str,size_t error_len) const172 PseudoTerminal::GetSlaveName (char *error_str, size_t error_len) const
173 {
174 if (error_str)
175 error_str[0] = '\0';
176
177 if (m_master_fd < 0)
178 {
179 if (error_str)
180 ::snprintf (error_str, error_len, "%s", "master file descriptor is invalid");
181 return NULL;
182 }
183 const char *slave_name = ::ptsname (m_master_fd);
184
185 if (error_str && slave_name == NULL)
186 ::strerror_r (errno, error_str, error_len);
187
188 return slave_name;
189 }
190
191
192 //----------------------------------------------------------------------
193 // Fork a child process and have its stdio routed to a pseudo terminal.
194 //
195 // In the parent process when a valid pid is returned, the master file
196 // descriptor can be used as a read/write access to stdio of the
197 // child process.
198 //
199 // In the child process the stdin/stdout/stderr will already be routed
200 // to the slave pseudo terminal and the master file descriptor will be
201 // closed as it is no longer needed by the child process.
202 //
203 // This class will close the file descriptors for the master/slave
204 // when the destructor is called, so be sure to call
205 // ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any
206 // file descriptors are going to be used past the lifespan of this
207 // object.
208 //
209 // RETURNS:
210 // in the parent process: the pid of the child, or -1 if fork fails
211 // in the child process: zero
212 //----------------------------------------------------------------------
213 lldb::pid_t
Fork(char * error_str,size_t error_len)214 PseudoTerminal::Fork (char *error_str, size_t error_len)
215 {
216 if (error_str)
217 error_str[0] = '\0';
218
219 pid_t pid = LLDB_INVALID_PROCESS_ID;
220 if (OpenFirstAvailableMaster (O_RDWR, error_str, error_len))
221 {
222 // Successfully opened our master pseudo terminal
223
224 pid = ::fork ();
225 if (pid < 0)
226 {
227 // Fork failed
228 if (error_str)
229 ::strerror_r (errno, error_str, error_len);
230 }
231 else if (pid == 0)
232 {
233 // Child Process
234 ::setsid();
235
236 if (OpenSlave (O_RDWR, error_str, error_len))
237 {
238 // Successfully opened slave
239 // We are done with the master in the child process so lets close it
240 CloseMasterFileDescriptor ();
241
242 #if defined(TIOCSCTTY)
243 // Acquire the controlling terminal
244 if (::ioctl (m_slave_fd, TIOCSCTTY, (char *)0) < 0)
245 {
246 if (error_str)
247 ::strerror_r (errno, error_str, error_len);
248 }
249 #endif
250 // Duplicate all stdio file descriptors to the slave pseudo terminal
251 if (::dup2 (m_slave_fd, STDIN_FILENO) != STDIN_FILENO)
252 {
253 if (error_str && !error_str[0])
254 ::strerror_r (errno, error_str, error_len);
255 }
256
257 if (::dup2 (m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO)
258 {
259 if (error_str && !error_str[0])
260 ::strerror_r (errno, error_str, error_len);
261 }
262
263 if (::dup2 (m_slave_fd, STDERR_FILENO) != STDERR_FILENO)
264 {
265 if (error_str && !error_str[0])
266 ::strerror_r (errno, error_str, error_len);
267 }
268 }
269 }
270 else
271 {
272 // Parent Process
273 // Do nothing and let the pid get returned!
274 }
275 }
276 return pid;
277 }
278
279 //----------------------------------------------------------------------
280 // The master file descriptor accessor. This object retains ownership
281 // of the master file descriptor when this accessor is used. Use
282 // ReleaseMasterFileDescriptor() if you wish this object to release
283 // ownership of the master file descriptor.
284 //
285 // Returns the master file descriptor, or -1 if the master file
286 // descriptor is not currently valid.
287 //----------------------------------------------------------------------
288 int
GetMasterFileDescriptor() const289 PseudoTerminal::GetMasterFileDescriptor () const
290 {
291 return m_master_fd;
292 }
293
294 //----------------------------------------------------------------------
295 // The slave file descriptor accessor.
296 //
297 // Returns the slave file descriptor, or -1 if the slave file
298 // descriptor is not currently valid.
299 //----------------------------------------------------------------------
300 int
GetSlaveFileDescriptor() const301 PseudoTerminal::GetSlaveFileDescriptor () const
302 {
303 return m_slave_fd;
304 }
305
306 //----------------------------------------------------------------------
307 // Release ownership of the master pseudo terminal file descriptor
308 // without closing it. The destructor for this class will close the
309 // master file descriptor if the ownership isn't released using this
310 // call and the master file descriptor has been opened.
311 //----------------------------------------------------------------------
312 int
ReleaseMasterFileDescriptor()313 PseudoTerminal::ReleaseMasterFileDescriptor ()
314 {
315 // Release ownership of the master pseudo terminal file
316 // descriptor without closing it. (the destructor for this
317 // class will close it otherwise!)
318 int fd = m_master_fd;
319 m_master_fd = invalid_fd;
320 return fd;
321 }
322
323 //----------------------------------------------------------------------
324 // Release ownership of the slave pseudo terminal file descriptor
325 // without closing it. The destructor for this class will close the
326 // slave file descriptor if the ownership isn't released using this
327 // call and the slave file descriptor has been opened.
328 //----------------------------------------------------------------------
329 int
ReleaseSlaveFileDescriptor()330 PseudoTerminal::ReleaseSlaveFileDescriptor ()
331 {
332 // Release ownership of the slave pseudo terminal file
333 // descriptor without closing it (the destructor for this
334 // class will close it otherwise!)
335 int fd = m_slave_fd;
336 m_slave_fd = invalid_fd;
337 return fd;
338 }
339
340