#!/bin/bash # Compile server manager for systemtap # # Copyright (C) 2008 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 publishes its presence on the network and then listens for # incoming connections. When a connection is detected, the stap-server script # is run to handle the request. # Catch ctrl-c and other termination signals trap 'terminate' SIGTERM SIGINT #----------------------------------------------------------------------------- # Helper functions. #----------------------------------------------------------------------------- # function: initialization PORT function initialization { # Default settings. avahi_type=_stap._tcp port=$1 test "X$port" = "X" && port=65000 export port2=$(($port + 1)) if netstat -atn | awk '{print $4}' | cut -f2 -d: | egrep -q "^($port|$port2)\$"; then # Whoops, the port is busy; try another one. initialization $((1024+($port + $RANDOM)%64000)) 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" # Call avahi-publish-service to advertise our presence. avahi-publish-service "Systemtap Compile Server on `uname -n`" \ $avahi_type $port "$txt" > /dev/null 2>&1 & echo "Systemtap Compile Server on `uname -n` listening on port $port" } # function: listen # # Listen for and handle requests to the server. function listen { # Loop forever accepting requests while true do for ((attempt=0; $attempt < 5; ++attempt)) do nc -ld $port 2>/dev/null | process_request & wait '%nc -l' rc=$? if test $rc = 0 -o $rc = 127; then break; # port was read ok fi done if test $attempt = 5; then fatal "ERROR: cannot listen on port $port. rc==$rc" fi done } # function: process_request # # Process an incoming request on stdin function process_request { read case $REPLY in request:) stap-server $port2 >/dev/null 2>&1 & wait '%stap-server' rc=$? test $rc = 127 && rc=0 ;; *) rc=1 esac exit $rc } # function: fatal [ MESSAGE ] # # Fatal error # Prints its arguments to stderr and exits function fatal { echo "$@" >&2 terminate exit 1 } # function: terminate # # Terminate gracefully. function terminate { echo "$0: Exiting" # Kill the running 'avahi-publish-service' job kill -s SIGTERM %avahi-publish-service 2> /dev/null wait '%avahi-publish-service' >/dev/null 2>&1 # Kill any running 'stap-server' job. kill -s SIGTERM "%stap-server" 2> /dev/null wait "%stap-server" >/dev/null 2>&1 # Kill any running 'nc -l' job. kill -s SIGTERM "%?nc -l" 2> /dev/null wait "%?nc - l" >/dev/null 2>&1 exit } #----------------------------------------------------------------------------- # Beginning of main line execution. #----------------------------------------------------------------------------- initialization "$@" advertise_presence listen