[comp.unix.questions] Friendly UMASK wanted

maart@cs.vu.nl (Maarten Litmaath) (02/02/90)

In article <2069@syma.sussex.ac.uk>,
	andy@syma.sussex.ac.uk (Andy Clews) writes:
\...
\		umask go-rw

Csh:
	alias	mask    'set tmp="`/full/path/of/mask \!*`"; eval $tmp'

Sh (supporting shell functions):

	mask()
	{
		tmp="`/full/path/of/mask $*`" 
		eval $tmp 
	}

...mask being the following shell script hack (Perl, Randal?).

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'mask'
sed 's/^X//' > 'mask' << '+ END-OF-FILE ''mask'
X#!/bin/sh
X# @(#)mask 1.0 90/02/02 Maarten Litmaath
X# mask g-wx,o=
X# mask -s
X
XUSAGE="
Xname=`basename $0`
Xecho 'Usage: '\$name' mode' >&2
Xecho '   or: '\$name' [-s]' >&2
Xecho 'mode: a symbolic string like \`g-wx,o='\\' >&2
Xecho '  or: the equivalent octal number' >&2
Xecho 'see chmod(1)' >&2
Xexit 1
X"
X
Xcase $# in
X0)
X	echo echo `umask`
X	exit 0
X	;;
X1)
X	;;
X*)
X	eval "$USAGE"
Xesac
X
Xcase $1 in
X-s)
X	set `
X		umask | sed -e 's/^0*//' -e 's/^.$/0&/' -e 's/^..$/0&/' \
X			-e 's/./& /g'
X	`
X	modes_7=
X	modes_6=x
X	modes_5=w
X	modes_4=wx
X	modes_3=r
X	modes_2=rx
X	modes_1=rw
X	modes_0=rwx
X	eval echo echo u=\$modes_$1,g=\$modes_$2,o=\$modes_$3
X	exit 0
Xesac
X
Xexpr x"$1" : 'x.*[^0-9]' > /dev/null || {
X	echo umask "$1"
X	exit 0
X}
X
Xset `
X	echo x"$1" | sed -e 's/.//' -e 's/^[-+=]/a&/' \
X		-e 's/,\\([-+=]\\)/,a\\1/g' \
X		-e 's/[-=],/-rwx,/g' -e 's/[-=]$/-rwx/' \
X		-e 's/+,/+rwx,/g' -e 's/+$/+rwx/' -e 's/./& /g' -e 's/$/,/'
X`
X
Xu_r=r
Xu_w=w
Xu_x=x
Xg_r=r
Xg_w=w
Xg_x=x
Xo_r=r
Xo_w=w
Xo_x=x
X
Xgroups=
Xperms=
X
Xfor i
Xdo
X	case $i in
X	[ugo])
X		groups="$groups $i"
X		;;
X	a)
X		groups="u g o"
X		;;
X	[-+=])
X		op=$i
X		;;
X	[rwx])
X		perms="$perms $i"
X		;;
X	,)
X		for group in $groups
X		do
X			case $op in
X			=)
X				eval ${group}_r=_
X				eval ${group}_w=_
X				eval ${group}_x=_
X			esac
X			for perm in $perms
X			do
X				case $op in
X				-)
X					bit=_
X					;;
X				*)
X					bit=$perm
X				esac
X				eval ${group}_$perm=$bit
X			done
X		done
X		groups=
X		perms=
X		;;
X	*)
X		eval "$USAGE"
X	esac
Xdone
X
X___=7
X__x=6
X_w_=5
X_wx=4
Xr__=3
Xr_x=2
Xrw_=1
Xrwx=0
X
Xeval echo umask 0\${$u_r$u_w$u_x}\${$g_r$g_w$g_x}\${$o_r$o_w$o_x}
+ END-OF-FILE mask
chmod 'u=rwx,g=,o=' 'mask'
set `wc -c 'mask'`
count=$1
case $count in
1555)	:;;
*)	echo 'Bad character count in ''mask' >&2
		echo 'Count should be 1555' >&2
esac
exit 0
--
  What do the following have in common:  access(2), SysV echo, O_NONDELAY?  |
  Maarten Litmaath @ VU Amsterdam:  maart@cs.vu.nl,  uunet!mcsun!botter!maart

lwall@jato.Jpl.Nasa.Gov (Larry Wall) (02/03/90)

In article <5265@star.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
: In article <2069@syma.sussex.ac.uk>,
: 	andy@syma.sussex.ac.uk (Andy Clews) writes:
: \...
: \		umask go-rw
: 
: Csh:
: 	alias	mask    'set tmp="`/full/path/of/mask \!*`"; eval $tmp'
: 
: Sh (supporting shell functions):
: 
: 	mask()
: 	{
: 		tmp="`/full/path/of/mask $*`" 
: 		eval $tmp 
: 	}
: 
: ...mask being the following shell script hack (Perl, Randal?).
: 
[123 line shell script from purgatory deleted]

Well, I'm not Randal, but here's the same thing in perl, 40 lines:

#!/usr/bin/perl

($name = $0) =~ s!.*/!!;
$umask = umask;

$USAGE = <<EOM;
Usage: $name mode
   or: $name [-s]
mode: a symbolic string like `g-wx,o='
  or: the equivalent octal number
see chmod(1)
EOM

($arg,$extra) = @ARGV;
die $USAGE if $extra;

if ($arg eq '') {		# report numerically
    printf "echo %o\n",umask;
}
elsif ($arg eq '-s') {		# report symbolically
    for (',o', ',g', 'u') {
	for ('x', 'w', 'r') {
	    $sym = $_ . $sym unless $umask & 1;  $umask >>= 1;
	}
	$sym = "$_=" . $sym;
    }
    print "echo $sym\n";
}
elsif ($arg =~ /^\d+$/) {	# change numerically
    print "umask $arg\n";
}
else {				# change symbolically (cheat: let chmod do it)
    $tmp="/tmp/umask$$";
    open(TMP,">$tmp") || die "$name: Can't create $tmp: $!\n";
    chmod ~$umask & 0777, $tmp;
    ($err = `chmod $ARGV[0] $tmp 2>&1`) =~ s/chmod/$name/; die $err if $err;
    ($dev,$ino,$mode) = stat TMP;
    unlink $tmp;
    printf "umask %o\n", ~$mode & 0777;
}

Larry Wall
lwall@jpl-devvax.jpl.nasa.gov

decot@hpisod2.HP.COM (Dave Decot) (02/03/90)

> X#!/bin/sh
> X# @(#)mask 1.0 90/02/02 Maarten Litmaath
> X# mask g-wx,o=
> X# mask -s

This does not conform to POSIX.2, in that it does not have an -o option
to force octal output, the + operation does not seem to work (it always sets
the involved mode parts to 0, regardless of the previous value), and most
importantly, the modes are interpreted upside down.  That is, this script
assumes:

   $ umask -o
   022
   $ umask -s
   u=,g=w,o=w


POSIX.2 requires:

   $ umask -o
   022
   $ umask -s
   u=rwx,g=rx,o=rx
   $ umask o+w,g-r
   $ umask -s
   u=rwx,g=x,o=rwx
   $ umask -o
   0060

Here's a version of Maarten's script that fixes the above problems.
The default output style when no arguments are present is
implementation-defined, as far as POSIX.2 is concerned, but I prefer
symbolic output by default, so my script does that.

Some versions of sh don't understand that "[-+=])" as a case label
means to test for -, but rather try to do something stupid with the -
(probably ranges), so I also changed that.

Dave
----------------

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Dave Decot <decot@hpisod2> on Fri Feb  2 16:21:42 1990
#
# This archive contains:
#	mask	
#

unset LANG

echo x - mask
cat >mask <<'@EOF'
#!/bin/sh
# @(#)mask 1.0 90/02/02 Maarten Litmaath
# @(#)mask 1.1 90/02/03 Dave Decot
# mask g-wx,o=
# mask -s

USAGE="
name=`basename $0`
echo 'Usage: '\$name' mode' >&2
echo '   or: '\$name' [-s|-o]' >&2
echo 'mode: a symbolic string like \`g-wx,o='\\' >&2
echo '  or: the equivalent octal number' >&2
echo 'see chmod(1)' >&2
exit 1
"

case $# in
 0) arg="-s" ;;
 1) arg="$1" ;;
 *) eval "$USAGE" ;;
esac

modes_7=___
modes_6=__x
modes_5=_w_
modes_4=_wx
modes_3=r__
modes_2=r_x
modes_1=rw_
modes_0=rwx

expr x"$arg" : 'x.*[^0-9]' > /dev/null || {
	echo umask "$arg"
	exit 0
}

case "$arg" in
-s)	 style=symbolic ;;
-o)      style=octal ;;
-[rwx]*|x-*) ;;
-*)	  eval "$USAGE" ;;
x*)	  ;;
esac

set `umask \
  |  sed -e 's/^0*//' -e 's/^$/0/' -e 's/^.$/0&/' -e 's/^..$/0&/' -e 's/./& /g'`

output=`eval echo "u="'$'"modes_$1,g="'$'"modes_$2,o="'$'"modes_$3"`

case $style in
    symbolic) eval echo echo "$output" | tr -d _
	      exit 0 ;;
    octal)    echo umask
	      exit 0 ;;
esac

set -- `echo $output | sed -e "s/./& /g" -e "s/[=,ugo]//g"`

for i in u g o
do
    for j in r w x
    do
	eval ${i}_${j}=$1
	shift
    done
done

set -- "$arg"

set `
	echo x"$1" | sed -e 's/.//' -e 's/^[-+=]/a&/' \
		-e 's/,\\([-+=]\\)/,a\\1/g' \
		-e 's/[-=],/-rwx,/g' -e 's/[-=]$/-rwx/' \
		-e 's/+,/+rwx,/g' -e 's/+$/+rwx/' -e 's/./& /g' -e 's/$/,/'
`

groups=
perms=

for i
do
	case $i in
	[ugo])
		groups="$groups $i"
		;;
	a)
		groups="u g o"
		;;
	-)
		op=$i
		;;
	[+=])
		op=$i
		;;
	[rwx])
		perms="$perms $i"
		;;
	,)
		for group in $groups
		do
			case $op in
			=)
				eval ${group}_r=_
				eval ${group}_w=_
				eval ${group}_x=_
			esac
			for perm in $perms
			do
				case $op in
				-)
					bit=_
					;;
				*)
					bit=$perm
					;;
				esac
				eval ${group}_$perm=$bit
			done
		done
		groups=
		perms=
		;;
	*)
		eval "$USAGE"
	esac
done

___=7
__x=6
_w_=5
_wx=4
r__=3
r_x=2
rw_=1
rwx=0

eval echo umask 0\${$u_r$u_w$u_x}\${$g_r$g_w$g_x}\${$o_r$o_w$o_x}
@EOF

chmod 755 mask

exit 0

maart@cs.vu.nl (Maarten Litmaath) (02/06/90)

In article <10650080@hpisod2.HP.COM>,
	decot@hpisod2.HP.COM (Dave Decot) writes:
\...
\> X# @(#)mask 1.0 90/02/02 Maarten Litmaath
\..., the modes are interpreted upside down.  That is, this script
\assumes:
\
\   $ umask -o
\   022
\   $ umask -s
\   u=,g=w,o=w

The abovementioned claim is false.  I have umask 022; when I type `mask -s'
(using version 1), I get:

	echo u=rwx,g=rx,o=rx

[sic]
Anyway, thanks for your corrections/extensions.
--
  The meek get the earth, Henry the moon, the rest of us have other plans.  |
  Maarten Litmaath @ VU Amsterdam:  maart@cs.vu.nl,  uunet!mcsun!botter!maart

decot@hpisod2.HP.COM (Dave Decot) (02/11/90)

> \> X# @(#)mask 1.0 90/02/02 Maarten Litmaath
> \..., the modes are interpreted upside down.  That is, this script
> \assumes:
> \
> \   $ umask -o
> \   022
> \   $ umask -s
> \   u=,g=w,o=w
> 
> The abovementioned claim is false.  I have umask 022; when I type `mask -s'
> (using version 1), I get:
> 
> 	echo u=rwx,g=rx,o=rx
> 
> [sic]
> Anyway, thanks for your corrections/extensions.

Sorry, you're right.  Since it didn't understand "+" and "-" at all correctly,
I was confused into that impression.

Dave