You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1121 lines
33 KiB

# --- SDE-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
#
# Filename: package/.../specter/specter-1.4-0003-EXEC-plugin-zombie.patch
# Copyright (C) 2011 The OpenSDE Project
#
# More information can be found in the files COPYING and README.
#
# This patch file is dual-licensed. It is available under the license the
# patched project is licensed under, as long as it is an OpenSource license
# as defined at http://www.opensource.org/ (e.g. BSD, X11) or 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.
# --- SDE-COPYRIGHT-NOTE-END ---
Description: Prevent EXEC plugin from creating zombie processes
Origin: Upstream (http://bazaar.launchpad.net/~ruby/specter/trunk/diff/5)
=== modified file 'plugins/specter_EXEC.c'
--- specter-1.4/plugins/specter_EXEC.c 2008-01-06 17:26:23 +0000
+++ specter-1.4/plugins/specter_EXEC.c 2008-02-22 19:27:02 +0000
@@ -5,12 +5,12 @@
* This target executes application on packet receive, expanding few
* conversion tags into values appropriate for current packet.
*
- * (C) 2004,2005 by Michal Kwiatkowski <ruby@joker.linuxstuff.pl>
+ * (C) 2004-2005,2008 by Michal Kwiatkowski <ruby@joker.linuxstuff.pl>
*/
/*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
+ * it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
@@ -60,407 +60,420 @@
#endif
static config_entry_t my_config[] = {
- { .key = "command", .type = CONFIG_TYPE_STRING, .options = CONFIG_OPT_MANDATORY },
- { .key = "wait", .type = CONFIG_TYPE_BOOLEAN, .options = CONFIG_OPT_NONE,
- .u = { .value = 0 } },
- { .key = "force", .type = CONFIG_TYPE_BOOLEAN, .options = CONFIG_OPT_NONE,
- .u = { .value = 0 } },
- { .key = "environment", .type = CONFIG_TYPE_BOOLEAN, .options = CONFIG_OPT_NONE,
- .u = { .value = 0 } },
+ { .key = "command", .type = CONFIG_TYPE_STRING, .options = CONFIG_OPT_MANDATORY },
+ { .key = "wait", .type = CONFIG_TYPE_BOOLEAN, .options = CONFIG_OPT_NONE,
+ .u = { .value = 0 } },
+ { .key = "force", .type = CONFIG_TYPE_BOOLEAN, .options = CONFIG_OPT_NONE,
+ .u = { .value = 0 } },
+ { .key = "environment", .type = CONFIG_TYPE_BOOLEAN, .options = CONFIG_OPT_NONE,
+ .u = { .value = 0 } },
};
/* structure to lower number of operations during execution time */
struct arguments {
- int type;
- union {
- char *str;
- char c;
- } u;
+ int type;
+ union {
+ char *str;
+ char c;
+ } u;
};
#define ATT_FLAG 0x4
enum {
- ARG_TYPE_NONE = 0x0, /* array terminator */
- ARG_TYPE_IRET = 0x1,
- ARG_TYPE_STRING = 0x2,
- ARG_TYPE_IRET_ATT = ARG_TYPE_IRET|ATT_FLAG,
- ARG_TYPE_STRING_ATT = ARG_TYPE_STRING|ATT_FLAG,
+ ARG_TYPE_NONE = 0x0, /* array terminator */
+ ARG_TYPE_IRET = 0x1,
+ ARG_TYPE_STRING = 0x2,
+ ARG_TYPE_IRET_ATT = ARG_TYPE_IRET|ATT_FLAG,
+ ARG_TYPE_STRING_ATT = ARG_TYPE_STRING|ATT_FLAG,
};
struct redirection {
- char file[PATH_MAX];
- int flags;
+ char file[PATH_MAX];
+ int flags;
};
struct my_data {
- char execline[EXEC_MAX_LINE];
- struct arguments args[EXEC_MAX_ARGS+1];
- struct redirection stdin, stdout, stderr;
- int free_command;
+ char execline[EXEC_MAX_LINE];
+ struct arguments args[EXEC_MAX_ARGS+1];
+ struct redirection stdin, stdout, stderr;
+ int free_command;
};
/* here goes conversion stuff */
#define LOCAL_RET_NUM 10
static struct {
- char name[SPECTER_IRET_NAME_LEN];
- specter_iret_t *p;
- char c;
+ char name[SPECTER_IRET_NAME_LEN];
+ specter_iret_t *p;
+ char c;
} local_ret[LOCAL_RET_NUM] = {
/* 0 */{ "oob.in", NULL, 'I' },
- { "oob.out", NULL, 'O' },
- { "ip.saddr", NULL, 'S' },
- { "ip.daddr", NULL, 'D' },
- { "ip.protocol", NULL, 'P' },
+ { "oob.out", NULL, 'O' },
+ { "ip.saddr", NULL, 'S' },
+ { "ip.daddr", NULL, 'D' },
+ { "ip.protocol", NULL, 'P' },
/* 5 */{ "tcp.sport", NULL, 's' },
- { "tcp.dport", NULL, 'd' },
- { "udp.sport", NULL, 's' },
- { "udp.dport", NULL, 'd' },
- { "icmp.type", NULL, 'i' },
+ { "tcp.dport", NULL, 'd' },
+ { "udp.sport", NULL, 's' },
+ { "udp.dport", NULL, 'd' },
+ { "icmp.type", NULL, 'i' },
};
static specter_iret_t *find_tag(const char c)
{
- int ctr;
- specter_iret_t *iret = NULL;
-
- for (ctr = 0; ctr < LOCAL_RET_NUM; ctr++)
- if (local_ret[ctr].c == c) {
- iret = local_ret[ctr].p;
- if (IS_VALID(iret))
- break;
- }
-
- return iret;
+ int ctr;
+ specter_iret_t *iret = NULL;
+
+ for (ctr = 0; ctr < LOCAL_RET_NUM; ctr++)
+ if (local_ret[ctr].c == c) {
+ iret = local_ret[ctr].p;
+ if (IS_VALID(iret))
+ break;
+ }
+
+ return iret;
}
static int fill_tag(const char c)
{
- int ctr;
-
- for (ctr = 0; ctr < LOCAL_RET_NUM; ctr++) {
- if (local_ret[ctr].c == c) {
- if ((local_ret[ctr].p = find_iret(local_ret[ctr].name)) != NULL)
- return 0;
- }
- }
-
- return -1;
+ int ctr;
+
+ for (ctr = 0; ctr < LOCAL_RET_NUM; ctr++) {
+ if (local_ret[ctr].c == c) {
+ if ((local_ret[ctr].p = find_iret(local_ret[ctr].name)) != NULL)
+ return 0;
+ }
+ }
+
+ return -1;
}
static void check_status(char *comm, pid_t pid, int status)
{
- if (WIFEXITED(status)) {
- if (WEXITSTATUS(status)) {
- specter_log(SPECTER_NOTICE, "%s[%i] returned %i.\n",
- comm, pid, WEXITSTATUS(status));
- } else {
- specter_log(SPECTER_DEBUG, "%s[%i] returned 0.\n",
- comm, pid);
- }
- } else if (WIFSIGNALED(status)) {
- specter_log(SPECTER_NOTICE, "%s[%i] terminated by signal #%i.\n",
- comm, pid, WTERMSIG(status));
- }
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status)) {
+ specter_log(SPECTER_NOTICE, "%s[%i] returned %i.\n",
+ comm, pid, WEXITSTATUS(status));
+ } else {
+ specter_log(SPECTER_DEBUG, "%s[%i] returned 0.\n",
+ comm, pid);
+ }
+ } else if (WIFSIGNALED(status)) {
+ specter_log(SPECTER_NOTICE, "%s[%i] terminated by signal #%i.\n",
+ comm, pid, WTERMSIG(status));
+ }
}
static int fill_arg(char *buff, specter_iret_t *iret, int size)
{
- int number = 0;
-
- if (!IS_VALID(iret)) {
- return -1;
- }
-
- switch (iret->type) {
- case SPECTER_IRET_INT8:
- number += snprintf(buff, size, "%d", iret->value.i8);
- break;
- case SPECTER_IRET_INT16:
- number += snprintf(buff, size, "%d", iret->value.i16);
- break;
- case SPECTER_IRET_INT32:
- number += snprintf(buff, size, "%d", iret->value.i32);
- break;
- case SPECTER_IRET_INT64:
- number += snprintf(buff, size, "%lld", iret->value.i64);
- break;
- case SPECTER_IRET_UINT8:
- number += snprintf(buff, size, "%u", iret->value.ui8);
- break;
- case SPECTER_IRET_UINT16:
- number += snprintf(buff, size, "%u", iret->value.ui16);
- break;
- case SPECTER_IRET_UINT32:
- number += snprintf(buff, size, "%u", iret->value.ui32);
- break;
- case SPECTER_IRET_UINT64:
- number += snprintf(buff, size, "%llu", iret->value.ui64);
- break;
- case SPECTER_IRET_BOOL:
- number += snprintf(buff, size, "%d", iret->value.b);
- break;
- case SPECTER_IRET_IPADDR:
- {
- struct in_addr ia;
- char *str;
-
- ia.s_addr = ntohl(iret->value.ui32);
- str = inet_ntoa(ia);
-
- if (strlen(str) > EXEC_ARG_SPACE - 1) {
- specter_log(SPECTER_DEBUG,
- "Address too long: %s.\n", str);
- return -1;
- }
- strncpy(buff, str, size);
- number += strlen(str);
- }
- break;
- case SPECTER_IRET_STRING:
- strncpy(buff, (char *)iret->value.ptr, size);
- number += strlen((char *)iret->value.ptr);
- break;
- default:
- specter_log(SPECTER_DEBUG,
- "Unknown key type %i for \"%s\".\n",
- iret->type, iret->name);
- return -1;
- break;
- }
-
- return number;
+ int number = 0;
+
+ if (!IS_VALID(iret)) {
+ return -1;
+ }
+
+ switch (iret->type) {
+ case SPECTER_IRET_INT8:
+ number += snprintf(buff, size, "%d", iret->value.i8);
+ break;
+ case SPECTER_IRET_INT16:
+ number += snprintf(buff, size, "%d", iret->value.i16);
+ break;
+ case SPECTER_IRET_INT32:
+ number += snprintf(buff, size, "%d", iret->value.i32);
+ break;
+ case SPECTER_IRET_INT64:
+ number += snprintf(buff, size, "%lld", iret->value.i64);
+ break;
+ case SPECTER_IRET_UINT8:
+ number += snprintf(buff, size, "%u", iret->value.ui8);
+ break;
+ case SPECTER_IRET_UINT16:
+ number += snprintf(buff, size, "%u", iret->value.ui16);
+ break;
+ case SPECTER_IRET_UINT32:
+ number += snprintf(buff, size, "%u", iret->value.ui32);
+ break;
+ case SPECTER_IRET_UINT64:
+ number += snprintf(buff, size, "%llu", iret->value.ui64);
+ break;
+ case SPECTER_IRET_BOOL:
+ number += snprintf(buff, size, "%d", iret->value.b);
+ break;
+ case SPECTER_IRET_IPADDR:
+ {
+ struct in_addr ia;
+ char *str;
+
+ ia.s_addr = ntohl(iret->value.ui32);
+ str = inet_ntoa(ia);
+
+ if (strlen(str) > EXEC_ARG_SPACE - 1) {
+ specter_log(SPECTER_DEBUG,
+ "Address too long: %s.\n", str);
+ return -1;
+ }
+ strncpy(buff, str, size);
+ number += strlen(str);
+ }
+ break;
+ case SPECTER_IRET_STRING:
+ strncpy(buff, (char *)iret->value.ptr, size);
+ number += strlen((char *)iret->value.ptr);
+ break;
+ default:
+ specter_log(SPECTER_DEBUG,
+ "Unknown key type %i for \"%s\".\n",
+ iret->type, iret->name);
+ return -1;
+ break;
+ }
+
+ return number;
}
static void exec_fini(config_entry_t *ce, void *data)
{
- int ret, status;
- struct my_data *md = data;
-
- while ((ret = waitpid(-1, &status, WNOHANG)) > 0) {
- check_status(md->args[0].u.str, ret, status);
- }
-
- if (md->free_command) {
- /* mallocated by strdup() in exec_init() */
- free(md->args[0].u.str);
- }
-
- free(data);
+ int ret, status;
+ struct my_data *md = data;
+
+ while ((ret = waitpid(-1, &status, WNOHANG)) > 0) {
+ check_status(md->args[0].u.str, ret, status);
+ }
+
+ if (md->free_command) {
+ /* mallocated by strdup() in exec_init() */
+ free(md->args[0].u.str);
+ }
+
+ free(data);
}
static inline int get_word(char *dst, char *src, int size)
{
- int ctr = 0;
-
- while (*src == ' ' || *src == '\t') {
- ctr++;
- src++;
- }
-
- if (*src == '\0')
- return 0;
-
- while (*src != ' ' && *src != '\t' && *src != '\0' && ctr < size) {
- *dst++ = *src++;
- ctr++;
- }
-
- return ctr;
-}
-
+ int ctr = 0;
+
+ while (*src == ' ' || *src == '\t') {
+ ctr++;
+ src++;
+ }
+
+ if (*src == '\0')
+ return 0;
+
+ while (*src != ' ' && *src != '\t' && *src != '\0' && ctr < size) {
+ *dst++ = *src++;
+ ctr++;
+ }
+
+ return ctr;
+}
+
+static char *application_name = NULL;
+static void sigchld_hanlder(int signal)
+{
+ int pid, status;
+
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ check_status(application_name, pid, status);
+ }
+}
static void *exec_init(config_entry_t *ce)
{
- struct my_data *data;
- char *tmp, *line;
- int ctr, new_arg;
- struct stat st;
-
- if ((data = malloc(sizeof(struct my_data))) == NULL) {
- specter_log(SPECTER_FATAL, "Couldn't allocate data: %s.\n",
- strerror(errno));
- return NULL;
- }
-
- memset(data, 0x0, sizeof(data));
- tmp = GET_CE(ce,0)->u.string;
- line = data->execline;
- ctr = 0;
- new_arg = 1;
-
- /* divide execline into separate args */
- while (*tmp) {
- if (*tmp == ' ' || *tmp == '\t') {
- while (*tmp == ' ' || *tmp == '\t')
- tmp++;
- *line++ = '\0';
- new_arg = 1;
- } else if (*tmp == '%' && *++tmp != '%') {
- if (fill_tag(*tmp) == -1) {
- specter_log(SPECTER_FATAL,
- "Bad exec tag: \"%%%c\".\n", *tmp);
- return NULL;
- }
- if (!new_arg) {
- data->args[ctr-1].type |= ATT_FLAG;
- *line++ = '\0';
- }
- data->args[ctr].u.c = *tmp++;
- data->args[ctr].type = ARG_TYPE_IRET;
- if (++ctr == EXEC_MAX_ARGS) {
- specter_log(SPECTER_FATAL,
- "Command line has too many arguments.\n");
- return NULL;
- }
- new_arg = 0;
- } else if ((*tmp == '>') || (*tmp == '1' && *(tmp+1) == '>' && tmp++)) {
- int ret;
- if (*++tmp == '>') {
- tmp++;
- data->stdout.flags = O_WRONLY|O_CREAT|O_APPEND;
- } else {
- data->stdout.flags = O_WRONLY|O_CREAT|O_TRUNC;
- }
- if ((ret = get_word(data->stdout.file, tmp, PATH_MAX)) == 0) {
- specter_log(SPECTER_FATAL, "Empty filename in command "
- "line stdout redirection.\n");
- return NULL;
- }
- tmp += ret;
- new_arg = 1;
- } else if (*tmp == '2' && *(tmp+1) == '>' && tmp++) {
- int ret;
- if (*++tmp == '>') {
- tmp++;
- data->stderr.flags = O_WRONLY|O_CREAT|O_APPEND;
- } else {
- data->stderr.flags = O_WRONLY|O_CREAT|O_TRUNC;
- }
- if ((ret = get_word(data->stderr.file, tmp, PATH_MAX)) == 0) {
- specter_log(SPECTER_FATAL, "Empty filename in command "
- "line stderr redirection.\n");
- return NULL;
- }
- tmp += ret;
- new_arg = 1;
- } else if (*tmp == '&' && *(tmp+1) == '>' && tmp++) {
- int ret;
- if (*++tmp == '>') {
- tmp++;
- data->stdout.flags = O_WRONLY|O_CREAT|O_APPEND;
- data->stderr.flags = O_WRONLY|O_CREAT|O_APPEND;
- } else {
- data->stdout.flags = O_WRONLY|O_CREAT|O_TRUNC;
- data->stderr.flags = O_WRONLY|O_CREAT|O_TRUNC;
- }
- if ((ret = get_word(data->stdout.file, tmp, PATH_MAX)) == 0) {
- specter_log(SPECTER_FATAL, "Empty filename in command "
- "line stdout redirection.\n");
- return NULL;
- }
- get_word(data->stderr.file, tmp, PATH_MAX);
- tmp += ret;
- new_arg = 1;
- } else if (*tmp == '<') {
- int ret;
- tmp++;
- data->stdin.flags = O_RDONLY;
- if ((ret = get_word(data->stdin.file, tmp, PATH_MAX)) == 0) {
- specter_log(SPECTER_FATAL, "Empty filename in command "
- "line stdin redirection.\n");
- return NULL;
- }
- tmp += ret;
- new_arg = 1;
- } else {
- if (new_arg || data->args[ctr-1].type == ARG_TYPE_IRET) {
- if (!new_arg) {
- data->args[ctr-1].type |= ATT_FLAG;
- }
- data->args[ctr].u.str = line;
- data->args[ctr].type = ARG_TYPE_STRING;
- if (++ctr == EXEC_MAX_ARGS) {
- specter_log(SPECTER_FATAL,
- "Command line has too many arguments.\n");
- return NULL;
- }
- new_arg = 0;
- }
- /* it's not a special character - rewrite it */
- *line++ = *tmp++;
- }
- }
-
- *line = '\0';
- data->args[ctr].type = ARG_TYPE_NONE;
+ struct my_data *data;
+ char *tmp, *line;
+ int ctr, new_arg;
+ struct stat st;
+
+ if ((data = malloc(sizeof(struct my_data))) == NULL) {
+ specter_log(SPECTER_FATAL, "Couldn't allocate data: %s.\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ memset(data, 0x0, sizeof(data));
+ tmp = GET_CE(ce,0)->u.string;
+ line = data->execline;
+ ctr = 0;
+ new_arg = 1;
+
+ /* divide execline into separate args */
+ while (*tmp) {
+ if (*tmp == ' ' || *tmp == '\t') {
+ while (*tmp == ' ' || *tmp == '\t')
+ tmp++;
+ *line++ = '\0';
+ new_arg = 1;
+ } else if (*tmp == '%' && *++tmp != '%') {
+ if (fill_tag(*tmp) == -1) {
+ specter_log(SPECTER_FATAL,
+ "Bad exec tag: \"%%%c\".\n", *tmp);
+ return NULL;
+ }
+ if (!new_arg) {
+ data->args[ctr-1].type |= ATT_FLAG;
+ *line++ = '\0';
+ }
+ data->args[ctr].u.c = *tmp++;
+ data->args[ctr].type = ARG_TYPE_IRET;
+ if (++ctr == EXEC_MAX_ARGS) {
+ specter_log(SPECTER_FATAL,
+ "Command line has too many arguments.\n");
+ return NULL;
+ }
+ new_arg = 0;
+ } else if ((*tmp == '>') || (*tmp == '1' && *(tmp+1) == '>' && tmp++)) {
+ int ret;
+ if (*++tmp == '>') {
+ tmp++;
+ data->stdout.flags = O_WRONLY|O_CREAT|O_APPEND;
+ } else {
+ data->stdout.flags = O_WRONLY|O_CREAT|O_TRUNC;
+ }
+ if ((ret = get_word(data->stdout.file, tmp, PATH_MAX)) == 0) {
+ specter_log(SPECTER_FATAL, "Empty filename in command "
+ "line stdout redirection.\n");
+ return NULL;
+ }
+ tmp += ret;
+ new_arg = 1;
+ } else if (*tmp == '2' && *(tmp+1) == '>' && tmp++) {
+ int ret;
+ if (*++tmp == '>') {
+ tmp++;
+ data->stderr.flags = O_WRONLY|O_CREAT|O_APPEND;
+ } else {
+ data->stderr.flags = O_WRONLY|O_CREAT|O_TRUNC;
+ }
+ if ((ret = get_word(data->stderr.file, tmp, PATH_MAX)) == 0) {
+ specter_log(SPECTER_FATAL, "Empty filename in command "
+ "line stderr redirection.\n");
+ return NULL;
+ }
+ tmp += ret;
+ new_arg = 1;
+ } else if (*tmp == '&' && *(tmp+1) == '>' && tmp++) {
+ int ret;
+ if (*++tmp == '>') {
+ tmp++;
+ data->stdout.flags = O_WRONLY|O_CREAT|O_APPEND;
+ data->stderr.flags = O_WRONLY|O_CREAT|O_APPEND;
+ } else {
+ data->stdout.flags = O_WRONLY|O_CREAT|O_TRUNC;
+ data->stderr.flags = O_WRONLY|O_CREAT|O_TRUNC;
+ }
+ if ((ret = get_word(data->stdout.file, tmp, PATH_MAX)) == 0) {
+ specter_log(SPECTER_FATAL, "Empty filename in command "
+ "line stdout redirection.\n");
+ return NULL;
+ }
+ get_word(data->stderr.file, tmp, PATH_MAX);
+ tmp += ret;
+ new_arg = 1;
+ } else if (*tmp == '<') {
+ int ret;
+ tmp++;
+ data->stdin.flags = O_RDONLY;
+ if ((ret = get_word(data->stdin.file, tmp, PATH_MAX)) == 0) {
+ specter_log(SPECTER_FATAL, "Empty filename in command "
+ "line stdin redirection.\n");
+ return NULL;
+ }
+ tmp += ret;
+ new_arg = 1;
+ } else {
+ if (new_arg || data->args[ctr-1].type == ARG_TYPE_IRET) {
+ if (!new_arg) {
+ data->args[ctr-1].type |= ATT_FLAG;
+ }
+ data->args[ctr].u.str = line;
+ data->args[ctr].type = ARG_TYPE_STRING;
+ if (++ctr == EXEC_MAX_ARGS) {
+ specter_log(SPECTER_FATAL,
+ "Command line has too many arguments.\n");
+ return NULL;
+ }
+ new_arg = 0;
+ }
+ /* it's not a special character - rewrite it */
+ *line++ = *tmp++;
+ }
+ }
+
+ *line = '\0';
+ data->args[ctr].type = ARG_TYPE_NONE;
#ifdef DEBUG
- for (ctr = 0; data->args[ctr].type != ARG_TYPE_NONE; ctr++) {
- printf("%i: ", ctr);
- if (data->args[ctr].type & ARG_TYPE_STRING)
- printf("string: %s", data->args[ctr].u.str);
- else
- printf("tag: %c", data->args[ctr].u.c);
- if (data->args[ctr].type & ATT_FLAG)
- printf(" <attached>");
- printf("\n");
- }
+ for (ctr = 0; data->args[ctr].type != ARG_TYPE_NONE; ctr++) {
+ printf("%i: ", ctr);
+ if (data->args[ctr].type & ARG_TYPE_STRING)
+ printf("string: %s", data->args[ctr].u.str);
+ else
+ printf("tag: %c", data->args[ctr].u.c);
+ if (data->args[ctr].type & ATT_FLAG)
+ printf(" <attached>");
+ printf("\n");
+ }
#endif
- if (data->args[0].type != ARG_TYPE_STRING) {
- specter_log(SPECTER_FATAL, "First argument of command should be a plain string.\n");
- return NULL;
- }
-
- /* check if file exists and is an executable */
- if (stat(data->args[0].u.str, &st) == -1) {
- tmp = getenv("PATH");
- while (1) {
- char command[256];
- char *t = strchr(tmp, ':');
- if (t)
- *t = '\0';
-
- /* prepend path to given command */
- snprintf(command, 255, "%s/%s", tmp, data->args[0].u.str);
-
- if ((stat(command, &st) != -1)
- && (st.st_mode & (S_IXOTH|S_IXGRP|S_IXUSR))
- && (st.st_mode & S_IFREG)) {
- data->args[0].u.str = strdup(command);
- data->free_command = 1;
- specter_log(SPECTER_DEBUG, "Command \"%s\" prepared.\n",
- data->args[0].u.str);
- return data;
- }
-
- if (t)
- tmp = t+1;
- else
- break;
- }
- } else {
- if (!(st.st_mode & (S_IXOTH|S_IXGRP|S_IXUSR)) || !(st.st_mode & S_IFREG)) {
- specter_log(SPECTER_FATAL, "\"%s\" isn't an executable.\n",
- data->args[0].u.str);
- return NULL;
- } else { /* everything's fine */
- specter_log(SPECTER_DEBUG, "Command \"%s\" prepared.\n",
- data->args[0].u.str);
- return data;
- }
- }
-
- /* strerror() will return error from last stat() */
- specter_log(SPECTER_FATAL, "Couldn't find executable \"%s\" in $PATH: %s.\n",
- data->args[0].u.str, strerror(errno));
- return NULL;
+ if (data->args[0].type != ARG_TYPE_STRING) {
+ specter_log(SPECTER_FATAL, "First argument of command should be a plain string.\n");
+ return NULL;
+ }
+
+ /* Handle child signals right away to prevent creation of zombie processes. */
+ application_name = data->args[0].u.str;
+ signal(SIGCHLD, &sigchld_hanlder);
+
+ /* check if file exists and is an executable */
+ if (stat(data->args[0].u.str, &st) == -1) {
+ tmp = getenv("PATH");
+ while (1) {
+ char command[256];
+ char *t = strchr(tmp, ':');
+ if (t)
+ *t = '\0';
+
+ /* prepend path to given command */
+ snprintf(command, 255, "%s/%s", tmp, data->args[0].u.str);
+
+ if ((stat(command, &st) != -1)
+ && (st.st_mode & (S_IXOTH|S_IXGRP|S_IXUSR))
+ && (st.st_mode & S_IFREG)) {
+ data->args[0].u.str = strdup(command);
+ data->free_command = 1;
+ specter_log(SPECTER_DEBUG, "Command \"%s\" prepared.\n",
+ data->args[0].u.str);
+ return data;
+ }
+
+ if (t)
+ tmp = t+1;
+ else
+ break;
+ }
+ } else {
+ if (!(st.st_mode & (S_IXOTH|S_IXGRP|S_IXUSR)) || !(st.st_mode & S_IFREG)) {
+ specter_log(SPECTER_FATAL, "\"%s\" isn't an executable.\n",
+ data->args[0].u.str);
+ return NULL;
+ } else { /* everything's fine */
+ specter_log(SPECTER_DEBUG, "Command \"%s\" prepared.\n",
+ data->args[0].u.str);
+ return data;
+ }
+ }
+
+ /* strerror() will return error from last stat() */
+ specter_log(SPECTER_FATAL, "Couldn't find executable \"%s\" in $PATH: %s.\n",
+ data->args[0].u.str, strerror(errno));
+ return NULL;
}
@@ -468,172 +481,161 @@
static int exec_output(config_entry_t *ce, void *data)
{
- static char buff[LOCAL_RET_NUM][EXEC_ARG_SPACE];
- static char *argv[EXEC_MAX_ARGS+1];
- char *curr_buf = buff[0];
- int ctr, status, ret, use_buf;
- int buff_ctr, argv_ctr;
- struct my_data *md = data;
-
- /* first check if any previously executed children returned */
- while ((ret = waitpid(-1, &status, WNOHANG)) > 0) {
- check_status(md->args[0].u.str, ret, status);
- }
-
- /* resolve tags */
- buff_ctr = argv_ctr = use_buf = 0;
- curr_buf = buff[0];
- for (ctr = 0; md->args[ctr].type != ARG_TYPE_NONE; ctr++) {
-
- if (buff_space_left <= 0) {
- specter_log(SPECTER_ERROR, "Argument too long.\n");
- return 0;
- }
-
- if (md->args[ctr].type & ARG_TYPE_IRET) {
- specter_iret_t *iret;
-
- if (buff_ctr == LOCAL_RET_NUM) {
- specter_log(SPECTER_ERROR, "No space for arguments.\n");
- return -1;
- }
-
- if ((iret = find_tag(md->args[ctr].u.c)) == NULL) {
- /* should never happen due to checks in exec_init() */
- specter_log(SPECTER_ERROR,
- "Unknown tag: %c.\n", md->args[ctr].u.c);
- return -1;
- }
-
- if ((ret = fill_arg(curr_buf, iret, buff_space_left)) == -1) {
- if (GET_CE(ce,2)->u.value) {
- strncat(curr_buf, "invalid", buff_space_left);
- curr_buf += 7;
- } else {
- specter_log(SPECTER_DEBUG, "Required key \"%s\" invalid.\n",
- iret->name);
- return 0;
- }
- } else {
- curr_buf += ret;
- }
-
- use_buf = 1;
- } else if (md->args[ctr].type & ARG_TYPE_STRING) {
- if ((md->args[ctr-1].type & ATT_FLAG)
- || (md->args[ctr].type & ATT_FLAG)) {
- strncpy(curr_buf, md->args[ctr].u.str, buff_space_left);
- curr_buf += strlen(md->args[ctr].u.str);
- }
- else {
- argv[argv_ctr++] = md->args[ctr].u.str;
- }
- }
-
- if (!(md->args[ctr].type & ATT_FLAG) && use_buf) {
- argv[argv_ctr++] = buff[buff_ctr];
- curr_buf = buff[++buff_ctr];
- use_buf = 0;
- }
- }
-
- specter_log(SPECTER_DEBUG, "Executing command \"%s\".\n", argv[0]);
-
- /* execute */
- ret = fork();
- if (ret == -1) {
- specter_log(SPECTER_ERROR, "Couldn't fork(): %s.\n",
- strerror(errno));
- return 0;
- } else if (ret) { /* parent */
- if (GET_CE(ce,1)->u.value) {
- if (waitpid(ret, &status, 0x0) != -1)
- check_status(argv[0], ret, status);
- }
- } else { /* child */
- static char *envp[] = { NULL };
- int fd;
-
- /* delete specter's signal handlers */
- signal(SIGTERM, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
-
- /* handle redirections */
- if (md->stdin.file[0] != '\0') {
- if ((fd = open(md->stdin.file, md->stdin.flags)) == -1) {
- specter_log(SPECTER_ERROR, "Error opening file \"%s\": %s.\n",
- md->stdin.file, strerror(errno));
- exit(1);
- }
- if (dup2(fd, 0) == -1) {
- specter_log(SPECTER_ERROR, "Error redirecting stdin stream: %s.\n",
- strerror(errno));
- exit(1);
- }
- }
- if (md->stdout.file[0] != '\0') {
- if ((fd = open(md->stdout.file, md->stdout.flags, S_IRUSR|S_IWUSR)) == -1) {
- specter_log(SPECTER_ERROR, "Error opening file \"%s\": %s.\n",
- md->stdout.file, strerror(errno));
- exit(1);
- }
- if (dup2(fd, 1) == -1) {
- specter_log(SPECTER_ERROR, "Error redirecting stdout stream: %s.\n",
- strerror(errno));
- exit(1);
- }
- }
- if (md->stderr.file[0] != '\0') {
- if ((fd = open(md->stderr.file, md->stderr.flags, S_IRUSR|S_IWUSR)) == -1) {
- specter_log(SPECTER_ERROR, "Error opening file \"%s\": %s.\n",
- md->stderr.file, strerror(errno));
- exit(1);
- }
- if (dup2(fd, 2) == -1) {
- specter_log(SPECTER_ERROR, "Error redirecting stderr stream: %s.\n",
- strerror(errno));
- exit(1);
- }
- }
-
- /* finally execute command */
- if (GET_CE(ce,3)->u.value) {
- if (execve(argv[0], argv, environ) == -1) {
- specter_log(SPECTER_ERROR, "Couldn't execve(): %s.\n",
- strerror(errno));
- exit(1);
- }
- } else {
- if (execve(argv[0], argv, envp) == -1) {
- specter_log(SPECTER_ERROR, "Couldn't execve(): %s.\n",
- strerror(errno));
- exit(1);
- }
- }
- }
-
- return 0;
+ static char buff[LOCAL_RET_NUM][EXEC_ARG_SPACE];
+ static char *argv[EXEC_MAX_ARGS+1];
+ char *curr_buf = buff[0];
+ int ctr, status, ret, use_buf;
+ int buff_ctr, argv_ctr;
+ struct my_data *md = data;
+
+ /* resolve tags */
+ buff_ctr = argv_ctr = use_buf = 0;
+ curr_buf = buff[0];
+ for (ctr = 0; md->args[ctr].type != ARG_TYPE_NONE; ctr++) {
+
+ if (buff_space_left <= 0) {
+ specter_log(SPECTER_ERROR, "Argument too long.\n");
+ return 0;
+ }
+
+ if (md->args[ctr].type & ARG_TYPE_IRET) {
+ specter_iret_t *iret;
+
+ if (buff_ctr == LOCAL_RET_NUM) {
+ specter_log(SPECTER_ERROR, "No space for arguments.\n");
+ return -1;
+ }
+
+ if ((iret = find_tag(md->args[ctr].u.c)) == NULL) {
+ /* should never happen due to checks in exec_init() */
+ specter_log(SPECTER_ERROR,
+ "Unknown tag: %c.\n", md->args[ctr].u.c);
+ return -1;
+ }
+
+ if ((ret = fill_arg(curr_buf, iret, buff_space_left)) == -1) {
+ if (GET_CE(ce,2)->u.value) {
+ strncat(curr_buf, "invalid", buff_space_left);
+ curr_buf += 7;
+ } else {
+ specter_log(SPECTER_DEBUG, "Required key \"%s\" invalid.\n",
+ iret->name);
+ return 0;
+ }
+ } else {
+ curr_buf += ret;
+ }
+
+ use_buf = 1;
+ } else if (md->args[ctr].type & ARG_TYPE_STRING) {
+ if ((md->args[ctr-1].type & ATT_FLAG)
+ || (md->args[ctr].type & ATT_FLAG)) {
+ strncpy(curr_buf, md->args[ctr].u.str, buff_space_left);
+ curr_buf += strlen(md->args[ctr].u.str);
+ }
+ else {
+ argv[argv_ctr++] = md->args[ctr].u.str;
+ }
+ }
+
+ if (!(md->args[ctr].type & ATT_FLAG) && use_buf) {
+ argv[argv_ctr++] = buff[buff_ctr];
+ curr_buf = buff[++buff_ctr];
+ use_buf = 0;
+ }
+ }
+
+ specter_log(SPECTER_DEBUG, "Executing command \"%s\".\n", argv[0]);
+
+ /* execute */
+ ret = fork();
+ if (ret == -1) {
+ specter_log(SPECTER_ERROR, "Couldn't fork(): %s.\n",
+ strerror(errno));
+ return 0;
+ } else if (ret == 0) { /* child */
+ static char *envp[] = { NULL };
+ int fd;
+
+ /* delete specter's signal handlers */
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+
+ /* handle redirections */
+ if (md->stdin.file[0] != '\0') {
+ if ((fd = open(md->stdin.file, md->stdin.flags)) == -1) {
+ specter_log(SPECTER_ERROR, "Error opening file \"%s\": %s.\n",
+ md->stdin.file, strerror(errno));
+ exit(1);
+ }
+ if (dup2(fd, 0) == -1) {
+ specter_log(SPECTER_ERROR, "Error redirecting stdin stream: %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+ if (md->stdout.file[0] != '\0') {
+ if ((fd = open(md->stdout.file, md->stdout.flags, S_IRUSR|S_IWUSR)) == -1) {
+ specter_log(SPECTER_ERROR, "Error opening file \"%s\": %s.\n",
+ md->stdout.file, strerror(errno));
+ exit(1);
+ }
+ if (dup2(fd, 1) == -1) {
+ specter_log(SPECTER_ERROR, "Error redirecting stdout stream: %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+ if (md->stderr.file[0] != '\0') {
+ if ((fd = open(md->stderr.file, md->stderr.flags, S_IRUSR|S_IWUSR)) == -1) {
+ specter_log(SPECTER_ERROR, "Error opening file \"%s\": %s.\n",
+ md->stderr.file, strerror(errno));
+ exit(1);
+ }
+ if (dup2(fd, 2) == -1) {
+ specter_log(SPECTER_ERROR, "Error redirecting stderr stream: %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* finally execute command */
+ if (GET_CE(ce,3)->u.value) {
+ if (execve(argv[0], argv, environ) == -1) {
+ specter_log(SPECTER_ERROR, "Couldn't execve(): %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ } else {
+ if (execve(argv[0], argv, envp) == -1) {
+ specter_log(SPECTER_ERROR, "Couldn't execve(): %s.\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+ }
+
+ return 0;
}
#undef buff_space_left
static specter_output_t exec_op = {
- .name = "exec",
- .ce_base = my_config,
- .ce_num = 4,
- .init = &exec_init,
- .fini = &exec_fini,
- .output = &exec_output,
+ .name = "exec",
+ .ce_base = my_config,
+ .ce_num = 4,
+ .init = &exec_init,
+ .fini = &exec_fini,
+ .output = &exec_output,
};
void _init(void)
{
- if (register_output(&exec_op, 0) == -1) {
- specter_log(SPECTER_FATAL, "Can't register.\n");
- exit(EXIT_FAILURE);
- }
+ if (register_output(&exec_op, 0) == -1) {
+ specter_log(SPECTER_FATAL, "Can't register.\n");
+ exit(EXIT_FAILURE);
+ }
}
-