diff options
author | Dave Brolley <brolley@redhat.com> | 2009-09-18 18:17:15 -0400 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2009-09-18 18:17:15 -0400 |
commit | a6a2869a0f4f784bab36410722f6161eab0f4503 (patch) | |
tree | 251da07c5e0741499401fc55eaf353f57a4062f4 | |
parent | f6efd18a0bcae7697651f794fd2d2ebcf66faf62 (diff) | |
download | systemtap-steved-a6a2869a0f4f784bab36410722f6161eab0f4503.tar.gz systemtap-steved-a6a2869a0f4f784bab36410722f6161eab0f4503.tar.xz systemtap-steved-a6a2869a0f4f784bab36410722f6161eab0f4503.zip |
stap-start-server(->stap-serverd) now accept -r -R -I -B and -a options for cross compilation.
Server correctly advertises itself wrt -r and -a.
Fix bug in stap-server: fatal function was potentially recursive.
-rwxr-xr-x | stap-client | 62 | ||||
-rwxr-xr-x | stap-env | 26 | ||||
-rwxr-xr-x | stap-find-servers | 2 | ||||
-rwxr-xr-x | stap-server | 80 | ||||
-rw-r--r-- | stap-server-connect.c | 35 | ||||
-rwxr-xr-x | stap-serverd | 242 |
6 files changed, 365 insertions, 82 deletions
diff --git a/stap-client b/stap-client index 3f2eb0a1..18e24ca9 100755 --- a/stap-client +++ b/stap-client @@ -38,7 +38,7 @@ function initialization { # Default location for server certificates if we're not root # Must be owned by us. - local uid uname + local uid if test $EUID != 0; then if test -e $stap_user_ssl_db/client; then if check_db $stap_user_ssl_db/client $EUID $USER; then @@ -61,8 +61,7 @@ function initialization { m_name= module_name=stap_$$ uname_r="`uname -r`" - uname_v="`uname -v`" - uname_m="`uname -m`" + arch=`get_arch` # Default variable settings find_all= @@ -129,7 +128,6 @@ function parse_options { first_token=`expr "$first_token" : '-\(.*\)'` dash_seen=1 first_char=`expr "$first_token" : '\(.\).*'` - cmdline2="$cmdline2 -" fi fi if test $dash_seen = 0; then @@ -155,14 +153,14 @@ function parse_options { case $first_char in a) get_arg $first_token $2 - cmdline2="${cmdline2}s '$stap_arg'" + process_a $stap_arg ;; b) b_specified=1 ;; B) get_arg $first_token $2 - cmdline2="${cmdline2}s '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" ;; c) get_arg $first_token "$2" @@ -170,7 +168,7 @@ function parse_options { ;; D) get_arg $first_token $2 - cmdline2="${cmdline2}D '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" ;; e) get_arg $first_token "$2" @@ -185,12 +183,12 @@ function parse_options { ;; l) get_arg $first_token $2 - cmdline2="${cmdline2}l '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" p_phase=2 ;; L) get_arg $first_token $2 - cmdline2="${cmdline2}l '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" p_phase=2 ;; m) @@ -215,18 +213,18 @@ function parse_options { ;; s) get_arg $first_token $2 - cmdline2="${cmdline2}s '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" ;; S) get_arg $first_token $2 - cmdline2="${cmdline2}s '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" ;; v) v_level=$(($v_level + 1)) ;; x) get_arg $first_token $2 - cmdline2="${cmdline2}x '$stap_arg'" + cmdline2="${cmdline2} -$first_char '$stap_arg'" ;; *) # An unknown or unimportant flag. Ignore it, but pass it on to the server. @@ -235,7 +233,7 @@ function parse_options { if test $advance_p = 0; then # Just another flag character. Consume it. - cmdline2="$cmdline2$first_char" + cmdline2="$cmdline2 -$first_char" first_token=`expr "$first_token" : '.\(.*\)'` if test "X$first_token" = "X"; then advance_p=$(($advance_p + 1)) @@ -333,7 +331,7 @@ function process_server { # Process the -c flag. function process_c { c_cmd="$1" - cmdline2="${cmdline2}c '$1'" + cmdline2="${cmdline2} -c '$1'" } # function: process_e ARGUMENT @@ -350,7 +348,7 @@ function process_e { script_file= fi fi - cmdline2="${cmdline2}e '$1'" + cmdline2="${cmdline2} -e '$1'" } # function: process_I ARGUMENT @@ -359,7 +357,7 @@ function process_e { function process_I { local local_name=`include_file_or_directory tapsets $1` test "X$local_name" != "X" || return - cmdline2="${cmdline2}I 'tapsets/$local_name'" + cmdline2="${cmdline2} -I 'tapsets/$local_name'" } # function: process_m ARGUMENT @@ -368,7 +366,7 @@ function process_I { function process_m { module_name="$1" m_name="$1" - cmdline2="${cmdline2}m '$1'" + cmdline2="${cmdline2} -m '$1'" } # function: process_o ARGUMENT @@ -376,7 +374,7 @@ function process_m { # Process the -o flag. function process_o { stdout_redirection="$1" - cmdline2="${cmdline2}o '$1'" + cmdline2="${cmdline2} -o '$1'" } # function: process_p ARGUMENT @@ -384,7 +382,7 @@ function process_o { # Process the -p flag. function process_p { p_phase=$1 - cmdline2="${cmdline2}p '$1'" + cmdline2="${cmdline2} -p '$1'" } # function: process_r ARGUMENT @@ -414,13 +412,23 @@ function process_r { fi } +# function: process_a ARGUMENT +# +# Process the -a flag. +function process_a { + if test "X$1" != "X$arch"; then + arch=$1 + find_all="--all" + fi +} + # function: process_R ARGUMENT # # Process the -R flag. function process_R { local local_name=`include_file_or_directory runtime $1` test "X$local_name" != "X" || return - cmdline2="${cmdline2}R 'runtime/$local_name'" + cmdline2="${cmdline2} -R 'runtime/$local_name'" } # function: include_file_or_directory PREFIX NAME @@ -479,7 +487,7 @@ function create_request { # # Generate the client's sysinfo and echo it to stdout function client_sysinfo { - echo "$uname_r $uname_v $uname_m" + echo "$uname_r $arch" } # function: package_request @@ -680,9 +688,9 @@ function choose_server { fatal "Server port not provided by avahi" fi - # Does the server build for the kernel release that we want? - release=`expr "$remain" : ".sysinfo=\\\([^ ]*\\\).*"` - test "X$release" != "X$uname_r" && continue + # Does the server build for the kernel release and architecture that we want? + sysinfo=`expr "$remain" : "'sysinfo=\\\(.*\\\)'"` + test "X$sysinfo" != "X$uname_r $arch" && continue ssl_db=`send_receive $name $port` test "X$ssl_db" != "X" && echo $ssl_db && return @@ -758,8 +766,10 @@ function process_response { module_name=`expr "$module_name" : '\(.*\)\.ko'` fi elif test "X$script_file" != "X" -o "X$e_script" != "X"; then - stream_output - fatal "no module returned by the server" + if test "X$rc" != "X" -a $rc = 0; then + stream_output + fatal "no module returned by the server" + fi fi fi @@ -40,3 +40,29 @@ fi stap_signing_db=$stap_sysconfdir/systemtap/staprun stap_certfile=stap.cert stap_old_certfile=stap-server.cert + +function get_arch { + # PR4186: Copy logic from coreutils uname (uname -i) to squash + # i?86->i386. Actually, copy logic from linux top-level Makefile + # to squash uname -m -> $(SUBARCH). + + local machine=`uname -m` + machine=`expr "$machine" : '\(...\).*'` + case $machine in + i48) machine="i386" ;; + i58) machine="i386" ;; + i68) machine="i386" ;; + sun) machine="sparc64" ;; + arm) machine="arm" ;; + sa1) machine="arm" ;; + s39) machine="s390" ;; + ppc) machine="powerpc" ;; + mip) machine="mips" ;; + sh2) machine="sh" ;; + sh3) machine="sh" ;; + sh4) machine="sh" ;; + *) machine="unknown" ;; + esac + + echo $machine +} diff --git a/stap-find-servers b/stap-find-servers index 5b00e51e..8eda71e8 100755 --- a/stap-find-servers +++ b/stap-find-servers @@ -140,7 +140,7 @@ function match_server { function client_sysinfo { if test "X$sysinfo_client" = "X"; then # Add some info from uname - sysinfo_client="`uname -rvm`" + sysinfo_client="`uname -r` `get_arch`" fi echo sysinfo=$sysinfo_client } diff --git a/stap-server b/stap-server index 98b54d96..51abf62f 100755 --- a/stap-server +++ b/stap-server @@ -34,38 +34,36 @@ function initialization { unprivileged=0 stap_options= - # Request file name. zip_client=$1 - test "X$zip_client" != "X" || \ - fatal "Client request file not specified" - test -f $zip_client || \ - fatal "Unable to find request file $zip_client" - - # Temp directory we will be working in tmpdir_server=$2 - test "X$tmpdir_server" != "X" || \ - fatal "Server temporary directory not specified" - test -d $tmpdir_server || \ - fatal "Unable to find temporary directory $tmpdir_server" + zip_server=$3 + ssl_db=$4 + server_options="$5" + + # This script is not intended to be called directly, so if the arguments + # aren't specified correctly, just exit with non-zero + test "X$tmpdir_server" != "X" || exit 2 + test -d $tmpdir_server || exit 3 tmpdir_env=`dirname $tmpdir_server` - # Signed reponse file name. - zip_server=$3 - test "X$zip_server" != "X" || \ - fatal ".zip archive file not specified" + # Response file name. + test "X$zip_server" != "X" || exit 4 # Make sure the specified .zip file exists. - test -f $zip_server || \ - fatal "Unable to find .zip archive file $zip_server" + test -f $zip_server || exit 5 + + # Request file name. + test "X$zip_client" != "X" || exit 6 + test -f $zip_client || exit 7 # Where is the ssl certificate/key database? - ssl_db=$4 - test "X$ssl_db" != "X" || \ - fatal "SSL certificate database not specified" - test -d $ssl_db || \ - fatal "Unable to find SSL certificate database $ssl_db" + test "X$ssl_db" != "X" || exit 8 + test -d $ssl_db || exit 9 nss_pw=$ssl_db/pw - test -f $nss_pw || \ - fatal "Unable to find SSL certificate database password file $nss_pw" + test -f $nss_pw || exit 10 + + # What are the options that the server was started with? + eval parse_options "$server_options" + nss_cert=stap-server touch $tmpdir_server/stdout @@ -127,7 +125,7 @@ function check_request { function server_sysinfo { if test "X$sysinfo_server" = "X"; then # Add some info from uname - sysinfo_server="`uname -rvm`" + sysinfo_server="`uname -r` `get_arch`" fi echo "$sysinfo_server" } @@ -233,11 +231,19 @@ function parse_options { case $first_char in a) get_arg $first_token $2 - stap_options="$stap_options -$first_char $stap_arg" + if test $unprivileged = 1; then + fatal "You can't specify -$first_char and --unprivileged together." + else + stap_options="$stap_options -$first_char $stap_arg" + fi ;; B) get_arg $first_token $2 - stap_options="$stap_options -$first_char $stap_arg" + if test $unprivileged = 1; then + fatal "You can't specify -$first_char and --unprivileged together." + else + stap_options="$stap_options -$first_char $stap_arg" + fi ;; d) get_arg $first_token $2 @@ -246,7 +252,7 @@ function parse_options { D) get_arg $first_token $2 if test $unprivileged = 1; then - fatal "You can't specify -D and --unprivileged together." + fatal "You can't specify -$first_char and --unprivileged together." else stap_options="$stap_options -$first_char $stap_arg" fi @@ -259,7 +265,7 @@ function parse_options { I) get_arg $first_token $2 if test $unprivileged = 1; then - fatal "You can't specify -I and --unprivileged together." + fatal "You can't specify -$first_char and --unprivileged together." else stap_options="$stap_options -$first_char $stap_arg" fi @@ -289,10 +295,18 @@ function parse_options { get_arg $first_token $2 process_p $stap_arg ;; + r) + get_arg $first_token $2 + if test $unprivileged = 1; then + fatal "You can't specify -$first_char and --unprivileged together." + else + stap_options="$stap_options -$first_char $stap_arg" + fi + ;; R) get_arg $first_token $2 if test $unprivileged = 1; then - fatal "You can't specify -R and --unprivileged together." + fatal "You can't specify -$first_char and --unprivileged together." else stap_options="$stap_options -$first_char $stap_arg" fi @@ -411,7 +425,7 @@ function create_response { ln -s $tmpdir_stap `basename $tmpdir_stap` # Sign the resulting module if --unprivileged was specified. - if test $unprivileged = 1 -a $p_phase -ge 4; then + if test $unprivileged = 1 -a $p_phase -ge 4 -a $stap_rc = 0; then modname=$tmpdir_stap/`grep -m1 '^.*\.ko$' stdout` if test "X$modname" != "X"; then ${stap_exec_prefix}stap-sign-module $modname $ssl_db @@ -436,8 +450,8 @@ function package_response { cd $tmpdir_env # Compress the server's temporary directory into a .zip archive. - (rm $zip_server && zip -r $zip_server `basename $tmpdir_server` > /dev/null) || \ - fatal "zip of server response tree, $tmpdir_server, failed" + (rm $zip_server && zip -r $zip_server `basename $tmpdir_server` > /dev/null) + return $? } # function: fatal [ MESSAGE ] diff --git a/stap-server-connect.c b/stap-server-connect.c index 33d4983b..e93ae37b 100644 --- a/stap-server-connect.c +++ b/stap-server-connect.c @@ -41,6 +41,7 @@ static char *dbdir = NULL; static char requestFileName[] = "/tmp/stap.server.client.zip.XXXXXX"; static char responseDirName[] = "/tmp/stap.server.XXXXXX"; static char responseZipName[] = "/tmp/stap.server.XXXXXX.zip.XXXXXX"; +static const char *stapOptions = ""; static void Usage(const char *progName) @@ -471,15 +472,18 @@ handle_connection(PRFileDesc *tcpSocket) sizeof (requestFileName) + 1 + sizeof (responseDirName) + 1 + sizeof (responseZipName) + 1 + - strlen (dbdir) + 1); + strlen (dbdir) + 1 + + 1 + strlen (stapOptions) + 1 + + 1); if (! cmdline) { errWarn ("PORT_Alloc"); secStatus = SECFailure; goto cleanup; } - sprintf (cmdline, "%s/stap-server %s %s %s %s", stap_server_prefix, - requestFileName, responseDirName, responseZipName, dbdir); + sprintf (cmdline, "%s/stap-server %s %s %s %s '%s'", stap_server_prefix, + requestFileName, responseDirName, responseZipName, dbdir, + stapOptions); rc = system (cmdline); PR_Free (cmdline); @@ -703,25 +707,26 @@ getPassword(char *fileName) int main(int argc, char **argv) { - char * progName = NULL; - char * nickName = NULL; - char * passwordFile = NULL; - unsigned short port = 0; - SECStatus secStatus; - PLOptState * optstate; - PLOptStatus status; + const char * progName = NULL; + const char * nickName = NULL; + char * passwordFile = NULL; + unsigned short port = 0; + SECStatus secStatus; + PLOptState * optstate; + PLOptStatus status; progName = PL_strdup(argv[0]); - optstate = PL_CreateOptState(argc, argv, "d:p:n:w:"); + optstate = PL_CreateOptState(argc, argv, "d:p:n:w:s:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch(optstate->option) { - case 'd': dbdir = PL_strdup(optstate->value); break; - case 'n': nickName = PL_strdup(optstate->value); break; - case 'p': port = PORT_Atoi(optstate->value); break; - case 'w': passwordFile = PL_strdup(optstate->value); break; + case 'd': dbdir = PL_strdup(optstate->value); break; + case 'n': nickName = PL_strdup(optstate->value); break; + case 'p': port = PORT_Atoi(optstate->value); break; + case 'w': passwordFile = PL_strdup(optstate->value); break; + case 's': stapOptions = PL_strdup(optstate->value); break; default: case '?': Usage(progName); } diff --git a/stap-serverd b/stap-serverd index 4eee8c38..08b16008 100755 --- a/stap-serverd +++ b/stap-serverd @@ -24,9 +24,18 @@ trap 'terminate' SIGTERM SIGINT #----------------------------------------------------------------------------- # function: initialization PORT function initialization { + # Initial values + port= + ssl_db= + stap_options= + uname_r="`uname -r`" + arch="`get_arch`" + + # Parse the arguments + parse_options "$@" + # What port will we listen on? - port=$1 - test "X$port" = "X" && port=65000 + test "X$port" = "X" && port=$((1024+$RANDOM%64000)) while netstat -atn | awk '{print $4}' | cut -f2 -d: | egrep -q "^$port\$"; do # Whoops, the port is busy; try another one. @@ -35,7 +44,6 @@ function initialization { done # Where is the ssl certificate/key database? - ssl_db=$2 if test "X$ssl_db" = "X"; then ssl_db=$stap_ssl_db/server # Update the certificate file if it is old. @@ -73,14 +81,231 @@ function initialization { nss_cert=stap-server } +# function: parse_options [ STAP-OPTIONS ] +# +# Examine the command line. We need not do much checking, but we do need to +# parse all options in order to discover the ones we're interested in. +function parse_options { + while test $# != 0 + do + advance_p=0 + dash_seen=0 + + # Start of a new token. + first_token=$1 + + # Process the option. + until test $advance_p != 0 + do + # Identify the next option + first_char=`expr "$first_token" : '\(.\).*'` + if test $dash_seen = 0; then + if test "$first_char" = "-"; then + if test "$first_token" != "-"; then + # It's not a lone dash, so it's an option. + # Is it a long option (i.e. --option)? + second_char=`expr "$first_token" : '.\(.\).*'` + if test "X$second_char" = "X-"; then + case `expr "$first_token" : '--\([^=]*\)'` in + port) + get_long_arg $first_token $2 + port=$stap_arg + ;; + ssl) + get_long_arg $first_token $2 + ssl_db=$stap_arg + ;; + *) + warning "Option '$first_token' ignored" + advance_p=$(($advance_p + 1)) + break + ;; + esac + fi + # It's not a lone dash, or a long option, so it's a short option string. + # Remove the dash. + first_token=`expr "$first_token" : '-\(.*\)'` + dash_seen=1 + first_char=`expr "$first_token" : '\(.\).*'` + fi + fi + if test $dash_seen = 0; then + # The dash has not been seen. This is not an option at all. + warning "Option '$first_token' ignored" + advance_p=$(($advance_p + 1)) + break + fi + fi + + # We are at the start of an option. Look at the first character. + case $first_char in + a) + get_arg $first_token $2 + process_a $stap_arg + ;; + B) + get_arg $first_token $2 + stap_options="$stap_options -$first_char $stap_arg" + ;; + c) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + d) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + D) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + e) + get_arg $first_token "$2" + warning "Option '-$first_char '$stap_arg' ignored'" + ;; + I) + get_arg $first_token $2 + stap_options="$stap_options -$first_char $stap_arg" + ;; + l) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + L) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + m) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + o) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + p) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + r) + get_arg $first_token $2 + process_r $stap_arg + ;; + R) + get_arg $first_token $2 + stap_options="$stap_options -$first_char $stap_arg" + ;; + s) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + S) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + x) + get_arg $first_token $2 + warning "Option '-$first_char $stap_arg' ignored" + ;; + *) + # An unknown flag. Ignore it. + ;; + esac + + if test $advance_p = 0; then + # Just another flag character. Consume it. + warning "Option '-$first_char' ignored" + first_token=`expr "$first_token" : '.\(.*\)'` + if test "X$first_token" = "X"; then + advance_p=$(($advance_p + 1)) + fi + fi + done + + # Consume the arguments we just processed. + while test $advance_p != 0 + do + shift + advance_p=$(($advance_p - 1)) + done + done +} + +# function: get_arg FIRSTWORD SECONDWORD +# +# Collect an argument to the given short option +function get_arg { + # Remove first character. Advance to the next token, if the first one + # is exhausted. + local first=`expr "$1" : '.\(.*\)'` + if test "X$first" = "X"; then + shift + advance_p=$(($advance_p + 1)) + first=$1 + fi + stap_arg="$first" + advance_p=$(($advance_p + 1)) +} + +# function: get_arg FIRSTWORD SECONDWORD +# +# Collect an argument to the given long option +function get_long_arg { + # Remove first character. Advance to the next token, if the first one + # is exhausted. + local first=`expr "$1" : '.*\=\(.*\)'` + if test "X$first" = "X"; then + shift + advance_p=$(($advance_p + 1)) + first=$1 + fi + stap_arg="$first" + advance_p=$(($advance_p + 1)) +} + +# function: process_a ARGUMENT +# +# Process the -a flag. +function process_a { + if test "X$1" != "X$arch"; then + arch=$1 + stap_options="$stap_options -a $1" + fi +} + +# function: process_r ARGUMENT +# +# Process the -r flag. +function process_r { + local first_char=`expr "$1" : '\(.\).*'` + + if test "$first_char" = "/"; then # fully specified path + kernel_build_tree=$1 + version_file_name="$kernel_build_tree/include/config/kernel.release" + # The file include/config/kernel.release within the + # build tree is used to pull out the version information + release=`cat $version_file_name 2>/dev/null` + if test "X$release" = "X"; then + fatal "Missing $version_file_name" + return + fi + else + # kernel release specified directly + release=$1 + fi + + if test "X$release" != "X$uname_r"; then + uname_r=$release + stap_options="$stap_options -r $release" + fi +} + # function: advertise_presence # # Advertise the availability of the server on the network. function advertise_presence { # Build up a string representing our server's properties. - # TODO: this needs fleshing out. - local sysinfo=`uname -rvm` - local txt="sysinfo=$sysinfo" + local txt="sysinfo=$uname_r $arch" # Call avahi-publish-service to advertise our presence. avahi-publish-service "Systemtap Compile Server on `uname -n`" \ @@ -95,7 +320,10 @@ function advertise_presence { function listen { # The stap-server-connect program will listen forever # accepting requests. - ${stap_exec_prefix}stap-server-connect -p $port -n $nss_cert -d $ssl_db -w $nss_pw 2>&1 & + ${stap_exec_prefix}stap-server-connect \ + -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ + -s "$stap_options" \ + 2>&1 & wait '%${stap_exec_prefix}stap-server-connect' >/dev/null 2>&1 } |