]> sourceware.org Git - systemtap.git/blame - stap-client
New basic tests for client/server.
[systemtap.git] / stap-client
CommitLineData
ab19dac7
DB
1#!/bin/bash
2
3# Compile server client for systemtap
4#
64aa100f 5# Copyright (C) 2008, 2009 Red Hat Inc.
ab19dac7
DB
6#
7# This file is part of systemtap, and is free software. You can
8# redistribute it and/or modify it under the terms of the GNU General
9# Public License (GPL); either version 2, or (at your option) any
10# later version.
11
12# This script examines the systemtap command line and packages the files and
13# information needed to execute the command. This is then sent to a trusted
14# systemtap server which will process the request and return the resulting
15# kernel module (if requested) and any other information generated by the
16# request. If a kernel module is generated, this script will load the module
17# and execute it using 'staprun', if requested.
18
7f772051
DB
19# Catch ctrl-c and other termination signals
20trap 'terminate' SIGTERM
21trap 'interrupt' SIGINT
1598733b 22trap 'ignore_signal' SIGHUP SIGPIPE
7f772051 23
ab19dac7
DB
24#-----------------------------------------------------------------------------
25# Helper functions.
26#-----------------------------------------------------------------------------
27# function: configuration
28function configuration {
552276c8
DB
29 # INSTALL-HOOK These settings work for running the client from the source tree
30 # INSTALL-HOOK using the dejagnu test harness and will be overridden at install
31 # INSTALL-HOOK time.
32 exec_prefix=
33 sysconfdir=`pwd`/net
34
35 # General configuration
ab19dac7
DB
36 tmpdir_prefix_client=stap.client
37 tmpdir_prefix_server=stap.server
f087e30e 38 avahi_service_tag=_stap._tcp
ab19dac7
DB
39}
40
41# function: initialization
42function initialization {
c5b08ee1
DB
43 our_host_name=`expr "$HOSTNAME" : "\\\([a-zA-Z0-9-]*\\\).*"`
44 our_domain_name=`expr "$HOSTNAME" : "$our_host_name\\\(.*\\\)"`
45
d5658775 46 rc=0
ab19dac7
DB
47 wd=`pwd`
48 umask 0
b7afc05d 49 staprun_running=0
ab19dac7 50
64aa100f 51 # Default location for server certificates if we're not root
552276c8
DB
52 # Must be owned by us.
53 local uid uname
64aa100f 54 if test $EUID != 0; then
552276c8
DB
55 if test -e $HOME/.systemtap/ssl/client; then
56 if check_db $HOME/.systemtap/ssl/client $EUID $USER; then
57 local_ssl_dbs=$HOME/.systemtap/ssl/client
58 fi
cbac7162 59 fi
64aa100f 60 fi
552276c8
DB
61 # Additional location for all users. Must be owned by root.
62 if test "X$sysconfdir" != "X"; then
63 if test -e $sysconfdir/systemtap/ssl/client; then
64 if check_db $sysconfdir/systemtap/ssl/client 0 root; then
65 public_ssl_dbs=$sysconfdir/systemtap/ssl/client
66 fi
67 fi
cbac7162 68 fi
64aa100f 69
ab19dac7
DB
70 # Default options settings
71 p_phase=5
72 v_level=0
73 keep_temps=0
1598733b 74 b_specified=0
ab19dac7 75
cbac7162
DB
76 # Default variable settings
77 find_all=
78
ab19dac7
DB
79 # Create a temporary directory to package things in
80 # Do this before parsing the command line so that there is a place
81 # to put -I and -R directories.
82 tmpdir_client=`mktemp -dt $tmpdir_prefix_client.XXXXXX` || \
552276c8 83 fatal "Cannot create temporary directory " $tmpdir_client
ab19dac7
DB
84 tmpdir_env=`dirname $tmpdir_client`
85}
86
87# function: parse_options [ STAP-OPTIONS ]
88#
89# Examine the command line. We need not do much checking, but we do need to
90# parse all options in order to discover the ones we're interested in.
91# The server will take care of most situations and return the appropriate
92# output.
93#
94function parse_options {
95 cmdline=
d5658775
DB
96 cmdline1=
97 cmdline2=
ab19dac7
DB
98 while test $# != 0
99 do
100 advance_p=0
101 dash_seen=0
102
103 # Start of a new token.
104 first_token=$1
105 until test $advance_p != 0
106 do
107 # Identify the next option
108 first_char=`expr "$first_token" : '\(.\).*'`
d5658775 109 second_char=
ab19dac7
DB
110 if test $dash_seen = 0; then
111 if test "$first_char" = "-"; then
112 if test "$first_token" != "-"; then
d5658775
DB
113 # It's not a lone dash, so it's an option.
114 # Is it a long option (i.e. --option)?
115 second_char=`expr "$first_token" : '.\(.\).*'`
1cecb3c5
DB
116 if test "X$second_char" = "X-"; then
117 long_option=`expr "$first_token" : '--\(.*\)=.*'`
118 test "X$long_option" != "X" || long_option=`expr "$first_token" : '--\(.*\)'`
119 case $long_option in
120 ssl)
121 process_ssl $first_token
122 ;;
078198eb
DB
123 server)
124 process_server $first_token
125 ;;
1cecb3c5
DB
126 *)
127 # An unknown or unimportant option.
128 # Ignore it, but pass it on to the server.
129 cmdline2="$cmdline2 $first_token"
130 ;;
131 esac
132 advance_p=$(($advance_p + 1))
133 break
d5658775 134 fi
1cecb3c5
DB
135 # It's not a lone dash, or a long option, so it's a short option string.
136 # Remove the dash.
137 first_token=`expr "$first_token" : '-\(.*\)'`
138 dash_seen=1
139 first_char=`expr "$first_token" : '\(.\).*'`
140 cmdline2="$cmdline2 -"
ab19dac7
DB
141 fi
142 fi
143 if test $dash_seen = 0; then
144 # The dash has not been seen. This is either the script file
d5658775 145 # name, a long argument or an argument to be passed to the probe module.
ab19dac7
DB
146 # If this is the first time, and -e has not been specified,
147 # then it could be the name of the script file.
d5658775
DB
148 if test "X$second_char" = "X-"; then
149 cmdline2="$cmdline2 $first_token"
150 elif test "X$e_script" = "X" -a "X$script_file" = "X"; then
ab19dac7 151 script_file=$first_token
d5658775
DB
152 cmdline1="$cmdline2"
153 cmdline2=
b5935516 154 elif test "$first_char" != "'"; then
d5658775 155 cmdline2="$cmdline2 '$first_token'"
b5935516
DB
156 else
157 cmdline2="$cmdline2 $first_token"
ab19dac7
DB
158 fi
159 advance_p=$(($advance_p + 1))
ab19dac7
DB
160 break
161 fi
162 fi
163
164 # We are at the start of an option. Look at the first character.
165 case $first_char in
1598733b
DB
166 b)
167 b_specified=1
168 ;;
ab19dac7
DB
169 c)
170 get_arg $first_token "$2"
171 process_c "$stap_arg"
172 ;;
173 D)
174 get_arg $first_token $2
d5658775 175 cmdline2="${cmdline2}D '$stap_arg'"
ab19dac7
DB
176 ;;
177 e)
178 get_arg $first_token "$2"
179 process_e "$stap_arg"
180 ;;
181 I)
182 get_arg $first_token $2
183 process_I $stap_arg
184 ;;
185 k)
186 keep_temps=1
187 ;;
188 l)
189 get_arg $first_token $2
d5658775 190 cmdline2="${cmdline2}l '$stap_arg'"
ab19dac7
DB
191 ;;
192 m)
193 get_arg $first_token $2
1598733b 194 process_m $stap_arg
ab19dac7
DB
195 ;;
196 o)
197 get_arg $first_token $2
198 process_o $stap_arg
199 ;;
200 p)
201 get_arg $first_token $2
202 process_p $stap_arg
203 ;;
204 r)
205 get_arg $first_token $2
1598733b 206 cmdline2="${cmdline2}r '$stap_arg'"
ab19dac7
DB
207 ;;
208 R)
209 get_arg $first_token $2
210 process_R $stap_arg
211 ;;
212 s)
213 get_arg $first_token $2
1598733b 214 cmdline2="${cmdline2}s '$stap_arg'"
ab19dac7
DB
215 ;;
216 v)
217 v_level=$(($v_level + 1))
218 ;;
219 x)
220 get_arg $first_token $2
1598733b 221 cmdline2="${cmdline2}x '$stap_arg'"
ab19dac7
DB
222 ;;
223 *)
224 # An unknown or unimportant flag. Ignore it, but pass it on to the server.
225 ;;
226 esac
227
228 if test $advance_p = 0; then
229 # Just another flag character. Consume it.
d5658775 230 cmdline2="$cmdline2$first_char"
ab19dac7
DB
231 first_token=`expr "$first_token" : '.\(.*\)'`
232 if test "X$first_token" = "X"; then
233 advance_p=$(($advance_p + 1))
234 fi
235 fi
236 done
237
238 # Consume the arguments we just processed.
239 while test $advance_p != 0
240 do
241 shift
242 advance_p=$(($advance_p - 1))
243 done
244 done
245
246 # If the script file was given and it's not '-', then replace it with its
247 # client-temp-name in the command string.
0e47827d
DB
248 if test "X$script_file" != "X"; then
249 local local_name
250 if test "$script_file" != "-"; then
251 local_name=`generate_client_temp_name $script_file`
252 else
253 local_name=$script_file
254 fi
d5658775
DB
255 cmdline="$cmdline1 script/$local_name $cmdline2"
256 else
257 cmdline="$cmdline1 $cmdline2"
ab19dac7 258 fi
64aa100f 259
cbac7162
DB
260 # Processing based on final options settings
261 # Complete the list of local certificate databases
64aa100f 262 local_ssl_dbs="$additional_local_ssl_dbs $local_ssl_dbs"
cbac7162 263
552276c8
DB
264 # We must have at least one usable certificate database.
265 test "X$local_ssl_dbs" != "X " -o "X$public_ssl_dbs" != "X" || \
266 fatal "No usable certificate databases found"
267
cbac7162
DB
268 # We can use any server if the phase is less than 5
269 if test $p_phase -lt 5; then
270 find_all="--all"
271 fi
ab19dac7
DB
272}
273
274# function: get_arg FIRSTWORD SECONDWORD
275#
276# Collect an argument to the given option
277function get_arg {
278 # Remove first character.
279 local opt=`expr "$1" : '\(.\).*'`
280 local first=`expr "$1" : '.\(.*\)'`
281
282 # Advance to the next token, if the first one is exhausted.
283 if test "X$first" = "X"; then
284 shift
285 advance_p=$(($advance_p + 1))
286 first=$1
287 fi
288
289 test "X$first" != "X" || \
290 fatal "Missing argument to -$opt"
291
292 stap_arg="$first"
293 advance_p=$(($advance_p + 1))
294}
295
1cecb3c5
DB
296# function: process_ssl ARGUMENT
297#
298# Process the --ssl option.
299function process_ssl {
300 local db=`expr "$1" : '--ssl=\(.*\)'`
301
302 test "X$db" != "X" || \
303 fatal "Missing argument to --ssl"
cbac7162
DB
304
305 check_db $db || return
306
64aa100f 307 additional_local_ssl_dbs="$additional_local_ssl_dbs $db"
1cecb3c5
DB
308}
309
078198eb
DB
310# function: process_server ARGUMENT
311#
312# Process the --server option.
313function process_server {
314 local spec=`expr "$1" : '--server=\(.*\)'`
315
316 test "X$spec" != "X" || \
317 fatal "Missing argument to --server"
318
319 specified_servers="$specified_servers $spec"
320}
321
ab19dac7
DB
322# function: process_c ARGUMENT
323#
324# Process the -c flag.
325function process_c {
326 c_cmd="$1"
d5658775 327 cmdline2="${cmdline2}c '$1'"
ab19dac7
DB
328}
329
330# function: process_e ARGUMENT
331#
332# Process the -e flag.
333function process_e {
334 # Only the first -e option is recognized and it overrides any script file name
335 # which may have already been identified.
336 if test "X$e_script" = "X"; then
337 e_script="$1"
d5658775
DB
338 if test "X$script_file" != "X"; then
339 cmdline1="$cmdline1 $script_file $cmdline2"
340 cmdline2=
341 script_file=
342 fi
ab19dac7 343 fi
d5658775 344 cmdline2="${cmdline2}e '$1'"
ab19dac7
DB
345}
346
347# function: process_I ARGUMENT
348#
349# Process the -I flag.
350function process_I {
351 local local_name=`include_file_or_directory tapsets $1`
352 test "X$local_name" != "X" || return
d5658775 353 cmdline2="${cmdline2}I 'tapsets/$local_name'"
ab19dac7
DB
354}
355
1598733b
DB
356# function: process_m ARGUMENT
357#
358# Process the -m flag.
359function process_m {
360 m_name="$1"
361 cmdline2="${cmdline2}m '$1'"
362}
363
ab19dac7
DB
364# function: process_o ARGUMENT
365#
366# Process the -o flag.
367function process_o {
1598733b 368 stdout_redirection="$1"
d5658775 369 cmdline2="${cmdline2}o '$1'"
ab19dac7
DB
370}
371
372# function: process_p ARGUMENT
373#
374# Process the -p flag.
375function process_p {
376 p_phase=$1
d5658775 377 cmdline2="${cmdline2}p '$1'"
ab19dac7
DB
378}
379
380# function: process_R ARGUMENT
381#
382# Process the -R flag.
383function process_R {
384 local local_name=`include_file_or_directory runtime $1`
385 test "X$local_name" != "X" || return
d5658775 386 cmdline2="${cmdline2}R 'runtime/$local_name'"
ab19dac7
DB
387}
388
389# function: include_file_or_directory PREFIX NAME
390#
391# Include the given file or directory in the client's temporary
392# tree to be sent to the server.
393function include_file_or_directory {
0e47827d 394 # Add a symbolic link of the named file or directory to our temporary directory
ab19dac7
DB
395 local local_name=`generate_client_temp_name $2`
396 mkdir -p $tmpdir_client/$1/`dirname $local_name` || \
552276c8 397 fatal "Could not create $tmpdir_client/$1/`dirname $local_name`"
ab19dac7 398 ln -s /$local_name $tmpdir_client/$1/$local_name || \
552276c8 399 fatal "Could not link $tmpdir_client/$1/$local_name to /$local_name"
d5658775 400 echo "$local_name"
ab19dac7
DB
401}
402
403# function: generate_client_temp_name NAME
404#
405# Generate the name to be used for the given file/directory relative to the
406# client's temporary directory.
407function generate_client_temp_name {
408 # Transform the name into a fully qualified path name
d5658775 409 local full_name=`echo "$1" | sed "s,^\\\([^/]\\\),$wd/\\\\1,"`
ab19dac7
DB
410
411 # The same name without the initial / or trailing /
d5658775
DB
412 local local_name=`echo "$full_name" | sed 's,^/\(.*\),\1,'`
413 local_name=`echo "$local_name" | sed 's,\(.*\)/$,\1,'`
414 echo "$local_name"
ab19dac7
DB
415}
416
417# function: create_request
418#
419# Add information to the client's temp directory representing the request
420# to the server.
421function create_request {
422 # Work in our temporary directory
423 cd $tmpdir_client
424
425 if test "X$script_file" != "X"; then
426 if test "$script_file" = "-"; then
427 mkdir -p $tmpdir_client/script || \
552276c8 428 fatal "Cannot create temporary directory " $tmpdir_client/script
0e47827d 429 cat > $tmpdir_client/script/$script_file
ab19dac7
DB
430 else
431 include_file_or_directory script $script_file > /dev/null
432 fi
433 fi
434
161be0d9
DB
435 # Add the necessary info to special files in our temporary directory.
436 echo "cmdline: $cmdline" > cmdline
437 echo "sysinfo: `client_sysinfo`" > sysinfo
ab19dac7
DB
438}
439
440# function client_sysinfo
441#
442# Generate the client's sysinfo and echo it to stdout
443function client_sysinfo {
444 if test "X$sysinfo_client" = "X"; then
ab19dac7 445 # Add some info from uname
b7278cda 446 sysinfo_client="`uname -rvm`"
ab19dac7 447 fi
d5658775 448 echo "$sysinfo_client"
ab19dac7
DB
449}
450
451# function: package_request
452#
453# Package the client's temp directory into a form suitable for sending to the
454# server.
455function package_request {
1cecb3c5 456 # Package up the temporary directory into a zip file
ab19dac7
DB
457 cd $tmpdir_env
458
459 local tmpdir_client_base=`basename $tmpdir_client`
1cecb3c5 460 zip_client=$tmpdir_env/`mktemp $tmpdir_client_base.zip.XXXXXX` || \
552276c8 461 fatal "Cannot create temporary file " $zip_client
ab19dac7 462
1cecb3c5 463 (rm $zip_client && zip -r $zip_client $tmpdir_client_base > /dev/null) || \
552276c8 464 fatal "zip of request tree, $tmpdir_client, failed"
ab19dac7
DB
465}
466
467# function: unpack_response
468#
89dd03e3 469# Unpack the zip file received from the server and make the contents available
ab19dac7
DB
470# for printing the results and/or running 'staprun'.
471function unpack_response {
66e1a139 472 tmpdir_server=`mktemp -dt $tmpdir_prefix_client.server.XXXXXX` || \
552276c8 473 fatal "Cannot create temporary file " $tmpdir_server
66e1a139 474
1cecb3c5 475 # Unpack the server output directory
89dd03e3
DB
476 unzip -d $tmpdir_server $zip_server > /dev/null || \
477 fatal "Cannot unpack server response, $zip_server"
478
479 # Check the contents of the expanded directory. It should contain a
480 # single directory whose name matches stap.server.??????
481 local num_files=`ls $tmpdir_server | wc -l`
482 test $num_files = 1 || \
483 fatal "Wrong number of files in server's temp directory"
484 test -d $tmpdir_server/stap.server.?????? || \
485 fatal "`ls $tmpdir_server` does not match the expected name or is not a directory"
486 # Move the contents of the directory down one level.
487 mv $tmpdir_server/stap.server.??????/* $tmpdir_server
488 rm -fr $tmpdir_server/stap.server.??????
66e1a139 489
89dd03e3 490 # Check the contents of the directory. It should contain:
66e1a139
DB
491 # 1) a file called stdout
492 # 2) a file called stderr
b7afc05d 493 # 3) a file called rc
89dd03e3
DB
494 # 4) optionally a directory named to match stap??????
495 num_files=`ls $tmpdir_server | wc -l`
496 test $num_files = 4 -o $num_files = 3 || \
552276c8 497 fatal "Wrong number of files in server's temp directory"
66e1a139 498 test -f $tmpdir_server/stdout || \
552276c8 499 fatal "`pwd`/$tmpdir_server/stdout does not exist or is not a regular file"
66e1a139 500 test -f $tmpdir_server/stderr || \
552276c8 501 fatal "`pwd`/$tmpdir_server/stderr does not exist or is not a regular file"
b7afc05d 502 test -f $tmpdir_server/rc || \
552276c8 503 fatal "`pwd`/$tmpdir_server/rc does not exist or is not a regular file"
66e1a139 504
0e47827d 505 # See if there is a systemtap temp directory
9e494cbb 506 tmpdir_stap=`cd $tmpdir_server && ls | grep stap......\$ 2>/dev/null`
0e47827d
DB
507 if test "X$tmpdir_stap" != "X"; then
508 test -d $tmpdir_server/$tmpdir_stap || \
9e494cbb 509 fatal "$tmpdir_server/$tmpdir_stap is not a directory"
0e47827d
DB
510
511 # Move the systemtap temp directory to a local temp location, if -k
512 # was specified.
513 if test $keep_temps = 1; then
514 local local_tmpdir_stap=`mktemp -dt stapXXXXXX` || \
552276c8 515 fatal "Cannot create temporary directory " $local_tmpdir_stap
0e47827d
DB
516 mv $tmpdir_server/$tmpdir_stap/* $local_tmpdir_stap 2>/dev/null
517 rm -fr $tmpdir_server/$tmpdir_stap
518
519 # Correct the name of the temp directory in the server's stderr output
520 sed -i "s,^Keeping temporary directory.*,Keeping temporary directory \"$local_tmpdir_stap\"," $tmpdir_server/stderr
521 tmpdir_stap=$local_tmpdir_stap
522 else
7f772051
DB
523 # Make sure we own the systemtap temp directory if we are root.
524 test $EUID = 0 && chown $EUID:$EUID $tmpdir_server/$tmpdir_stap
0e47827d 525 fi
ab19dac7 526 fi
ab19dac7
DB
527}
528
529# function: find_and_connect_to_server
530#
0e47827d 531# Find and establish connection with a compatible stap server.
ab19dac7 532function find_and_connect_to_server {
078198eb
DB
533 local num_servers=0
534
535 # Make a place to receive the response file.
89dd03e3
DB
536 zip_server=`mktemp -t $tmpdir_prefix_client.server.zip.XXXXXX` || \
537 fatal "Cannot create temporary file " $zip_server
078198eb 538
cbac7162
DB
539 # Make a place to record connection errors
540 touch $tmpdir_client/connect
541
078198eb
DB
542 # If servers were specified on the command line, then try them
543 # in sequence. Don't try any other servers.
544 if test "X$specified_servers" != "X"; then
545 for server in $specified_servers; do
546 num_servers=$(($num_servers + 1))
547
548 # If the server is completely specified, (i.e. server:port),
549 # then try it directly.
550 port=`expr "$server" : '.\+:\([0-9]\+\)'`
551 if test "X$port" != "X"; then
552 name=`expr "$server" : '\(.\+\):[0-9]\+'`
553
554 # If we have been given an ip address, then try to resolve it to a name.
555 # If we have been given a name, try to resolve the full name.
556 # The full name is needed in order to validate the server's certificate.
557 address=`expr "$name" : '\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)'`
558 if test "X$address" = "X"; then
559 # We've been given a host name
560 full_name=`nslookup $name | awk '/^Name\:/ {print $2}'`
561 if test "X$full_name" != "X"; then
562 name=$full_name
563 fi
564 else
565 # We've been given an ip address.
c5b08ee1
DB
566 name=`nslookup $address | awk '/in-addr\.arpa/ {print $4}'`
567 name=`expr "$name" : '\(.*\)\.'`
078198eb
DB
568 if test "X$name" = "X"; then
569 echo "Cannot resolve ip address $address" >> $tmpdir_client/connect
570 continue
571 fi
572 fi
573
574 # Now try to contact the given server.
575 ssl_db=`send_receive $name $port`
576 test "X$ssl_db" != "X" && return
577 continue
578 fi
579
580 # Otherwise select the matching server from the available servers
581 # and use the port it is advertizing.
582 #
583 # Have we been given an ip address? If so, just use it.
584 address=`expr "$server" : '\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)'`
585 if test "X$address" = "X"; then
586 # We have not been given an ip address. Try to resolve it as a host name.
c5b08ee1
DB
587 if test "X$server" = "Xlocalhost"; then
588 # We don't want the address of the loopback interface here. Avahi will present
589 # the actual ip address.
590 server=$our_host_name$our_domain_name
591 fi
078198eb
DB
592 address=`nslookup $server | awk '/^Address\:[ \t][0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/ {print $2}'`
593 if test "X$address" = "X"; then
c5b08ee1
DB
594 echo "Cannot resolve server $server" >> $tmpdir_client/connect
595 continue
078198eb
DB
596 fi
597 fi
598
cbac7162 599 if test `${exec_prefix}stap-find-servers $find_all | grep $address | wc -l` = "0"; then
0c44723c 600 warning "No server is available on $server" 2>> $tmpdir_client/connect
078198eb
DB
601 continue
602 fi
603
cbac7162 604 ssl_db=`${exec_prefix}stap-find-servers $find_all | grep $address | choose_server`
078198eb
DB
605 test "X$ssl_db" != "X" && return
606 done
607 else
608 # No servers specified. Find available servers and choose one of them.
609 # Remember which ssl certificate database was used to authenticate the chosen
610 # server.
cbac7162 611 ssl_db=`${exec_prefix}stap-find-servers $find_all | choose_server`
078198eb
DB
612 test "X$ssl_db" != "X" && return
613
cbac7162 614 num_servers=`${exec_prefix}stap-find-servers $find_all | wc -l`
078198eb
DB
615 fi
616
617 if test $num_servers = 0; then
552276c8 618 fatal "Unable to find a server"
078198eb
DB
619 fi
620
621 cat $tmpdir_client/connect >&2
552276c8 622 fatal "Unable to connect to a server"
ab19dac7
DB
623}
624
0e47827d 625# function: choose_server
ab19dac7 626#
0e47827d
DB
627# Examine each line from stdin and attempt to connect to each server
628# specified until successful.
078198eb
DB
629# echo the name of the ssl certificate database used to successfully authenticate
630# the server.
0e47827d 631function choose_server {
c5b08ee1 632 local name ip port remain
078198eb 633
c5b08ee1 634 while read name ip port remain
ab19dac7 635 do
c5b08ee1 636 if test "X$name" = "X"; then
552276c8 637 fatal "Server name not provided by avahi"
1cecb3c5
DB
638 fi
639
c5b08ee1 640# if test "X$ip" = "X"; then
552276c8 641# fatal "Server ip address not provided by avahi"
c5b08ee1 642# fi
ab19dac7 643
0e47827d 644 if test "X$port" = "X"; then
552276c8 645 fatal "Server port not provided by avahi"
ab19dac7
DB
646 fi
647
c5b08ee1 648 ssl_db=`send_receive $name $port`
078198eb 649 test "X$ssl_db" != "X" && echo $ssl_db && return
ab19dac7 650 done
0e47827d
DB
651}
652
078198eb 653# function: send_receive SERVER PORT
0e47827d 654#
1cecb3c5 655# Connect to the server, send the request and receive the response
078198eb
DB
656# echo the name of the ssl certificate database used to successfully authenticate
657# the server.
1cecb3c5 658function send_receive {
078198eb
DB
659 local server=$1
660 local port=$2
b5935516 661
c5b08ee1
DB
662 # The server must match the dns name on the certificate
663 # and must be 'localhost' if the server is on the local host.
664 local server_host_name=`expr "$server" : "\\\([a-zA-Z0-9-]*\\\).*"`
665 local server_domain_name=`expr "$server" : "$server_host_name\\\(.*\\\)"`
666
667 if test "X$server_domain_name" = "X.local"; then
668 server_domain_name=$our_domain_name
669 fi
670 if test "X$server_host_name$server_domain_name" = "Xlocalhost$our_domain_name"; then
671 server=localhost
672 elif test "X$server_host_name$server_domain_name" = "X$our_host_name$our_domain_name"; then
673 server=localhost
674 else
675 server=$server_host_name$server_domain_name
676 fi
677
078198eb
DB
678 # Try to connect using each of the given local certificate databases in turn
679 # for verification.
680 for db in $local_ssl_dbs
681 do
682 # Send the request and receive the response using stap-client-connect
c5b08ee1 683 echo "Attempting connection with $server:$port using certificate database in '$db'" >> $tmpdir_client/connect
89dd03e3 684 ${exec_prefix}stap-client-connect -i $zip_client -o $zip_server -d $db -p $port -h $server >> $tmpdir_client/connect 2>&1 &
078198eb
DB
685 wait '%${exec_prefix}stap-client-connect'
686 test $? = 0 && echo $db && return
687 sleep 1
688 done
64aa100f 689
078198eb 690 # Next, try the public certificate databases.
64aa100f
DB
691 for db in $public_ssl_dbs
692 do
693 # Send the request and receive the response using stap-client-connect
c5b08ee1 694 echo "Attempting connection with $server:$port using certificate database in '$db'" >> $tmpdir_client/connect
89dd03e3 695 ${exec_prefix}stap-client-connect -i $zip_client -o $zip_server -d $db -p $port -h $server >> $tmpdir_client/connect 2>&1 &
21325e0c 696 wait '%${exec_prefix}stap-client-connect'
078198eb 697 test $? = 0 && echo $db && return
64aa100f
DB
698 sleep 1
699 done
ab19dac7 700
64aa100f 701 # Could not connect using any of the certificate databases
ab19dac7
DB
702}
703
b7afc05d 704# function: process_response
ab19dac7
DB
705#
706# Write the stdout and stderr from the server to stdout and stderr respectively.
b7afc05d 707function process_response {
1598733b 708 # Pick up the results of running stap on the server.
1cecb3c5 709 cd $tmpdir_server
1598733b
DB
710 rc=`cat rc`
711
712 # Copy the module to the current directory, if -m was specified
713 if test "X$m_name" != "X"; then
714 if test -f $tmpdir_stap/$m_name.ko; then
715 cp $tmpdir_stap/$m_name.ko $wd
716 else
717 stream_output
718 fatal "module $tmpdir_stap/$m_name.ko does not exist"
719 fi
720 fi
721
ab19dac7 722 # Output stdout and stderr as directed
1598733b
DB
723 stream_output
724}
725
726# function: stream_output
727#
728# Output stdout and stderr as directed
729function stream_output {
66e1a139
DB
730 cd $tmpdir_server
731 cat stderr >&2
1598733b 732 cat stdout
ab19dac7
DB
733}
734
735# function: maybe_call_staprun
736#
737# Call staprun using the module returned from the server, if requested.
738function maybe_call_staprun {
d5658775
DB
739 if test $rc != 0; then
740 # stap run on the server failed, so don't bother
741 return
742 fi
0e47827d 743
d5658775
DB
744 if test $p_phase -ge 4; then
745 # There should be a systemtap temporary directory.
746 if test "X$tmpdir_stap" = "X"; then
747 # OK if no script specified
7f772051 748 if test "X$e_script" != "X" -o "X$script_file" != "X"; then
552276c8 749 fatal "systemtap temporary directory is missing in server response"
d5658775
DB
750 fi
751 return
752 fi
753
754 # There should be a module.
0e47827d 755 local mod_name=`ls $tmpdir_stap | grep '.ko$'`
d5658775 756 if test "X$mod_name" = "X"; then
552276c8 757 fatal "No module was found in $tmpdir_stap"
d5658775 758 fi
0e47827d 759
d5658775 760 if test $p_phase = 5; then
1598733b
DB
761 test $v_level -gt 0 && echo "Pass 5: starting run." >&2
762
d5658775 763 # We have a module. Try to run it
7f772051
DB
764 # If a -c command was specified, pass it along.
765 if test "X$c_cmd" != "X"; then
766 staprun_opts="-c '$c_cmd'"
767 fi
768
769 # The -v level will be one less than what was specified
770 # for us.
1598733b 771 for ((vl=$((v_level - 1)); $vl > 0; --vl))
d5658775
DB
772 do
773 staprun_opts="$staprun_opts -v"
774 done
7f772051 775
1598733b
DB
776 # if -o was specified, pass it along
777 if test "X$stdout_redirection" != "X"; then
778 staprun_opts="$staprun_opts -o $stdout_redirection"
779 fi
780
7f772051
DB
781 # Run it in the background and wait for it. This
782 # way any signals send to us can be caught.
1598733b
DB
783 if test $v_level -ge 2; then
784 echo "running `which staprun` $staprun_opts $tmpdir_stap/`ls $tmpdir_stap | grep '.ko$'`" >&2
785 fi
21325e0c 786 eval `staprun_PATH` "$staprun_opts" \
1598733b 787 $tmpdir_stap/`ls $tmpdir_stap | grep '.ko$'`
b7afc05d 788 staprun_running=1
1598733b 789 wait '%?staprun' > /dev/null 2>&1
d5658775 790 rc=$?
b7afc05d 791 staprun_running=0
7f772051
DB
792 # 127 from wait means that the job was already finished.
793 test $rc=127 && rc=0
1598733b
DB
794
795 # Wait until the job actually disappears so that its output is complete.
796 while jobs '%?staprun' >/dev/null 2>&1
797 do
798 sleep 1
799 done
800
801 test $v_level -gt 0 && echo "Pass 5: run completed in 0usr/0sys/0real ms." >&2
d5658775 802 fi
ab19dac7
DB
803 fi
804}
805
0e47827d
DB
806# function: staprun_PATH
807#
808# Compute a PATH suitable for running staprun.
809function staprun_PATH {
21325e0c
DB
810 # If $SYSTEMTAP_STAPRUN is set, then use that
811 if test "X$SYSTEMTAP_STAPRUN" != "X"; then
812 echo $SYSTEMTAP_STAPRUN
d52261ec
DB
813 return
814 fi
815
21325e0c
DB
816 # Otherwise, if there is an exec_prefix, then use it.
817 if test "X$exec_prefix" != "X"; then
818 echo ${exec_prefix}staprun
0e47827d
DB
819 return
820 fi
821
21325e0c
DB
822 # Otherwise, we have been called by the dejagnu test harness as 'stap'
823 # and we are the first 'stap' on the path. Since staprun may call
824 # 'stap', remove the PATH component where we live from the PATH in order to
825 # avoid recursion.
826 local first_stap=`which stap`
0e47827d 827 local PATH_component=`dirname $first_stap`
21325e0c 828 echo "PATH=$PATH staprun" | sed "s,$PATH_component,,g"
0e47827d
DB
829}
830
552276c8 831# function: check_db DBNAME [ EUID USER ]
cbac7162
DB
832#
833# Check the security of the given database directory.
834function check_db {
835 local dir=$1
552276c8
DB
836 local euid=$2
837 local user=$3
cbac7162
DB
838 local rc=0
839
840 # Check that we have been given a directory
841 if ! test -e $dir; then
842 warning "Certificate database '$dir' does not exist"
843 return 1
844 fi
845 if ! test -d $dir; then
846 warning "Certificate database '$dir' is not a directory"
847 return 1
848 fi
849
552276c8
DB
850 # If euid has been specified, then this directory must be owned by that
851 # user.
852 if test "X$euid" != "X"; then
853 local ownerid=`stat -c "%u" $dir`
854 if test "X$ownerid" != "X$euid"; then
855 warning "Certificate database '$dir' must be owned by $user"
856 rc=1
857 fi
858 fi
859
cbac7162 860 # Check that we can read the directory
4d6a58a6 861 if ! test -r $dir; then
cbac7162
DB
862 warning "Certificate database '$dir' is not readble"
863 rc=1
864 fi
865
866 # Check the access permissions of the directory
867 local perm=0`stat -c "%a" $dir`
4d6a58a6
DB
868 if test $((($perm & 0400) == 0400)) = 0; then
869 warning "Certificate database '$dir' should be readable by the owner"
870 fi
871 if test $((($perm & 0200) == 0200)) = 0; then
872 warning "Certificate database '$dir' should be writeable by the owner"
873 fi
874 if test $((($perm & 0100) == 0100)) = 0; then
875 warning "Certificate database '$dir' should be searchable by the owner"
876 fi
877 if test $((($perm & 0040) == 0040)) = 0; then
878 warning "Certificate database '$dir' should be readable by the group"
879 fi
cbac7162
DB
880 if test $((($perm & 0020) == 0020)) = 1; then
881 warning "Certificate database '$dir' must not be writable by the group"
882 rc=1
883 fi
4d6a58a6
DB
884 if test $((($perm & 0010) == 0010)) = 0; then
885 warning "Certificate database '$dir' should be searchable by the group"
886 fi
887 if test $((($perm & 0004) == 0004)) = 0; then
888 warning "Certificate database '$dir' should be readable by others"
889 fi
cbac7162
DB
890 if test $((($perm & 0002) == 0002)) = 1; then
891 warning "Certificate database '$dir' must not be writable by others"
892 rc=1
893 fi
4d6a58a6
DB
894 if test $((($perm & 0001) == 0001)) = 0; then
895 warning "Certificate database '$dir' should be searchable by others"
896 fi
cbac7162
DB
897
898 # Now check the permissions of the critical files.
552276c8
DB
899 check_db_file $dir/cert8.db $euid $user || rc=1
900 check_db_file $dir/key3.db $euid $user || rc=1
901 check_db_file $dir/secmod.db $euid $user || rc=1
cbac7162
DB
902
903 test $rc = 1 && warning "Unable to use certificate database '$dir' due to errors"
904
905 return $rc
906}
907
552276c8 908# function: check_db_file FILENAME [ EUID USER ]
cbac7162 909#
4d6a58a6 910# Check the security of the given database file.
cbac7162
DB
911function check_db_file {
912 local file=$1
913 local rc=0
914
915 # Check that we have been given a file
916 if ! test -e $file; then
917 warning "Certificate database file '$file' does not exist"
918 return 1
919 fi
920 if ! test -f $file; then
921 warning "Certificate database file '$file' is not a regular file"
922 return 1
923 fi
924
552276c8
DB
925 # If euid has been specified, then this directory must be owned by that
926 # user.
927 if test "X$euid" != "X"; then
928 local ownerid=`stat -c "%u" $file`
929 if test "X$ownerid" != "X$euid"; then
930 warning "Certificate database file '$file' must be owned by $user"
931 rc=1
932 fi
933 fi
934
cbac7162
DB
935 # Check that we can read the file
936 if ! test -r $file; then
937 warning "Certificate database file '$file' is not readble"
938 rc=1
939 fi
940
941 # Check the access permissions of the file
942 local perm=0`stat -c "%a" $file`
4d6a58a6
DB
943 if test $((($perm & 0400) == 0400)) = 0; then
944 warning "Certificate database file '$file' should be readable by the owner"
945 fi
946 if test $((($perm & 0200) == 0200)) = 0; then
947 warning "Certificate database file '$file' should be writeable by the owner"
948 fi
cbac7162
DB
949 if test $((($perm & 0100) == 0100)) = 1; then
950 warning "Certificate database file '$file' must not be executable by the owner"
951 rc=1
952 fi
4d6a58a6
DB
953 if test $((($perm & 0040) == 0040)) = 0; then
954 warning "Certificate database file '$file' should be readable by the group"
955 fi
cbac7162
DB
956 if test $((($perm & 0020) == 0020)) = 1; then
957 warning "Certificate database file '$file' must not be writable by the group"
958 rc=1
959 fi
960 if test $((($perm & 0010) == 0010)) = 1; then
961 warning "Certificate database file '$file' must not be executable by the group"
962 rc=1
963 fi
4d6a58a6
DB
964 if test $((($perm & 0004) == 0004)) = 0; then
965 warning "Certificate database file '$file' should be readable by others"
966 fi
cbac7162
DB
967 if test $((($perm & 0002) == 0002)) = 1; then
968 warning "Certificate database file '$file' must not be writable by others"
969 rc=1
970 fi
971 if test $((($perm & 0001) == 0001)) = 1; then
972 warning "Certificate database file '$file' must not be executable by others"
973 rc=1
974 fi
975
976 return $rc
977}
4d6a58a6 978
cbac7162
DB
979# function: warning [ MESSAGE ]
980#
981# Warning error
982# Prints its arguments to stderr
983function warning {
984 echo "$0: WARNING:" "$@" >&2
985}
986
ab19dac7
DB
987# function: fatal [ MESSAGE ]
988#
989# Fatal error
990# Prints its arguments to stderr and exits
991function fatal {
552276c8 992 echo "$0: ERROR:" "$@" >&2
66e1a139
DB
993 cleanup
994 exit 1
995}
996
ab19dac7
DB
997# function cleanup
998#
999# Cleanup work files unless asked to keep them.
1000function cleanup {
1001 # Clean up.
1002 cd $tmpdir_env
1003 if test $keep_temps != 1; then
1004 rm -fr $tmpdir_client
1cecb3c5 1005 rm -f $zip_client
89dd03e3 1006 rm -f $zip_server
ab19dac7
DB
1007 rm -fr $tmpdir_server
1008 fi
1009}
1010
7f772051
DB
1011# function: terminate
1012#
1013# Terminate gracefully.
1014function terminate {
1015 # Clean up
1598733b 1016 echo "$0: terminated by signal" >&2
7f772051
DB
1017 cleanup
1018
1019 # Kill any running staprun job
1598733b 1020 kill -s SIGTERM '%?staprun' 2>/dev/null
7f772051 1021
1cecb3c5 1022 # Kill any stap-client-connect job
72629a44 1023 kill -s SIGTERM '%${exec_prefix}stap-client-connect' 2>/dev/null
1cecb3c5 1024
7f772051
DB
1025 exit 1
1026}
1027
1028# function: interrupt
1029#
1030# Pass an interrupt (ctrl-C) to staprun
1031function interrupt {
1032 # Pass the signal on to any running staprun job
1598733b
DB
1033 if test $staprun_running = 1; then
1034 kill -s SIGINT '%?staprun' 2>/dev/null
1035 return
1036 fi
1037
1cecb3c5 1038 # Kill any stap-client-connect job
64aa100f 1039 # SIGINT won't do it.
72629a44 1040 kill -s SIGTERM '%${exec_prefix}stap-client-connect' 2>/dev/null
1cecb3c5 1041
1598733b
DB
1042 # If staprun was not running, then exit.
1043 cleanup
1044 exit 1
1045}
b7afc05d 1046
1598733b
DB
1047# function: ignore_signal
1048#
1049# Called in order to ignore a signal
1050function ignore_signal {
1051 :
7f772051
DB
1052}
1053
ab19dac7
DB
1054#-----------------------------------------------------------------------------
1055# Beginning of main line execution.
1056#-----------------------------------------------------------------------------
1057configuration
1058initialization
1059parse_options "$@"
1060create_request
1061package_request
1062find_and_connect_to_server
32a1dfe9 1063unpack_response
b7afc05d 1064process_response
ab19dac7
DB
1065maybe_call_staprun
1066cleanup
1067
d5658775 1068exit $rc
This page took 0.159447 seconds and 5 git commands to generate.