summaryrefslogtreecommitdiffstats
path: root/stap-server-request
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-12-21 19:26:16 -0500
committerDave Brolley <brolley@redhat.com>2009-12-21 19:26:16 -0500
commit600450900a5e98404c91104d2cb20cddce42838e (patch)
treee0a54b23be5755ec80c72f8b16a6281b5540c661 /stap-server-request
parentd12a5be645d7036e7834308e714496f57adda852 (diff)
downloadsystemtap-steved-600450900a5e98404c91104d2cb20cddce42838e.tar.gz
systemtap-steved-600450900a5e98404c91104d2cb20cddce42838e.tar.xz
systemtap-steved-600450900a5e98404c91104d2cb20cddce42838e.zip
PR 10905: initscript improvements.
Make the stap-server initscript available as $bindir/stap-server Reimplement the stap-server initscript as a thin wrapper around $bindir/stap-server.
Diffstat (limited to 'stap-server-request')
-rwxr-xr-xstap-server-request512
1 files changed, 512 insertions, 0 deletions
diff --git a/stap-server-request b/stap-server-request
new file mode 100755
index 00000000..d1731895
--- /dev/null
+++ b/stap-server-request
@@ -0,0 +1,512 @@
+#!/bin/bash
+
+# Compile server for systemtap
+#
+# Copyright (C) 2008, 2009 Red Hat Inc.
+#
+# This file is part of systemtap, and is free software. You can
+# redistribute it and/or modify it under the terms of the GNU General
+# Public License (GPL); either version 2, or (at your option) any
+# later version.
+
+# This script unpacks the tar file provided on stdin and uses the information
+# contained in the unpacked tree to build the requested systemtap kernel module.
+# This module is then written to stdout.
+
+# Catch ctrl-c and other termination signals
+trap 'terminate' SIGTERM SIGINT
+
+# Initialize the environment
+. ${PKGLIBEXECDIR}stap-env
+
+#-----------------------------------------------------------------------------
+# Helper functions.
+#-----------------------------------------------------------------------------
+# function: initialization
+function initialization {
+ # Initialization
+ stap_rc=0
+ wd=`pwd`
+
+ # Default options settings
+ p_phase=5
+ keep_temps=0
+ unprivileged=0
+ stap_options=
+
+ zip_client=$1
+ tmpdir_server=$2
+ 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`
+
+ # Response file name.
+ test "X$zip_server" != "X" || exit 4
+ # Make sure the specified .zip file exists.
+ 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?
+ test "X$ssl_db" != "X" || exit 8
+ test -d $ssl_db || exit 9
+ nss_pw=$ssl_db/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
+ touch $tmpdir_server/stderr
+}
+
+# function: unpack_request
+#
+# Unpack the zip file received from the client and make the contents
+# available for use when running 'stap'
+function unpack_request {
+ cd $tmpdir_server
+
+ # Unpack the zip file.
+ unzip $zip_client > /dev/null || \
+ fatal "Cannot unpack zip archive $zip_client"
+
+ # Identify the client's request tree. The zip file should have expanded
+ # into a single directory named to match $stap_tmpdir_prefix_client.??????
+ # which should now be the only item in the current directory.
+ test "`ls | wc -l`" = 3 || \
+ fatal "Wrong number of files after expansion of client's zip file"
+
+ tmpdir_client=`ls | grep $stap_tmpdir_prefix_client.......\$`
+
+ test "X$tmpdir_client" != "X" || \
+ fatal "Client zip file did not expand as expected"
+
+ # Move the client's temp directory to a local temp location
+ local local_tmpdir_client=`mktemp -dt $stap_tmpdir_prefix_server.client.XXXXXX` || \
+ fatal "Cannot create temporary client request directory " $local_tmpdir_client
+ mv $tmpdir_client/* $local_tmpdir_client
+ rm -fr $tmpdir_client
+ tmpdir_client=$local_tmpdir_client
+}
+
+# function: check_request
+#
+# Examine the contents of the request to make sure that they are valid.
+function check_request {
+ # Work in the temporary directory provided by the client
+ cd $tmpdir_client
+
+ # Add the necessary info from files in our temporary directory.
+ cmdline=`read_data_file cmdline`
+ test "X$cmdline" != "X" || exit 1
+
+ eval parse_options "$cmdline"
+
+ client_sysinfo=`read_data_file sysinfo`
+ test "X$client_sysinfo" != "X" || exit 1
+
+ check_compatibility "$client_sysinfo" "`server_sysinfo`"
+}
+
+# function server_sysinfo
+#
+# Generate the server's sysinfo and echo it to stdout
+function server_sysinfo {
+ if test "X$sysinfo_server" = "X"; then
+ # Add some info from uname
+ sysinfo_server="`uname -r` `stap_get_arch`"
+ fi
+ echo "$sysinfo_server"
+}
+
+# function check_compaibility SYSINFO1 SYSINFO2
+#
+# Make sure that systemtap as described by SYSINFO1 and SYSINFO2 are compaible
+function check_compatibility {
+ # Compatibility is irrelevant. The client can choose any server
+ # it sees fit
+ return
+}
+
+# function: read_data_file PREFIX
+#
+# Find a file whose name is '$1' and whose first line
+# contents are '$1: .*'. Read and echo the data.
+function read_data_file {
+ test -f $1 || \
+ fatal "Data file $1 not found"
+
+ # Open the file
+ exec 3< $1
+
+ # Verify the first line of the file.
+ read <&3
+ line="$REPLY"
+ data=`expr "$line" : "$1: \\\(.*\\\)"`
+ if test "X$data" = "X"; then
+ fatal "Data in file $1 is incorrect"
+ return
+ fi
+
+ # Close the file
+ exec 3<&-
+
+ # Now read the entire file.
+ cat $1 | sed "s/$1: //"
+}
+
+# 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 {
+ # We need to know in advance if --unprivileged was specified.
+ all_options=" ""$@"" "
+ token=`expr "$all_options" : '.* \(--unprivileged\) .*'`
+ if test "X$token" = "X--unprivileged"; then
+ unprivileged=1
+ fi
+
+ 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
+ advance_p=$(($advance_p + 1))
+ stap_options="$stap_options $first_token"
+ break
+ 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 either the script file
+ # name or an arument to be passed to the probe module.
+ # If this is the first time, and -e has not been specified,
+ # then it could be the name of the script file.
+ if test "X$e_script" = "X" -a "X$script_file" = "X"; then
+ script_file="$first_token"
+ fi
+ if test "$first_char" != "'"; then
+ stap_options="$stap_options '$first_token'"
+ else
+ stap_options="$stap_options $first_token"
+ fi
+ 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
+ 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
+ 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
+ stap_options="$stap_options -$first_char $stap_arg"
+ ;;
+ D)
+ 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
+ ;;
+ e)
+ get_arg $first_token "$2"
+ stap_options="$stap_options -$first_char '$stap_arg'"
+ process_e "$stap_arg"
+ ;;
+ I)
+ 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
+ ;;
+ k)
+ keep_temps=1
+ ;;
+ l)
+ get_arg $first_token $2
+ stap_options="$stap_options -$first_char $stap_arg"
+ process_p 2
+ ;;
+ L)
+ get_arg $first_token $2
+ stap_options="$stap_options -$first_char $stap_arg"
+ process_p 2
+ ;;
+ m)
+ 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
+ ;;
+ o)
+ get_arg $first_token $2
+ stap_options="$stap_options -$first_char $stap_arg"
+ ;;
+ p)
+ 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 -$first_char and --unprivileged together."
+ else
+ stap_options="$stap_options -$first_char $stap_arg"
+ fi
+ ;;
+ s)
+ get_arg $first_token $2
+ stap_options="$stap_options -$first_char $stap_arg"
+ ;;
+ S)
+ get_arg $first_token $2
+ stap_options="$stap_options -$first_char $stap_arg"
+ ;;
+ x)
+ get_arg $first_token $2
+ stap_options="$stap_options -$first_char $stap_arg"
+ ;;
+ *)
+ # An unknown flag. Ignore it.
+ ;;
+ esac
+
+ if test $advance_p = 0; then
+ # Just another flag character. Consume it.
+ stap_options="$stap_options -$first_char"
+ 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 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: process_e ARGUMENT
+#
+# Process the -e flag.
+function process_e {
+ if test "X$e_script" = "X"; then
+ e_script="$1"
+ script_file=
+ fi
+}
+
+# function: process_p ARGUMENT
+#
+# Process the -p flag.
+function process_p {
+ if test $1 -ge 1 -a $1 -le 5; then
+ p_phase=$1
+ fi
+}
+
+# function: call_stap
+#
+# Call 'stap' with the options provided. Don't run past phase 4.
+function call_stap {
+ # Invoke systemtap.
+ # Use -k so we can return results to the client
+ # Limit to -p4. i.e. don't run the module
+ cd $tmpdir_client
+ if test $p_phase -gt 4; then
+ server_p_phase=4
+ else
+ server_p_phase=$p_phase
+ fi
+
+ eval ${stap_exec_prefix}stap "$stap_options" -k -p $server_p_phase \
+ >> $tmpdir_server/stdout \
+ 2>> $tmpdir_server/stderr
+
+ stap_rc=$?
+}
+
+# function: create_response
+#
+# Add information to the server's temp directory representing the response
+# to the client.
+function create_response {
+ cd $tmpdir_server
+
+ # Get the name of the stap temp directory, which was kept, from stderr.
+ tmpdir_line=`cat stderr | grep "Keeping temp"`
+ tmpdir_stap=`expr "$tmpdir_line" : '.*"\(.*\)".*'`
+
+ # Remove the message about keeping the stap temp directory from stderr, unless
+ # the user did request to keep it.
+ if test "X$tmpdir_stap" != "X"; then
+ if test $keep_temps != 1; then
+ sed -i "/^Keeping temp/d" stderr
+ fi
+
+ # Add the contents of the stap temp directory to the server output directory
+ ln -s $tmpdir_stap `basename $tmpdir_stap`
+
+ # Sign the resulting module if --unprivileged was specified.
+ 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_pkglibexecdir}stap-sign-module $modname $ssl_db
+ fi
+ fi
+ fi
+
+ # If the user specified -p5, remove the name of the kernel module from stdout.
+ if test $p_phase = 5; then
+ sed -i '/\.ko$/d' stdout
+ fi
+
+ # The return status of the stap command.
+ echo -n $stap_rc > rc
+}
+
+# function: package_response
+#
+# Package the server's temp directory into a form suitable for sending to the
+# client.
+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)
+ return $?
+}
+
+# function: fatal [ MESSAGE ]
+#
+# Fatal error
+# Prints its arguments to stderr and exits
+function fatal {
+ echo "$0: ERROR:" "$@" >> $tmpdir_server/stderr
+ echo -n 1 > $tmpdir_server/rc
+ package_response
+ cleanup
+ exit 1
+}
+
+# Non fatal error
+# Prints its arguments to stderr but does not exit
+function error {
+ echo "$0: ERROR:" "$@" >> $tmpdir_server/stderr
+}
+
+# function cleanup
+#
+# Cleanup work files unless asked to keep them.
+function cleanup {
+ # Clean up.
+ cd $tmpdir_env
+ if test $keep_temps != 1; then
+ rm -fr $tmpdir_server
+ rm -fr $tmpdir_client
+ rm -fr $tmpdir_stap
+ fi
+}
+
+# function: terminate
+#
+# Terminate gracefully.
+function terminate {
+ # Clean up
+ cleanup
+ exit 1
+}
+
+#-----------------------------------------------------------------------------
+# Beginning of main line execution.
+#-----------------------------------------------------------------------------
+initialization "$@"
+unpack_request
+check_request
+call_stap
+create_response
+package_response
+cleanup
+
+exit 0