diff --git a/Makefile.in b/Makefile.in index 3e9da5008..3a4a030c3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -104,8 +104,9 @@ BUILTIN_DOC_HDR := $(BUILTIN_DOC_SRC:.txt=.doxygen) CMD_DOC_SRC := doc_src/count.txt doc_src/dirh.txt doc_src/dirs.txt \ doc_src/fishd.txt doc_src/help.txt doc_src/mimedb.txt \ doc_src/nextd.txt doc_src/open.txt doc_src/popd.txt \ - doc_src/prevd.txt doc_src/pushd.txt doc_src/set_color.txt \ - doc_src/tokenize.txt doc_src/type.txt + doc_src/prevd.txt doc_src/psub.txt doc_src/pushd.txt \ + doc_src/set_color.txt doc_src/tokenize.txt doc_src/type.txt \ + doc_src/umask.txt # # Files generated by running doxygen on the files in $(CMD_DOC_SRC) diff --git a/doc_src/umask.txt b/doc_src/umask.txt index 7995543da..cda5ff838 100644 --- a/doc_src/umask.txt +++ b/doc_src/umask.txt @@ -7,15 +7,23 @@ \subsection umask-description Description With no argument, the current file-creation mask is printed, if an -argument is specified, it is the new file creation mask. +argument is specified, it is the new file creation mask. The mask may +be specified as an octal number, in which case it is interpreted as +the rights that should be masked away, i.e. it is the inverse of the +file permissions any new files will have. If a synbolic mask is +specified, the actual file permission bits, and not the inverse, are +specified. - -h or --help print this message - -S or --symbolic prints the file-creation mask in symbolic form instead of octal form. Use man chmod for more information. - -p or --as-command prints any output in a form that may be reused as input -The umask implementation in fish should behave identically to the one in bash. +The umask implementation in fish should behave identically to the one +in bash. \subsection umask-example Example -umask 600 sets the file creation mask to read and write for the owner and no permissions at all for any other users. +umask 177 or umask u=rwsets the file +creation mask to read and write for the owner and no permissions at +all for any other users. diff --git a/env.c b/env.c index 8fda3a7df..8fac2c2cb 100644 --- a/env.c +++ b/env.c @@ -15,7 +15,6 @@ #include #include - #if HAVE_NCURSES_H #include #else @@ -27,6 +26,7 @@ #endif #include +#include #include "util.h" #include "wutil.h" @@ -385,6 +385,24 @@ void env_set( const wchar_t *key, fish_setlocale(LC_ALL,val); } + if( wcscmp( key, L"umask" ) == 0) + { + wchar_t *end; + int mask; + + if( val && wcslen(val) ) + { + errno=0; + mask = wcstol( val, &end, 8 ); + + if( !errno && !*end ) + { + umask( mask ); + } + } + } + + /* Zero element arrays are internaly not coded as null but as this placeholder string */ diff --git a/exec.c b/exec.c index c09758dc1..40f686baa 100644 --- a/exec.c +++ b/exec.c @@ -58,10 +58,6 @@ pid_t getpgid( pid_t pid ); */ #define FORK_ERROR L"Could not create child process - exiting" -/** - Default value for the umask -*/ -#define UMASK_DEFAULT 0664 /** List of all pipes used by internal pipes. These must be closed in @@ -70,36 +66,6 @@ pid_t getpgid( pid_t pid ); */ static array_list_t *open_fds=0; -/** - The umask. Recalculated every time exec is run. by calling get_umask(). -*/ -static int umask_val; - -/** - Calculate the current value of the umask. Should be done once at - the beginning of each call to exec. Uses the $umask environment - variable, if available, defaults to the constant UMASK_DEFAULT. -*/ -static int get_umask() -{ - wchar_t *m = env_get( L"umask" ); - wchar_t *end; - int mask; - - if( !m || !wcslen(m) ) - return UMASK_DEFAULT; - - errno=0; - mask = wcstol( m, &end, 8 ); - - if( errno || *end ) - { - return UMASK_DEFAULT; - } - - return mask; -} - void exec_close( int fd ) { @@ -313,7 +279,7 @@ static void handle_child_io( io_data_t *io ) break; case IO_FILE: if( (tmp=wopen( io->param1.filename, - io->param2.flags, umask_val ))==-1 ) + io->param2.flags, 0777 ) )==-1 ) { debug( 1, FILE_ERROR, @@ -516,7 +482,7 @@ static io_data_t *io_transmogrify( io_data_t * in ) { int fd; - if( (fd=wopen( in->param1.filename, in->param2.flags, umask_val ))==-1 ) + if( (fd=wopen( in->param1.filename, in->param2.flags, 0777 ) )==-1 ) { debug( 1, FILE_ERROR, @@ -676,9 +642,7 @@ void exec( job_t *j ) Set to 1 if something goes wrong while exec:ing the job, in which case the cleanup code will kick in. */ int exec_error=0; - - umask_val = get_umask(); debug( 4, L"Exec job %ls with id %d", j->command, j->job_id ); @@ -890,7 +854,7 @@ void exec( job_t *j ) in->filename); */ builtin_stdin=wopen( in->param1.filename, - in->param2.flags, umask_val ); + in->param2.flags, 0777 ); if( builtin_stdin == -1 ) { debug( 1, diff --git a/init/completions/help.fish b/init/completions/help.fish index ca2748f33..4dd2f46fd 100644 --- a/init/completions/help.fish +++ b/init/completions/help.fish @@ -6,6 +6,10 @@ for i in (builtin -n) complete -c help -x -a $i -d 'Help for the '$i' builtin' end +for i in count dirh dirs help mimedb nextd open popd prevd pushd set_color tokenize psub umask type + complete -c help -x -a $i -d 'Help for the '$i' command' +end + for i in syntax todo bugs history; complete -c help -x -a $i -d 'Help section on '$i end diff --git a/init/fish_function.fish b/init/fish_function.fish index 55e8bf8db..8417220cd 100644 --- a/init/fish_function.fish +++ b/init/fish_function.fish @@ -154,7 +154,7 @@ function help -d "Show help for the fish shell" set fish_help_page "builtins.html\#"$fish_help_item end - if contains -- $fish_help_item count dirh dirs help mimedb nextd open popd prevd pushd set_color tokenize + if contains -- $fish_help_item count dirh dirs help mimedb nextd open popd prevd pushd set_color tokenize psub umask type set fish_help_page "commands.html\#"$fish_help_item end @@ -755,48 +755,82 @@ echo end function __fish_umask_parse -d "Parses a file permission specification as into an octal version" - # Test if already a valid octal mask - if echo $argv | grep -E '^[0-7]{1,4}$' >/dev/null - echo $argv + # Test if already a valid octal mask, and pad it with zeros + if echo $argv | grep -E '^(0|)[0-7]{1,3}$' >/dev/null + for i in (seq (echo 5-(echo $argv|wc -c)|bc)); set -- argv 0$argv; end + echo $argv else - set res 0 0 0 - set el (echo $argv|tr , \n) + # Test if argument really is a valid symbolic mask + if not echo $argv | grep -E '^(((u|g|o|a|)(=|\+|-)|)(r|w|x)*)(,(((u|g|o|a|)(=|\+|-)|)(r|w|x)*))*$' >/dev/null + echo umask: Invalid mask $argv >&2 + return 1 + end + + set -e implicit_all + + # Make sure the current umask is defined + if not set -q umask + set umask 0000 + end + + # If umask is invalid, reset it + if not echo $umask | grep -E '^(0|)[0-7]{1,3}$' >/dev/null + set umask 0000 + end + + # Pad umask with zeros + for i in (seq (echo 5-(echo $umask|wc -c)|bc)); set -- argv 0$umask; end + + # Insert inverted umask into res variable + + set tmp $umask + for i in 1 2 3 + set -- tmp (echo $tmp|cut -c 2-) + set -- res[$i] (echo 7-(echo $tmp|cut -c 1)|bc) + end + + set -- el (echo $argv|tr , \n) for i in $el switch $i case 'u*' set idx 1 - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case 'g*' set idx 2 - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case 'o*' set idx 3 - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case 'a*' set idx 1 2 3 - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case '*' + set implicit_all 1 set idx 1 2 3 end switch $i case '=*' set mode set - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case '+*' set mode add - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case '-*' set mode remove - set i (echo $i| cut -c 2-) + set -- i (echo $i| cut -c 2-) case '*' + if not set -q implicit_all + echo umask: Invalid mask $argv >&2 + return + end set mode set end @@ -806,41 +840,67 @@ function __fish_umask_parse -d "Parses a file permission specification as into a end set val 0 - if echo $perm |grep 'r' >/dev/null + if echo $i |grep 'r' >/dev/null set val 4 end - if echo $perm |grep 'w' >/dev/null + if echo $i |grep 'w' >/dev/null set val (echo $val + 2|bc) end - if echo $perm |grep 'x' >/dev/null + if echo $i |grep 'x' >/dev/null set val (echo $val + 1|bc) end for j in $idx - set res[$j] $val + switch $mode + case set + set res[$j] $val + + case add + set res[$j] (perl -e 'print( ( '$res[$j]'|'$val[$j]' )."\n" )') + + case remove + set res[$j] (perl -e 'print( ( (7-'$res[$j]')&'$val[$j]' )."\n" )') + end end end - echo $res[1]$res[2]$res[3] + + for i in 1 2 3 + set res[$i] (echo 7-$res[$i]|bc) + end + echo 0$res[1]$res[2]$res[3] end end function __fish_umask_print_symbolic set -l res "" - set -l letter u g o + set -l letter a u g o - for i in 1 2 3 + # Make sure the current umask is defined + if not set -q umask + set umask 0000 + end + + # If umask is invalid, reset it + if not echo $umask | grep -E '^(0|)[0-7]{1,3}$' >/dev/null + set umask 0000 + end + + # Pad umask with zeros + for i in (seq (echo 5-(echo $umask|wc -c)|bc)); set -- argv 0$umask; end + + for i in 2 3 4 set res $res,$letter[$i]= set val (echo $umask|cut -c $i) - if contains $val 4 5 6 7 + if contains $val 0 1 2 3 set res {$res}r end - if contains $val 2 3 6 7 + if contains $val 0 1 4 5 set res {$res}w end - if contains $val 1 3 5 7 + if contains $val 0 2 4 6 set res {$res}x end @@ -896,7 +956,7 @@ function umask -d "Set default file permission mask" case 0 if not set -q umask - set -g umask 664 + set -g umask 113 end if test $as_command -eq 1 echo umask $umask