1 #include <lib/base/console.h>
2 #include <lib/base/eerror.h>
3 #include <sys/vfs.h> // for statfs
9 int bidirpipe(int pfd[], char *cmd , char *argv[])
11 int pfdin[2]; /* from child to parent */
12 int pfdout[2]; /* from parent to child */
13 int pfderr[2]; /* stderr from child to parent */
14 int pid; /* child's pid */
16 if ( pipe(pfdin) == -1 || pipe(pfdout) == -1 || pipe(pfderr) == -1)
19 if ( ( pid = fork() ) == -1 )
21 else if (pid == 0) /* child process */
24 if ( close(0) == -1 || close(1) == -1 || close(2) == -1 )
27 if (dup(pfdout[0]) != 0 || dup(pfdin[1]) != 1 || dup(pfderr[1]) != 2 )
30 if (close(pfdout[0]) == -1 || close(pfdout[1]) == -1 ||
31 close(pfdin[0]) == -1 || close(pfdin[1]) == -1 ||
32 close(pfderr[0]) == -1 || close(pfderr[1]) == -1 )
35 for (unsigned int i=3; i < 90; ++i )
41 if (close(pfdout[0]) == -1 || close(pfdin[1]) == -1 || close(pfderr[1]) == -1)
51 eConsoleAppContainer::eConsoleAppContainer()
52 :pid(-1), killstate(0), in(0), out(0), err(0)
54 for (int i=0; i < 3; ++i)
58 int eConsoleAppContainer::execute( const std::string &cmd )
64 // eDebug("cmd = %s", cmd.c_str() );
65 int cnt=2; // path to app + terminated 0
66 std::string str(cmd.length()?cmd:"");
68 // kill spaces at beginning
69 unsigned int pos = str.find_first_not_of(' ');
70 if (pos != std::string::npos && pos)
71 str = str.substr(pos);
73 // kill spaces at the end
74 pos = str.find_last_not_of(' ');
75 if (pos != std::string::npos && (pos+1) < str.length())
76 str = str.erase(pos+1);
78 unsigned int slen=str.length();
82 std::map<char,char> brackets;
83 brackets.insert(std::pair<char,char>('\'','\''));
84 brackets.insert(std::pair<char,char>('"','"'));
85 brackets.insert(std::pair<char,char>('`','`'));
86 brackets.insert(std::pair<char,char>('(',')'));
87 brackets.insert(std::pair<char,char>('{','}'));
88 brackets.insert(std::pair<char,char>('[',']'));
89 brackets.insert(std::pair<char,char>('<','>'));
91 unsigned int idx=str.find(' ');
92 std::string path = str.substr(0, idx != std::string::npos ? idx : slen );
93 // eDebug("path = %s", path.c_str() );
94 unsigned int plen = path.length();
96 std::string cmds = slen > plen ? str.substr( plen+1 ) : "";
97 unsigned int clen = cmds.length();
98 // eDebug("cmds = %s", cmds.c_str() );
101 std::map<char,char>::iterator it = brackets.find(cmds[idx]);
102 while ( (idx = cmds.find(' ',idx) ) != std::string::npos ) // count args
104 if (it != brackets.end())
106 if (cmds[idx-1] == it->second)
109 if (it == brackets.end())
112 it = brackets.find(cmds[idx+1]);
117 // eDebug("idx = %d, %d counted spaces", idx, cnt-2);
122 // eDebug("increase cnt");
125 // eDebug("%d args", cnt-2);
126 char **argv = new char*[cnt]; // min two args... path and terminating 0
127 argv[0] = new char[ plen ];
128 strcpy( argv[0], path.c_str() );
129 argv[cnt-1] = 0; // set terminating null
131 if ( cnt > 2 ) // more then default args?
133 cnt=1; // do not overwrite path in argv[0]
135 it = brackets.find(cmds[0]);
137 while ( (idx = cmds.find(' ',idx)) != std::string::npos ) // parse all args..
139 bool bracketClosed=false;
140 if ( it != brackets.end() )
142 if (cmds[idx-1]==it->second)
148 if ( it == brackets.end() )
150 std::string tmp = cmds.substr(0, idx);
154 tmp.erase(tmp.length()-1, 1);
157 argv[cnt] = new char[ tmp.length()+1 ];
158 // eDebug("idx=%d, arg = %s", idx, tmp.c_str() );
159 strcpy( argv[cnt++], tmp.c_str() );
160 cmds.erase(0, idx+1);
161 // eDebug("str = %s", cmds.c_str() );
162 it = brackets.find(cmds[0]);
168 if ( it != brackets.end() )
171 cmds.erase(cmds.length()-1, 1);
173 // store the last arg
174 argv[cnt] = new char[ cmds.length() ];
175 strcpy( argv[cnt], cmds.c_str() );
180 // get one read ,one write and the err pipe to the prog..
184 // eDebug("%d is %s", tmp, argv[tmp++]);
186 pid = bidirpipe(fd, argv[0], argv);
188 while ( cnt >= 0 ) // release heap memory
190 // eDebug("delete argv[%d]", cnt);
191 delete [] argv[cnt--];
193 // eDebug("delete argv");
199 eDebug("pipe in = %d, out = %d, err = %d", fd[0], fd[1], fd[2]);
201 in = new eSocketNotifier(eApp, fd[0], POLLIN|POLLPRI|POLLHUP );
202 out = new eSocketNotifier(eApp, fd[1], POLLOUT, false);
203 err = new eSocketNotifier(eApp, fd[2], POLLIN|POLLPRI );
204 CONNECT(in->activated, eConsoleAppContainer::readyRead);
205 CONNECT(out->activated, eConsoleAppContainer::readyWrite);
206 CONNECT(err->activated, eConsoleAppContainer::readyErrRead);
210 eConsoleAppContainer::~eConsoleAppContainer()
215 void eConsoleAppContainer::kill()
217 if ( killstate != -1 )
219 eDebug("user kill(SIGKILL) console App");
221 ::kill(pid, SIGKILL);
224 while( outbuf.size() ) // cleanup out buffer
226 queue_data d = outbuf.front();
236 void eConsoleAppContainer::sendCtrlC()
238 if ( killstate != -1 )
240 eDebug("user send SIGINT(Ctrl-C) to console App");
245 void eConsoleAppContainer::closePipes()
268 eDebug("pipes closed");
269 while( outbuf.size() ) // cleanup out buffer
271 queue_data d = outbuf.front();
277 void eConsoleAppContainer::readyRead(int what)
279 if (what & POLLPRI|POLLIN)
281 // eDebug("what = %d");
283 int readed = read(fd[0], buf, 2047);
284 // eDebug("%d bytes read", readed);
285 if ( readed != -1 && readed )
287 /* for ( int i = 0; i < readed; i++ )
288 eDebug("%d = %c (%02x)", i, buf[i], buf[i] );*/
290 /*emit*/ dataAvail(buf);
292 else if (readed == -1)
293 eDebug("readerror %d", errno);
295 if (what & eSocketNotifier::Hungup)
297 eDebug("child has terminated");
299 /*emit*/ appClosed(killstate);
303 void eConsoleAppContainer::readyErrRead(int what)
305 if (what & POLLPRI|POLLIN)
307 // eDebug("what = %d");
309 int readed = read(fd[2], buf, 2047);
310 // eDebug("%d bytes read", readed);
311 if ( readed != -1 && readed )
313 /* for ( int i = 0; i < readed; i++ )
314 eDebug("%d = %c (%02x)", i, buf[i], buf[i] );*/
316 /*emit*/ dataAvail(buf);
318 else if (readed == -1)
319 eDebug("readerror %d", errno);
323 void eConsoleAppContainer::write( const char *data, int len )
325 char *tmp = new char[len];
326 memcpy(tmp, data, len);
327 outbuf.push(queue_data(tmp,len));
331 void eConsoleAppContainer::readyWrite(int what)
333 if (what&POLLOUT && outbuf.size() )
335 queue_data d = outbuf.front();
337 if ( ::write( fd[1], d.data, d.len ) != d.len )
339 /* emit */ dataSent(-1);
340 // eDebug("writeError");
344 /* emit */ dataSent(0);
345 // eDebug("write ok");
349 if ( !outbuf.size() )