summaryrefslogtreecommitdiffstats
path: root/kdesu/kdesu_pty.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kdesu/kdesu_pty.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdesu/kdesu_pty.cpp')
-rw-r--r--kdesu/kdesu_pty.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/kdesu/kdesu_pty.cpp b/kdesu/kdesu_pty.cpp
new file mode 100644
index 000000000..3b0499f58
--- /dev/null
+++ b/kdesu/kdesu_pty.cpp
@@ -0,0 +1,302 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ * $Id$
+ *
+ * This file is part of the KDE project, module kdesu.
+ * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ *
+ * This file contains code from TEShell.C of the KDE konsole.
+ * Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+ *
+ * This is free software; you can use this library under the GNU Library
+ * General Public License, version 2. See the file "COPYING.LIB" for the
+ * exact licensing terms.
+ *
+ * pty.cpp: Access to PTY's on different systems a la UNIX98.
+ */
+
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* Needed for getpt, ptsname in glibc 2.1.x systems */
+#endif
+
+#include <config.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#if defined(__osf__) || defined(__CYGWIN__)
+#include <pty.h>
+#endif
+
+#include <qglobal.h>
+#include <qcstring.h>
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include "kdesu_pty.h"
+
+// stdlib.h is meant to declare the prototypes but doesn't :(
+#ifndef __THROW
+#define __THROW
+#endif
+
+#ifdef HAVE_GRANTPT
+extern "C" int grantpt(int fd) __THROW;
+#endif
+
+#ifdef HAVE_PTSNAME
+extern "C" char * ptsname(int fd) __THROW;
+#endif
+
+#ifdef HAVE_UNLOCKPT
+extern "C" int unlockpt(int fd) __THROW;
+#endif
+
+#ifdef HAVE__GETPTY
+extern "C" char *_getpty(int *, int, mode_t, int);
+#endif
+
+#ifdef HAVE_PTY_H
+ #include <pty.h>
+#endif
+
+#include <termios.h>
+
+#ifdef HAVE_LIBUTIL_H
+ #include <libutil.h>
+#elif defined(HAVE_UTIL_H)
+ #include <util.h>
+#endif
+
+PTY::PTY()
+{
+ ptyfd = -1;
+}
+
+PTY::~PTY()
+{
+ if (ptyfd >= 0)
+ close(ptyfd);
+}
+
+
+// Opens a pty master and returns its filedescriptor.
+
+int PTY::getpt()
+{
+
+#if defined(HAVE_GETPT) && defined(HAVE_PTSNAME)
+
+ // 1: UNIX98: preferred way
+ ptyfd = ::getpt();
+ ttyname = ::ptsname(ptyfd);
+ return ptyfd;
+
+#elif defined(HAVE_OPENPTY)
+ // 2: BSD interface
+ // More preferred than the linux hacks
+ char name[30];
+ int master_fd, slave_fd;
+ if (openpty(&master_fd, &slave_fd, name, 0L, 0L) != -1) {
+ ttyname = name;
+ name[5]='p';
+ ptyname = name;
+ close(slave_fd); // We don't need this yet // Yes, we do.
+ ptyfd = master_fd;
+ return ptyfd;
+ }
+ ptyfd = -1;
+ kdDebug(900) << k_lineinfo << "Opening pty failed.\n";
+ return -1;
+
+#elif defined(HAVE__GETPTY)
+ // 3: Irix interface
+ int master_fd;
+ ttyname = _getpty(&master_fd,O_RDWR,0600,0);
+ if (ttyname)
+ ptyfd = master_fd;
+ else{
+ ptyfd = -1;
+ kdDebug(900) << k_lineinfo << "Opening pty failed.error" << errno << '\n';
+ }
+ return ptyfd;
+
+#else
+
+ // 4: Open terminal device directly
+ // 4.1: Try /dev/ptmx first. (Linux w/ Unix98 PTYs, Solaris)
+
+ ptyfd = open("/dev/ptmx", O_RDWR);
+ if (ptyfd >= 0) {
+ ptyname = "/dev/ptmx";
+#ifdef HAVE_PTSNAME
+ ttyname = ::ptsname(ptyfd);
+ return ptyfd;
+#elif defined (TIOCGPTN)
+ int ptyno;
+ if (ioctl(ptyfd, TIOCGPTN, &ptyno) == 0) {
+ ttyname.sprintf("/dev/pts/%d", ptyno);
+ return ptyfd;
+ }
+#endif
+ close(ptyfd);
+ }
+
+ // 4.2: Try /dev/pty[p-e][0-f] (Linux w/o UNIX98 PTY's)
+
+ for (const char *c1 = "pqrstuvwxyzabcde"; *c1 != '\0'; c1++)
+ {
+ for (const char *c2 = "0123456789abcdef"; *c2 != '\0'; c2++)
+ {
+ ptyname.sprintf("/dev/pty%c%c", *c1, *c2);
+ ttyname.sprintf("/dev/tty%c%c", *c1, *c2);
+ if (access(ptyname, F_OK) < 0)
+ goto linux_out;
+ ptyfd = open(ptyname, O_RDWR);
+ if (ptyfd >= 0)
+ return ptyfd;
+ }
+ }
+linux_out:
+
+ // 4.3: Try /dev/pty%d (SCO, Unixware)
+
+ for (int i=0; i<256; i++)
+ {
+ ptyname.sprintf("/dev/ptyp%d", i);
+ ttyname.sprintf("/dev/ttyp%d", i);
+ if (access(ptyname, F_OK) < 0)
+ break;
+ ptyfd = open(ptyname, O_RDWR);
+ if (ptyfd >= 0)
+ return ptyfd;
+ }
+
+
+ // Other systems ??
+ ptyfd = -1;
+ kdDebug(900) << k_lineinfo << "Unknown system or all methods failed.\n";
+ return -1;
+
+#endif // HAVE_GETPT && HAVE_PTSNAME
+
+}
+
+
+int PTY::grantpt()
+{
+ if (ptyfd < 0)
+ return -1;
+
+#ifdef HAVE_GRANTPT
+
+ return ::grantpt(ptyfd);
+
+#elif defined(HAVE_OPENPTY)
+
+ // the BSD openpty() interface chowns the devices properly for us,
+ // no need to do this at all
+ return 0;
+
+#else
+
+ // konsole_grantpty only does /dev/pty??
+ if (ptyname.left(8) != "/dev/pty")
+ return 0;
+
+ // Use konsole_grantpty:
+ if (KStandardDirs::findExe("konsole_grantpty").isEmpty())
+ {
+ kdError(900) << k_lineinfo << "konsole_grantpty not found.\n";
+ return -1;
+ }
+
+ // As defined in konsole_grantpty.c
+ const int pty_fileno = 3;
+
+ pid_t pid;
+ if ((pid = fork()) == -1)
+ {
+ kdError(900) << k_lineinfo << "fork(): " << perror << "\n";
+ return -1;
+ }
+
+ if (pid)
+ {
+ // Parent: wait for child
+ int ret;
+ waitpid(pid, &ret, 0);
+ if (WIFEXITED(ret) && !WEXITSTATUS(ret))
+ return 0;
+ kdError(900) << k_lineinfo << "konsole_grantpty returned with error: "
+ << WEXITSTATUS(ret) << "\n";
+ return -1;
+ } else
+ {
+ // Child: exec konsole_grantpty
+ if (ptyfd != pty_fileno && dup2(ptyfd, pty_fileno) < 0)
+ _exit(1);
+ execlp("konsole_grantpty", "konsole_grantpty", "--grant", (void *)0);
+ kdError(900) << k_lineinfo << "exec(): " << perror << "\n";
+ _exit(1);
+ }
+
+ // shut up, gcc
+ return 0;
+
+#endif // HAVE_GRANTPT
+}
+
+
+/**
+ * Unlock the pty. This allows connections on the slave side.
+ */
+
+int PTY::unlockpt()
+{
+ if (ptyfd < 0)
+ return -1;
+
+#ifdef HAVE_UNLOCKPT
+
+ // (Linux w/ glibc 2.1, Solaris, ...)
+
+ return ::unlockpt(ptyfd);
+
+#elif defined(TIOCSPTLCK)
+
+ // Unlock pty (Linux w/ UNIX98 PTY's & glibc 2.0)
+ int flag = 0;
+ return ioctl(ptyfd, TIOCSPTLCK, &flag);
+
+#else
+
+ // Other systems (Linux w/o UNIX98 PTY's, ...)
+ return 0;
+
+#endif
+
+}
+
+
+/**
+ * Return the slave side name.
+ */
+
+QCString PTY::ptsname()
+{
+ if (ptyfd < 0)
+ return 0;
+
+ return ttyname;
+}
+