summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/MyPty.cpp22
-rw-r--r--noncore/apps/opie-console/procctl.cpp2
2 files changed, 18 insertions, 6 deletions
diff --git a/noncore/apps/opie-console/MyPty.cpp b/noncore/apps/opie-console/MyPty.cpp
index 10828b0..cacb4ce 100644
--- a/noncore/apps/opie-console/MyPty.cpp
+++ b/noncore/apps/opie-console/MyPty.cpp
@@ -37,263 +37,275 @@
37 One can create many instances of this class within a program. 37 One can create many instances of this class within a program.
38 As a side effect of using this class, a signal(2) handler is 38 As a side effect of using this class, a signal(2) handler is
39 installed on SIGCHLD. 39 installed on SIGCHLD.
40 40
41 \par FIXME 41 \par FIXME
42 42
43 [NOTE: much of the technical stuff below will be replaced by forkpty.] 43 [NOTE: much of the technical stuff below will be replaced by forkpty.]
44 44
45 publish the SIGCHLD signal if not related to an instance. 45 publish the SIGCHLD signal if not related to an instance.
46 46
47 clearify TEPty::done vs. TEPty::~TEPty semantics. 47 clearify TEPty::done vs. TEPty::~TEPty semantics.
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 70
71#include <stdlib.h> 71#include <stdlib.h>
72#include <stdio.h> 72#include <stdio.h>
73#include <signal.h> 73#include <signal.h>
74#include <fcntl.h> 74#include <fcntl.h>
75#include <unistd.h> 75#include <unistd.h>
76#include <termios.h> 76#include <termios.h>
77#include <sys/types.h> 77#include <sys/types.h>
78#include <sys/ioctl.h> 78#include <sys/ioctl.h>
79#include <sys/wait.h> 79#include <sys/wait.h>
80 80
81#ifdef HAVE_OPENPTY 81#ifdef HAVE_OPENPTY
82#include <pty.h> 82#include <pty.h>
83#endif 83#endif
84 84
85#include "procctl.h"
85#include "MyPty.h" 86#include "MyPty.h"
86 87
87 88
88#undef VERBOSE_DEBUG 89#undef VERBOSE_DEBUG
89 90
90 91
91/* -------------------------------------------------------------------------- */ 92/* -------------------------------------------------------------------------- */
92 93
93/*! 94/*!
94 Informs the client program about the 95 Informs the client program about the
95 actual size of the window. 96 actual size of the window.
96*/ 97*/
97 98
98void MyPty::setSize(int lines, int columns) 99void MyPty::setSize(int lines, int columns)
99{ 100{
100 struct winsize wsize; 101 struct winsize wsize;
101 wsize.ws_row = (unsigned short)lines; 102 wsize.ws_row = (unsigned short)lines;
102 wsize.ws_col = (unsigned short)columns; 103 wsize.ws_col = (unsigned short)columns;
103 if(m_fd < 0) return; 104 if(m_fd < 0) return;
104 ioctl(m_fd,TIOCSWINSZ,(char *)&wsize); 105 ioctl(m_fd,TIOCSWINSZ,(char *)&wsize);
105} 106}
106 107
107 108
108void MyPty::donePty() 109void MyPty::donePty()
109{ 110{
110 // This is code from the Qt DumbTerminal example 111 // This is code from the Qt DumbTerminal example
111 int status = 0; 112 int status = 0;
112 113
113 ::close(m_fd); 114 ::close(m_fd);
114 115
115 if (m_cpid) { 116 if (m_cpid) {
117 qWarning("killing!!!");
116 kill(m_cpid, SIGHUP); 118 kill(m_cpid, SIGHUP);
117 waitpid(m_cpid, &status, 0); 119 waitpid(m_cpid, &status, 0);
118 } 120 }
119 121
120 emit done(status); 122 m_cpid = 0;
123// emit done(status);
121} 124}
122 125
123 126
124const char* MyPty::deviceName() 127const char* MyPty::deviceName()
125{ 128{
126 return m_ttynam; 129 return m_ttynam;
127} 130}
128 131
129 132
130void MyPty::error() 133void MyPty::error()
131{ 134{
135 qWarning("error");
132 // This is code from the Qt DumbTerminal example 136 // This is code from the Qt DumbTerminal example
133 donePty(); 137 donePty();
134} 138}
135 139
136void MyPty::start() { 140void MyPty::start() {
137 char* cmd = "/bin/sh"; 141 char* cmd = "/bin/sh";
138 QStrList lis; 142 QStrList lis;
139 int r =run(cmd, lis, 0, 0); 143 int r =run(cmd, lis, 0, 0);
140 r = r; 144 r = r;
141} 145}
142/*! 146/*!
143 start the client program. 147 start the client program.
144*/ 148*/
145int MyPty::run(const char* cmd, QStrList &, const char*, int) 149int MyPty::run(const char* cmd, QStrList &, const char*, int)
146{ 150{
147 // This is code from the Qt DumbTerminal example 151 // This is code from the Qt DumbTerminal example
148 m_cpid = fork(); 152 m_cpid = fork();
149 153
150 if ( !m_cpid ) { 154 if ( !m_cpid ) {
151 // child - exec shell on tty 155 // child - exec shell on tty
152 for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL); 156 for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
153 int ttyfd = ::open(m_ttynam, O_RDWR); 157 int ttyfd = ::open(m_ttynam, O_RDWR);
154 dup2(ttyfd, STDIN_FILENO); 158 dup2(ttyfd, STDIN_FILENO);
155 dup2(ttyfd, STDOUT_FILENO); 159 dup2(ttyfd, STDOUT_FILENO);
156 dup2(ttyfd, STDERR_FILENO); 160 dup2(ttyfd, STDERR_FILENO);
157 // should be done with tty, so close it 161 // should be done with tty, so close it
158 ::close(ttyfd); 162 ::close(ttyfd);
159 static struct termios ttmode; 163 static struct termios ttmode;
160 if ( setsid() < 0 ) 164 if ( setsid() < 0 )
161 perror( "failed to set process group" ); 165 perror( "failed to set process group" );
162#if defined (TIOCSCTTY) 166#if defined (TIOCSCTTY)
163 // grabbed from APUE by Stevens 167 // grabbed from APUE by Stevens
164 ioctl(STDIN_FILENO, TIOCSCTTY, 0); 168 ioctl(STDIN_FILENO, TIOCSCTTY, 0);
165#endif 169#endif
166 tcgetattr( STDIN_FILENO, &ttmode ); 170 tcgetattr( STDIN_FILENO, &ttmode );
167 ttmode.c_cc[VINTR] = 3; 171 ttmode.c_cc[VINTR] = 3;
168 ttmode.c_cc[VERASE] = 8; 172 ttmode.c_cc[VERASE] = 8;
169 tcsetattr( STDIN_FILENO, TCSANOW, &ttmode ); 173 tcsetattr( STDIN_FILENO, TCSANOW, &ttmode );
170 setenv("TERM","vt100",1); 174 setenv("TERM","vt100",1);
171 setenv("COLORTERM","0",1); 175 setenv("COLORTERM","0",1);
172 176
173 if (getuid() == 0) { 177 if (getuid() == 0) {
174 char msg[] = "WARNING: You are running this shell as root!\n"; 178 char msg[] = "WARNING: You are running this shell as root!\n";
175 write(ttyfd, msg, sizeof(msg)); 179 write(ttyfd, msg, sizeof(msg));
176 } 180 }
177 execl(cmd, cmd, 0); 181 execl(cmd, cmd, 0);
178 182
179 donePty(); 183 donePty();
180 exit(-1); 184 exit(-1);
181 } 185 }
182 186
183 // parent - continue as a widget 187 // parent - continue as a widget
184 QSocketNotifier* sn_r = new QSocketNotifier(m_fd,QSocketNotifier::Read,this); 188 QSocketNotifier* sn_r = new QSocketNotifier(m_fd,QSocketNotifier::Read,this);
185 QSocketNotifier* sn_e = new QSocketNotifier(m_fd,QSocketNotifier::Exception,this); 189// QSocketNotifier* sn_e = new QSocketNotifier(m_fd,QSocketNotifier::Exception,this);
186 connect(sn_r,SIGNAL(activated(int)),this,SLOT(readPty())); 190 connect(sn_r,SIGNAL(activated(int)),this,SLOT(readPty()));
187 connect(sn_e,SIGNAL(activated(int)),this,SLOT(error())); 191// connect(sn_e,SIGNAL(activated(int)),this,SLOT(error()));
188 192
189 return 0; 193 return 0;
190} 194}
191 195
192int MyPty::openPty() 196int MyPty::openPty()
193{ 197{
194 // This is code from the Qt DumbTerminal example 198 // This is code from the Qt DumbTerminal example
195 int ptyfd = -1; 199 int ptyfd = -1;
196 200
197#ifdef HAVE_OPENPTY 201#ifdef HAVE_OPENPTY
198 int ttyfd; 202 int ttyfd;
199 if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) ) 203 if ( openpty(&ptyfd,&ttyfd,ttynam,0,0) )
200 ptyfd = -1; 204 ptyfd = -1;
201 else 205 else
202 close(ttyfd); // we open the ttynam ourselves. 206 close(ttyfd); // we open the ttynam ourselves.
203#else 207#else
204 for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) { 208 for (const char* c0 = "pqrstuvwxyzabcde"; ptyfd < 0 && *c0 != 0; c0++) {
205 for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) { 209 for (const char* c1 = "0123456789abcdef"; ptyfd < 0 && *c1 != 0; c1++) {
206 sprintf(m_ptynam,"/dev/pty%c%c",*c0,*c1); 210 sprintf(m_ptynam,"/dev/pty%c%c",*c0,*c1);
207 sprintf(m_ttynam,"/dev/tty%c%c",*c0,*c1); 211 sprintf(m_ttynam,"/dev/tty%c%c",*c0,*c1);
208 if ((ptyfd = ::open(m_ptynam,O_RDWR)) >= 0) { 212 if ((ptyfd = ::open(m_ptynam,O_RDWR)) >= 0) {
209 if (geteuid() != 0 && !access(m_ttynam,R_OK|W_OK) == 0) { 213 if (geteuid() != 0 && !access(m_ttynam,R_OK|W_OK) == 0) {
210 ::close(ptyfd); 214 ::close(ptyfd);
211 ptyfd = -1; 215 ptyfd = -1;
212 } 216 }
213 } 217 }
214 } 218 }
215 } 219 }
216#endif 220#endif
217 221
218 if ( ptyfd < 0 ) { 222 if ( ptyfd < 0 ) {
219 qApp->exit(1); 223 qApp->exit(1);
220 return -1; 224 return -1;
221 } 225 }
222 226
223 return ptyfd; 227 return ptyfd;
224} 228}
225 229
226/*! 230/*!
227 Create an instance. 231 Create an instance.
228*/ 232*/
229MyPty::MyPty(const Profile&) : m_cpid(0) 233MyPty::MyPty(const Profile&) : m_cpid(0)
230{ 234{
231 m_fd = openPty(); 235 m_fd = openPty();
236 ProcCtl* ctl = ProcCtl::self();
232} 237}
233 238
234/*! 239/*!
235 Destructor. 240 Destructor.
236 Note that the related client program is not killed 241 Note that the related client program is not killed
237 (yet) when a instance is deleted. 242 (yet) when a instance is deleted.
238*/ 243*/
239MyPty::~MyPty() 244MyPty::~MyPty()
240{ 245{
241 donePty(); 246 donePty();
242} 247}
243QString MyPty::identifier()const { 248QString MyPty::identifier()const {
244 return QString::fromLatin1("term"); 249 return QString::fromLatin1("term");
245} 250}
246QString MyPty::name()const{ 251QString MyPty::name()const{
247 return identifier(); 252 return identifier();
248} 253}
249bool MyPty::open() { 254bool MyPty::open() {
250 start(); 255 start();
251 return true; 256 return true;
252} 257}
253void MyPty::close() { 258void MyPty::close() {
254 donePty(); 259 donePty();
255} 260}
256void MyPty::reload( const Profile& ) { 261void MyPty::reload( const Profile& ) {
257 262
258} 263}
259/*! sends len bytes through the line */ 264/*! sends len bytes through the line */
260void MyPty::send(const QByteArray& ar) 265void MyPty::send(const QByteArray& ar)
261{ 266{
262 267 qWarning("sending!");
263#ifdef VERBOSE_DEBUG 268#ifdef VERBOSE_DEBUG
264 // verbose debug 269 // verbose debug
265 printf("sending bytes:\n"); 270 printf("sending bytes:\n");
266 for (uint i = 0; i < ar.count(); i++) 271 for (uint i = 0; i < ar.count(); i++)
267 printf("%c", ar[i]); 272 printf("%c", ar[i]);
268 printf("\n"); 273 printf("\n");
269#endif 274#endif
270 275
271 ::write(m_fd, ar.data(), ar.count()); 276 ::write(m_fd, ar.data(), ar.count());
272} 277}
273 278
274/*! indicates that a block of data is received */ 279/*! indicates that a block of data is received */
275void MyPty::readPty() 280void MyPty::readPty()
276{ 281{
282 qWarning("read");
277 QByteArray buf(4096); 283 QByteArray buf(4096);
278 284
279 int len = ::read( m_fd, buf.data(), 4096 ); 285 int len = ::read( m_fd, buf.data(), 4096 );
280 286
281 if (len == -1) 287 if (len == -1 || len == 0) {
288 qWarning("donePty!!! now!");
282 donePty(); 289 donePty();
290 qWarning("return %s", sender()->className() );
291 delete sender();
292 return;
293 }
283 294
284 if (len < 0) 295 if (len < 0)
285 return; 296 return;
286 297
298
287 buf.resize(len); 299 buf.resize(len);
288 emit received(buf); 300 emit received(buf);
289 301
290#ifdef VERBOSE_DEBUG 302#ifdef VERBOSE_DEBUG
291 // verbose debug 303 // verbose debug
292 printf("read bytes:\n"); 304 printf("read bytes:\n");
293 for (uint i = 0; i < buf.count(); i++) 305 for (uint i = 0; i < buf.count(); i++)
294 printf("%c", buf[i]); 306 printf("%c", buf[i]);
295 printf("\n"); 307 printf("\n");
296#endif 308#endif
297 309
298} 310}
299 311
diff --git a/noncore/apps/opie-console/procctl.cpp b/noncore/apps/opie-console/procctl.cpp
index b0b6846..d1cfaf6 100644
--- a/noncore/apps/opie-console/procctl.cpp
+++ b/noncore/apps/opie-console/procctl.cpp
@@ -26,72 +26,72 @@ void ProcCtl::add(pid_t pi, int fd ) {
26 con->status = 0; 26 con->status = 0;
27 con->prev = m_last; 27 con->prev = m_last;
28 28
29 m_last = con; 29 m_last = con;
30 30
31} 31}
32void ProcCtl::remove( pid_t pi ) { 32void ProcCtl::remove( pid_t pi ) {
33 /* 33 /*
34 * We first check if the last item 34 * We first check if the last item
35 * is equal to pi the we 35 * is equal to pi the we
36 * 36 *
37 */ 37 */
38 ProcContainer* con; 38 ProcContainer* con;
39 if (m_last->pid == pi ) { 39 if (m_last->pid == pi ) {
40 con = m_last; 40 con = m_last;
41 m_last = con->prev; 41 m_last = con->prev;
42 delete con; 42 delete con;
43 return; 43 return;
44 } 44 }
45 45
46 con = m_last; 46 con = m_last;
47 ProcContainer* forw = 0l; 47 ProcContainer* forw = 0l;
48 while (con ) { 48 while (con ) {
49 /* remove it */ 49 /* remove it */
50 if ( pi == con->pid ) { 50 if ( pi == con->pid ) {
51 forw->prev = con->prev; 51 forw->prev = con->prev;
52 delete con; 52 delete con;
53 return; 53 return;
54 } 54 }
55 55
56 forw = con; 56 forw = con;
57 con = con->prev; 57 con = con->prev;
58 } 58 }
59 59
60} 60}
61void ProcCtl::remove( ProcContainer con ) { 61void ProcCtl::remove( ProcContainer con ) {
62 remove( con.pid ); 62 remove( con.pid );
63} 63}
64int ProcCtl::status(pid_t pid )const{ 64int ProcCtl::status(pid_t pid )const{
65 ProcContainer *con = m_last; 65 ProcContainer *con = m_last;
66 while (con) { 66 while (con) {
67 if (con->pid == pid ) 67 if (con->pid == pid )
68 return con->status; 68 return con->status;
69 con = con->prev; 69 con = con->prev;
70 } 70 }
71 return -1; 71 return -1;
72} 72}
73void ProcCtl::signal_handler(int) { 73void ProcCtl::signal_handler(int) {
74 qWarning("signal handler"); 74 qWarning("signal handler in ProcCtl");
75 int status; 75 int status;
76 signal( SIGCHLD, signal_handler ); 76 signal( SIGCHLD, signal_handler );
77 pid_t pi = waitpid( -1, &status, WNOHANG ); 77 pid_t pi = waitpid( -1, &status, WNOHANG );
78 78
79 /* 79 /*
80 * find the container for pid 80 * find the container for pid
81 * 81 *
82 */ 82 */
83 if ( pi < 0 ) { 83 if ( pi < 0 ) {
84 return; 84 return;
85 } 85 }
86 86
87 ProcContainer* con = m_last; 87 ProcContainer* con = m_last;
88 while (con) { 88 while (con) {
89 if ( con->pid == pi ) { 89 if ( con->pid == pi ) {
90 con->status = status; 90 con->status = status;
91 char result = 1; 91 char result = 1;
92 /* give a 'signal' */ 92 /* give a 'signal' */
93 ::write(con->fd, &result, 1 ); 93 ::write(con->fd, &result, 1 );
94 } 94 }
95 con = con->prev; 95 con = con->prev;
96 } 96 }
97} 97}