diff --git a/main.cpp b/main.cpp index 65ea7125f..153ced78d 100644 --- a/main.cpp +++ b/main.cpp @@ -729,12 +729,16 @@ int main(int argc,char **argv) // like OSX's launchd. if (upgPath) { Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str()); + std::string updateLogPath(homeDir); + updateLogPath.append("/autoupdate.log"); + Utils::rm(updateLogPath.c_str()); + Utils::redirectUnixOutputs(updateLogPath.c_str(),(const char *)0); ::execl(upgPath,upgPath,(char *)0); } exitCode = 3; fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)"); } break; -#endif +#endif // __WINDOWS__ / __UNIX_LIKE__ case Node::NODE_UNRECOVERABLE_ERROR: { exitCode = 3; const char *termReason = node->reasonForTermination(); diff --git a/node/Utils.cpp b/node/Utils.cpp index b19121988..e1dbedaaa 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #endif @@ -50,6 +51,28 @@ namespace ZeroTier { const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; +bool Utils::redirectUnixOutputs(const char *stdoutPath,const char *stderrPath) + throw() +{ + int fdout = ::open(stdoutPath,O_WRONLY|O_CREAT); + if (fdout > 0) { + int fderr; + if (stderrPath) { + fderr = ::open(stderrPath,O_WRONLY|O_CREAT); + if (fderr <= 0) { + ::close(fdout); + return false; + } + } else fderr = fdout; + ::close(STDOUT_FILENO); + ::close(STDERR_FILENO); + ::dup2(fdout,STDOUT_FILENO); + ::dup2(fderr,STDERR_FILENO); + return true; + } + return false; +} + std::map Utils::listDirectory(const char *path) { std::map r; diff --git a/node/Utils.hpp b/node/Utils.hpp index bafe0b399..91620d781 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -58,6 +58,21 @@ namespace ZeroTier { class Utils { public: +#ifdef __UNIX_LIKE__ + /** + * Close STDOUT_FILENO and STDERR_FILENO and replace them with output to given path + * + * This can be called after fork() and prior to exec() to suppress output + * from a subprocess, such as auto-update. + * + * @param stdoutPath Path to file to use for stdout + * @param stderrPath Path to file to use for stderr, or NULL for same as stdout (default) + * @return True on success + */ + static bool redirectUnixOutputs(const char *stdoutPath,const char *stderrPath = (const char *)0) + throw(); +#endif + /** * Perform a time-invariant binary comparison *