diff --git a/src/Makefile.am b/src/Makefile.am index 2738008b..96643524 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,6 +55,7 @@ tincd_SOURCES = \ route.c route.h \ rsa.h \ rsagen.h \ + script.c script.h \ splay_tree.c splay_tree.h \ sptps.c sptps.h \ subnet.c subnet.h \ @@ -73,6 +74,7 @@ tinc_SOURCES = \ list.c list.h \ names.c names.h \ netutl.c netutl.h \ + script.c script.h \ sptps.c sptps.h \ subnet_parse.c subnet.h \ tincctl.c tincctl.h \ diff --git a/src/graph.c b/src/graph.c index b4c01bb5..396e35a3 100644 --- a/src/graph.c +++ b/src/graph.c @@ -53,8 +53,8 @@ #include "names.h" #include "netutl.h" #include "node.h" -#include "process.h" #include "protocol.h" +#include "script.h" #include "subnet.h" #include "utils.h" #include "xalloc.h" diff --git a/src/invitation.c b/src/invitation.c index e6567bae..188ea2db 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -27,6 +27,7 @@ #include "names.h" #include "netutl.h" #include "rsagen.h" +#include "script.h" #include "sptps.h" #include "tincctl.h" #include "utils.h" @@ -395,17 +396,15 @@ int cmd_invite(int argc, char *argv[]) { xasprintf(&url, "%s/%s%s", address, hash, cookie); // Call the inviation-created script - setenv("NAME", myname, true); - setenv("NETNAME", netname, true); - setenv("NODE", argv[1], true); - setenv("INVITATION_FILE", filename, true); - setenv("INVITATION_URL", url, true); - char *scriptname; - xasprintf(&scriptname, "\"%s" SLASH "invitation-created\"", confbase); - system(scriptname); - free(scriptname); - unsetenv("NODE"); - unsetenv("INVITATION"); + char *envp[6] = {}; + xasprintf(&envp[0], "NAME=%s", myname); + xasprintf(&envp[1], "NETNAME=%s", netname); + xasprintf(&envp[2], "NODE=%s", argv[1]); + xasprintf(&envp[3], "INVITATION_FILE=%s", filename); + xasprintf(&envp[4], "INVITATION_URL=%s", url); + execute_script("invitation-created", envp); + for(int i = 0; i < 6 && envp[i]; i++) + free(envp[i]); puts(url); free(url); diff --git a/src/net.c b/src/net.c index bf6cfcf1..286f1576 100644 --- a/src/net.c +++ b/src/net.c @@ -32,7 +32,6 @@ #include "names.h" #include "net.h" #include "netutl.h" -#include "process.h" #include "protocol.h" #include "subnet.h" #include "xalloc.h" diff --git a/src/net_packet.c b/src/net_packet.c index f79c9a75..11592312 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -42,7 +42,6 @@ #include "net.h" #include "netutl.h" #include "protocol.h" -#include "process.h" #include "route.h" #include "utils.h" #include "xalloc.h" diff --git a/src/net_setup.c b/src/net_setup.c index 35cd3f79..b9c5df7a 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -38,6 +38,7 @@ #include "protocol.h" #include "route.h" #include "rsa.h" +#include "script.h" #include "subnet.h" #include "utils.h" #include "xalloc.h" diff --git a/src/process.c b/src/process.c index cbb190a5..c1038bcd 100644 --- a/src/process.c +++ b/src/process.c @@ -214,72 +214,4 @@ bool detach(void) { return true; } -bool execute_script(const char *name, char **envp) { -#ifdef HAVE_SYSTEM - char *scriptname; - char *command; - xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension); - - /* First check if there is a script */ - - if(access(scriptname, F_OK)) { - free(scriptname); - 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); - else - xasprintf(&command, "\"%s\"", scriptname); - - 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); - } - } - - if(status != -1) { -#ifdef WEXITSTATUS - if(WIFEXITED(status)) { /* Child exited by itself */ - if(WEXITSTATUS(status)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Script %s exited with non-zero status %d", - name, WEXITSTATUS(status)); - return false; - } - } else if(WIFSIGNALED(status)) { /* Child was killed by a signal */ - logger(DEBUG_ALWAYS, LOG_ERR, "Script %s was killed by signal %d (%s)", - name, WTERMSIG(status), strsignal(WTERMSIG(status))); - return false; - } else { /* Something strange happened */ - logger(DEBUG_ALWAYS, LOG_ERR, "Script %s terminated abnormally", name); - return false; - } -#endif - } else { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno)); - return false; - } -#endif - return true; -} diff --git a/src/process.h b/src/process.h index 0b296dbe..4cdf711b 100644 --- a/src/process.h +++ b/src/process.h @@ -1,7 +1,7 @@ /* process.h -- header file for process.c Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2010 Guus Sliepen + 2000-2013 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 @@ -25,7 +25,6 @@ extern bool do_detach; extern bool sigalrm; extern void setup_signals(void); -extern bool execute_script(const char *, char **); extern bool detach(void); extern bool kill_other(int); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index f309a40d..147c3b48 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -38,9 +38,9 @@ #include "netutl.h" #include "node.h" #include "prf.h" -#include "process.h" #include "protocol.h" #include "rsa.h" +#include "script.h" #include "sptps.h" #include "utils.h" #include "xalloc.h" diff --git a/src/script.c b/src/script.c new file mode 100644 index 00000000..9a43d531 --- /dev/null +++ b/src/script.c @@ -0,0 +1,126 @@ +/* + script.c -- call an external script + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "conf.h" +#include "logger.h" +#include "names.h" +#include "script.h" +#include "xalloc.h" + +bool execute_script(const char *name, char **envp) { +#ifdef HAVE_SYSTEM + char *scriptname; + char *command; + + xasprintf(&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); + + const char *p = pathext; + bool found = false; + while(p && *p) { + const char *q = strchr(p, ';'); + if(q) { + memcpy(ext, p, q - p); + ext[q - p] = 0; + *q++; + } else { + strcpy(ext, p); + } + if((found = !access(fullname, F_OK))) + break; + p = q; + } + if(!found) { + free(scriptname); + return true; + } + } else +#endif + + if(access(scriptname, F_OK)) { + free(scriptname); + 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); + else + xasprintf(&command, "\"%s\"", scriptname); + + 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); + } + } + + if(status != -1) { +#ifdef WEXITSTATUS + if(WIFEXITED(status)) { /* Child exited by itself */ + if(WEXITSTATUS(status)) { + logger(DEBUG_ALWAYS, LOG_ERR, "Script %s exited with non-zero status %d", + name, WEXITSTATUS(status)); + return false; + } + } else if(WIFSIGNALED(status)) { /* Child was killed by a signal */ + logger(DEBUG_ALWAYS, LOG_ERR, "Script %s was killed by signal %d (%s)", + name, WTERMSIG(status), strsignal(WTERMSIG(status))); + return false; + } else { /* Something strange happened */ + logger(DEBUG_ALWAYS, LOG_ERR, "Script %s terminated abnormally", name); + return false; + } +#endif + } else { + logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno)); + return false; + } +#endif + return true; +} diff --git a/src/script.h b/src/script.h new file mode 100644 index 00000000..446a3b95 --- /dev/null +++ b/src/script.h @@ -0,0 +1,26 @@ +/* + script.h -- header file for script.c + Copyright (C) 1999-2005 Ivo Timmermans, + 2000-2013 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __TINC_SCRIPT_H__ +#define __TINC_SCRIPT_H__ + +extern bool execute_script(const char *, char **); + +#endif /* __TINC_SCRIPT_H__ */ diff --git a/src/subnet.c b/src/subnet.c index 3b980303..7ff8f7aa 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -29,7 +29,7 @@ #include "net.h" #include "netutl.h" #include "node.h" -#include "process.h" +#include "script.h" #include "subnet.h" #include "utils.h" #include "xalloc.h" diff --git a/src/tincctl.c b/src/tincctl.c index f133e2de..956771f7 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -65,6 +65,8 @@ static bool force = false; bool tty = true; bool confbasegiven = false; bool netnamegiven = false; +char *scriptinterpreter = NULL; +char *scriptextension = ""; #ifdef HAVE_MINGW static struct WSAData wsa_state;