Zooming in dotter broken

jkb at mrc-lmb.cam.ac.uk jkb at mrc-lmb.cam.ac.uk
Tue Sep 4 08:06:16 EST 2001


In <3B936214.ECED52B0 at sanger.ac.uk> Ed Griffiths <edgrif at sanger.ac.uk> writes:

> NO, this doesn't work, argv[0] only contains the string by which the program
> was invoked, e.g. if you type "./dotter" to start the program then argv[0]
> will only contain "./dotter". The jumping through hoops is because dotter is
> invoked both as a stand alone program and from within xace and we just want
> one load of code to do both.

You can add pwd on if need be. We use this trick, albeit in a shell script
instead of C main, for finding out the directory our scripts reside in. The
logic in bourne shell is simply:

# Finds the directory holding this program
find_dir() {
    arg0=$1

    # Protect against ls, sed and echo being exported shell functions.
    # Eg ls() { ls -F ${@+"$@"} }; export ls
    unset ls
    unset sed
    unset echo
    
    orig_dir=`pwd`
    must_loop=yes

    # The looping is to protect against symbolic links. We find the location
    # of arg0, but if arg0 is a link to elsewhere then we go around again
    # finding its location (noting that symlinks may be ether relative
    # or full pathnames).
    while [ -n "$must_loop" ]
    do
	cur_dir=`pwd`
    
	# Find directory that $arg0 resides in
	case $arg0 in
	    /*)
		# Full pathname, not much to do
		dir=`echo $arg0 | sed 's:/[^/]*$::'`
		;;
	    *)
		# Relative pathname, add current directory.
		dir=`echo $cur_dir/$arg0 | sed 's:/[^/]*$::'`
		;;
	esac
    
	if [ -h $arg0 ]
	then
	    # NOTE: This statement will not work when $arg0 is a filename
	    # containing "-> ".
	    lnto=`ls -l -- $arg0 | sed 's/.*-> //'`
	    lndir=`echo $lnto | sed 's:/[^/]*$::'`
	    case $lndir in
		/*)
		    # Absolute symlink
		    dirto=$lndir
		    ;;
		*)
		    # Relative symlink
		    dirto=`echo $arg0 | sed "s:/[^/]*\$:/$lndir:"`
		    ;;
	    esac

	    cd "$dirto"
	    arg0=`echo $lnto | sed 's:.*/::'`
	    must_loop=yes
	else
	    must_loop=
	fi
    done
    
    # To tidy up cases with ../ and ./ we cd to the directory, getcwd, and then
    # cd back again
    cd "$dir"
    dir=`pwd`
    cd "$orig_dir"
    
    echo $dir
}

For C the sed statements mainly just boil down to a strrchrs. The symbolic
link stuff uses ls in /bin/sh, but lstat is a better choice for C. Can anyone
see any flaws in the above logic? Getting the symlink stuff correct is far
from obvious - we need to find where the 'real' script is, not just the
symlink to it, as some people simply seem to have a ~/bin directory containing
links to individual programs instead of setting their PATHs.

However ignoring this stuff, my personal choice is simply to use system()
(assuming it's not setuid and so security isn't an issue) or execlp() to run
programs and let the users set up their PATH correctly.

We try to have the policy of "if it works for you on the command line then it
should work within our programs". This then covers not only PATH, but all
those other quirky environment variables that some apps require.

> You might imagine that one of ths standard C library functions would implement
> the function "given this program name, examine my environment and construct the
> full pathname of the executable that will actually be run when I type that
> name". Sadly this function does not exist, I really don't know why....so we do
> our best....

Indeed. I've always wanted the ability of finding the location of a file by an 
open file descriptor. Things like lsof seem to imply that this information is
available in the kernel somewhere, but perhaps not on all Unixes.

James
--
James Bonfield (jkb at mrc-lmb.cam.ac.uk)   Tel: 01223 402499   Fax: 01223 213556
Medical Research Council - Laboratory of Molecular Biology,
Hills Road, Cambridge, CB2 2QH, England.
Also see Staden Package WWW site at http://www.mrc-lmb.cam.ac.uk/pubseq/





More information about the Acedb mailing list