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.
1120 lines
33 KiB
1120 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); |
|
+ } |
|
} |
|
- |
|
|
|
|