From 55881ad49bd6cc8a40d2be32919c6938188af81b Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Mon, 26 Aug 2013 11:39:21 -0400 Subject: [PATCH] stapsh: add option command The new option command allows stap to change the behaviour of stapsh depending on the scheme used. For now, only "verbose" is a valid option. This is especially useful for the unix scheme, where we connect to an already running instance of stapsh. Options are sent to stapsh right after a successful handshake. - remote.cxx: send options after successful handshake - staprun/stapsh.c: add option command and verbose option --- remote.cxx | 25 +++++++++++++++++ staprun/stapsh.c | 71 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 16 deletions(-) diff --git a/remote.cxx b/remote.cxx index 5f2a413e9..67879d4ed 100644 --- a/remote.cxx +++ b/remote.cxx @@ -305,6 +305,8 @@ class stapsh : public remote { fdin(-1), fdout(-1), IN(0), OUT(0) {} + vector options; + virtual int prepare() { int rc = 0; @@ -426,6 +428,25 @@ class stapsh : public remote { this->remote_version = uname[1]; this->s = s->clone(uname[2], uname[3]); + + // set any option requested + if (!this->options.empty()) + { + // check first if the option command is supported + if (strverscmp("2.4", this->remote_version.c_str()) > 0) + throw runtime_error(_F("stapsh %s does not support options", + this->remote_version.c_str())); + + for (vector::iterator it = this->options.begin(); + it != this->options.end(); ++it) + { + send_command("option " + *it + "\n"); + string reply = get_reply(); + if (reply != "OK\n") + throw runtime_error(_F("could not set option %s: %s", + it->c_str(), reply.c_str())); + } + } } public: @@ -496,6 +517,10 @@ class unix_stapsh : public stapsh { unix_stapsh(systemtap_session& s, const uri_decoder& ud) : stapsh(s) { + // set verbosity to the requested level + for (unsigned i = 1; i < s.perpass_verbose[4]; i++) + this->options.push_back("verbose"); + sockaddr_un server; server.sun_family = AF_UNIX; if (ud.path.empty()) diff --git a/staprun/stapsh.c b/staprun/stapsh.c index dbfac4c94..6c7257e4a 100644 --- a/staprun/stapsh.c +++ b/staprun/stapsh.c @@ -18,6 +18,13 @@ // to facilitate compatibility checks, in case the protocol needs to // change. MACHINE and RELEASE are reported as given by uname. // +// command: option OPTIONNAME +// reply: OK / error message +// desc: Enables the option OPTIONNAME. Introduced in v2.4. Currently +// supported options are: +// +// verbose: Increases verbosity of debug statements. +// // command: file SIZE NAME // DATA // reply: OK / error message @@ -72,6 +79,7 @@ struct stapsh_handler { static int do_hello(void); +static int do_option(void); static int do_file(void); static int do_run(void); static int do_quit(void); @@ -82,6 +90,7 @@ static const int signals[] = { static const struct stapsh_handler commands[] = { { "stap", do_hello }, + { "option", do_option }, { "file", do_file }, { "run", do_run }, { "quit", do_quit }, @@ -94,6 +103,16 @@ static pid_t staprun_pid = -1; static unsigned verbose = 0; +struct stapsh_option { + const char* name; + unsigned* var; +}; + +static const struct stapsh_option options[] = { + { "verbose", &verbose }, +}; +static const unsigned noptions = sizeof(options) / sizeof(*options); + #define dbug(level, format, args...) do { if (verbose >= level) \ fprintf (stderr, "stapsh:%s:%d " format, __FUNCTION__, __LINE__, ## args); \ } while (0) @@ -106,6 +125,22 @@ static unsigned verbose = 0; #define die(format, args...) ({ dbug(1, format, ## args); cleanup(2); }) +// Send a reply back to the client on stdout +static int __attribute__ ((format (printf, 1, 2))) +reply(const char* format, ...) +{ + va_list args, dbug_args; + va_start (args, format); + va_copy (dbug_args, args); + vdbug (1, format, dbug_args); + int ret = vprintf (format, args); + fflush (stdout); + va_end (dbug_args); + va_end (args); + return ret; +} + + static void __attribute__ ((noreturn)) cleanup(int status) { @@ -233,22 +268,6 @@ qpdecode(char* s) } -// Send a reply back to the client on stdout -static int __attribute__ ((format (printf, 1, 2))) -reply(const char* format, ...) -{ - va_list args, dbug_args; - va_start (args, format); - va_copy (dbug_args, args); - vdbug (1, format, dbug_args); - int ret = vprintf (format, args); - fflush (stdout); - va_end (dbug_args); - va_end (args); - return ret; -} - - static int do_hello() { @@ -265,6 +284,26 @@ do_hello() return 0; } +static int +do_option() +{ + char *opt = strtok(NULL, STAPSH_TOK_DELIM); + if (opt == NULL) + return reply("ERROR: Could not parse option\n"); + + // find and affect option + unsigned i; + for (i = 0; i < noptions; ++i) + if (strcmp(opt, options[i].name) == 0) + { + dbug(2, "turning on option %s\n", opt); + (*options[i].var)++; + reply("OK\n"); + return 0; + } + return reply("ERROR: Invalid option\n"); +} + static int do_file() { -- 2.43.5