head 1.26; access; symbols SHTOOL_2_0_8:1.25 SHTOOL_2_0_7:1.22 SHTOOL_2_0_6:1.20 SHTOOL_2_0_5:1.20 SHTOOL_2_0_4:1.20 SHTOOL_2_0_3:1.19 SHTOOL_2_0_2:1.19 SHTOOL_2_0_1:1.18 SHTOOL_2_0_0:1.18 SHTOOL_2_0b3:1.18 SHTOOL_2_0b2:1.18 SHTOOL_2_0b1:1.18 SHTOOL_1_6:1.12.0.2 SHTOOL_1_6_2:1.12 SHTOOL_1_6_1:1.12 SHTOOL_1_6_0:1.12 SHTOOL_1_5:1.10.0.2 SHTOOL_1_5_4:1.10 SHTOOL_1_5_3:1.10 SHTOOL_1_5_2:1.10 SHTOOL_1_5_1:1.8 SHTOOL_1_5_0:1.8 SHTOOL_1_4_9:1.8 SHTOOL_1_4_8:1.8 SHTOOL_1_4_7:1.6 SHTOOL_1_4_6:1.6 SHTOOL_1_4_5:1.6 SHTOOL_1_4_4:1.6 SHTOOL_1_4_3:1.6 SHTOOL_1_4_2:1.6 SHTOOL_1_4_1:1.6 SHTOOL_1_4_0:1.6 SHTOOL_1_3_3:1.5 SHTOOL_1_3_2:1.5 SHTOOL_1_3_1:1.4 SHTOOL_1_3_0:1.4 SHTOOL_1_2_9:1.1.1.1 SHTOOL_1_2_8:1.1.1.1 SHTOOL_1_2_7:1.1.1.1 SHTOOL_1_2_6:1.1.1.1 SHTOOL_1_2_5:1.1.1.1 SHTOOL_1_2_4:1.1.1.1 SHTOOL_1_2_3:1.1.1.1 SHTOOL_1_2_2:1.1.1.1 SHTOOL_1_2_1:1.1.1.1 SHTOOL_1_2_0:1.1.1.1 RSE:1.1.1; locks; strict; comment @# @; 1.26 date 2008.12.23.19.12.05; author rse; state Exp; branches; next 1.25; commitid HJElUbvJ02gjMCvt; 1.25 date 2008.06.06.12.15.11; author rse; state Exp; branches; next 1.24; commitid ocdYOzoyLLxRTS5t; 1.24 date 2008.04.02.20.13.43; author rse; state Exp; branches; next 1.23; commitid eB5Wirx8MdMyDzXs; 1.23 date 2008.04.02.20.12.04; author rse; state Exp; branches; next 1.22; commitid xd2Jq3h5PA50DzXs; 1.22 date 2007.05.19.19.09.39; author rse; state Exp; branches; next 1.21; commitid OPUF1UBbllBTwzis; 1.21 date 2007.05.15.19.35.48; author rse; state Exp; branches; next 1.20; commitid GJKJUVDzn7sdO3is; 1.20 date 2006.02.04.09.43.25; author rse; state Exp; branches; next 1.19; commitid oWk7BmnyAitJtfkr; 1.19 date 2005.06.15.08.14.35; author rse; state Exp; branches; next 1.18; 1.18 date 2004.02.12.16.06.27; author rse; state Exp; branches; next 1.17; 1.17 date 2004.01.01.16.54.20; author rse; state Exp; branches; next 1.16; 1.16 date 2003.08.13.14.20.34; author rse; state Exp; branches; next 1.15; 1.15 date 2003.05.09.09.50.13; author rse; state Exp; branches; next 1.14; 1.14 date 2003.02.11.13.00.50; author rse; state Exp; branches; next 1.13; 1.13 date 2003.02.11.12.56.40; author rse; state Exp; branches; next 1.12; 1.12 date 2001.12.31.15.06.04; author rse; state Exp; branches; next 1.11; 1.11 date 2001.09.23.10.58.10; author rse; state Exp; branches; next 1.10; 1.10 date 2001.01.17.09.55.11; author rse; state Exp; branches; next 1.9; 1.9 date 2000.11.29.19.58.58; author rse; state Exp; branches; next 1.8; 1.8 date 2000.03.12.13.28.24; author rse; state Exp; branches; next 1.7; 1.7 date 2000.03.12.11.12.21; author rse; state Exp; branches; next 1.6; 1.6 date 99.07.01.14.48.42; author rse; state Exp; branches; next 1.5; 1.5 date 99.06.28.15.18.44; author rse; state Exp; branches; next 1.4; 1.4 date 99.06.17.07.35.08; author rse; state Exp; branches; next 1.3; 1.3 date 99.06.12.14.46.37; author rse; state Exp; branches; next 1.2; 1.2 date 99.06.12.14.08.49; author rse; state Exp; branches; next 1.1; 1.1 date 99.04.29.11.20.00; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 99.04.29.11.20.00; author rse; state Exp; branches; next ; desc @@ 1.26 log @Fix "mkln -s /foo /foo/bar" (achieving a "bar -> ." symlink) @ text @## ## mkln -- Make link with calculation of relative paths ## Copyright (c) 1998-2008 Ralf S. Engelschall ## ## This file is part of shtool and free software; you can redistribute ## it and/or modify it under the terms of the GNU General Public ## License as published by the Free Software Foundation; either version ## 2 of the License, or (at your option) any later version. ## ## This file is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ## USA, or contact Ralf S. Engelschall . ## str_tool="mkln" str_usage="[-t|--trace] [-f|--force] [-s|--symbolic] [ ...] " arg_spec="2+" opt_spec="t.f.s." opt_alias="t:trace,f:force,s:symbolic" opt_t=no opt_f=no opt_s=no . ./sh.common # determine source(s) and destination args=$# srcs="" while [ $# -gt 1 ]; do srcs="$srcs $1" shift done dst="$1" if [ ! -d $dst ]; then if [ $args -gt 2 ]; then echo "$msgprefix:Error: multiple sources not allowed when target isn't a directory" 1>&2 shtool_exit 1 fi fi # determine link options lnopt="" if [ ".$opt_f" = .yes ]; then lnopt="$lnopt -f" fi if [ ".$opt_s" = .yes ]; then lnopt="$lnopt -s" fi # iterate over sources for src in $srcs; do # determine if one of the paths is an absolute path, # because then we _have_ to use an absolute symlink oneisabs=0 srcisabs=0 dstisabs=0 case $src in /* ) oneisabs=1; srcisabs=1 ;; esac case $dst in /* ) oneisabs=1; dstisabs=1 ;; esac # split source and destination into dir and base name if [ -d $src ]; then srcdir=`echo $src | sed -e 's;/*$;;'` srcbase="" else srcdir=`echo $src | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'` srcbase=`echo $src | sed -e 's;.*/\([^/]*\)$;\1;'` fi if [ -d $dst ]; then dstdir=`echo $dst | sed -e 's;/*$;;'` dstbase="" else dstdir=`echo $dst | sed -e 's;^[^/]*$;;' -e 's;^\(.*/\)[^/]*$;\1;' -e 's;\(.\)/$;\1;'` dstbase=`echo $dst | sed -e 's;.*/\([^/]*\)$;\1;'` fi # consistency check if [ ".$dstdir" != . ]; then if [ ! -d $dstdir ]; then echo "$msgprefix:Error: destination directory not found: $dstdir" 1>&2 shtool_exit 1 fi fi # make sure the source is reachable from the destination if [ $dstisabs = 1 ]; then if [ $srcisabs = 0 ]; then if [ ".$srcdir" = . ]; then srcdir="`pwd | sed -e 's;/*$;;'`" srcisabs=1 oneisabs=1 elif [ -d $srcdir ]; then srcdir="`cd $srcdir; pwd | sed -e 's;/*$;;'`" srcisabs=1 oneisabs=1 fi fi fi # split away a common prefix prefix="" if [ ".$srcdir" = ".$dstdir" ] && [ ".$srcdir" != . ]; then prefix="$srcdir/" srcdir="" dstdir="" else while [ ".$srcdir" != . ] && [ ".$dstdir" != . ]; do presrc=`echo $srcdir | sed -e 's;^\([^/][^/]*\)/.*;\1;'` predst=`echo $dstdir | sed -e 's;^\([^/][^/]*\)/.*;\1;'` if [ ".$presrc" != ".$predst" ]; then break fi prefix="$prefix$presrc/" srcdir=`echo $srcdir | sed -e 's;^[^/][^/]*/*;;'` dstdir=`echo $dstdir | sed -e 's;^[^/][^/]*/*;;'` done fi # destination prefix is just the common prefix dstpre="$prefix" # determine source prefix which is the reverse directory # step-up corresponding to the destination directory srcpre="" allow_relative_srcpre=no if [ ".$prefix" != . ] && [ ".$prefix" != ./ ]; then allow_relative_srcpre=yes fi if [ $oneisabs = 0 ]; then allow_relative_srcpre=yes fi if [ ".$opt_s" != .yes ]; then allow_relative_srcpre=no fi if [ ".$allow_relative_srcpre" = .yes ]; then pl="$dstdir/" OIFS="$IFS"; IFS='/' for pe in $pl; do [ ".$pe" = . ] && continue [ ".$pe" = .. ] && continue srcpre="../$srcpre" done IFS="$OIFS" else if [ $srcisabs = 1 ]; then srcpre="$prefix" fi fi # determine destination symlink name if [ ".$dstbase" = . ]; then if [ ".$srcbase" != . ]; then dstbase="$srcbase" else dstbase=`echo "$prefix$srcdir" | sed -e 's;/*$;;' -e 's;.*/\([^/]*\)$;\1;'` fi fi # special case (usually on "mkln -s /foo /foo/bar", etc) if [ ".$srcpre$srcdir$srcbase" = . ]; then srcdir="." fi # now finalize source and destination directory paths srcdir=`echo $srcdir | sed -e 's;\([^/]\)$;\1/;'` dstdir=`echo $dstdir | sed -e 's;\([^/]\)$;\1/;'` # run the final link command if [ ".$opt_t" = .yes ]; then echo "ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase" fi eval ln$lnopt $srcpre$srcdir$srcbase $dstpre$dstdir$dstbase done shtool_exit 0 ## ## manual page ## =pod =head1 NAME B - B enhanced ln(1) replacement =head1 SYNOPSIS B [B<-t>|B<--trace>] [B<-f>|B<--force>] [B<-s>|B<--symbolic>] I [I ...] I =head1 DESCRIPTION This is a ln(1) style command. It is enhanced to provide automatic calculation and usage of relative links with the shortest possible path, if possible. Usually if I and I are not absolute paths or at least they share a common prefix except the root directory (``C''). When more than one I is specified, all of them are linked into I. =head1 OPTIONS The following command line options are available. =over 4 =item B<-t>, B<--trace> Enable the output of the essential shell commands which are executed. =item B<-f>, B<--force> Force the creation of the link even if it exists. Default is to fail with error. =item B<-s>, B<--symbolic> Create a symbolic link instead of a hard-link. =back =head1 EXAMPLE # shell script shtool mkln -s foo/bar baz/quux =head1 HISTORY The B B command was originally written by Ralf S. Engelschall Erse@@engelschall.comE in 1998 for I. =head1 SEE ALSO shtool(1), ln(1). =cut @ 1.25 log @Fix argument handling in "shtool mkln" command @ text @d117 2 a118 2 presrc=`echo $srcdir | sed -e 's;^\([^/]*\)/.*;\1;'` predst=`echo $dstdir | sed -e 's;^\([^/]*\)/.*;\1;'` d123 2 a124 2 srcdir=`echo $srcdir | sed -e 's;^[^/]*/*;;'` dstdir=`echo $dstdir | sed -e 's;^[^/]*/*;;'` d168 5 @ 1.24 log @adjust copyright for year 2008 @ text @d33 1 a33 1 args=$? @ 1.23 log @remove trailing spaces @ text @d3 1 a3 1 ## Copyright (c) 1998-2007 Ralf S. Engelschall @ 1.22 log @Adjust copyright for year 2007. @ text @d137 1 a137 1 fi d140 1 a140 1 fi d143 1 a143 1 fi @ 1.21 log @1. Fix "shtool mkln" by fixing the determination whether relative source paths can be used or not. 2. Make "shtool install" more robust by quoting arguments. @ text @d3 1 a3 1 ## Copyright (c) 1998-2006 Ralf S. Engelschall @ 1.20 log @Adjust copyright for year 2006 @ text @d134 11 a144 6 isroot=0 if [ ".$prefix" = . ] || [ ".$prefix" = ./ ]; then isroot=1 fi if [ $oneisabs = 0 ] || [ $isroot = 0 ]; then @ 1.19 log @Adjust copyright for year 2005 @ text @d3 1 a3 1 ## Copyright (c) 1998-2005 Ralf S. Engelschall @ 1.18 log @Embedded the command documentation from shtool.pod into the individual sh.xxxx scripts and this way split the large shtool(1) manual page into individual manual pages shtool-xxxx(1). Submitted partly by: Thomas Lotterer @ text @d3 1 a3 1 ## Copyright (c) 1998-2004 Ralf S. Engelschall @ 1.17 log @Bump copyright year for 2004 @ text @d3 1 a3 2 ## Copyright (c) 1999-2004 Ralf S. Engelschall ## Originally written for shtool d173 67 @ 1.16 log @Replace "[ x -o/-a x ]" constructs with "[ x ] ||/&& [ x ]" and "egrep"/"fgrep" constructs with compatible "grep" or "case" constructs. This way GNU shtool is now more POSIX 1003.1-2001 compliant. Submitted by: Paul Eggert @ text @d3 1 a3 1 ## Copyright (c) 1999-2003 Ralf S. Engelschall @ 1.15 log @Fix calculation of effective source path in "shtool mkln" command for destination paths containing "/./" sequence and for source paths consisting of no directory parts at all. Discovered by: Michael Schloh v. Bennewitz @ text @d112 1 a112 1 if [ ".$srcdir" = ".$dstdir" -a ".$srcdir" != . ]; then d117 1 a117 1 while [ ".$srcdir" != . -a ".$dstdir" != . ]; do d135 6 a140 1 if [ $oneisabs = 0 ] || [ ".$prefix" != . -a ".$prefix" != ./ ]; then @ 1.14 log @Bump year in copyright messages to cover new year 2003. @ text @d33 1 d98 5 a102 1 if [ -d $srcdir ]; then d139 2 a140 1 [ ".$pe" = . ] && continue @ 1.13 log @Fixed error exit in all commands by introducing an "shtool_exit" function (which correctly cleans up temporary files) and replacing all "exit" calls with "shtool_exit". THIS THE FIRST TIME INTRODUCED THE USAGE OF A SHELL FUNCTION TO THE SHTOOL CODE. This is known to break on _very_ anchient and broken Bourne-Shell implementations and is considered to be no longer a real problem in the year 2003. Especially there is no alternative way anyway. @ text @d3 1 a3 1 ## Copyright (c) 1999-2002 Ralf S. Engelschall @ 1.12 log @bump copyright years @ text @d43 1 a43 1 exit 1 d90 1 a90 1 exit 1 @ 1.11 log @*** empty log message *** @ text @d3 1 a3 1 ## Copyright (c) 1999-2001 Ralf S. Engelschall @ 1.10 log @*** empty log message *** @ text @d23 1 a23 1 str_usage="[-t] [-f] [-s] [ ...] " d26 1 @ 1.9 log @*** empty log message *** @ text @d3 1 a3 1 ## Copyright (c) 1999-2000 Ralf S. Engelschall @ 1.8 log @*** empty log message *** @ text @d106 1 a106 1 if [ ".$srcdir" = ".$dstdir" ] && [ ".$srcdir" != . ]; then d111 1 a111 1 while [ ".$srcdir" != . ] && [ ".$dstdir" != . ]; do @ 1.7 log @*** empty log message *** @ text @d25 4 a28 1 opt_spec="tfs" @ 1.6 log @*** empty log message *** @ text @d3 1 a3 1 ## Copyright (c) 1999 Ralf S. Engelschall @ 1.5 log @*** empty log message *** @ text @d23 1 a23 1 str_usage="[-v] [-f] [-s] [ ...] " d25 1 a25 1 opt_spec="vfs" d154 1 a154 1 if [ ".$opt_v" = .yes ]; then @ 1.4 log @*** empty log message *** @ text @d27 1 a27 1 . sh.common @ 1.3 log @*** empty log message *** @ text @d23 1 a23 1 str_usage="[-v] [-f] [-s] [ ...] " @ 1.2 log @*** empty log message *** @ text @d3 1 a3 1 ## Copyright (c) 1999 Ralf S. Engelschall, All Rights Reserved. d5 15 @ 1.1 log @Initial revision @ text @a0 1 #!/bin/sh d2 1 a2 1 ## mkln -- Extended ln(1) command which calculates relative links d4 1 a4 1 ## Usage: mkln [-v] [-f] [-s] [ ...] d7 7 a13 18 # # command line parsing # verbose=no force=no symbolic=no while [ ".$1" != . ]; do case $1 in -v) verbose=yes; shift; continue ;; -f) force=yes; shift; continue ;; -s) symbolic=yes; shift; continue ;; *) break ;; esac done if [ $# -lt 2 ]; then echo "$0:Usage: mkln [-v] [-f] [-s] [ ...] " 1>&2 exit 1 fi d23 1 a23 1 echo "$0:Error: multiple sources not allowed when destination isn't a directory" 1>&2 a27 1 # a28 1 # d30 1 a30 1 if [ $force = yes ]; then d33 1 a33 1 if [ $symbolic = yes ]; then a36 1 # a37 1 # a38 5 # debugging if [ $verbose = yes ]; then echo "src=\"$src\" dst=\"$dst\":" fi a66 8 # debugging if [ $verbose = yes ]; then echo " STATE 1:" echo " srcisabs=$srcisabs srcdir=\"$srcdir\" srcbase=\"$srcbase\"" echo " dstisabs=$dstisabs dstdir=\"$dstdir\" dstbase=\"$dstbase\"" echo " oneisabs=$oneisabs" fi d70 1 a70 1 echo "$0:Error: destination directory not found: $dstdir" 1>&2 a81 7 # debugging if [ $verbose = yes ]; then echo " STATE 2:" echo " srcisabs=$srcisabs srcdir=\"$srcdir\" srcbase=\"$srcbase\"" echo " dstisabs=$dstisabs dstdir=\"$dstdir\" dstbase=\"$dstbase\"" echo " oneisabs=$oneisabs" fi a104 9 # debugging if [ $verbose = yes ]; then echo " STATE 3:" echo " prefix=$prefix" echo " srcisabs=$srcisabs srcdir=\"$srcdir\" srcbase=\"$srcbase\"" echo " dstisabs=$dstisabs dstdir=\"$dstdir\" dstbase=\"$dstbase\"" echo " oneisabs=$oneisabs" fi a124 9 # debugging if [ $verbose = yes ]; then echo " STATE 4:" echo " prefix=$prefix" echo " srcisabs=$srcisabs srcpre=\"$srcpre\" srcdir=\"$srcdir\" srcbase=\"$srcbase\"" echo " dstisabs=$dstisabs dstpre=\"$dstpre\" dstdir=\"$dstdir\" dstbase=\"$dstbase\"" echo " oneisabs=$oneisabs" fi a137 9 # debugging if [ $verbose = yes ]; then echo " STATE 5:" echo " prefix=$prefix" echo " srcisabs=$srcisabs srcpre=\"$srcpre\" srcdir=\"$srcdir\" srcbase=\"$srcbase\"" echo " dstisabs=$dstisabs dstpre=\"$dstpre\" dstdir=\"$dstdir\" dstbase=\"$dstbase\"" echo " oneisabs=$oneisabs" fi d139 1 a139 2 if [ $verbose = yes ]; then echo " RESULT:" a143 1 exit 0 @ 1.1.1.1 log @Import of shtool 1.2.0 @ text @@