home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume07 / sccs.sh < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  18.8 KB

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