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=rw
sets 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