GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
kpty.cpp
Go to the documentation of this file.
1 /*
2 
3  This file is part of the KDE libraries
4  Copyright (C) 2002, 2013 Waldo Bastian <bastian@kde.org>
5  Copyright (C) 2002-2003,2007 Oswald Buddenhagen <ossi@kde.org>
6 
7  Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Library General Public
11  License as published by the Free Software Foundation; either
12  version 2 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Library General Public License for more details.
18 
19  You should have received a copy of the GNU Library General Public License
20  along with this library; see the file COPYING.LIB. If not, write to
21  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28 
29 #include "unix/kpty_p.h"
30 
31 #ifdef __sgi
32 #define __svr4__
33 #endif
34 
35 #ifdef __osf__
36 #define _OSF_SOURCE
37 #include <float.h>
38 #endif
39 
40 #ifdef _AIX
41 #define _ALL_SOURCE
42 #endif
43 
44 // __USE_XOPEN isn't defined by default in ICC
45 // (needed for ptsname(), grantpt() and unlockpt())
46 #ifdef __INTEL_COMPILER
47 # ifndef __USE_XOPEN
48 # define __USE_XOPEN
49 # endif
50 #endif
51 
52 #include <sys/types.h>
53 #include <sys/ioctl.h>
54 #include <sys/time.h>
55 #include <sys/resource.h>
56 #include <sys/stat.h>
57 #include <sys/param.h>
58 
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <time.h>
62 #include <stdlib.h>
63 #include <stdio.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include <grp.h>
67 
68 #ifdef Q_OS_MAC
69 # include <util.h>
70 #else
71 # if defined(HAVE_PTY_H)
72 # include <pty.h>
73 # endif
74 # ifdef HAVE_LIBUTIL_H
75 # include <libutil.h>
76 # elif defined(HAVE_UTIL_H)
77 # include <util.h>
78 # endif
79 #endif
80 
81 /*
82 #ifdef HAVE_UTEMPTER
83 extern "C" {
84 # include <utempter.h>
85 }
86 #else
87 # include <utmp.h>
88 # ifdef HAVE_UTMPX
89 # include <utmpx.h>
90 # endif
91 # if !defined(_PATH_UTMPX) && defined(_UTMPX_FILE)
92 # define _PATH_UTMPX _UTMPX_FILE
93 # endif
94 # if !defined(_PATH_WTMPX) && defined(_WTMPX_FILE)
95 # define _PATH_WTMPX _WTMPX_FILE
96 # endif
97 #endif
98 */
99 
100 /* for HP-UX (some versions) the extern C is needed, and for other
101  platforms it doesn't hurt */
102 extern "C" {
103 #include <termios.h>
104 #if defined(HAVE_TERMIO_H)
105 # include <termio.h> // struct winsize on some systems
106 #endif
107 }
108 
109 #if defined (_HPUX_SOURCE)
110 # define _TERMIOS_INCLUDED
111 # include <bsdtty.h>
112 #endif
113 
114 #ifdef HAVE_SYS_STROPTS_H
115 # include <sys/stropts.h> // Defines I_PUSH
116 # define _NEW_TTY_CTRL
117 #endif
118 
119 #if defined(HAVE_TCGETATTR)
120 # define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode)
121 #elif defined(TIOCGETA)
122 # define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode)
123 #elif defined(TCGETS)
124 # define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode)
125 #else
126 # error No method available to get terminal attributes
127 #endif
128 
129 #if defined(HAVE_TCSETATTR) && defined(TCSANOW)
130 # define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode)
131 #elif defined(TIOCSETA)
132 # define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode)
133 #elif defined(TCSETS)
134 # define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode)
135 #else
136 # error No method available to set terminal attributes
137 #endif
138 
139 #include <QtCore>
140 
141 // not defined on HP-UX for example
142 #ifndef CTRL
143 # define CTRL(x) ((x) & 037)
144 #endif
145 
146 #define TTY_GROUP "tty"
147 
148 #ifndef PATH_MAX
149 # ifdef MAXPATHLEN
150 # define PATH_MAX MAXPATHLEN
151 # else
152 # define PATH_MAX 1024
153 # endif
154 #endif
155 
156 ///////////////////////
157 // private functions //
158 ///////////////////////
159 
160 //////////////////
161 // private data //
162 //////////////////
163 
165  masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent)
166 {
167 }
168 
169 KPtyPrivate::KPtyPrivate(KPty *parent, int _masterFd, int _slaveFd):
170  masterFd(_masterFd), slaveFd(_slaveFd), ownMaster(true), q_ptr(parent)
171 {
172 }
173 
174 
176 {
177 }
178 
180 {
181 // return !QProcess::execute(KStandardDirs::findExe("kgrantpty"),
182 // QStringList() << (grant?"--grant":"--revoke") << QString::number(masterFd));
183  return true;
184 }
185 
186 /////////////////////////////
187 // public member functions //
188 /////////////////////////////
189 
191  d_ptr(new KPtyPrivate(this))
192 {
193 }
194 
195 KPty::KPty(int masterFd, int slaveFd) :
196  d_ptr(new KPtyPrivate(this, masterFd, slaveFd))
197 {
198 }
199 
201  d_ptr(d)
202 {
203  d_ptr->q_ptr = this;
204 }
205 
207 {
208  close();
209  delete d_ptr;
210 }
211 
213 {
214  Q_D(KPty);
215 
216  if (d->masterFd >= 0) {
217  return true;
218  }
219 
220  d->ownMaster = true;
221 
222  QByteArray ptyName;
223 
224  // Find a master pty that we can open ////////////////////////////////
225 
226  // Because not all the pty animals are created equal, they want to
227  // be opened by several different methods.
228 
229  // We try, as we know them, one by one.
230 
231 #ifdef HAVE_OPENPTY
232 
233  char ptsn[PATH_MAX];
234  if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0))
235  {
236  d->masterFd = -1;
237  d->slaveFd = -1;
238  qWarning() << "Can't open a pseudo teletype";
239  return false;
240  }
241  d->ttyName = ptsn;
242 
243 #else
244 
245 #ifdef HAVE__GETPTY // irix
246 
247  char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0);
248  if (ptsn) {
249  d->ttyName = ptsn;
250  goto grantedpt;
251  }
252 
253 #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN)
254 
255 #ifdef HAVE_POSIX_OPENPT
256  d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY);
257 #elif defined(HAVE_GETPT)
258  d->masterFd = ::getpt();
259 #elif defined(PTM_DEVICE)
260  d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY);
261 #else
262 # error No method to open a PTY master detected.
263 #endif
264  if (d->masterFd >= 0)
265  {
266 #ifdef HAVE_PTSNAME
267  char *ptsn = ptsname(d->masterFd);
268  if (ptsn) {
269  d->ttyName = ptsn;
270 #else
271  int ptyno;
272  if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) {
273  char buf[32];
274  sprintf(buf, "/dev/pts/%d", ptyno);
275  d->ttyName = buf;
276 #endif
277 #ifdef HAVE_GRANTPT
278  if (!grantpt(d->masterFd))
279  goto grantedpt;
280 #else
281  goto gotpty;
282 #endif
283  }
284  ::close(d->masterFd);
285  d->masterFd = -1;
286  }
287 #endif // HAVE_PTSNAME || TIOCGPTN
288 
289  // Linux device names, FIXME: Trouble on other systems?
290  for (const char* s3 = "pqrstuvwxyzabcde"; *s3; s3++)
291  {
292  for (const char* s4 = "0123456789abcdef"; *s4; s4++)
293  {
294  ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toAscii();
295  d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toAscii();
296 
297  d->masterFd = ::open(ptyName.data(), O_RDWR);
298  if (d->masterFd >= 0)
299  {
300 #ifdef Q_OS_SOLARIS
301  /* Need to check the process group of the pty.
302  * If it exists, then the slave pty is in use,
303  * and we need to get another one.
304  */
305  int pgrp_rtn;
306  if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
307  ::close(d->masterFd);
308  d->masterFd = -1;
309  continue;
310  }
311 #endif /* Q_OS_SOLARIS */
312  if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits
313  {
314  if (!geteuid())
315  {
316  struct group* p = getgrnam(TTY_GROUP);
317  if (!p)
318  p = getgrnam("wheel");
319  gid_t gid = p ? p->gr_gid : getgid ();
320 
321  if (!chown(d->ttyName.data(), getuid(), gid)) {
322  chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
323  }
324  }
325  goto gotpty;
326  }
327  ::close(d->masterFd);
328  d->masterFd = -1;
329  }
330  }
331  }
332 
333  qWarning() << "Can't open a pseudo teletype";
334  return false;
335 
336  gotpty:
337  struct stat st;
338  if (stat(d->ttyName.data(), &st))
339  return false; // this just cannot happen ... *cough* Yeah right, I just
340  // had it happen when pty #349 was allocated. I guess
341  // there was some sort of leak? I only had a few open.
342  if (((st.st_uid != getuid()) ||
343  (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
344  !d->chownpty(true))
345  {
346  qWarning()
347  << "chownpty failed for device " << ptyName << "::" << d->ttyName
348  << "\nThis means the communication can be eavesdropped." << endl;
349  }
350 
351 #if defined(HAVE_GRANTPT) || defined(HAVE__GETPTY)
352  grantedpt:
353 #endif
354 
355 #ifdef HAVE_REVOKE
356  revoke(d->ttyName.data());
357 #endif
358 
359 #ifdef HAVE_UNLOCKPT
360  unlockpt(d->masterFd);
361 #elif defined(TIOCSPTLCK)
362  int flag = 0;
363  ioctl(d->masterFd, TIOCSPTLCK, &flag);
364 #endif
365 
366  d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY);
367  if (d->slaveFd < 0)
368  {
369  qWarning() << "Can't open slave pseudo teletype";
370  ::close(d->masterFd);
371  d->masterFd = -1;
372  return false;
373  }
374 
375 #if (defined(__svr4__) || defined(__sgi__))
376  // Solaris
377  ioctl(d->slaveFd, I_PUSH, "ptem");
378  ioctl(d->slaveFd, I_PUSH, "ldterm");
379 #endif
380 
381 #endif /* HAVE_OPENPTY */
382  fcntl(d->masterFd, F_SETFD, FD_CLOEXEC);
383  fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC);
384 
385  struct ::termios t;
386  tcGetAttr(&t);
387  t.c_iflag &= ~IXON;
388  t.c_lflag &= ~ECHOCTL;
389  tcSetAttr(&t);
390  return true;
391 }
392 
394 {
395  Q_D(KPty);
396 
397  if (d->slaveFd < 0)
398  return;
399  ::close(d->slaveFd);
400  d->slaveFd = -1;
401 }
402 
404 {
405  Q_D(KPty);
406 
407  if (d->masterFd < 0)
408  return;
409  closeSlave();
410  if (d->ownMaster) {
411 #ifndef HAVE_OPENPTY
412  // don't bother resetting unix98 pty, it will go away after closing master anyway.
413  if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) {
414  if (!geteuid()) {
415  struct stat st;
416  if (!stat(d->ttyName.data(), &st)) {
417  if (!chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1)) {
418  chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
419  }
420  }
421  } else {
422  fcntl(d->masterFd, F_SETFD, 0);
423  d->chownpty(false);
424  }
425  }
426  #endif
427  }
428  ::close(d->masterFd);
429  d->masterFd = -1;
430 }
431 
432 // XXX Supposedly, tc[gs]etattr do not work with the master on Solaris.
433 // Please verify.
434 
435 bool KPty::tcGetAttr(struct ::termios *ttmode) const
436 {
437  Q_D(const KPty);
438 
439  return _tcgetattr(d->masterFd, ttmode) == 0;
440 }
441 
442 bool KPty::tcSetAttr(struct ::termios *ttmode)
443 {
444  Q_D(KPty);
445 
446  return _tcsetattr(d->masterFd, ttmode) == 0;
447 }
448 
449 bool KPty::setWinSize(int lines, int columns)
450 {
451  Q_D(KPty);
452 
453  struct winsize winSize;
454  memset(&winSize, 0, sizeof(winSize));
455  winSize.ws_row = (unsigned short)lines;
456  winSize.ws_col = (unsigned short)columns;
457  return ioctl(d->masterFd, TIOCSWINSZ, (char *)&winSize) == 0;
458 }
459 
460 bool KPty::setEcho(bool echo)
461 {
462  struct ::termios ttmode;
463  if (!tcGetAttr(&ttmode))
464  return false;
465  if (!echo)
466  ttmode.c_lflag &= ~ECHO;
467  else
468  ttmode.c_lflag |= ECHO;
469  return tcSetAttr(&ttmode);
470 }
471 
472 const char *KPty::ttyName() const
473 {
474  Q_D(const KPty);
475 
476  return d->ttyName.data();
477 }
478 
479 int KPty::masterFd() const
480 {
481  Q_D(const KPty);
482 
483  return d->masterFd;
484 }
485 
486 int KPty::slaveFd() const
487 {
488  Q_D(const KPty);
489 
490  return d->slaveFd;
491 }
int masterFd() const
Definition: kpty.cpp:479
bool chownpty(bool grant)
Definition: kpty.cpp:179
int fcntl(int fd, int cmd, long arg)
const char * ttyName() const
Definition: kpty.cpp:472
KPty * q_ptr
Definition: kpty_p.h:46
bool tcGetAttr(struct::termios *ttmode) const
Wrapper around tcgetattr(3).
Definition: kpty.cpp:435
gid_t getgid(void)
void closeSlave()
Close the pty slave descriptor.
Definition: kpty.cpp:393
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:935
bool open()
Create a pty master/slave pair.
Definition: kpty.cpp:212
~KPty()
Destructor:
Definition: kpty.cpp:206
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
int slaveFd() const
Definition: kpty.cpp:486
bool setWinSize(int lines, int columns)
Change the logical (screen) size of the pty.
Definition: kpty.cpp:449
#define PATH_MAX
Definition: kpty.cpp:152
returns the type of the matrix and caches it for future use Called with more than one the function will not attempt to guess the type if it is still unknown This is useful for debugging purposes The possible matrix types depend on whether the matrix is full or and can be one of the following able sis tem and mark type as unknown tem as the structure of the matrix explicitly gives this(Sparse matrices only) tem code
Definition: matrix_type.cc:120
uid_t geteuid(void)
#define ECHO
KPty()
Constructor.
Definition: kpty.cpp:190
void close()
Close the pty master/slave pair.
Definition: kpty.cpp:403
bool tcSetAttr(struct::termios *ttmode)
Wrapper around tcsetattr(3) with mode TCSANOW.
Definition: kpty.cpp:442
virtual ~KPtyPrivate()
Definition: kpty.cpp:175
subroutine stat(x, n, av, var, xmin, xmax)
Definition: tstgmn.for:111
p
Definition: lu.cc:138
KPtyPrivate(KPty *parent)
Definition: kpty.cpp:164
KPtyPrivate *const d_ptr
Definition: kpty.h:162
bool setEcho(bool echo)
Set whether the pty should echo input.
Definition: kpty.cpp:460
Provides primitives for opening & closing a pseudo TTY pair, assigning the controlling TTY...
Definition: kpty.h:35
#define TTY_GROUP
Definition: kpty.cpp:146
uid_t getuid(void)