home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume7 / sccs.sh < prev    next >
Text File  |  1989-08-07  |  19KB  |  830 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Cetia, Toulon, France
  3. keywords: SCCS, sources
  4. subject: v07i123: functions to maintain SCCS'ed source trees
  5. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6. Reply-To: chris@cetia.UUCP (Chris Bertin)
  7.  
  8. Posting-number: Volume 7, Issue 123
  9. Submitted-by: chris@cetia.UUCP (Chris Bertin)
  10. Archive-name: sccs.sh
  11.  
  12. This is a file I keep in my home directory under the name '.shrc.sccs'. It
  13. contains quite a few functions that I use to manage SCCS, to do source tree
  14. comparisons, etc... This stuff has evolved over the years and some of the
  15. functions have gotten quite large; in fact, several of them should probably
  16. be turned into separate shell scripts. All these functions assume that the
  17. SCCS files are kept in an 'SCCS' directory. If you have the BSD 'sccs' command,
  18. several of these functions will lose some of their usefulness. I have never
  19. bothered with 'sccs' because I started to use these functions before the 'sccs'
  20. command came out.
  21.  
  22. ----------------------------------- cut here ---------------------------------
  23. ##
  24. ## ex:set sw=4:        # set shiftwidth to 4 when editing this file
  25. ##
  26. ##
  27. ##    SCCS functions
  28. ##
  29. ##                    Chris Bertin
  30. ##
  31. ##
  32.  
  33. Company=YOUR_SITE        # Used for header functions
  34.  
  35. # Files matching the following patterns will be skipped by 'recdiff'
  36. RECSKIP="tags *.out llib*.ln lib.*"
  37.  
  38. # admin files
  39. adm()
  40. {
  41.     [ ${#} -eq 0 ] && {
  42.     echo "Usage: adm files" >&2
  43.     return 1
  44.     }
  45.     [ -d SCCS ] || {
  46.     echo "Creating SCCS directory"
  47.     mkdir SCCS || return 1
  48.     }
  49.     for AFile do
  50.     admin -i${AFile} SCCS/s.${AFile} && {
  51.          rm -f ${AFile}
  52.          get SCCS/s.${AFile}
  53.     }
  54.     shift
  55.     done
  56.     unset AFile
  57. }
  58.  
  59. # admin all files in the current directory
  60. adminall()
  61. {
  62.     [ -f *.mk ] && AFile=`echo *.mk` || {
  63.         [ -f Makefile ] && AFile=Makefile || {
  64.             [ -f makefile ] && AFile=makefile
  65.         }
  66.     }
  67.     [ -f "${AFile}" ] && {
  68.     echo "Warning: doing a 'make clobber'"
  69.     sleep 5
  70.     make -f ${AFile} clobber
  71.     }
  72.     adm `ls | grep -v SCCS`
  73.     ls -l *
  74. }
  75.  
  76. # handle pending files in directory trees (default '.') using delall (see below)
  77. recdel()
  78. {
  79.     [ ${#} -gt 0 ] && List="$*" ||  List=`pwd`
  80.     CurDir=`pwd`
  81.     trap "cd ${CurDir}; echo '...Aborted'; trap 1 2 3; return -1 >&- 2>&-" 1 2 3
  82.     for Tree in ${List}; do
  83.     echo "Doing ${Tree}"
  84.     cd ${Tree} || continue
  85.     for Dir in `find . -type d ! -name SCCS -print | sed "s/^\.\///"` ; do
  86.         cd ${Dir} && delall || { cd ${CurDir}; trap 1 2 3; return 1; }
  87.         cd ${CurDir} && cd ${Tree}
  88.     done
  89.     cd ${CurDir}
  90.     done
  91.     unset CurDir Tree Dir List
  92.     trap 1 2 3
  93. }
  94.  
  95. # handle all pending files in the current directory (delta or unget or nothing)
  96. delall()
  97. {
  98.     [ ${#} -ne 0 ] && {
  99.     echo "Usage: delall" >&2
  100.     return 1
  101.     }
  102.     [ -z "`pend`" ] && {
  103.     echo "Nothing pending in `pwd`" >&2
  104.     return 0
  105.     }
  106.     for DLFile in `pend` ; do
  107.     echo ">> `pwd`/${DLFile}"
  108.     xdiff ${DLFile}
  109.     [ ! -t 1 ] && { echo "-----------------------------"; continue; }
  110.     while : ; do
  111.         echo "${DLFile}: [dacpqrsuv] (or '?' for help): \c"
  112.         read ANSWER < /dev/tty
  113.         # Note that there is no 'shift' here. They are handled by the
  114.         # functions called in each case. This is a major uglyness in 'sh'.
  115.         case "${ANSWER}" in
  116.         c*|C*)
  117.         CoMMent="`echo ${ANSWER} | sed 's/[a-zA-Z]* //'`"
  118.         echo "New comment is \"${CoMMent}\""
  119.         continue
  120.         ;;
  121.         a*|A*)
  122.         echo "Autodelta with comment: \"${CoMMent}\""
  123.         sleep 1
  124.         chkpfile ${DLFile} || continue
  125.         delta -y"${CoMMent}" SCCS/s.${DLFile}
  126.         getn ${DLFile}
  127.         ;;
  128.         d*|D*)
  129.         del ${DLFile}
  130.         ;;
  131.         p*|P*)
  132.         echo "Current autocomment is: \"${CoMMent}\"" 
  133.         continue
  134.         ;;
  135.         u*|U*)
  136.         ung ${DLFile}
  137.         ;;
  138.         r*|R*)
  139.         xdiff ${DLFile}
  140.         continue
  141.         ;;
  142.         v*|V*)
  143.         vi ${DLFile}
  144.         xdiff ${DLFile}
  145.         continue
  146.         ;;
  147.         s*|S*)
  148.         ${SHELL:-/bin/sh}
  149.         echo "exited"
  150.         continue
  151.         ;;
  152.         q*|Q*)
  153.         return 1
  154.         ;;
  155.         "")
  156.         echo "${DLFile} unchanged..."
  157.         ;;
  158.         ?*|*)
  159.         echo "Usage:\t\"c new auto comment\" (enter new comment)" >&2
  160.         echo "\t\"a\" (auto delta with previous auto comment)" >&2
  161.         echo "\t\"d\" (delta file manually)" >&2
  162.         echo "\t\"p\" (print autocomment)" >&2
  163.         echo "\t\"q\" (quit)" >&2
  164.         echo "\t\"r\" (redo)" >&2
  165.         echo "\t\"s\" (sub-shell)" >&2
  166.         echo "\t\"u\" (unget file)" >&2
  167.         echo "\t\"v\" (vi file)" >&2
  168.         echo "\t\"\"  (do nothing)" >&2
  169.         continue
  170.         ;;
  171.         esac
  172.         break
  173.     done
  174.     done
  175.     return 0
  176. }
  177.  
  178. # check if there is an 'SCCS' directory. Args are passed because 'sh' doesn't
  179. # stack arguments to functions.
  180. chkSCCSdir()
  181. {
  182.     [ -d SCCS ] || {
  183.     echo "No SCCS directory" >&2
  184.     return 1
  185.     }
  186.     return 0
  187. }
  188.  
  189. # check if file is SCCS'ed.
  190. chkSCCSfile()
  191. {
  192.     [ -f SCCS/s.${1} ] && return 0
  193.     echo "${1} not SCCS'ed" >&2
  194.     return 1
  195. }
  196.  
  197. # delta files
  198. del()
  199. {
  200.     [ ${#} -eq 0 ] && {
  201.     echo "Usage: del files" >&2
  202.     return 1
  203.     }
  204.     for DFile do
  205.     chkpfile ${DFile} || continue
  206.     delta SCCS/s.${DFile} && get SCCS/s.${DFile}
  207.     shift
  208.     done
  209.     unset DFile
  210. }
  211.  
  212. # check whether p file is valid
  213. chkpfile()
  214. {
  215.     [ ${#} -eq 0 ] && {
  216.     echo "Usage: chkpfile files" >&2
  217.     return 1
  218.     }
  219.     [ $# -ne 1 ] && { echo "Arg count"; return 1; }
  220.     [ -r SCCS/p.${1} ] || { echo "${1} not pending"; return 1; }
  221.     WhoAmI=`whoami`
  222.     WhoIsIt="`awk '{print $3}' < SCCS/p.${1}`"
  223.     [ "${WhoAmI}" != "${WhoIsIt}" ] && {
  224.     echo "You didn't get ${1} -- (`cat SCCS/p.${1}`)"
  225.     if [ -t 1 ]; then
  226.         echo "Fix it? \c"
  227.         read ANSWER < /dev/tty
  228.     else
  229.         ANSWER="${DEFCHKP}"
  230.     fi
  231.     case "${ANSWER}" in
  232.     y*|Y*)
  233.         echo "s/${WhoIsIt}/${WhoAmI}/\nw\nq" | ed - SCCS/p.${1}
  234.         [ ${?} -ne 0 ] && {
  235.         echo "Can't fix SCCS/p.${1} -- Sorry";
  236.         return 1;
  237.         }
  238.         [ -t 1 ] || echo "Pfile fixed"
  239.         return 0
  240.         ;;
  241.     *)
  242.         return 1
  243.         ;;
  244.     esac
  245.     }
  246.     return 0
  247. }
  248.  
  249. # get an SCCS file in edit mode
  250. gete()
  251. {
  252.     [ ${#} -eq 0 ] && {
  253.     echo "Usage: gete files" >&2
  254.     return 1
  255.     }
  256.     chkSCCSdir $* || return 1
  257.     for GEFile do
  258.     chkSCCSfile ${GEFile} && get -e SCCS/s.${GEFile}
  259.     shift
  260.     done
  261.     unset GEFile
  262. }
  263.  
  264. # get an SCCS file without editing
  265. getn()
  266. {
  267.     [ ${#} -eq 0 ] && {
  268.     echo "Usage: getn files" >&2
  269.     return 1
  270.     }
  271.     chkSCCSdir $* || return 1
  272.     for GNFile do
  273.     chkSCCSfile ${GNFile} && get SCCS/s.${GNFile}
  274.     shift
  275.     done
  276.     unset GNFile
  277. }
  278.  
  279. # get an SCCS file into standard output
  280. getp()
  281. {
  282.     [ ${#} -eq 0 ] && {
  283.     echo "Usage: getp files" >&2
  284.     return 1
  285.     }
  286.     chkSCCSdir $* || return 1
  287.     for GPFile do
  288.     chkSCCSfile ${GPFile} && get -p SCCS/s.${GPFile}
  289.     shift
  290.     done
  291.     unset GPFile
  292. }
  293.  
  294. # get given version of an SCCS file into standard output
  295. getv()
  296. {
  297.     [ ${#} -ne 2 ] && {
  298.     echo "Usage: getv version file" >&2
  299.     return 1
  300.     }
  301.     chkSCCSdir $* || return 1
  302.     VeRs=${1}
  303.     shift
  304.     chkSCCSfile ${1} && get -p -r${VeRs} SCCS/s.${1}
  305.     unset VeRs
  306. }
  307.  
  308. # unget SCCS files that have been get'ed but not modified (in current directory)
  309. cleanget()
  310. {
  311.     [ ${#} -ne 0 ] && {
  312.     echo "Usage: cleanget" >&2
  313.     return 1
  314.     }
  315.     CurDir=`pwd`
  316.     trap "cd ${CurDir}; echo '...Aborted'; trap 1 2 3; return -1 >&- 2>&-" 1 2 3
  317.     find . -type f -name "p.*" -print | while read CGfile; do
  318.     BaseName=`basename ${CGfile} | sed "s/p.//"`
  319.     cd `dirname ${CGfile}`/.. || continue
  320.     echo ${BaseName}: pending in directory `pwd`
  321.     get -k -p SCCS/s.${BaseName} 2>&- | ${DIFF:-diff} - ${BaseName} >&- 2>&- && {
  322.         echo No differences for SCCS/s.${BaseName}
  323.         CurDate=`/src/uts/m68k/bin/curdate ${BaseName}`
  324.         chkpfile ${BaseName} || continue
  325.         ung ${BaseName}
  326.         touch -m ${CurDate} ${BaseName}
  327.     }
  328.     cd ${CurDir}
  329.     done
  330.     unset CurDir CGfile CurDate BaseName
  331.     trap 1 2 3
  332. }
  333.  
  334. # SCCS history for SCCS files
  335. hist()
  336. {
  337.     [ ${#} -eq 0 ] && {
  338.     echo "Usage: hist files" >&2
  339.     return 1
  340.     }
  341.     chkSCCSdir $* || return 1
  342.     for HFile do
  343.     chkSCCSfile ${HFile} && prs -e \
  344.         -d'Delta for :M:: -- :I: --, Date: :D:\nUpdate: :C:' SCCS/s.${HFile}
  345.     shift
  346.     done
  347.     unset HFile
  348. }
  349.  
  350. # examine SCCS files
  351. m()
  352. {
  353.     [ ${#} -eq 0 ] && {
  354.     echo "Usage: m files" >&2
  355.     return 1
  356.     }
  357.     chkSCCSdir $* || return 1
  358.     for MFile do
  359.     chkSCCSfile ${MFile} && get -s -p SCCS/s.${MFile} | ${PAGER:-pg}
  360.     shift
  361.     done
  362.     unset MFile
  363. }
  364.  
  365. # show which SCCS files are pending. Optionnal args limit the name expansion
  366. pend()
  367. {
  368.     chkSCCSdir $* || return 1
  369.     [ -f SCCS/p.* ] && echo `ls SCCS/p.*${1} 2>&- | sed "s/^SCCS\/p.//"`
  370. }
  371.  
  372. # show all pending files in the given directory trees (default '.')
  373. pendall()
  374. {
  375.     [ ${#} -gt 0 ] && List="$*" ||  List=.
  376.     for Tree in ${List}; do
  377.     find ${Tree} -type f -name 'p.*' -print | \
  378.         sed -e 's/^\.\///' -e 's/SCCS\/p\.//'
  379.     done
  380.     unset Tree List
  381. }
  382.  
  383. # add a SCCS header to the given C files
  384. shead()
  385. {
  386.     [ ${#} -eq 0 ] && {
  387.     echo "Usage: shead files" >&2
  388.     return 1
  389.     }
  390.     for SFile do
  391.     echo '1i\n#ifndef lint\nstatic char ID[] = "%W% ${Company} %E%";\n#endif lint\n.\nw\nq' | ed - ${SFile}
  392.     done
  393.     unset SFile
  394. }
  395.  
  396. # add a SCCS header to the given header files
  397. shhead()
  398. {
  399.     [ ${#} -eq 0 ] && {
  400.     echo "Usage: shhead files" >&2
  401.     return 1
  402.     }
  403.     for SHFile do
  404.     echo '1i\n/* %W% ${Company} %E% */\n.\nw\nq' | ed - ${SHFile}
  405.     done
  406.     unset SHFile
  407. }
  408.  
  409. # add a SCCS header to the given FORTRAN files
  410. sfhead()
  411. {
  412.     [ ${#} -eq 0 ] && {
  413.     echo "Usage: sfhead files" >&2
  414.     return 1
  415.     }
  416.     for SFFile do
  417.     echo '1i\n* %W% ${Company} %Z%\n.\nw\nq' | ed - ${SFFile}
  418.     done
  419.     unset SFFile
  420. }
  421.  
  422. # add a SCCS header to the given SHELL (or MAKEFILE) files
  423. sshead() { smhead $*; }
  424. smhead()
  425. {
  426.     [ ${#} -eq 0 ] && {
  427.     echo "Usage: smhead files" >&2
  428.     return 1
  429.     }
  430.     for MHFile do
  431.     echo '1i\n# %W% ${Company} %Z%\nw\nq' | ed - ${MHFile}
  432.     done
  433.     unset MHFile
  434. }
  435.  
  436. # unget files
  437. ung()
  438. {
  439.     [ ${#} -eq 0 ] && {
  440.     echo "Usage: ung files" >&2
  441.     return 1
  442.     }
  443.     chkSCCSdir $* || return 1
  444.     for UFile do
  445.     chkSCCSfile ${UFile} && chkpfile ${UFile} && \
  446.         unget SCCS/s.${UFile} && get SCCS/s.${UFile}
  447.     shift
  448.     done
  449.     unset UFile
  450. }
  451.  
  452. # unget files without reextracting them
  453. ungn()
  454. {
  455.     [ ${#} -eq 0 ] && {
  456.     echo "Usage: ungn files" >&2
  457.     return 1
  458.     }
  459.     chkSCCSdir $* || return 1
  460.     for UNFile do
  461.     chkSCCSfile ${UNFile} && chkpfile ${UNFile} && unget SCCS/s.${UNFile}
  462.     shift
  463.     done
  464.     unset UNFile
  465. }
  466.  
  467. # show SCCS versions
  468. vs()
  469. {
  470.     [ ${#} -eq 0 ] && {
  471.     echo "Usage: vs files" >&2
  472.     return 1
  473.     }
  474.     chkSCCSdir $* || return 1
  475.     for VFile do
  476.     chkSCCSfile ${VFile} && prs -d"Current delta for :M:: -- :I: --, Date: :D:\nLast update: :C:" SCCS/s.${VFile}
  477.     shift
  478.     done
  479.     unset VFile
  480. }
  481.  
  482. # show SCCS versions of a full directory
  483. vss()
  484. {
  485.     [ ${#} -eq 0 ] && {
  486.     echo "Usage: vss sccs_directory" >&2
  487.     return 1
  488.     }
  489.     prs -d"Current delta for :M:: -- :I: --, Date: :D:\nLast update: :C:" $1
  490. }
  491.  
  492. # diff an SCCS file and its extracted counterpart
  493. xdiff()
  494. {
  495.     [ ${#} -eq 0 ] && {
  496.     echo "Usage: xdiff files" >&2
  497.     return 1
  498.     }
  499.     chkSCCSdir $* || return 1
  500.     for XFile do
  501.     chkSCCSfile ${XFile} || continue
  502.     [ ! -f ${XFile} ] && {
  503.          ls ${XFile}
  504.          continue
  505.     }
  506.     vs ${XFile} && get -p SCCS/s.${XFile} | ${DIFF:-diff} - ${XFile} 2>&1 | ${PAGER:-pg}
  507.     done
  508.     unset XFile
  509. }
  510.  
  511. ## sccsdiff between 2 versions
  512. scdiff()
  513. {
  514.     [ ${#} -lt 3 ] && {
  515.     echo "Usage: scdiff rel1 rel2 files" >&2
  516.     return 1
  517.     }
  518.     R1=$1; shift
  519.     R2=$1; shift
  520.     chkSCCSdir $* || return 1
  521.     for SFiLE do
  522.     chkSCCSfile ${SFiLE} || continue
  523.     sccsdiff -r${R1} -r${R2} SCCS/s.${SFiLE} | ${PAGER:-pg}
  524.     done
  525.     unset R1 R2 SFiLE
  526. }
  527.  
  528. # recursive difference between 2 trees, using diffall (See below)
  529. recdiff()
  530. {
  531.     Skip=
  532.     Flag=
  533.     for Opt in "$@"; do
  534.     case ${Opt} in
  535.     -F|-f) Flag="${Flag} -f"
  536.         [ ${Opt} = "-f" ] && Fopt="-o -type l"; shift
  537.         ;;
  538.     -o) Flag="${Flag} -o"; shift
  539.         ;;
  540.     -s) Skip="! -name SCCS" ;shift
  541.         ;;
  542.     *)  break
  543.         ;;
  544.         esac
  545.     done
  546.     [ \( ${#} -eq 1 -a ${1} = '-' \) -o ${#} -eq 2 ] && {
  547.     :
  548.     } || {
  549.     echo "Usage:\trecdiff [-f] [-F] [-o] [-s] ['-' or dir1] dir2" >&2
  550.     echo "\t-f: follow symbolic links in destination" >&2
  551.     echo "\t-F: follow symbolic links both in source and destination" >&2
  552.     echo "\t-o: compare non ascii files" >&2
  553.     echo "\t-s: skip SCCS directories" >&2
  554.     echo "\t- : If first argument is '-', do recursive SCCS diffs" >&2
  555.     return 1
  556.     }
  557.     BaseDir="."
  558.     Arg1=${1}
  559.     Arg2=${2}
  560.     if [ ${Arg1} = "-" ]; then
  561.     Skip="! -name SCCS"
  562.     [ ${#} = 1 ] && set - "." || BaseDir=${2}
  563.     Sdiff=true
  564.     shift
  565.     else
  566.     Sdiff=false
  567.     fi
  568.     CurDir=`pwd`
  569.     for Dir do
  570.     [ ! -d ${Dir} ] && {
  571.         echo "${Dir}: not a directory"
  572.         unset Dir
  573.         return 1
  574.     }
  575.     done
  576.     if [ ${Sdiff} = false ]; then
  577.     cd ${Arg2} || return 1
  578.     Dest=`pwd`
  579.     cd ${CurDir} || return 1
  580.     fi
  581.     if [ ${Sdiff} = false ]; then
  582.     cd ${Arg1} || return 1
  583.     fi
  584.     trap "cd ${CurDir}; echo '...Aborted'; trap 1 2 3; return -1 >&- 2>&-" 1 2 3
  585.  
  586.     find ${BaseDir} ${Skip} \( -type d ${Fopt} \) -print | sed "s/^\.\///" | \
  587.     while read Dir; do
  588.     [ -d ${Dir} ] || continue
  589.     echo "------ Directory: ${CurDir}/${Dir} ------"
  590.     cd ${Dir} || continue
  591.     if [ ${Sdiff} = true ]; then
  592.         if [ -d SCCS ]; then
  593.         Pending="`pend`"
  594.         if [ "${Pending}" != "" ]; then
  595.             diffall ${Flag} - ${Pending} || break
  596.         fi
  597.         fi
  598.         cd ${CurDir}
  599.         continue
  600.     fi
  601.     if [ ! -d ${Dest}/${Dir} ]; then
  602.         diffall ${Flag} ${Dir} ${Dest}    # for error handling
  603.     else
  604.         List=""
  605.         for F in `ls -a`; do
  606.         [ -z "${RECSKIP}" ] || {
  607.             for FF in `echo ${RECSKIP}` ; do
  608.             [ ${FF} = ${F} ] && {
  609.                 echo "===== ${F} ===== Skipped"
  610.                 continue 2
  611.             }
  612.             done
  613.         }
  614.         [ -f ${F} ] && List="${List} ${F}"
  615.         done
  616.         [ -z "${List}" ] || diffall ${Flag} ${List} ${Dest}/${Dir} || break
  617.     fi
  618.     cd ${CurDir}
  619.     cd ${Arg1}
  620.     done
  621.     cd ${CurDir}
  622.     unset Arg1 Arg2 CurDir Skip Dir Dest Flag Fopt F List Opt Pending Sdiff
  623.     trap 1 2 3
  624. }
  625.  
  626. # diff a series of files with their SCCS counterpart or another directory
  627. diffall()
  628. {
  629.     Dusage() {
  630.     echo "Usage:\tdiffall [-f] [-o] ['-' or files] [directory]" >&2
  631.     echo "\t-f: follow symbolic links" >&2
  632.     echo "\t-o: compare non ascii files" >&2
  633.     }
  634.     Nodiff() { REDO=0; echo "$* No differences"; }
  635.     Follow=false
  636.     Dotos=false
  637.     for Opt in "$@"; do
  638.     case ${Opt} in
  639.     -f) Follow=true; shift
  640.         ;;
  641.     -o) Dotos=true; shift
  642.         ;;
  643.     *)  break
  644.         ;;
  645.         esac
  646.     done
  647.     [ "$1" = "" ] && { Dusage; return 1; }
  648.     if [ "$1" = "-" ]; then
  649.     XdIfF=true
  650.     DiR="."
  651.     shift
  652.     chkSCCSdir $*
  653.     else
  654.     Args=$*
  655.     XdIfF=false
  656.     DiR=`echo $* | sed "s/.* //"`
  657.     [ ! -d "${DiR}" ] && {
  658.         echo "${DiR}: not a directory" >&2
  659.         Dusage
  660.         return 1
  661.     }
  662.     ls ${DiR} > /tmp/di$$
  663.     More=`ls | ${DIFF:-diff} - /tmp/di$$ | grep "^> " | sed "s/^> //"`
  664.     rm -f /tmp/di$$
  665.     [ -z "${More}" ] || echo "\nWARNING: `echo ${More}` only in ${DiR}\n"
  666.     set ${Args}
  667.     unset More Args
  668.     fi
  669.     Dcheckread() {
  670.     for FIle do
  671.         [ -d ${FIle} -o -c ${FIle} -o -b ${FIle} -o ! -r ${FIle} ] && {
  672.         echo "skipping `file ${FIle}`"
  673.         unset FIle
  674.         return 1
  675.         }
  676.     done
  677.     unset FIle
  678.     return 0
  679.     }
  680.     for FiLe do
  681.     [ "${FiLe}" = "${DiR}" ] && break
  682.     REDO=1
  683.     while [ ${REDO} -gt 0 ] ; do
  684.         [ ${REDO} -eq 1 ] && echo  "====== ${FiLe} ===== \c"
  685.         if [ ${REDO} -eq 2 ]; then
  686.         : do nothing. We got here because of wrong answer below
  687.         elif [ "${XdIfF}" = "true" ] ; then
  688.         [ -d ${FiLe} ] && {
  689.             echo "${FiLe}: Directory"
  690.             REDO=0
  691.             continue
  692.         }
  693.         if Dcheckread ${FiLe} SCCS/s.${FiLe} ; then
  694.             get -p -s SCCS/s.${FiLe} 2>&- | ${CMP:-cmp} - ${FiLe} 2>&1 && {
  695.             Nodiff
  696.             continue
  697.             }
  698.             get -p -s SCCS/s.${FiLe}| ${DIFF:-diff} - ${FiLe} | \
  699.               ${PAGER:-pg}
  700.         fi
  701.         else
  702.         if [ ${Follow} = false -a \
  703.              `ls -l ${FiLe} 2>&- | grep -c " -> "` -eq 1 ] ; then
  704.             echo "${FiLe}: Symbolic link\c"
  705.             if [ "`ls -d ${DiR}/${FiLe} 2>&-`" != "${DiR}/${FiLe}" ]; then
  706.             echo "s differ: ${DiR}/${FiLe} doesn't exist"
  707.             elif [ `ls -l ${DiR}/${FiLe} | grep -c " -> "` -eq 1 ]; then
  708.             ls -l ${FiLe} 2>&- | sed "s/.* -> //" > /tmp/dall.$$
  709.             ls -l ${DiR}/${FiLe} 2>&- | sed "s/.* -> //" | \
  710.                 ${DIFF:-diff} - /tmp/dall.$$ >&- 2>&-
  711.             [ ${?} = 0 ] && {
  712.                 rm -f /tmp/dall.$$
  713.                 Nodiff "s,"
  714.                 continue
  715.             } || {
  716.                 rm -f /tmp/dall.$$
  717.                 echo "s differ:"
  718.                 ls -l ${FiLe} ${DiR}/${FiLe}
  719.             }
  720.             else
  721.             echo " but ${FiLe} differ: `file ${DiR}/${FiLe}`"
  722.             fi
  723.         else
  724.             if Dcheckread ${FiLe} ${DiR}/${FiLe}; then
  725.             if file ${FiLe} | \
  726.               egrep " executable| archive| object|    data" >&-; then
  727.                 echo "`file ${FiLe} | \
  728.                 sed 's/[     ][     ]*/ /g'` -> \c"
  729.                 [ ${Dotos} = false ] && {
  730.                 echo "Ignored"
  731.                 REDO=0
  732.                 continue
  733.                 }
  734.                 ${CMP:-cmp} ${FiLe} ${DiR}/${FiLe} 2>&1 && {
  735.                 Nodiff
  736.                 continue
  737.                 }
  738.             else
  739.                 ${CMP:-cmp} ${FiLe} ${DiR}/`basename ${FiLe}` 2>&1 && {
  740.                 Nodiff
  741.                 continue
  742.                 }
  743.                 ${DIFF:-diff} ${FiLe} ${DiR} | ${PAGER:-pg}
  744.             fi
  745.             fi
  746.         fi
  747.         fi
  748.         [ ! -t 1 ] && { REDO=0; continue; }
  749.         echo "====== ${FiLe} done ===== Hit return to continue: \c"
  750.         REDO=0
  751.         read a < /dev/tty
  752.         [ -z "${a}" ] && continue
  753.         case ${a} in
  754.         vi|e|v)    REDO=1 ; vi ${FiLe} ;;
  755.         mod)    REDO=2 ; echo "cpio: -m option will be used"; Dopt=m ;;
  756.         nomod)    REDO=2 ; echo "cpio: no -m option"; Dopt="" ;;
  757.         redo|r)    REDO=1 ;;
  758.         quit|q)    return 1 ;;
  759.         put|PUT)    REDO=1
  760.             [ ${XdIfF} = true ] && {
  761.                 echo "Cannot put with '-' option" >&2
  762.                 REDO=2
  763.                 continue;
  764.             }
  765.             if [ ${a} = PUT ]; then
  766.                 rm -r ${DiR}/${FiLe} || {
  767.                 REDO=2
  768.                 continue
  769.                 }
  770.             fi
  771.             if [ -f ${FiLe} ] ; then
  772.                 find ${FiLe} -print | cpio -pduvv${Dopt} ${DiR}
  773.             elif [ -d ../${FiLe} ] ; then
  774.                 mkdir ${DiR}/${FiLe} || {
  775.                 REDO=2
  776.                 continue
  777.                 }
  778.                 cd ..; find ${FiLe} -print | cpio -pduvv${Dopt} ${DiR}
  779.             else
  780.                 echo "case not handled"
  781.                 REDO=2
  782.             fi
  783.             ;;
  784.         get|GET)    REDO=1
  785.             if [ ${XdIfF} = true ]; then
  786.                 if [ -f SCCS/p.${FiLe} ]; then
  787.                 if [ ${a} = GET ]; then
  788.                     ung ${FiLe} || REDO=2
  789.                 else
  790.                     echo "File is out being edited. Use GET to overwrite"
  791.                     REDO=2
  792.                 fi
  793.                 fi
  794.                 [ ${REDO} -gt 0 ] && continue
  795.                 get SCCS/s.${FiLe} || REDO=2
  796.             else
  797.                 [ ${a} = GET ] && rm -rf ${FiLe}
  798.                 export Dopt
  799.                 ( Here=`pwd`; chdir ${DiR} && \
  800.                   find ${FiLe} -print | cpio -pduvv${Dopt} ${Here} )
  801.             fi
  802.             ;;
  803.         sh)        ${SHELL:-/bin/sh}
  804.             REDO=2 ;;
  805.         '?'|*)    echo "Usage:\tvi|e|v:\tedit local file" >&2
  806.             echo "\tr|redo:\tredo file" >&2
  807.             echo "\tq|quit:\tquit" >&2
  808.             echo "\tput:\tcopy local file to remote file" >&2
  809.             echo "\tPUT:\tsame but forcibly" >&2
  810.             echo "\t[no]mod:\t[don't] use -m option for put/get" >&2
  811.             echo "\tget:\tcopy remote file to local file (or get SCCS file)" >&2
  812.             echo "\tGET:\tsame but forcibly" >&2
  813.             echo "\tsh:\tsub-shell" >&2
  814.             echo "\t'?':\thelp" >&2
  815.             REDO=2 ;;
  816.         esac
  817.         unset a
  818.     done
  819.     done
  820.     unset FiLe Opt Follow Skip Dotos Follow REDO More Dopt Nodiff Dusage
  821.     return 0
  822. }
  823. ----------------------------------- cut here ---------------------------------
  824. -- 
  825. Chris Bertin    | -- CETIA -- 150, Av Marcelin Berthelot, Z.I. Toulon-Est
  826. +33(94)212005    | 83088 Toulon Cedex, France
  827.         | inria!cetia!chris
  828.  
  829.  
  830.