From ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: 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 --- kdesu/kdesu_pty.cpp | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 kdesu/kdesu_pty.cpp (limited to 'kdesu/kdesu_pty.cpp') 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 + * + * This file contains code from TEShell.C of the KDE konsole. + * Copyright (c) 1997,1998 by Lars Doelle + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(__osf__) || defined(__CYGWIN__) +#include +#endif + +#include +#include + +#include +#include +#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 +#endif + +#include + +#ifdef HAVE_LIBUTIL_H + #include +#elif defined(HAVE_UTIL_H) + #include +#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; +} + -- cgit v1.2.1