From 15dfda2819dc2b56c81d0438268fb8481b7e973b Mon Sep 17 00:00:00 2001 From: Christian Wiese Date: Thu, 17 Mar 2011 01:41:24 +0100 Subject: [PATCH] specter: integrated important patches from upstream --- ...-0001-postgres-plugin-initialization.patch | 33 + .../specter-1.4-0002-SQL-boolean.patch | 45 + .../specter-1.4-0003-EXEC-plugin-zombie.patch | 1120 +++++++++++++++++ .../specter/specter-1.4-0004-PATH_MAX.patch | 31 + 4 files changed, 1229 insertions(+) create mode 100644 network/specter/specter-1.4-0001-postgres-plugin-initialization.patch create mode 100644 network/specter/specter-1.4-0002-SQL-boolean.patch create mode 100644 network/specter/specter-1.4-0003-EXEC-plugin-zombie.patch create mode 100644 network/specter/specter-1.4-0004-PATH_MAX.patch diff --git a/network/specter/specter-1.4-0001-postgres-plugin-initialization.patch b/network/specter/specter-1.4-0001-postgres-plugin-initialization.patch new file mode 100644 index 000000000..a3f1ea1fb --- /dev/null +++ b/network/specter/specter-1.4-0001-postgres-plugin-initialization.patch @@ -0,0 +1,33 @@ +# --- SDE-COPYRIGHT-NOTE-BEGIN --- +# This copyright note is auto-generated by ./scripts/Create-CopyPatch. +# +# Filename: package/.../specter/specter-1.4-0001-postgres-plugin-initialization.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: Fixed postgres plugin initialization +Origin: Upstream (http://bazaar.launchpad.net/~ruby/specter/trunk/diff/2) + +=== modified file 'plugins/specter_PGSQL.c' +--- specter-1.4/plugins/specter_PGSQL.c 2008-01-06 17:26:23 +0000 ++++ specter-1.4/plugins/specter_PGSQL.c 2008-01-07 00:13:54 +0000 +@@ -73,7 +73,8 @@ + + strlen(GET_CE(ce,1)->u.string) + + strlen(GET_CE(ce,2)->u.string) + + strlen(GET_CE(ce,3)->u.string) +- + (GET_CE(ce,6)->u.value) ? 13 : 0; ++ + ((GET_CE(ce,6)->u.value) ? 13 : 0) ++ + strlen(GET_CE(ce,7)->u.string); + if ((initbuff = malloc(initlen)) == NULL) { + specter_log(SPECTER_FATAL, "Couldn't allocate data: %s.\n", + strerror(errno)); + diff --git a/network/specter/specter-1.4-0002-SQL-boolean.patch b/network/specter/specter-1.4-0002-SQL-boolean.patch new file mode 100644 index 000000000..66439d897 --- /dev/null +++ b/network/specter/specter-1.4-0002-SQL-boolean.patch @@ -0,0 +1,45 @@ +# --- SDE-COPYRIGHT-NOTE-BEGIN --- +# This copyright note is auto-generated by ./scripts/Create-CopyPatch. +# +# Filename: package/.../specter/specter-1.4-0002-SQL-boolean.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: Fixed SQL to use 'True' and 'False' for saving boolean values +Origin: Upstream (http://bazaar.launchpad.net/~ruby/specter/trunk/diff/4) + +=== modified file 'plugins/sql.c' +--- specter-1.4/plugins/sql.c 2008-01-06 17:26:23 +0000 ++++ specter-1.4/plugins/sql.c 2008-01-07 00:22:02 +0000 +@@ -126,9 +126,9 @@ + size_min += 16; + size_avg += 20; /* 18446744073709551615 */ + break; +- case SPECTER_IRET_BOOL: +- size_min++; +- size_avg++; ++ case SPECTER_IRET_BOOL: /* string "True" of "False" */ ++ size_min += 5; ++ size_avg += 5; + break; + case SPECTER_IRET_STRING: + size_min += 64; +@@ -265,7 +265,7 @@ + break; + case SPECTER_IRET_BOOL: + buff += snprintf(buff, buff_end-buff, +- "%i,", f->iret->value.b); ++ f->iret->value.b ? "True, " : "False,"); + break; + case SPECTER_IRET_STRING: + /* check if string is empty */ + diff --git a/network/specter/specter-1.4-0003-EXEC-plugin-zombie.patch b/network/specter/specter-1.4-0003-EXEC-plugin-zombie.patch new file mode 100644 index 000000000..b3f2a685a --- /dev/null +++ b/network/specter/specter-1.4-0003-EXEC-plugin-zombie.patch @@ -0,0 +1,1120 @@ +# --- 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 ++ * (C) 2004-2005,2008 by Michal Kwiatkowski + */ + + /* + * 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(" "); +- 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(" "); ++ 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); ++ } + } +- + diff --git a/network/specter/specter-1.4-0004-PATH_MAX.patch b/network/specter/specter-1.4-0004-PATH_MAX.patch new file mode 100644 index 000000000..2308c6f21 --- /dev/null +++ b/network/specter/specter-1.4-0004-PATH_MAX.patch @@ -0,0 +1,31 @@ +# --- SDE-COPYRIGHT-NOTE-BEGIN --- +# This copyright note is auto-generated by ./scripts/Create-CopyPatch. +# +# Filename: package/.../specter/specter-1.4-0004-PATH_MAX.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: Added limits.h include to specter.h, as we use PATH_MAX +Origin: Upstream (http://bazaar.launchpad.net/~ruby/specter/trunk/diff/12) + +=== modified file 'include/specter/specter.h' +--- specter-1.4/include/specter/specter.h 2008-02-25 01:34:02 +0000 ++++ specter-1.4/include/specter/specter.h 2008-06-17 09:15:14 +0000 +@@ -12,6 +12,7 @@ + #ifndef _SPECTER_H + #define _SPECTER_H + ++#include + #include + #include + #include +