*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2002-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
* a bi-directional pipe so that the user can read from and
* write to the program.
*/
-BPIPE *open_bpipe(char *prog, int wait, char *mode)
+BPIPE *open_bpipe(char *prog, int wait, const char *mode)
{
char *bargv[MAX_ARGV];
- int bargc;
+ int bargc, i;
int readp[2], writep[2];
POOLMEM *tprog;
int mode_read, mode_write;
build_argc_argv(mp_chr(tprog), &bargc, bargv, MAX_ARGV);
#ifdef xxxxxx
printf("argc=%d\n", bargc);
- int i;
for (i=0; i<bargc; i++) {
printf("argc=%d argv=%s:\n", i, bargv[i]);
}
return NULL;
}
if (mode_read && pipe(readp) == -1) {
+ if (mode_write) {
+ close(writep[0]);
+ close(writep[1]);
+ }
free(bpipe);
return NULL;
}
/* Start worker process */
switch (bpipe->worker_pid = fork()) {
case -1: /* error */
+ if (mode_write) {
+ close(writep[0]);
+ close(writep[1]);
+ }
+ if (mode_read) {
+ close(readp[0]);
+ close(readp[1]);
+ }
free(bpipe);
return NULL;
dup2(readp[1], 1); /* dup our read to his stdout */
dup2(readp[1], 2); /* and his stderr */
}
- for (int i=3; i<=32; i++) { /* close any open file descriptors */
+ closelog(); /* close syslog if open */
+ for (i=3; i<=32; i++) { /* close any open file descriptors */
close(i);
}
execvp(bargv[0], bargv); /* call the program */
return stat;
}
-/* Close both pipes and free resources */
+/*
+ * Close both pipes and free resources
+ *
+ * Returns: 0 on success
+ * errno on failure
+ */
int close_bpipe(BPIPE *bpipe)
{
int chldstatus = 0;
bmicrosleep(1, 0); /* wait one second */
remaining_wait--;
} else {
- stat = 1; /* set error status */
- errno = ETIME; /* set timed out */
+ stat = ETIME; /* set error status */
wpid = -1;
break; /* don't wait any longer */
}
if (wpid > 0) {
if (WIFEXITED(chldstatus)) { /* process exit()ed */
stat = WEXITSTATUS(chldstatus);
- Dmsg1(200, "status =%d\n", stat);
+ if (stat != 0) {
+ Dmsg1(100, "Non-zero status %s returned from child.\n", stat);
+ stat = ECHILD;
+ }
+ Dmsg1(200, "child status=%d\n", stat);
} else if (WIFSIGNALED(chldstatus)) { /* process died */
- stat = 1;
+ stat = ECHILD;
Dmsg0(200, "Signaled\n");
}
- if (stat != 0) {
- errno = ECHILD; /* set child errno */
- }
}
if (bpipe->timer_id) {
stop_child_timer(bpipe->timer_id);
* Contrary to my normal calling conventions, this program
*
* Returns: 0 on success
- * non-zero on error
+ * non-zero on error == errno
*/
int run_program(char *prog, int wait, POOLMEM *results)
{
mode = (char *)(results != NULL ? "r" : "");
bpipe = open_bpipe(prog, wait, mode);
if (!bpipe) {
- return 0;
+ return ENOENT;
}
if (results) {
mp_chr(results)[0] = 0;
- stat1 = fgets(mp_chr(results), sizeof_pool_memory(results), bpipe->rfd) == NULL;
+ fgets(mp_chr(results), sizeof_pool_memory(results), bpipe->rfd);
+ if (feof(bpipe->rfd)) {
+ stat1 = 0;
+ } else {
+ stat1 = ferror(bpipe->rfd);
+ }
+ if (stat1 < 0) {
+ Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
+ } else if (stat1 != 0) {
+ Dmsg1(100, "Run program fgets stat=%d\n", stat1);
+ }
} else {
stat1 = 0;
}
stat2 = close_bpipe(bpipe);
- return stat2 != 0 ? stat2 : stat1;
+ stat1 = stat2 != 0 ? stat2 : stat1;
+ Dmsg1(100, "Run program returning %d\n", stat1);
+ return stat1;
}