summaryrefslogtreecommitdiff
path: root/common/execute.c
diff options
context:
space:
mode:
authorEvan Hunt <each@isc.org>2007-02-08 20:38:49 +0000
committerEvan Hunt <each@isc.org>2007-02-08 20:38:49 +0000
commitacf073b2de2a5e9d13b9474eae017f28b2dbb44b (patch)
tree731b2558e8988810a53d3d1b619f6857cd0df68c /common/execute.c
parent4d3b06b208294a383525b307416e1cca616a3138 (diff)
downloadisc-dhcp-acf073b2de2a5e9d13b9474eae017f28b2dbb44b.tar.gz
The execute() statement has been changed from a "numeric expression" to
an "executable statement", so that it can now be used with the syntax "execute(cmd, arg, ...)" rather than "eval(execute(cmd, arg, ...))". [rt16620]
Diffstat (limited to 'common/execute.c')
-rw-r--r--common/execute.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/common/execute.c b/common/execute.c
index a5fc03a4..efcb39cc 100644
--- a/common/execute.c
+++ b/common/execute.c
@@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
-"$Id: execute.c,v 1.48 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: execute.c,v 1.48.116.1 2007/02/08 20:38:48 each Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -188,6 +188,86 @@ int execute_statements (result, packet, lease, client_state,
#endif
break;
+ case execute_statement: {
+#ifdef ENABLE_EXECUTE
+ struct expression *expr;
+ char **argv;
+ int i, argc = r->data.execute.argc;
+ pid_t p;
+
+ /* save room for the command and the NULL terminator */
+ argv = dmalloc((argc + 2) * sizeof(*argv), MDL);
+ if (!argv)
+ break;
+
+ argv[0] = dmalloc(strlen(r->data.execute.command) + 1,
+ MDL);
+ if (argv[0]) {
+ strcpy(argv[0], r->data.execute.command);
+ } else {
+ goto execute_out;
+ }
+
+ log_debug("execute_statement argv[0] = %s", argv[0]);
+
+ for (i = 1, expr = r->data.execute.arglist; expr;
+ expr = expr->data.arg.next, i++) {
+ memset (&ds, 0, sizeof(ds));
+ status = (evaluate_data_expression
+ (&ds, packet,
+ lease, client_state, in_options,
+ out_options, scope,
+ expr->data.arg.val, MDL));
+ if (status) {
+ argv[i] = dmalloc(ds.len + 1, MDL);
+ if (argv[i]) {
+ memcpy(argv[i], ds.data,
+ ds.len);
+ argv[i][ds.len] = 0;
+ log_debug("execute_statement argv[%d] = %s", i, argv[i]);
+ }
+ data_string_forget (&ds, MDL);
+ if (!argv[i]) {
+ log_debug("execute_statement failed argv[%d]", i);
+ goto execute_out;
+ }
+ } else {
+ log_debug("execute: bad arg %d", i);
+ goto execute_out;
+ }
+ }
+ argv[i] = NULL;
+
+ if ((p = fork()) > 0) {
+ int status;
+ waitpid(p, &status, 0);
+
+ if (status) {
+ log_error("execute: %s exit status %d",
+ argv[0], status);
+ }
+ } else if (p == 0) {
+ execvp(argv[0], argv);
+ log_error("Unable to execute %s: %m", argv[0]);
+ _exit(127);
+ } else {
+ log_error("execute: fork() failed");
+ }
+
+ execute_out:
+ for (i = 0; i <= argc; i++) {
+ if(argv[i])
+ dfree(argv[i], MDL);
+ }
+
+ dfree(argv, MDL);
+#else /* !ENABLE_EXECUTE */
+ log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
+ "is not defined).", MDL);
+#endif /* ENABLE_EXECUTE */
+ break;
+ }
+
case return_statement:
status = evaluate_expression
(result, packet,
@@ -624,6 +704,14 @@ int executable_statement_dereference (ptr, file, line)
dfree ((*ptr)->data.unset, file, line);
break;
+ case execute_statement:
+ if ((*ptr)->data.execute.command)
+ dfree ((*ptr)->data.execute.command, file, line);
+ if ((*ptr)->data.execute.arglist)
+ expression_dereference (&(*ptr) -> data.execute.arglist,
+ file, line);
+ break;
+
case supersede_option_statement:
case send_option_statement:
case default_option_statement:
@@ -650,6 +738,7 @@ void write_statements (file, statements, indent)
int indent;
{
struct executable_statement *r, *x;
+ struct expression *expr;
int result;
int status;
const char *s, *t, *dot;
@@ -882,6 +971,25 @@ void write_statements (file, statements, indent)
"", "", ");");
break;
+
+ case execute_statement:
+#ifdef ENABLE_EXECUTE
+ indent_spaces (file, indent);
+ col = token_print_indent(file, col, indent + 4, "", "",
+ "execute");
+ col = token_print_indent(file, col, indent + 4, " ", "",
+ "(");
+ col = token_print_indent(file, col, indent + 4, "\"", "\"", r->data.execute.command);
+ for (expr = r->data.execute.arglist; expr; expr = expr->data.arg.next) {
+ col = token_print_indent(file, col, indent + 4, "", " ", ",");
+ col = write_expression (file, expr->data.arg.val, col, indent + 4, 0);
+ }
+ col = token_print_indent(file, col, indent + 4, "", "", ");");
+#else /* !ENABLE_EXECUTE */
+ log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
+ "is not defined).", MDL);
+#endif /* ENABLE_EXECUTE */
+ break;
default:
log_fatal ("bogus statement type %d\n", r -> op);
@@ -1047,6 +1155,7 @@ int executable_statement_foreach (struct executable_statement *stmt,
break;
case log_statement:
case return_statement:
+ case execute_statement:
break;
}
}