KDEsu
kdesu_pty.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _GNU_SOURCE
00020 #define _GNU_SOURCE
00021 #endif
00022
00023 #include <config.h>
00024
00025 #include <stdio.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <sys/wait.h>
00035 #include <sys/ioctl.h>
00036 #if defined(__osf__) || defined(__CYGWIN__)
00037 #include <pty.h>
00038 #endif
00039
00040 #include <qglobal.h>
00041 #include <qcstring.h>
00042
00043 #include <kdebug.h>
00044 #include <kstandarddirs.h>
00045 #include "kdesu_pty.h"
00046
00047
00048 #ifndef __THROW
00049 #define __THROW
00050 #endif
00051
00052 #ifdef HAVE_GRANTPT
00053 extern "C" int grantpt(int fd) __THROW;
00054 #endif
00055
00056 #ifdef HAVE_PTSNAME
00057 extern "C" char * ptsname(int fd) __THROW;
00058 #endif
00059
00060 #ifdef HAVE_UNLOCKPT
00061 extern "C" int unlockpt(int fd) __THROW;
00062 #endif
00063
00064 #ifdef HAVE__GETPTY
00065 extern "C" char *_getpty(int *, int, mode_t, int);
00066 #endif
00067
00068 #ifdef HAVE_PTY_H
00069 #include <pty.h>
00070 #endif
00071
00072 #include <termios.h>
00073
00074 #ifdef HAVE_LIBUTIL_H
00075 #include <libutil.h>
00076 #elif defined(HAVE_UTIL_H)
00077 #include <util.h>
00078 #endif
00079
00080 PTY::PTY()
00081 {
00082 ptyfd = -1;
00083 }
00084
00085 PTY::~PTY()
00086 {
00087 if (ptyfd >= 0)
00088 close(ptyfd);
00089 }
00090
00091
00092
00093
00094 int PTY::getpt()
00095 {
00096
00097 #if defined(HAVE_GETPT) && defined(HAVE_PTSNAME)
00098
00099
00100 ptyfd = ::getpt();
00101 ttyname = ::ptsname(ptyfd);
00102 return ptyfd;
00103
00104 #elif defined(HAVE_OPENPTY)
00105
00106
00107 char name[30];
00108 int master_fd, slave_fd;
00109 if (openpty(&master_fd, &slave_fd, name, 0L, 0L) != -1) {
00110 ttyname = name;
00111 name[5]='p';
00112 ptyname = name;
00113 close(slave_fd);
00114 ptyfd = master_fd;
00115 return ptyfd;
00116 }
00117 ptyfd = -1;
00118 kdDebug(900) << k_lineinfo << "Opening pty failed.\n";
00119 return -1;
00120
00121 #elif defined(HAVE__GETPTY)
00122
00123 int master_fd;
00124 ttyname = _getpty(&master_fd,O_RDWR,0600,0);
00125 if (ttyname)
00126 ptyfd = master_fd;
00127 else{
00128 ptyfd = -1;
00129 kdDebug(900) << k_lineinfo << "Opening pty failed.error" << errno << '\n';
00130 }
00131 return ptyfd;
00132
00133 #else
00134
00135
00136
00137
00138 ptyfd = open("/dev/ptmx", O_RDWR);
00139 if (ptyfd >= 0) {
00140 ptyname = "/dev/ptmx";
00141 #ifdef HAVE_PTSNAME
00142 ttyname = ::ptsname(ptyfd);
00143 return ptyfd;
00144 #elif defined (TIOCGPTN)
00145 int ptyno;
00146 if (ioctl(ptyfd, TIOCGPTN, &ptyno) == 0) {
00147 ttyname.sprintf("/dev/pts/%d", ptyno);
00148 return ptyfd;
00149 }
00150 #endif
00151 close(ptyfd);
00152 }
00153
00154
00155
00156 for (const char *c1 = "pqrstuvwxyzabcde"; *c1 != '\0'; c1++)
00157 {
00158 for (const char *c2 = "0123456789abcdef"; *c2 != '\0'; c2++)
00159 {
00160 ptyname.sprintf("/dev/pty%c%c", *c1, *c2);
00161 ttyname.sprintf("/dev/tty%c%c", *c1, *c2);
00162 if (access(ptyname, F_OK) < 0)
00163 goto linux_out;
00164 ptyfd = open(ptyname, O_RDWR);
00165 if (ptyfd >= 0)
00166 return ptyfd;
00167 }
00168 }
00169 linux_out:
00170
00171
00172
00173 for (int i=0; i<256; i++)
00174 {
00175 ptyname.sprintf("/dev/ptyp%d", i);
00176 ttyname.sprintf("/dev/ttyp%d", i);
00177 if (access(ptyname, F_OK) < 0)
00178 break;
00179 ptyfd = open(ptyname, O_RDWR);
00180 if (ptyfd >= 0)
00181 return ptyfd;
00182 }
00183
00184
00185
00186 ptyfd = -1;
00187 kdDebug(900) << k_lineinfo << "Unknown system or all methods failed.\n";
00188 return -1;
00189
00190 #endif // HAVE_GETPT && HAVE_PTSNAME
00191
00192 }
00193
00194
00195 int PTY::grantpt()
00196 {
00197 if (ptyfd < 0)
00198 return -1;
00199
00200 #ifdef HAVE_GRANTPT
00201
00202 return ::grantpt(ptyfd);
00203
00204 #elif defined(HAVE_OPENPTY)
00205
00206
00207
00208 return 0;
00209
00210 #else
00211
00212
00213 if (ptyname.left(8) != "/dev/pty")
00214 return 0;
00215
00216
00217 if (KStandardDirs::findExe("konsole_grantpty").isEmpty())
00218 {
00219 kdError(900) << k_lineinfo << "konsole_grantpty not found.\n";
00220 return -1;
00221 }
00222
00223
00224 const int pty_fileno = 3;
00225
00226 pid_t pid;
00227 if ((pid = fork()) == -1)
00228 {
00229 kdError(900) << k_lineinfo << "fork(): " << perror << "\n";
00230 return -1;
00231 }
00232
00233 if (pid)
00234 {
00235
00236 int ret;
00237 waitpid(pid, &ret, 0);
00238 if (WIFEXITED(ret) && !WEXITSTATUS(ret))
00239 return 0;
00240 kdError(900) << k_lineinfo << "konsole_grantpty returned with error: "
00241 << WEXITSTATUS(ret) << "\n";
00242 return -1;
00243 } else
00244 {
00245
00246 if (ptyfd != pty_fileno && dup2(ptyfd, pty_fileno) < 0)
00247 _exit(1);
00248 execlp("konsole_grantpty", "konsole_grantpty", "--grant", (void *)0);
00249 kdError(900) << k_lineinfo << "exec(): " << perror << "\n";
00250 _exit(1);
00251 }
00252
00253
00254 return 0;
00255
00256 #endif // HAVE_GRANTPT
00257 }
00258
00259
00264 int PTY::unlockpt()
00265 {
00266 if (ptyfd < 0)
00267 return -1;
00268
00269 #ifdef HAVE_UNLOCKPT
00270
00271
00272
00273 return ::unlockpt(ptyfd);
00274
00275 #elif defined(TIOCSPTLCK)
00276
00277
00278 int flag = 0;
00279 return ioctl(ptyfd, TIOCSPTLCK, &flag);
00280
00281 #else
00282
00283
00284 return 0;
00285
00286 #endif
00287
00288 }
00289
00290
00295 QCString PTY::ptsname()
00296 {
00297 if (ptyfd < 0)
00298 return 0;
00299
00300 return ttyname;
00301 }
00302