Switch to unified view

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) {