00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
#ifdef HAVE_CONFIG_H
00028
#include <config.h>
00029
#endif
00030
00031
#ifdef __osf__
00032
#define _XOPEN_SOURCE_EXTENDED
00033
#define O_NDELAY O_NONBLOCK
00034
#endif
00035
00036
#include <sys/types.h>
00037
#include <sys/ioctl.h>
00038
#include <sys/stat.h>
00039
#include <sys/wait.h>
00040
#include <sys/time.h>
00041
#include <sys/resource.h>
00042
00043
#ifdef HAVE_SYS_STROPTS_H
00044
#include <sys/stropts.h>
00045
#define _NEW_TTY_CTRL
00046
#endif
00047
00048
#include <assert.h>
00049
#include <fcntl.h>
00050
#include <grp.h>
00051
#include <stdio.h>
00052
#include <stdlib.h>
00053
#include <signal.h>
00054
#include <termios.h>
00055
#include <time.h>
00056
#include <unistd.h>
00057
00058
#if defined (_HPUX_SOURCE)
00059
#define _TERMIOS_INCLUDED
00060
#include <bsdtty.h>
00061
#endif
00062
00063
#include <qintdict.h>
00064
#include <qsocketnotifier.h>
00065
#include <qstring.h>
00066
#include <qfile.h>
00067
00068
#include <klocale.h>
00069
#include <kstandarddirs.h>
00070
#include <kapplication.h>
00071
00072
#include "stty.h"
00073
00074
00075 #define PTY_FILENO 3
00076 #define BASE_CHOWN "konsole_grantpty"
00077
00078
namespace JAVADebugger
00079 {
00080
00081 static int chownpty(
int fd,
int grant)
00082
00083
00084
00085 {
00086 void(*tmp)(
int) = signal(SIGCHLD,SIG_DFL);
00087 pid_t pid = fork();
00088
if (pid < 0) {
00089 signal(SIGCHLD,tmp);
00090
return 0;
00091 }
00092
if (pid == 0) {
00093
00094
if (fd !=
PTY_FILENO && dup2(fd,
PTY_FILENO) < 0)
00095 ::exit(1);
00096
00097
QString path =
locate(
"exe",
BASE_CHOWN);
00098 execle(QFile::encodeName(path),
BASE_CHOWN, grant?
"--grant":
"--revoke", (
void *)0, NULL);
00099 ::exit(1);
00100 }
00101
if (pid > 0) {
00102
int w;
00103
00104
int rc = waitpid (pid, &w, 0);
00105
if (rc != pid)
00106 ::exit(1);
00107
00108
00109
00110
00111
00112
00113
00114 signal(SIGCHLD,tmp);
00115
return (rc != -1 && WIFEXITED(w) && WEXITSTATUS(w) == 0);
00116 }
00117 signal(SIGCHLD,tmp);
00118
return 0;
00119 }
00120
00121
00122
00123 STTY::STTY(
bool ext,
const QString &termAppName)
00124 :
QObject(),
00125 out(0),
00126 err(0),
00127 ttySlave(""),
00128 pid_(0)
00129 {
00130
if (ext) {
00131
findExternalTTY(termAppName);
00132 }
else {
00133
fout =
findTTY();
00134
if (
fout >= 0) {
00135
ttySlave =
QString(
tty_slave);
00136
out =
new QSocketNotifier(
fout, QSocketNotifier::Read);
00137 connect(
out, SIGNAL(activated(
int)),
this, SLOT(
OutReceived(
int)) );
00138 }
00139 }
00140 }
00141
00142
00143
00144 STTY::~STTY()
00145 {
00146
if (
pid_)
00147 ::kill(
pid_, SIGTERM);
00148
00149
if (
out) {
00150 ::close(
fout);
00151
delete out;
00152 }
00153
00154
00155
00156
00157
00158
00159 }
00160
00161
00162
00163 int STTY::findTTY()
00164 {
00165
int ptyfd = -1;
00166
bool needGrantPty = TRUE;
00167
00168
00169
00170
#ifdef __sgi__
00171
ptyfd = open(
"/dev/ptmx",O_RDWR);
00172
if (ptyfd < 0) {
00173
perror(
"Can't open a pseudo teletype");
00174
return(-1);
00175 }
00176 strncpy(
tty_slave, ptsname(ptyfd), 50);
00177 grantpt(ptyfd);
00178 unlockpt(ptyfd);
00179 needGrantPty = FALSE;
00180
#endif
00181
00182
00183
#ifdef TIOCGPTN
00184
strcpy(
pty_master,
"/dev/ptmx");
00185 strcpy(
tty_slave,
"/dev/pts/");
00186 ptyfd = open(
pty_master,O_RDWR);
00187
if (ptyfd >= 0) {
00188
int ptyno;
00189
if (ioctl(ptyfd, TIOCGPTN, &ptyno) == 0) {
00190
struct stat sbuf;
00191 sprintf(
tty_slave,
"/dev/pts/%d",ptyno);
00192
if (stat(
tty_slave,&sbuf) == 0 && S_ISCHR(sbuf.st_mode))
00193 needGrantPty = FALSE;
00194
else {
00195 close(ptyfd);
00196 ptyfd = -1;
00197 }
00198 }
else {
00199 close(ptyfd);
00200 ptyfd = -1;
00201 }
00202 }
00203
#endif
00204
00205
#if defined(_SCO_DS) || defined(__USLC__)
00206
if (ptyfd < 0) {
00207
for (
int idx = 0; idx < 256; idx++)
00208 { sprintf(
pty_master,
"/dev/ptyp%d", idx);
00209 sprintf(
tty_slave,
"/dev/ttyp%d", idx);
00210
if (access(
tty_slave, F_OK) < 0) { idx = 256;
break; }
00211
if ((ptyfd = open (
pty_master, O_RDWR)) >= 0)
00212 {
if (access (
tty_slave, R_OK|W_OK) == 0)
break;
00213 close(ptyfd); ptyfd = -1;
00214 }
00215 }
00216 }
00217
#endif
00218
if (ptyfd < 0) {
00219
for (
const char* s3 =
"pqrstuvwxyzabcde"; *s3 != 0; s3++) {
00220
for (
const char* s4 =
"0123456789abcdef"; *s4 != 0; s4++) {
00221 sprintf(
pty_master,
"/dev/pty%c%c",*s3,*s4);
00222 sprintf(
tty_slave,
"/dev/tty%c%c",*s3,*s4);
00223
if ((ptyfd = open(
pty_master, O_RDWR)) >= 0) {
00224
if (geteuid() == 0 || access(
tty_slave, R_OK|W_OK) == 0)
00225
break;
00226
00227 close(ptyfd);
00228 ptyfd = -1;
00229 }
00230 }
00231
00232
if (ptyfd >= 0)
00233
break;
00234 }
00235 }
00236
00237
if (ptyfd >= 0) {
00238
if (needGrantPty && !
chownpty(ptyfd, TRUE)) {
00239 fprintf(stderr,
"kdevelop: chownpty failed for device %s::%s.\n",
pty_master,
tty_slave);
00240 fprintf(stderr,
" : This means the session can be eavesdroped.\n");
00241 fprintf(stderr,
" : Make sure konsole_grantpty is installed and setuid root.\n");
00242 }
00243
00244 ::fcntl(ptyfd, F_SETFL, O_NDELAY);
00245
#ifdef TIOCSPTLCK
00246
int flag = 0;
00247 ioctl(ptyfd, TIOCSPTLCK, &flag);
00248
#endif
00249
}
00250
00251
return ptyfd;
00252 }
00253
00254
00255
00256 void STTY::OutReceived(
int f)
00257 {
00258
char buf[1024];
00259
int n;
00260
00261
00262
00263
while ((n = ::read(f, buf,
sizeof(buf)-1)) > 0) {
00264 *(buf+n) = 0;
00265
if ( f ==
fout )
00266 emit
OutOutput(buf);
00267
else
00268 emit
ErrOutput(buf);
00269 }
00270 }
00271
00272
00273
00274 #define FIFO_FILE "/tmp/debug_tty.XXXXXX"
00275
00276 bool STTY::findExternalTTY(
const QString &termApp)
00277 {
00278
QString appName(termApp.isEmpty() ?
QString(
"xterm") : termApp);
00279
00280
char fifo[] =
FIFO_FILE;
00281
int fifo_fd;
00282
if ((fifo_fd = mkstemp(fifo)) == -1)
00283
return false;
00284
00285 ::close(fifo_fd);
00286 ::unlink(fifo);
00287
00288
00289
#ifdef HAVE_MKFIFO
00290
if (::mkfifo(fifo, S_IRUSR|S_IWUSR) < 0)
00291
#else
00292
if (::mknod(fifo, S_IFIFO | S_IRUSR|S_IWUSR, 0) < 0)
00293
#endif
00294
return false;
00295
00296
int pid = ::fork();
00297
if (pid < 0) {
00298 ::unlink(fifo);
00299
return false;
00300 }
00301
00302
if (pid == 0) {
00303
00304
00305
00306
00307
00308
const char* prog = appName.latin1();
00309
QString script =
QString(
"tty>") + QString(fifo) +
00310 QString(
";"
00311
"trap \"\" INT QUIT TSTP;"
00312
"exec<&-;exec>&-;"
00313
"while :;do sleep 3600;done");
00314
const char* scriptStr = script.latin1();
00315
const char* end = 0;
00316
00317 ::execlp( prog, prog,
00318
00319
00320
"-caption", i18n(
"kdevelop: Debug application console").local8Bit().data(),
00321
"-e",
"sh",
00322
"-c", scriptStr,
00323 end);
00324
00325
00326 ::exit(1);
00327 }
00328
00329
00330
if (pid <= 0)
00331 ::exit(1);
00332
00333
00334
00335 fifo_fd = ::open(fifo, O_RDONLY);
00336
if (fifo_fd < 0)
00337
return false;
00338
00339
00340
00341
char ttyname[50];
00342
int n = ::read(fifo_fd, ttyname,
sizeof(ttyname)-
sizeof(
char));
00343
00344 ::close(fifo_fd);
00345 ::unlink(fifo);
00346
00347
00348
if (n <= 0)
00349
return false;
00350
00351
00352 ttyname[n] = 0;
00353
if (
char* newline = strchr(ttyname,
'\n'))
00354 *newline = 0;
00355
00356
ttySlave = ttyname;
00357
pid_ = pid;
00358
00359
return true;
00360 }
00361
00362 }
00363
00364
00365
#include "stty.moc"