|
a/src/utils/execmd.cpp |
|
b/src/utils/execmd.cpp |
1 |
#ifndef lint
|
1 |
#ifndef lint
|
2 |
static char rcsid[] = "@(#$Id: execmd.cpp,v 1.21 2006-12-14 13:53:43 dockes Exp $ (C) 2004 J.F.Dockes";
|
2 |
static char rcsid[] = "@(#$Id: execmd.cpp,v 1.22 2007-02-19 18:14:13 dockes Exp $ (C) 2004 J.F.Dockes";
|
3 |
#endif
|
3 |
#endif
|
4 |
/*
|
4 |
/*
|
5 |
* This program is free software; you can redistribute it and/or modify
|
5 |
* This program is free software; you can redistribute it and/or modify
|
6 |
* it under the terms of the GNU General Public License as published by
|
6 |
* it under the terms of the GNU General Public License as published by
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
... |
|
... |
140 |
if (pipeout[1] >= 0)
|
140 |
if (pipeout[1] >= 0)
|
141 |
close(pipeout[1]);
|
141 |
close(pipeout[1]);
|
142 |
}
|
142 |
}
|
143 |
};
|
143 |
};
|
144 |
|
144 |
|
145 |
|
|
|
146 |
int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
145 |
int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
147 |
const string *inputstring, string *output)
|
146 |
const string *inputstring, string *output)
|
148 |
{
|
147 |
{
|
|
|
148 |
// Need something to take note of my own errors (apart from the command's)
|
|
|
149 |
bool haderror = false;
|
|
|
150 |
|
149 |
{ // Debug and logging
|
151 |
{ // Debug and logging
|
150 |
string command = cmd + " ";
|
152 |
string command = cmd + " ";
|
151 |
for (list<string>::const_iterator it = args.begin();it != args.end();
|
153 |
for (list<string>::const_iterator it = args.begin();it != args.end();
|
152 |
it++) {
|
154 |
it++) {
|
153 |
command += "{" + *it + "} ";
|
155 |
command += "{" + *it + "} ";
|
154 |
}
|
156 |
}
|
155 |
LOGDEB(("ExecCmd::doexec: %s\n", command.c_str()));
|
157 |
LOGDEB(("ExecCmd::doexec: (%p|%p) %s\n",
|
|
|
158 |
inputstring, output, command.c_str()));
|
156 |
}
|
159 |
}
|
157 |
const char *input = inputstring ? inputstring->data() : 0;
|
160 |
const char *input = inputstring ? inputstring->data() : 0;
|
158 |
unsigned int inputlen = inputstring ? inputstring->length() : 0;
|
161 |
unsigned int inputlen = inputstring ? inputstring->length() : 0;
|
159 |
|
162 |
|
160 |
ExecCmdRsrc e;
|
163 |
ExecCmdRsrc e;
|
|
... |
|
... |
173 |
LOGERR(("ExecCmd::doexec: fork(2) failed. errno %d\n", errno));
|
176 |
LOGERR(("ExecCmd::doexec: fork(2) failed. errno %d\n", errno));
|
174 |
return -1;
|
177 |
return -1;
|
175 |
}
|
178 |
}
|
176 |
|
179 |
|
177 |
if (e.pid) {
|
180 |
if (e.pid) {
|
178 |
// Ignore SIGPIPE in here.
|
181 |
// Ignore SIGPIPE and block SIGCHLD in here.
|
179 |
void (*osig)(int);
|
182 |
void (*osig)(int);
|
180 |
osig = signal(SIGPIPE, SIG_IGN);
|
183 |
osig = signal(SIGPIPE, SIG_IGN);
|
|
|
184 |
sigset_t blkcld;
|
|
|
185 |
sigemptyset(&blkcld);
|
|
|
186 |
sigaddset(&blkcld, SIGCHLD);
|
|
|
187 |
sigprocmask(SIG_BLOCK, &blkcld, 0);
|
|
|
188 |
|
181 |
// Father process
|
189 |
// Father process
|
182 |
if (input) {
|
190 |
if (input) {
|
183 |
close(e.pipein[0]);
|
191 |
close(e.pipein[0]);
|
184 |
e.pipein[0] = -1;
|
192 |
e.pipein[0] = -1;
|
185 |
fcntl(e.pipein[1], F_SETFL, O_NONBLOCK);
|
193 |
fcntl(e.pipein[1], F_SETFL, O_NONBLOCK);
|
|
... |
|
... |
219 |
m_advise->newData(0);
|
227 |
m_advise->newData(0);
|
220 |
continue;
|
228 |
continue;
|
221 |
}
|
229 |
}
|
222 |
LOGERR(("ExecCmd::doexec: select(2) failed. errno %d\n",
|
230 |
LOGERR(("ExecCmd::doexec: select(2) failed. errno %d\n",
|
223 |
errno));
|
231 |
errno));
|
|
|
232 |
haderror = true;
|
224 |
break;
|
233 |
break;
|
225 |
}
|
234 |
}
|
226 |
if (e.pipein[1] >= 0 && FD_ISSET(e.pipein[1], &writefds)) {
|
235 |
if (e.pipein[1] >= 0 && FD_ISSET(e.pipein[1], &writefds)) {
|
227 |
int n = write(e.pipein[1], input + nwritten,
|
236 |
int n = write(e.pipein[1], input + nwritten,
|
228 |
inputlen - nwritten);
|
237 |
inputlen - nwritten);
|
229 |
if (n < 0) {
|
238 |
if (n < 0) {
|
230 |
LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n",
|
239 |
LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n",
|
231 |
errno));
|
240 |
errno));
|
|
|
241 |
haderror = true;
|
232 |
goto out;
|
242 |
goto out;
|
233 |
}
|
243 |
}
|
234 |
nwritten += n;
|
244 |
nwritten += n;
|
235 |
if (nwritten == inputlen) {
|
245 |
if (nwritten == inputlen) {
|
236 |
if (m_provide) {
|
246 |
if (m_provide) {
|
|
... |
|
... |
256 |
if (n == 0) {
|
266 |
if (n == 0) {
|
257 |
goto out;
|
267 |
goto out;
|
258 |
} else if (n < 0) {
|
268 |
} else if (n < 0) {
|
259 |
LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n",
|
269 |
LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n",
|
260 |
errno));
|
270 |
errno));
|
|
|
271 |
haderror = true;
|
261 |
goto out;
|
272 |
goto out;
|
262 |
} else if (n > 0) {
|
273 |
} else if (n > 0) {
|
263 |
// cerr << "READ: " << n << endl;
|
274 |
// cerr << "READ: " << n << endl;
|
264 |
output->append(buf, n);
|
275 |
output->append(buf, n);
|
265 |
if (m_advise)
|
276 |
if (m_advise)
|
|
... |
|
... |
269 |
}
|
280 |
}
|
270 |
}
|
281 |
}
|
271 |
|
282 |
|
272 |
out:
|
283 |
out:
|
273 |
int status = -1;
|
284 |
int status = -1;
|
274 |
signal(SIGPIPE, osig);
|
|
|
275 |
if (!m_cancelRequest) {
|
285 |
if (!m_cancelRequest) {
|
276 |
(void)waitpid(e.pid, &status, 0);
|
286 |
(void)waitpid(e.pid, &status, 0);
|
277 |
e.pid = -1;
|
287 |
e.pid = -1;
|
278 |
}
|
288 |
}
|
|
|
289 |
signal(SIGPIPE, osig);
|
|
|
290 |
sigprocmask(SIG_UNBLOCK, &blkcld, 0);
|
279 |
LOGDEB1(("ExecCmd::doexec: father got status 0x%x\n", status));
|
291 |
LOGDEB1(("ExecCmd::doexec: father got status 0x%x\n", status));
|
280 |
return status;
|
292 |
return haderror ? -1 : status;
|
281 |
|
293 |
|
282 |
} else {
|
294 |
} else {
|
283 |
// In child process. Set up pipes, environment, and exec command
|
295 |
// In child process. Set up pipes, environment, and exec command
|
284 |
|
296 |
|
285 |
if (input) {
|
297 |
if (input) {
|