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
1121 lines
33 KiB
14 years ago
|
# --- 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);
|
||
|
+ }
|
||
|
}
|
||
|
-
|
||
|
|