00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00067 #include <qfileinfo.h>
00068 #include <qapplication.h>
00069 #include <qsocketnotifier.h>
00070
00071 #include <stdlib.h>
00072 #include <stdio.h>
00073 #include <signal.h>
00074 #include <fcntl.h>
00075 #include <unistd.h>
00076 #include <termios.h>
00077 #include <sys/types.h>
00078 #include <sys/ioctl.h>
00079 #include <sys/wait.h>
00080
00081 #ifdef HAVE_OPENPTY
00082 #include <pty.h>
00083 #endif
00084
00085 #include "MyPty.h"
00086
00087
00088 #undef VERBOSE_DEBUG
00089
00090
00091
00092
00098 void MyPty::setSize(int lines, int columns)
00099 {
00100 struct winsize wsize;
00101 wsize.ws_row = (unsigned short)lines;
00102 wsize.ws_col = (unsigned short)columns;
00103 if(fd < 0) return;
00104 ioctl(fd,TIOCSWINSZ,(char *)&wsize);
00105 }
00106
00107
00108 void MyPty::donePty()
00109 {
00110
00111 int status = 0;
00112
00113 ::close(fd);
00114
00115 if (cpid) {
00116 kill(cpid, SIGHUP);
00117 waitpid(cpid, &status, 0);
00118 }
00119
00120 emit done(status);
00121 }
00122
00123
00124 const char* MyPty::deviceName()
00125 {
00126 return ttynam;
00127 }
00128
00129
00130 void MyPty::error()
00131 {
00132
00133 donePty();
00134 }
00135
00136
00140 int MyPty::run(const char* cmd, QStrList &, const char*, int)
00141 {
00142
00143 cpid = fork();
00144
00145 if ( !cpid ) {
00146
00147 for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
00148
00149
00150 signal(SIGSTOP, SIG_IGN);
00151 signal(SIGCONT, SIG_IGN);
00152 signal(SIGTSTP, SIG_IGN);
00153
00154 int ttyfd = open(ttynam, O_RDWR);
00155 dup2(ttyfd, STDIN_FILENO);
00156 dup2(ttyfd, STDOUT_FILENO);
00157 dup2(ttyfd, STDERR_FILENO);
00158
00159 close(ttyfd);
00160 static struct termios ttmode;
00161 if ( setsid() < 0 )
00162 perror( "failed to set process group" );
00163 #if defined (TIOCSCTTY)
00164
00165 ioctl(STDIN_FILENO, TIOCSCTTY, 0);
00166 #endif
00167 tcgetattr( STDIN_FILENO, &ttmode );
00168 ttmode.c_cc[VINTR] = 3;
00169 ttmode.c_cc[VERASE] = 8;
00170 tcsetattr( STDIN_FILENO, TCSANOW, &ttmode );
00171
00172 if(strlen(getenv("TERM"))<=0)
00173 setenv("TERM","vt100",1);
00174 setenv("COLORTERM","0",1);
00175
00176 if (getuid() == 0) {
00177 char msg[] = "WARNING: You are running this shell as root!\n";
00178 write(ttyfd, msg, sizeof(msg));
00179 }
00180
00181 QString ccmd = "-"+QFileInfo(cmd).fileName();
00182
00183 execl(cmd, ccmd.latin1(), 0);
00184
00185 donePty();
00186 exit(-1);
00187 }
00188
00189
00190 QSocketNotifier* sn_r = new QSocketNotifier(fd,QSocketNotifier::Read,this);
00191 QSocketNotifier* sn_e = new QSocketNotifier(fd,QSocketNotifier::Exception,this);
00192 connect(sn_r,SIGNAL(activated(int)),this,SLOT(readPty()));
00193 connect(sn_e,SIGNAL(activated(int)),this,SLOT(error()));
00194
00195 return 0;
00196 }
00197
00198 int MyPty::openPty()
00199 {
00200
00201 int ptyfd = -1;
00202
00203 #ifdef HAVE_OPENPTY
00204 int ttyfd;
00205 if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) )
00206 ptyfd = -1;
00207 else
00208 close(ttyfd);
00209 #else
00210 for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) {
00211 for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) {
00212 sprintf(ptynam,"/dev/pty%c%c",*c0,*c1);
00213 sprintf(ttynam,"/dev/tty%c%c",*c0,*c1);
00214 if ((ptyfd = ::open(ptynam,O_RDWR)) >= 0) {
00215 if (geteuid() != 0 && !access(ttynam,R_OK|W_OK) == 0) {
00216 ::close(ptyfd);
00217 ptyfd = -1;
00218 }
00219 }
00220 }
00221 }
00222 #endif
00223
00224 if ( ptyfd < 0 ) {
00225 qApp->exit(1);
00226 return -1;
00227 }
00228
00229 return ptyfd;
00230 }
00231
00235 MyPty::MyPty() : cpid(0)
00236 {
00237 fd = openPty();
00238 }
00239
00245 MyPty::~MyPty()
00246 {
00247 donePty();
00248 }
00249
00250
00252 void MyPty::send_bytes(const char* s, int len)
00253 {
00254
00255 #ifdef VERBOSE_DEBUG
00256
00257 printf("sending bytes:\n");
00258 for (int i = 0; i < len; i++)
00259 printf("%c", s[i]);
00260 printf("\n");
00261 #endif
00262
00263 ::write(fd, s, len);
00264 }
00265
00267 void MyPty::readPty()
00268 {
00269 char buf[4096];
00270
00271 int len = ::read( fd, buf, 4096 );
00272
00273 if (len == -1)
00274 donePty();
00275
00276 if (len < 0)
00277 return;
00278
00279 emit block_in(buf,len);
00280
00281 #ifdef VERBOSE_DEBUG
00282
00283 printf("read bytes:\n");
00284 for (int i = 0; i < len; i++)
00285 printf("%c", buf[i]);
00286 printf("\n");
00287 #endif
00288
00289 }
00290