#!/bin/sh
# dist-chmod --- fixup file/directory permissions recursively
# Author: Noah Friedman <friedman@splode.com>
# Public domain.

# $Id: dist-chmod,v 1.9 2018/01/15 21:13:43 friedman Exp $

setgid=
sticky=
bits=
owner=
verbose=

while : ; do
    case $1 in
        -0    ) bits=       ; shift ;;  # just for consistency
        -1    ) bits=o      ; shift ;;  # legacy dist-chmod1 behavior
        -2    ) bits=og     ; shift ;;  # legacy dist-chmod2 behavior
        -v    ) verbose=-v  ; set -x ; shift ;;
        -w    ) bits=$2     ; shift  ; shift ;;
        +s    ) setgid=,g+s ; shift  ;;
        -s    ) setgid=,g-s ; shift  ;;
        +t    ) sticky=,+t  ; shift  ;;
        -t    ) sticky=,-t  ; shift  ;;
        +x    ) fexec=,a+x  ; shift  ;;
        -x    ) fexec=,a-x  ; shift  ;;
        -[ou] ) owner=$2    ; shift  ; shift ;;
        --*   ) :           ; shift  ; break ;;
        -??*  ) opts=$1   # split single-letter options and reparse
                shift
                set fnord `echo $opts | sed -e 's/^-//;s/\(.\)/-\1 /g'` ${1+"$@"}
                shift ;;
        +??*  ) opts=$1   # split single-letter options and reparse
                shift
                set fnord `echo $opts | sed -e 's/^\+//;s/\(.\)/+\1 /g'` ${1+"$@"}
                shift ;;
        [-+]* ) echo "$1: Unknown option." 1>&2
                exit 1 ;;
        *     ) break ;;
    esac
done

fmode=a+rw
case $bits in
    ''      ) :                      ;;
    *[=+-]* ) fmode=$fmode,$bits     ;;
    *       ) fmode=$fmode,${bits}-w ;;
    [0-9]*  ) fmode=$bits
esac

dmode=a+x$setgid$sticky,$fmode
if find --version 2>&1 | grep 'GNU find' > /dev/null ; then
    find ${1+"$@"} ! -type l -type d -print0 \
        | xargs --null --no-run-if-empty chmod $verbose $dmode

    find ${1+"$@"} ! -type l -type f -print0 \
        | xargs --null --no-run-if-empty chmod $verbose $fmode$fexec
else
    case $verbose in
        '' ) print=       ;;
        *  ) print=-print ;;
    esac
    find ${1+"$@"} ! -type l -type d $print -exec chmod $dmode       '{}' ';'
    find ${1+"$@"} ! -type l -type f $print -exec chmod $fmode$fexec '{}' ';'
fi

case $owner in
    ''  ) exit $? ;;
    *:* ) : ;;
    *.* ) owner=`echo "$owner" | sed -e 's/\./:/'` ;;
esac

chown $verbose -h -R $owner ${1+"$@"}

# eof
