From: Miod Vallat Date: Thu, 22 May 2025 06:53:36 +0000 (+0200) Subject: Replace use of system(3) in pdnsutil with execvp(2). X-Git-Tag: dnsdist-2.0.0-beta1~50^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86a2b329818d48487aeac9426eb53639814de0d4;p=thirdparty%2Fpdns.git Replace use of system(3) in pdnsutil with execvp(2). --- diff --git a/pdns/pdnsutil.cc b/pdns/pdnsutil.cc index c437c1dee1..fbffdc9e0f 100644 --- a/pdns/pdnsutil.cc +++ b/pdns/pdnsutil.cc @@ -9,6 +9,8 @@ #endif #include +#include +#include #include "credentials.hh" #include "dnsseckeeper.hh" @@ -1246,16 +1248,64 @@ private: bool d_colors; }; -static int spawnEditor(const std::string& editor, const std::string& tmpfile, int gotoline) +static bool spawnEditor(const std::string& editor, const std::string& tmpfile, int gotoline, int &result) { - string cmdline; - - cmdline=editor+" "; - if(gotoline > 0) { - cmdline+="+"+std::to_string(gotoline)+" "; + pid_t child; + sigset_t mask, omask; + + // Ignore INT, QUIT and CHLD signals while the editor process runs + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGQUIT); + sigprocmask(SIG_BLOCK, &mask, &omask); + + switch (child = fork()) { + case 0: + { + std::array args; + size_t pos = 0; + std::string gotolinestr; + args[pos++] = editor.c_str(); + if (gotoline > 0) { + // TODO: if editor is 'ed', skip this; if 'ex' or 'vi', use '-c number' + gotolinestr = "+" + std::to_string(gotoline); + args[pos++] = gotolinestr.c_str(); + } + args[pos++] = tmpfile.c_str(); + args[pos++] = nullptr; + if (::execvp(args.at(0), const_cast(args.data())) != 0) { + ::exit(errno); + } + // std::unreachable(); + } + break; + case -1: + unixDie("Couldn't fork"); + break; + default: + { + pid_t pid; + int status; + do { + pid = waitpid(child, &status, 0); + } while (pid == -1 && errno == EINTR); + sigprocmask(SIG_SETMASK, &omask, NULL); + if (pid == -1) { + return false; + } + if (WIFEXITED(status)) { + result = WEXITSTATUS(status); + return true; + } + if (WIFSIGNALED(status)) { + result = 128 + WTERMSIG(status); + return true; + } + } + break; } - cmdline += tmpfile; - return system(cmdline.c_str()); + return false; } static int editZone(const ZoneName &zone, const PDNSColors& col) { @@ -1349,9 +1399,13 @@ static int editZone(const ZoneName &zone, const PDNSColors& col) { } editMore:; post.clear(); - if (spawnEditor(editor, tmpnam, gotoline) != 0) { + int result{0}; + if (!spawnEditor(editor, tmpnam, gotoline, result)) { unixDie("Editing file with: '"+editor+"', perhaps set EDITOR variable"); } + if (result != 0) { + throw std::runtime_error("Editing file with: '" + editor + "' returned non-zero status " + std::to_string(result)); + } ZoneParserTNG zpt(static_cast(tmpnam), g_rootzonename); zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps")); zpt.setMaxIncludes(::arg().asNum("max-include-depth"));