*
* Version $Id$
*/
-
/*
- Copyright (C) 2002-2004 Kern Sibbald and John Walker
+ Copyright (C) 2002-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
*/
+
#include "bacula.h"
#include "jcr.h"
* of seconds. Program killed if wait exceeded. Optionally
* return the output from the program (normally a single line).
*
+ * If the watchdog kills the program, fgets returns, and ferror is set
+ * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
+ *
* Contrary to my normal calling conventions, this program
*
* Returns: 0 on success
int stat1, stat2;
char *mode;
- if (results) {
- results[0] = 0;
- }
mode = (char *)(results != NULL ? "r" : "");
bpipe = open_bpipe(prog, wait, mode);
if (!bpipe) {
return ENOENT;
}
if (results) {
- fgets(results, sizeof_pool_memory(results), bpipe->rfd);
+ results[0] = 0;
+ int len = sizeof_pool_memory(results) - 1;
+ fgets(results, len, bpipe->rfd);
+ results[len] = 0;
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));
+ Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
} else if (stat1 != 0) {
- Dmsg1(100, "Run program fgets stat=%d\n", stat1);
+ Dmsg1(150, "Run program fgets stat=%d\n", stat1);
+ if (bpipe->timer_id) {
+ Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
+ /* NB: I'm not sure it is really useful for run_program. Without the
+ * following lines run_program would not detect if the program was killed
+ * by the watchdog. */
+ if (bpipe->timer_id->killed) {
+ stat1 = ETIME;
+ pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
+ }
+ }
}
} else {
stat1 = 0;
}
stat2 = close_bpipe(bpipe);
stat1 = stat2 != 0 ? stat2 : stat1;
- Dmsg1(100, "Run program returning %d\n", stat1);
+ Dmsg1(150, "Run program returning %d\n", stat1);
return stat1;
}
* Run an external program. Optionally wait a specified number
* of seconds. Program killed if wait exceeded (it is done by the
* watchdog, as fgets is a blocking function).
+ *
+ * If the watchdog kills the program, fgets returns, and ferror is set
+ * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
+ *
* Return the full output from the program (not only the first line).
*
* Contrary to my normal calling conventions, this program
int stat1, stat2;
char *mode;
POOLMEM* tmp;
+ char *buf;
+ const int bufsize = 32000;
if (results == NULL) {
return run_program(prog, wait, NULL);
}
+ sm_check(__FILE__, __LINE__, false);
+
tmp = get_pool_memory(PM_MESSAGE);
+ buf = (char *)malloc(bufsize+1);
mode = (char *)"r";
bpipe = open_bpipe(prog, wait, mode);
if (!bpipe) {
+ if (results) {
+ results[0] = 0;
+ }
return ENOENT;
}
- results[0] = 0;
-
+ sm_check(__FILE__, __LINE__, false);
+ tmp[0] = 0;
while (1) {
- fgets(tmp, sizeof_pool_memory(tmp), bpipe->rfd);
- Dmsg1(800, "Run program fgets=%s", tmp);
- pm_strcat(results, tmp);
+ buf[0] = 0;
+ fgets(buf, bufsize, bpipe->rfd);
+ buf[bufsize] = 0;
+ pm_strcat(tmp, buf);
if (feof(bpipe->rfd)) {
stat1 = 0;
Dmsg1(900, "Run program fgets stat=%d\n", stat1);
stat1 = ferror(bpipe->rfd);
}
if (stat1 < 0) {
- Dmsg2(900, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
+ berrno be;
+ Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
break;
} else if (stat1 != 0) {
Dmsg1(900, "Run program fgets stat=%d\n", stat1);
+ if (bpipe->timer_id) {
+ Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
+ if (bpipe->timer_id->killed) {
+ pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
+ stat1 = ETIME;
+ break;
+ }
+ }
}
}
-
+ int len = sizeof_pool_memory(results) - 1;
+ bstrncpy(results, tmp, len);
+ Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
stat2 = close_bpipe(bpipe);
stat1 = stat2 != 0 ? stat2 : stat1;
- Dmsg1(900, "Run program returning %d\n", stat);
+ Dmsg1(900, "Run program returning %d\n", stat1);
free_pool_memory(tmp);
+ free(buf);
return stat1;
}