summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDug Song <dugsong@cvs.openbsd.org>2000-06-25 08:40:00 +0000
committerDug Song <dugsong@cvs.openbsd.org>2000-06-25 08:40:00 +0000
commite90bdebbd82312254d4a139079a52719804aa3e4 (patch)
treed86005dbe483efbdbd94acafc28a81b7e995926d
parentd95d2c530183e0aaa130cacc98107bbde3634ac5 (diff)
pass variables to dhclient-script via a constructed environment, instead of a temporary shell script
-rw-r--r--usr.sbin/dhcp/dhclient/dhclient.c192
1 files changed, 116 insertions, 76 deletions
diff --git a/usr.sbin/dhcp/dhclient/dhclient.c b/usr.sbin/dhcp/dhclient/dhclient.c
index ab4c9ccfe21..f0796d8e3d0 100644
--- a/usr.sbin/dhcp/dhclient/dhclient.c
+++ b/usr.sbin/dhcp/dhclient/dhclient.c
@@ -56,7 +56,7 @@
#ifndef lint
static char copyright[] =
-"$Id: dhclient.c,v 1.7 1999/12/04 00:15:09 angelos Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+"$Id: dhclient.c,v 1.8 2000/06/25 08:39:59 dugsong Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -91,7 +91,6 @@ u_int16_t local_port;
u_int16_t remote_port;
int log_priority;
int no_daemon;
-int save_scripts;
int onetry;
static void usage PROTO ((void));
@@ -124,8 +123,6 @@ int main (argc, argv, envp)
ntohs (local_port));
} else if (!strcmp (argv [i], "-d")) {
no_daemon = 1;
- } else if (!strcmp (argv [i], "-D")) {
- save_scripts = 1;
} else if (!strcmp (argv [i], "-1")) {
onetry = 1;
} else if (argv [i][0] == '-') {
@@ -1771,47 +1768,76 @@ void write_client_lease (ip, lease)
/* Variables holding name of script and file pointer for writing to
script. Needless to say, this is not reentrant - only one script
can be invoked at a time. */
-char scriptName [256];
-FILE *scriptFile;
+char **scriptEnv = NULL;
+int scriptEnvsize = 0;
+
+void script_set_env (name, value)
+ char *name;
+ char *value;
+{
+ int i, namelen;
+
+ namelen = strlen(name);
+
+ for (i = 0; scriptEnv[i]; i++) {
+ if (strncmp(scriptEnv[i], name, namelen) == 0 &&
+ scriptEnv[i][namelen] == '=')
+ break;
+ }
+ if (scriptEnv[i]) {
+ /* Reuse the slot. */
+ free(scriptEnv[i]);
+ } else {
+ /* New variable. Expand if necessary. */
+ if (i >= scriptEnvsize - 1) {
+ scriptEnvsize += 50;
+ scriptEnv = realloc(scriptEnv, scriptEnvsize);
+ if (scriptEnv == NULL)
+ error("script_set_env: no memory for variable");
+ }
+ /* Need to set the NULL pointer at end of array beyond
+ the new slot. */
+ scriptEnv[i + 1] = NULL;
+ }
+ /* Allocate space and format the variable in the appropriate slot. */
+ scriptEnv[i] = malloc(strlen(name) + 1 + strlen(value) + 1);
+ if (scriptEnv[i] == NULL)
+ error("script_set_env: no memory for variable assignment");
+
+ snprintf(scriptEnv[i], strlen(name) + 1 + strlen(value) + 1,
+ "%s=%s", name, value);
+}
+
+void script_flush_env()
+{
+ int i;
+
+ for (i = 0; scriptEnv[i]; i++) {
+ free(scriptEnv[i]);
+ scriptEnv[i] = NULL;
+ }
+}
void script_init (ip, reason, medium)
struct interface_info *ip;
char *reason;
struct string_list *medium;
{
- int fd;
-#ifndef HAVE_MKSTEMP
+ scriptEnvsize = 100;
+ scriptEnv = malloc(scriptEnvsize * sizeof(char *));
- do {
-#endif
- strcpy (scriptName, "/tmp/dcsXXXXXX");
-#ifdef HAVE_MKSTEMP
- fd = mkstemp (scriptName);
-#else
- mktemp (scriptName);
- fd = creat (scriptName, 0600);
- } while (fd < 0);
-#endif
+ if (scriptEnv == NULL)
+ error ("script_init: no memory for environment initialization");
+
+ scriptEnv[0] = NULL;
-#ifdef HAVE_MKSTEMP
- if (fd == -1)
- error ("can't write script file: %m");
-#endif
-
- scriptFile = fdopen (fd, "w");
- if (!scriptFile)
- error ("can't write script file: %m");
- fprintf (scriptFile, "#!/bin/sh\n\n");
if (ip) {
- fprintf (scriptFile, "interface=\"%s\"\n", ip -> name);
- fprintf (scriptFile, "export interface\n");
+ script_set_env ("interface", ip -> name);
}
if (medium) {
- fprintf (scriptFile, "medium=\"%s\"\n", medium -> string);
- fprintf (scriptFile, "export medium\n");
+ script_set_env ("medium", medium -> string);
}
- fprintf (scriptFile, "reason=\"%s\"\n", reason);
- fprintf (scriptFile, "export reason\n");
+ script_set_env ("reason", reason);
}
void script_write_params (ip, prefix, lease)
@@ -1821,11 +1847,11 @@ void script_write_params (ip, prefix, lease)
{
int i;
u_int8_t dbuf [1500];
+ char name[1024], value[1024];
int len;
- fprintf (scriptFile, "%sip_address=\"%s\"\n",
- prefix, piaddr (lease -> address));
- fprintf (scriptFile, "export %sip_address\n", prefix);
+ snprintf (name, sizeof(name), "%sip_address", prefix);
+ script_set_env (name, piaddr (lease -> address));
/* For the benefit of Linux (and operating systems which may
have similar needs), compute the network address based on
@@ -1843,42 +1869,37 @@ void script_write_params (ip, prefix, lease)
lease -> options [DHO_SUBNET_MASK].data,
lease -> options [DHO_SUBNET_MASK].len);
netmask.len = lease -> options [DHO_SUBNET_MASK].len;
-
+
subnet = subnet_number (lease -> address, netmask);
if (subnet.len) {
- fprintf (scriptFile, "%snetwork_number=\"%s\";\n",
- prefix, piaddr (subnet));
- fprintf (scriptFile, "export %snetwork_number\n",
- prefix);
-
+ snprintf (name, sizeof(name), "%snetwork_number",
+ prefix);
+ script_set_env (name, piaddr (subnet));
+
if (!lease -> options [DHO_BROADCAST_ADDRESS].len) {
broadcast = broadcast_addr (subnet, netmask);
if (broadcast.len) {
- fprintf (scriptFile,
- "%s%s=\"%s\";\n", prefix,
- "broadcast_address",
- piaddr (broadcast));
- fprintf (scriptFile,
- "export %s%s\n", prefix,
- "broadcast_address");
+ snprintf (name, sizeof(name),
+ "%sbroadcast_address",
+ prefix);
+ script_set_env (name,
+ piaddr (broadcast));
}
}
}
}
-
+
if (lease -> filename) {
- fprintf (scriptFile, "%sfilename=\"%s\";\n",
- prefix, lease -> filename);
- fprintf (scriptFile, "export %sfilename\n", prefix);
+ snprintf (name, sizeof(name), "%sfilename", prefix);
+ script_set_env (name, lease -> filename);
}
if (lease -> server_name) {
- fprintf (scriptFile, "%sserver_name=\"%s\";\n",
- prefix, lease -> server_name);
- fprintf (scriptFile, "export %sserver_name\n", prefix);
+ snprintf (name, sizeof(name), "%sserver_name", prefix);
+ script_set_env (name, lease -> server_name);
}
for (i = 0; i < 256; i++) {
u_int8_t *dp;
-
+
if (ip -> client -> config -> defaults [i].len) {
if (lease -> options [i].len) {
switch (ip -> client ->
@@ -1948,35 +1969,54 @@ void script_write_params (ip, prefix, lease)
}
if (len) {
char *s = dhcp_option_ev_name (&dhcp_options [i]);
-
- fprintf (scriptFile, "%s%s=\"%s\"\n", prefix, s,
- pretty_print_option (i, dp, len, 0, 0));
- fprintf (scriptFile, "export %s%s\n", prefix, s);
+
+ snprintf (name, sizeof(name), "%s%s", prefix, s);
+ script_set_env (name, pretty_print_option (i, dp, len, 0, 0));
}
}
- fprintf (scriptFile, "%sexpiry=\"%d\"\n",
- prefix, (int)lease -> expiry); /* XXX */
- fprintf (scriptFile, "export %sexpiry\n", prefix);
+ snprintf (name, sizeof(name), "%sexpiry", prefix);
+ snprintf (value, sizeof(value), "%d", (int)lease -> expiry); /* XXX */
+ script_set_env (name, value);
}
int script_go (ip)
struct interface_info *ip;
{
- int rval;
+ char *p, *script_name, *script_argv[2];
+ pid_t pid, wait_pid;
+ int status;
if (ip)
- fprintf (scriptFile, "%s\n",
- ip -> client -> config -> script_name);
+ script_name = ip -> client -> config -> script_name;
+ else
+ script_name = top_level_config.script_name;
+
+ if ((p = strrchr(script_name, '/')) != NULL)
+ p++;
else
- fprintf (scriptFile, "%s\n",
- top_level_config.script_name);
- fprintf (scriptFile, "exit $?\n");
- fclose (scriptFile);
- chmod (scriptName, 0700);
- rval = system (scriptName);
- if (!save_scripts)
- unlink (scriptName);
- return rval;
+ p = script_name;
+
+ script_argv[0] = p;
+ script_argv[1] = NULL;
+
+ if ((pid = fork()) < 0)
+ error("Can't fork script: %m");
+
+ if (pid == 0) {
+ execve(script_name, script_argv, scriptEnv);
+ error("script_go: exec: %m");
+ }
+ script_flush_env();
+
+ wait_pid = wait((int *) &status);
+
+ if (wait_pid != -1) {
+ if (wait_pid != pid)
+ error ("got wrong pid");
+ if (WIFEXITED(status) || WIFSIGNALED(status))
+ return (WEXITSTATUS(status));
+ }
+ return (-1);
}
char *dhcp_option_ev_name (option)