#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <sys/wait.h>
#include <errno.h>
-#define PROGRAM_SIZE 100
-#define FIELD_PROGRAM
-
-#define strfieldcpy(to, from) \
-do { \
- to[sizeof(to)-1] = '\0'; \
- strncpy(to, from, sizeof(to)-1); \
-} while (0)
+#include "checkers.h"
+#include "vector.h"
+#include "structs.h"
+#include "util.h"
+#include "debug.h"
int execute_program(char *path, char *value, int len)
{
int retval;
int count;
int status;
- int fds[2];
+ int fds[2], null_fd;
pid_t pid;
char *pos;
- char arg[PROGRAM_SIZE];
- char *argv[sizeof(arg) / 2];
+ char arg[CALLOUT_MAX_SIZE];
+ int argc = sizeof(arg) / 2;
+ char *argv[argc + 1];
int i;
i = 0;
if (strchr(path, ' ')) {
- strfieldcpy(arg, path);
+ strlcpy(arg, path, sizeof(arg));
pos = arg;
- while (pos != NULL) {
+ while (pos != NULL && i < argc) {
if (pos[0] == '\'') {
/* don't separate if in apostrophes */
pos++;
retval = pipe(fds);
- if (retval != 0)
+ if (retval != 0) {
+ condlog(0, "error creating pipe for callout: %s", strerror(errno));
return -1;
-
+ }
pid = fork();
close(STDOUT_FILENO);
/* dup write side of pipe to STDOUT */
- dup(fds[1]);
+ if (dup(fds[1]) < 0)
+ return -1;
+
+ /* Ignore writes to stderr */
+ null_fd = open("/dev/null", O_WRONLY);
+ if (null_fd > 0) {
+ close(STDERR_FILENO);
+ retval = dup(null_fd);
+ close(null_fd);
+ }
retval = execv(argv[0], argv);
-
+ condlog(0, "error execing %s : %s", argv[0], strerror(errno));
exit(-1);
case -1:
+ condlog(0, "fork failed: %s", strerror(errno));
+ close(fds[0]);
+ close(fds[1]);
return -1;
default:
/* parent reads from fds[0] */
i += count;
if (i >= len-1) {
+ condlog(0, "not enough space for response from %s", argv[0]);
retval = -1;
break;
}
}
- if (count < 0)
+ if (count < 0) {
+ condlog(0, "no response from %s", argv[0]);
retval = -1;
+ }
if (i > 0 && value[i-1] == '\n')
i--;
wait(&status);
close(fds[0]);
- if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
- retval = -1;
+ retval = -1;
+ if (WIFEXITED(status)) {
+ status = WEXITSTATUS(status);
+ if (status == 0)
+ retval = 0;
+ else
+ condlog(0, "%s exited with %d", argv[0], status);
+ }
+ else if (WIFSIGNALED(status))
+ condlog(0, "%s was terminated by signal %d", argv[0], WTERMSIG(status));
+ else
+ condlog(0, "%s terminated abnormally", argv[0]);
}
return retval;
}
+
+extern int
+apply_format (char * string, char * cmd, struct path * pp)
+{
+ char * pos;
+ char * dst;
+ char * p;
+ char * q;
+ int len;
+ int myfree;
+
+ if (!string)
+ return 1;
+
+ if (!cmd)
+ return 1;
+
+ dst = cmd;
+ p = dst;
+ pos = strchr(string, '%');
+ myfree = CALLOUT_MAX_SIZE;
+
+ if (!pos) {
+ strcpy(dst, string);
+ return 0;
+ }
+
+ len = (int) (pos - string) + 1;
+ myfree -= len;
+
+ if (myfree < 2)
+ return 1;
+
+ snprintf(p, len, "%s", string);
+ p += len - 1;
+ pos++;
+
+ switch (*pos) {
+ case 'n':
+ len = strlen(pp->dev) + 1;
+ myfree -= len;
+
+ if (myfree < 2)
+ return 1;
+
+ snprintf(p, len, "%s", pp->dev);
+ for (q = p; q < p + len; q++) {
+ if (q && *q == '!')
+ *q = '/';
+ }
+ p += len - 1;
+ break;
+ case 'd':
+ len = strlen(pp->dev_t) + 1;
+ myfree -= len;
+
+ if (myfree < 2)
+ return 1;
+
+ snprintf(p, len, "%s", pp->dev_t);
+ p += len - 1;
+ break;
+ default:
+ break;
+ }
+ pos++;
+
+ if (!*pos) {
+ condlog(3, "formatted callout = %s", dst);
+ return 0;
+ }
+
+ len = strlen(pos) + 1;
+ myfree -= len;
+
+ if (myfree < 2)
+ return 1;
+
+ snprintf(p, len, "%s", pos);
+ condlog(3, "reformatted callout = %s", dst);
+ return 0;
+}