#! /bin/sh # Question 1: # Use the command basename and command substitution to write a simple # program that prints its own name. This should still work, even if the # program is renamed. Here is an example of running it: # $ ./myname.sh # This is myname.sh # $ mv myname.sh what-is-my-name # $ ./what-is-my-name # This is what-is-my-name prog=$(basename $0) echo "This is $prog" #! /bin/sh # Question 2: # Use the id program to determine the effective user ID number of the # user that runs the program. Print the message "I am root" if the user # id number is 0; print a different message otherwise. # Note: you should check the user id number, not the user id name. uid_num=$(id -u) if [ "$uid_num" -eq 0 ] then echo "I am root" else echo "I am not root" fi #! /bin/sh # Question 3: # Write a script that prints an error message and exits if a lockfile # exists. A lockfile is a file in the /tmp directory, with a name # equal to the basename of the script, followed by the string, # ``.lock'' For example, if the name of the script is lockit, then the # name of the lockfile shall be /tmp/lockit.lock prog=$(basename $0) lockfile="/tmp/${prog}.lock" if [ -e "$lockfile" ] then echo "lockfile exists" exit 1 else echo "No existing lockfile" fi # just to help in testing: sleep 60 #! /bin/sh # Question 4: # Modify your answer to question 3 so that the lockfile will be # /var/lock/subsys/basename of script.lock if the user executing it is # root, /tmp/basename of script.lock otherwise. prog=$(basename $0) uid_num=$(id -u) lockfile="/tmp/${prog}.lock" [ "$uid_num" -eq 0 ] && lockfile=/var/lock/subsys/${prog}.lock if [ -e "$lockfile" ] then echo "lockfile exists" exit 1 else echo "No existing lockfile" fi # just to help in testing: sleep 60 #! /bin/sh # Question 5: # Modify your answer to question 4 so that: # o if the lockfile exists, the program will print an error # message and terminate; # o if the lockfile doesn't exist, then the program creates it, # and makes sure that the lockfile was successfully created; # o when the program exits normally, it will remove the lockfile. prog=$(basename $0) uid_num=$(id -u) lockfile="/tmp/${prog}.lock" [ "$uid_num" -eq 0 ] && lockfile=/var/lock/subsys/${prog}.lock if [ -e "$lockfile" ] then echo "lockfile exists" exit 1 else touch $lockfile [ -e $lockfile ] || { echo "$prog: cannot create $lockfile"; exit 1; } fi # just to help in testing: sleep 60 rm -f $lockfile #! /bin/sh # Example to show signal handling for (( i = 1; i < 32; ++i )) do trap "echo caught signal $i; exit 1" $i done echo My process ID is $$ echo "Now copy and paste the following into another window:" echo 'for ((i=0;i < 32; ++i));do if ((i==9 || i==19));then let ++i;fi;echo Sending signal $i:;kill -$i '$$';sleep 1;done' echo Then try pasting this code, and understand why this process terminates: echo 'for ((i=0;i < 32; ++i));do echo Sending signal $i:;kill -$i '$$';sleep 1;done' # So how can we terminate it? # Note: # The colon `:' is the null statement that can be used wherever the # syntax requires a statement. It returns the value 0 (i.e., true). # In this case, it gives us an infinite loop. # Try: # $ help : while : do sleep 1 done # Try running this in one window, and in another window, type this: # for ((i=0;i < 32; ++i));do if ((i==9 || i==19));then let ++i;fi;echo Sending signal $i:;kill -$i 21306;sleep 1;done # Of course, instead of 21306, put the process ID of this process. # Then try removing the "if ((i==9 || i==19));then let ++i;fi;" statement, # and run it again. # Question 6: # Download the script # http://ictlab.tyict.vtc.edu.hk/ossi/lectures/shell/bin/trapall. # Make it executable and run it. Send the executing process all # signals in the range 1..31 as described in the existing comments # in the file. Modify it so that it will still print the message, but # it will exit when it receives any signal. In the modified program, # add comments that: # o explain how you could terminate the original program; # o list all signals in the range 1..31 that the original program could # not trap; # o explain why the signals you list cannot be trapped by the original # program. # Nick's answers: # 1. I saw the process ID of the trapall process, and in another window, # typed: # $ kill -9 process_id # or # $ kill -KILL process_id # where process_id is the PID of the trapall process. # 2. Only signals 9 (SIGKILL) and 19 (SIGSTOP) could not be handled # 3. The operating system ensures that these two processes cannot be # handled by a process. The KILL signal ensures that the system # administrator always has a way to terminate a process. The STOP # signal ensures that debuggers can always single step through a # program, and that a system administrator may "freeze" a process and # examine the process at leisure. This may be useful to examine a # process started by a cracker who has intruded into a system and has # run a program that needs to be examined to understand what damage # the cracker is trying to achieve. #! /bin/sh # Question 7: # Modify your answer to question 5 so that if the program receives any # of the following signals: INT, TERM, HUP or QUIT, the program will do # all of the following: # o print a message; # o remove the lockfile; # o exit with a non-zero exit status. prog=$(basename $0) uid_num=$(id -u) lockfile="/tmp/${prog}.lock" [ "$uid_num" -eq 0 ] && lockfile=/var/lock/subsys/${prog}.lock signal_handler() { echo "received a signal; terminating" rm -f $lockfile exit 1 } if [ -e "$lockfile" ] then echo "lockfile exists" exit 1 else trap signal_handler INT TERM HUP QUIT touch $lockfile [ -e $lockfile ] || { echo "$prog: cannot create $lockfile"; exit 1; } fi # just to help in testing: sleep 60 rm -f $lockfile Question 8: Configure your system with keychain, as described at the web site: http://www.gentoo.org/proj/en/keychain.xml. Does this work for you? Write a text file keychain-setup.txt which lists the steps you used to set up keychain in 30 lines or less. Use your own words. Nick's answer: The instructions on the web site did not work for me. I found that I needed to also modify ~/.bashrc as well, since although calling keychain from ~/.bash_profile created the file ~/.keychain/${HOSTNAME}-sh and correctly started the agent and loaded the keys, it did not always source the correct values into my shell, so that by putting the line [ -r ~/.keychain/${HOSTNAME}-sh ] && source ~/.keychain/${HOSTNAME}-sh into my ~/.bashrc, I found that keychain always worked for me at home. In the College, I found that it was necessary to set the hostname on the machine that I was using, since otherwise all machines would have the same hostname of localhost.localdomain, and my file ~/.keychain/localhost.localdomain-sh would be overwritten by new keychain information from another computer if I did not change my hostname. I changed the hostname by editing /etc/sysconfig/network and setting a value for the variable HOSTNAME. I also added the same hostname in /etc/hosts as the first name for the IP address 127.0.0.1 in addition to the names localhost and localhost.localdomain. In ~/.bash_profile, I put the lines: [ -x /usr/bin/keychain ] && keychain ~/.ssh/id_rsa [ -r ~/.keychain/${HOSTNAME}-sh ] && source ~/.keychain/${HOSTNAME}-sh #! /bin/sh # Question 9: # Modify your answer to question 7 so that your program will: # o source the keychain information about where your agent is; # o use the rsync program to copy the contents of the directory # ~/public_html to the directory ~/public_html-backup in your own # account on another computer. # For example, if your local account contains the file # ~/public_html/important.html, then the file # ~/public_html-backup/important.html will be created on the remote # computer if it does not exist, and the content will be identical on # both machines. prog=$(basename $0) usage() { cat <