X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fscript.c;h=d4db8894de860b0b5a40010d7ccb5a05409c2430;hp=6389cb4b19ca0559a9c74373e0c83f7d30b598e8;hb=c2dc3784f127ef6db6e9960a4abecc1aab6f4e31;hpb=19e42b76f546dc3baee4a5d6a4f161155d279c74 diff --git a/src/script.c b/src/script.c index 6389cb4b..d4db8894 100644 --- a/src/script.c +++ b/src/script.c @@ -1,7 +1,7 @@ /* script.c -- call an external script Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2015 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,21 +26,59 @@ #include "script.h" #include "xalloc.h" +#ifdef HAVE_PUTENV +static void unputenv(const char *p) { + const char *e = strchr(p, '='); + if(!e) + return; + int len = e - p; +#ifndef HAVE_UNSETENV +#ifdef HAVE_MINGW + // Windows requires putenv("FOO=") to unset %FOO% + len++; +#endif +#endif + char var[len + 1]; + strncpy(var, p, len); + var[len] = 0; +#ifdef HAVE_UNSETENV + unsetenv(var); +#else + // We must keep what we putenv() around in memory. + // To do this without memory leaks, keep things in a list and reuse if possible. + static list_t list = {}; + for list_each(char, data, &list) { + if(!strcmp(data, var)) { + putenv(data); + return; + } + } + char *data = xstrdup(var); + list_insert_tail(&list, data); + putenv(data); +#endif +} +#else +static void putenv(const char *p) {} +static void unputenv(const char *p) {} +#endif + bool execute_script(const char *name, char **envp) { -#ifdef HAVE_SYSTEM - char *scriptname; + char scriptname[PATH_MAX]; char *command; - xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension); + snprintf(scriptname, sizeof scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension); /* First check if there is a script */ #ifdef HAVE_MINGW if(!*scriptextension) { const char *pathext = getenv("PATHEXT") ?: ".COM;.EXE;.BAT;.CMD"; - char fullname[strlen(scriptname) + strlen(pathext)]; - char *ext = fullname + strlen(scriptname); - strcpy(fullname, scriptname); + size_t pathlen = strlen(pathext); + size_t scriptlen = strlen(scriptname); + char fullname[scriptlen + pathlen + 1]; + char *ext = fullname + scriptlen; + strncpy(fullname, scriptname, sizeof fullname); const char *p = pathext; bool found = false; @@ -51,32 +89,26 @@ bool execute_script(const char *name, char **envp) { ext[q - p] = 0; q++; } else { - strcpy(ext, p); + strncpy(ext, p, pathlen + 1); } if((found = !access(fullname, F_OK))) break; p = q; } - if(!found) { - free(scriptname); + if(!found) return true; - } } else #endif - if(access(scriptname, F_OK)) { - free(scriptname); + if(access(scriptname, F_OK)) return true; - } logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name); -#ifdef HAVE_PUTENV /* Set environment */ for(int i = 0; envp[i]; i++) putenv(envp[i]); -#endif if(scriptinterpreter) xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname); @@ -86,19 +118,11 @@ bool execute_script(const char *name, char **envp) { int status = system(command); free(command); - free(scriptname); /* Unset environment */ - for(int i = 0; envp[i]; i++) { - char *e = strchr(envp[i], '='); - if(e) { - char p[e - envp[i] + 1]; - strncpy(p, envp[i], e - envp[i]); - p[e - envp[i]] = '\0'; - putenv(p); - } - } + for(int i = 0; envp[i]; i++) + unputenv(envp[i]); if(status != -1) { #ifdef WEXITSTATUS @@ -121,6 +145,6 @@ bool execute_script(const char *name, char **envp) { logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno)); return false; } -#endif + return true; }