summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/MyPty.cpp6
1 files changed, 2 insertions, 4 deletions
diff --git a/noncore/apps/opie-console/MyPty.cpp b/noncore/apps/opie-console/MyPty.cpp
index c3c58be..23d4966 100644
--- a/noncore/apps/opie-console/MyPty.cpp
+++ b/noncore/apps/opie-console/MyPty.cpp
@@ -48,323 +48,321 @@
48 check if pty is restartable via run after done. 48 check if pty is restartable via run after done.
49 49
50 \par Pseudo terminals 50 \par Pseudo terminals
51 51
52 Pseudo terminals are a unique feature of UNIX, and always come in form of 52 Pseudo terminals are a unique feature of UNIX, and always come in form of
53 pairs of devices (/dev/ptyXX and /dev/ttyXX), which are connected to each 53 pairs of devices (/dev/ptyXX and /dev/ttyXX), which are connected to each
54 other by the operating system. One may think of them as two serial devices 54 other by the operating system. One may think of them as two serial devices
55 linked by a null-modem cable. Being based on devices the number of 55 linked by a null-modem cable. Being based on devices the number of
56 simultanous instances of this class is (globally) limited by the number of 56 simultanous instances of this class is (globally) limited by the number of
57 those device pairs, which is 256. 57 those device pairs, which is 256.
58 58
59 Another technic are UNIX 98 PTY's. These are supported also, and prefered 59 Another technic are UNIX 98 PTY's. These are supported also, and prefered
60 over the (obsolete) predecessor. 60 over the (obsolete) predecessor.
61 61
62 There's a sinister ioctl(2), signal(2) and job control stuff 62 There's a sinister ioctl(2), signal(2) and job control stuff
63 nessesary to make everything work as it should. 63 nessesary to make everything work as it should.
64*/ 64*/
65 65
66 66
67#include <qapplication.h> 67#include <qapplication.h>
68#include <qsocketnotifier.h> 68#include <qsocketnotifier.h>
69#include <qstring.h> 69#include <qstring.h>
70#include <qfile.h> 70#include <qfile.h>
71 71
72#include <stdlib.h> 72#include <stdlib.h>
73#include <stdio.h> 73#include <stdio.h>
74#include <signal.h> 74#include <signal.h>
75#include <fcntl.h> 75#include <fcntl.h>
76#include <unistd.h> 76#include <unistd.h>
77#include <termios.h> 77#include <termios.h>
78#include <sys/types.h> 78#include <sys/types.h>
79#include <sys/ioctl.h> 79#include <sys/ioctl.h>
80#include <sys/wait.h> 80#include <sys/wait.h>
81 81
82#ifdef HAVE_OPENPTY 82#ifdef HAVE_OPENPTY
83#include <pty.h> 83#include <pty.h>
84#endif 84#endif
85 85
86#include "procctl.h" 86#include "procctl.h"
87#include "MyPty.h" 87#include "MyPty.h"
88 88
89 89
90#undef VERBOSE_DEBUG 90#undef VERBOSE_DEBUG
91 91
92 92
93/* -------------------------------------------------------------------------- */ 93/* -------------------------------------------------------------------------- */
94 94
95/*! 95/*!
96 Informs the client program about the 96 Informs the client program about the
97 actual size of the window. 97 actual size of the window.
98*/ 98*/
99 99
100void MyPty::setSize(int lines, int columns) 100void MyPty::setSize(int lines, int columns)
101{ 101{
102 qWarning("setting size"); 102 qWarning("setting size");
103 struct winsize wsize; 103 struct winsize wsize;
104 wsize.ws_row = (unsigned short)lines; 104 wsize.ws_row = (unsigned short)lines;
105 wsize.ws_col = (unsigned short)columns; 105 wsize.ws_col = (unsigned short)columns;
106 if(m_fd < 0) return; 106 if(m_fd < 0) return;
107 ioctl(m_fd,TIOCSWINSZ,(char *)&wsize); 107 ioctl(m_fd,TIOCSWINSZ,(char *)&wsize);
108} 108}
109 109
110 110
111void MyPty::donePty() 111void MyPty::donePty()
112{ 112{
113 // This is code from the Qt DumbTerminal example 113 // This is code from the Qt DumbTerminal example
114 114
115 ::close(m_fd); 115 ::close(m_fd);
116 116
117 if (m_cpid) { 117 if (m_cpid) {
118 kill(m_cpid, SIGHUP); 118 kill(m_cpid, SIGHUP);
119 //waitpid(m_cpid, &status, 0); 119 //waitpid(m_cpid, &status, 0);
120 delete m_sn_e; 120 delete m_sn_e;
121 delete m_sn_r; 121 delete m_sn_r;
122 m_sn_e = 0l; 122 m_sn_e = 0l;
123 m_sn_r = 0l; 123 m_sn_r = 0l;
124 } 124 }
125 125
126 m_cpid = 0; 126 m_cpid = 0;
127 m_fd = -1; 127 m_fd = -1;
128// emit done(status); 128// emit done(status);
129} 129}
130 130
131 131
132const char* MyPty::deviceName() 132const char* MyPty::deviceName()
133{ 133{
134 return m_ttynam; 134 return m_ttynam;
135} 135}
136 136
137 137
138void MyPty::error() 138void MyPty::error()
139{ 139{
140 // This is code from the Qt DumbTerminal example 140 // This is code from the Qt DumbTerminal example
141 donePty(); 141 donePty();
142} 142}
143 143
144void MyPty::start() { 144void MyPty::start() {
145 QStrList lis; 145 QStrList lis;
146 int r =run(m_cmd.latin1(), lis, 0, 0); 146 int r =run(m_cmd.latin1(), lis, 0, 0);
147 r = r; 147 r = r;
148} 148}
149/*! 149/*!
150 start the client program. 150 start the client program.
151*/ 151*/
152int MyPty::run(const char* cmd, QStrList &, const char*, int) 152int MyPty::run(const char* cmd, QStrList &, const char*, int)
153{ 153{
154 // This is code from the Qt DumbTerminal example 154 // This is code from the Qt DumbTerminal example
155 m_cpid = fork(); 155 m_cpid = fork();
156 156
157 if ( !m_cpid ) { 157 if ( !m_cpid ) {
158 // child - exec shell on tty 158 // child - exec shell on tty
159 for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL); 159 for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
160 int ttyfd = ::open(m_ttynam, O_RDWR); 160 int ttyfd = ::open(m_ttynam, O_RDWR);
161 dup2(ttyfd, STDIN_FILENO); 161 dup2(ttyfd, STDIN_FILENO);
162 dup2(ttyfd, STDOUT_FILENO); 162 dup2(ttyfd, STDOUT_FILENO);
163 dup2(ttyfd, STDERR_FILENO); 163 dup2(ttyfd, STDERR_FILENO);
164 // should be done with tty, so close it 164 // should be done with tty, so close it
165 ::close(ttyfd); 165 ::close(ttyfd);
166 static struct termios ttmode; 166 static struct termios ttmode;
167 if ( setsid() < 0 ) 167 if ( setsid() < 0 )
168 perror( "failed to set process group" ); 168 perror( "failed to set process group" );
169#if defined (TIOCSCTTY) 169#if defined (TIOCSCTTY)
170 // grabbed from APUE by Stevens 170 // grabbed from APUE by Stevens
171 ioctl(STDIN_FILENO, TIOCSCTTY, 0); 171 ioctl(STDIN_FILENO, TIOCSCTTY, 0);
172#endif 172#endif
173 tcgetattr( STDIN_FILENO, &ttmode ); 173 tcgetattr( STDIN_FILENO, &ttmode );
174 ttmode.c_cc[VINTR] = 3; 174 ttmode.c_cc[VINTR] = 3;
175 ttmode.c_cc[VERASE] = 8; 175 ttmode.c_cc[VERASE] = 8;
176 tcsetattr( STDIN_FILENO, TCSANOW, &ttmode ); 176 tcsetattr( STDIN_FILENO, TCSANOW, &ttmode );
177 setenv("TERM",m_term,1); 177 setenv("TERM",m_term,1);
178 setenv("COLORTERM","0",1); 178 setenv("COLORTERM","0",1);
179 EnvironmentMap::Iterator it; 179 EnvironmentMap::Iterator it;
180 for (it = m_env.begin(); it != m_env.end(); it++) { 180 for (it = m_env.begin(); it != m_env.end(); it++) {
181 setenv(it.key().latin1(), it.data().latin1(), 1); 181 setenv(it.key().latin1(), it.data().latin1(), 1);
182 } 182 }
183 if (getuid() == 0) { 183 if (getuid() == 0) {
184 char msg[] = "WARNING: You are running this shell as root!\n"; 184 char msg[] = "WARNING: You are running this shell as root!\n";
185 write(ttyfd, msg, sizeof(msg)); 185 write(ttyfd, msg, sizeof(msg));
186 } 186 }
187 execl(cmd, cmd, 0); 187 execl(cmd, cmd, 0);
188 188
189 donePty(); 189 donePty();
190 exit(-1); 190 exit(-1);
191 } 191 }
192 192
193 // parent - continue as a widget 193 // parent - continue as a widget
194 delete m_sn_r; 194 delete m_sn_r;
195 m_sn_r = new QSocketNotifier(m_fd,QSocketNotifier::Read,this); 195 m_sn_r = new QSocketNotifier(m_fd,QSocketNotifier::Read,this);
196 delete m_sn_e; 196 delete m_sn_e;
197 m_sn_e = new QSocketNotifier(m_fd,QSocketNotifier::Exception,this); 197 m_sn_e = new QSocketNotifier(m_fd,QSocketNotifier::Exception,this);
198 connect(m_sn_r,SIGNAL(activated(int)),this,SLOT(readPty())); 198 connect(m_sn_r,SIGNAL(activated(int)),this,SLOT(readPty()));
199 connect(m_sn_e,SIGNAL(activated(int)),this,SLOT(error())); 199 connect(m_sn_e,SIGNAL(activated(int)),this,SLOT(error()));
200 200
201 return 0; 201 return 0;
202} 202}
203 203
204int MyPty::openPty() 204int MyPty::openPty()
205{ 205{
206 // This is code from the Qt DumbTerminal example 206 // This is code from the Qt DumbTerminal example
207 int ptyfd = -1; 207 int ptyfd = -1;
208 208
209#ifdef HAVE_OPENPTY 209#ifdef HAVE_OPENPTY
210 int ttyfd; 210 int ttyfd;
211 if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) ) 211 if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) )
212 ptyfd = -1; 212 ptyfd = -1;
213 else 213 else
214 close(ttyfd); // we open the ttynam ourselves. 214 close(ttyfd); // we open the ttynam ourselves.
215#else 215#else
216 for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) { 216 for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) {
217 for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) { 217 for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) {
218 sprintf(m_ptynam,"/dev/pty%c%c",*c0,*c1); 218 sprintf(m_ptynam,"/dev/pty%c%c",*c0,*c1);
219 sprintf(m_ttynam,"/dev/tty%c%c",*c0,*c1); 219 sprintf(m_ttynam,"/dev/tty%c%c",*c0,*c1);
220 if ((ptyfd = ::open(m_ptynam,O_RDWR)) >= 0) { 220 if ((ptyfd = ::open(m_ptynam,O_RDWR)) >= 0) {
221 if (geteuid() != 0 && !access(m_ttynam,R_OK|W_OK) == 0) { 221 if (geteuid() != 0 && !access(m_ttynam,R_OK|W_OK) == 0) {
222 ::close(ptyfd); 222 ::close(ptyfd);
223 ptyfd = -1; 223 ptyfd = -1;
224 } 224 }
225 } 225 }
226 } 226 }
227 } 227 }
228#endif 228#endif
229 229
230 if ( ptyfd < 0 ) { 230 if ( ptyfd < 0 ) {
231 //qApp->exit(1); 231 //qApp->exit(1);
232 return -1; 232 return -1;
233 } 233 }
234 234
235 return ptyfd; 235 return ptyfd;
236} 236}
237 237
238/*! 238/*!
239 Create an instance. 239 Create an instance.
240*/ 240*/
241MyPty::MyPty(const Profile& prof) : m_cpid(0) 241MyPty::MyPty(const Profile& prof) : m_cpid(0)
242{ 242{
243 243
244 int term = prof.readNumEntry("Terminal", Profile::VT100 ); 244 int term = prof.readNumEntry("Terminal", Profile::VT100 );
245 switch( term ) { 245 switch( term ) {
246 default: 246 default:
247 case Profile::VT100: 247 case Profile::VT100:
248 case Profile::VT102: 248 case Profile::VT102:
249 m_term = "vt100"; 249 m_term = "vt100";
250 break; 250 break;
251 case Profile::Linux: 251 case Profile::Linux:
252 m_term = "linux"; 252 m_term = "linux";
253 break; 253 break;
254 case Profile::XTerm: 254 case Profile::XTerm:
255 m_term = "xterm"; 255 m_term = "xterm";
256 break; 256 break;
257 } 257 }
258 m_sn_e = 0l; 258 m_sn_e = 0l;
259 m_sn_r = 0l; 259 m_sn_r = 0l;
260 m_fd = openPty(); 260 m_fd = openPty();
261 ProcCtl* ctl = ProcCtl::self(); 261 ProcCtl* ctl = ProcCtl::self();
262 Q_UNUSED(ctl); 262 Q_UNUSED(ctl);
263 reload(prof); 263 reload(prof);
264} 264}
265 265
266/*! 266/*!
267 Destructor. 267 Destructor.
268 Note that the related client program is not killed 268 Note that the related client program is not killed
269 (yet) when a instance is deleted. 269 (yet) when a instance is deleted.
270*/ 270*/
271MyPty::~MyPty() 271MyPty::~MyPty()
272{ 272{
273 donePty(); 273 donePty();
274} 274}
275QString MyPty::identifier()const { 275QString MyPty::identifier()const {
276 return QString::fromLatin1("term"); 276 return QString::fromLatin1("term");
277} 277}
278QString MyPty::name()const{ 278QString MyPty::name()const{
279 return identifier(); 279 return identifier();
280} 280}
281bool MyPty::open() { 281bool MyPty::open() {
282 if (m_fd < 0) 282 if (m_fd < 0)
283 m_fd = openPty(); 283 m_fd = openPty();
284 284
285 start(); 285 start();
286 return true; 286 return true;
287} 287}
288void MyPty::close() { 288void MyPty::close() {
289 donePty(); 289 donePty();
290 m_fd = openPty(); 290 m_fd = openPty();
291} 291}
292void MyPty::reload( const Profile& prof) { 292void MyPty::reload( const Profile& prof) {
293 m_env.clear(); 293 m_env.clear();
294 m_cmd = prof.readEntry("Command", "/bin/sh"); 294 m_cmd = prof.readEntry("Command", "/bin/sh");
295 295
296 /* 296 /*
297 * Lets check if m_cmd actually 297 * Lets check if m_cmd actually
298 * exists.... 298 * exists....
299 * we try to use bin/bash and if 299 * we try to use bin/bash and if
300 * this fails we 300 * this fails we
301 * will fallback to /bin/sh 301 * will fallback to /bin/sh
302 * which should be there 100% 302 * which should be there 100%
303 */ 303 */
304 if ( !QFile::exists(QFile::encodeName(m_cmd) ) ) 304 if ( m_cmd.stripWhiteSpace() == "/bin/bash" && !QFile::exists(QFile::encodeName(m_cmd) ) )
305 if (QFile::exists("/bin/bash") )
306 m_cmd = "/bin/bash";
307 else
308 m_cmd = "/bin/sh"; 305 m_cmd = "/bin/sh";
306
309 307
310 int envcount = prof.readNumEntry("EnvVars", 0); 308 int envcount = prof.readNumEntry("EnvVars", 0);
311 for (int i=0; i<envcount; i++) { 309 for (int i=0; i<envcount; i++) {
312 QString name = prof.readEntry("Env_Name_" + QString::number(i), ""); 310 QString name = prof.readEntry("Env_Name_" + QString::number(i), "");
313 QString value = prof.readEntry("Env_Value_" + QString::number(i), ""); 311 QString value = prof.readEntry("Env_Value_" + QString::number(i), "");
314 if (!(name.isEmpty() || value.isEmpty())) { 312 if (!(name.isEmpty() || value.isEmpty())) {
315 m_env.insert(name, value); 313 m_env.insert(name, value);
316 } 314 }
317 } 315 }
318} 316}
319/*! sends len bytes through the line */ 317/*! sends len bytes through the line */
320void MyPty::send(const QByteArray& ar) 318void MyPty::send(const QByteArray& ar)
321{ 319{
322#ifdef VERBOSE_DEBUG 320#ifdef VERBOSE_DEBUG
323 // verbose debug 321 // verbose debug
324 printf("sending bytes:\n"); 322 printf("sending bytes:\n");
325 for (uint i = 0; i < ar.count(); i++) 323 for (uint i = 0; i < ar.count(); i++)
326 printf("%c", ar[i]); 324 printf("%c", ar[i]);
327 printf("\n"); 325 printf("\n");
328#endif 326#endif
329 327
330 ::write(m_fd, ar.data(), ar.count()); 328 ::write(m_fd, ar.data(), ar.count());
331} 329}
332 330
333/*! indicates that a block of data is received */ 331/*! indicates that a block of data is received */
334void MyPty::readPty() 332void MyPty::readPty()
335{ 333{
336 QByteArray buf(4096); 334 QByteArray buf(4096);
337 335
338 int len = ::read( m_fd, buf.data(), 4096 ); 336 int len = ::read( m_fd, buf.data(), 4096 );
339 337
340 if (len == -1 || len == 0) { 338 if (len == -1 || len == 0) {
341 donePty(); 339 donePty();
342 return; 340 return;
343 } 341 }
344 342
345 if (len < 0) 343 if (len < 0)
346 return; 344 return;
347 345
348 346
349 buf.resize(len); 347 buf.resize(len);
350 emit received(buf); 348 emit received(buf);
351 349
352#ifdef VERBOSE_DEBUG 350#ifdef VERBOSE_DEBUG
353 // verbose debug 351 // verbose debug
354 printf("read bytes:\n"); 352 printf("read bytes:\n");
355 for (uint i = 0; i < buf.count(); i++) 353 for (uint i = 0; i < buf.count(); i++)
356 printf("%c", buf[i]); 354 printf("%c", buf[i]);
357 printf("\n"); 355 printf("\n");
358#endif 356#endif
359 357
360} 358}
361QBitArray MyPty::supports()const { 359QBitArray MyPty::supports()const {
362 QBitArray ar(3); 360 QBitArray ar(3);
363 //autoconnect 361 //autoconnect
364 ar[0] = 1; 362 ar[0] = 1;
365 // 363 //
366 ar[1] = 0; 364 ar[1] = 0;
367 ar[2] = 0; 365 ar[2] = 0;
368 366
369 return ar; 367 return ar;
370} 368}