From 17c4835f08ad60df7ecde02eba4d9d47ae5a055d Mon Sep 17 00:00:00 2001 From: axel Date: Mon, 17 Oct 2005 23:24:12 +1000 Subject: [PATCH] Initial imlementation of uname shellscript function darcs-hash:20051017132412-ac50b-0c82581051eb6819ae8316a27f4b83401446e3df.gz --- complete.c | 67 +----------- doc_src/doc.hdr | 5 +- event.c | 2 +- exec.c | 46 +++++++- init/fish_function.fish | 236 +++++++++++++++++++++++++++++++++++++--- output.c | 63 +++++++---- output.h | 29 +++++ 7 files changed, 339 insertions(+), 109 deletions(-) diff --git a/complete.c b/complete.c index 35c6c7a16..8acf8e45a 100644 --- a/complete.c +++ b/complete.c @@ -1792,28 +1792,14 @@ static int complete_variable( const wchar_t *var, if( varlen > namelen ) continue; -/* wprintf( L"Try %ls\n", name );*/ - if( wcsncmp( var, name, varlen) == 0 ) { wchar_t *value = expand_escape_variable( env_get( name )); wchar_t *blarg; /* - What should the description of the variable be? - - If the variable doesn't have a value, or of the value is - really long, we just describe it as 'Variable', but if - the value is 1..16 characters long, we describe it as - 'Variable: VALUE'. + Variable description is 'Variable: VALUE */ -/* if( wcslen(value) < 1 || wcslen(value) > 16 ) - { - blarg = wcsdupcat( &name[varlen], COMPLETE_VAR_DESC ); - } - else - {*/ blarg = wcsdupcat2( &name[varlen], COMPLETE_VAR_DESC_VAL, value, 0 ); -// } if( blarg ) { @@ -1853,7 +1839,6 @@ static int try_complete_variable( const wchar_t *cmd, } return 0; - } /** @@ -1952,14 +1937,9 @@ static int try_complete_user( const wchar_t *cmd, free( pw_name ); } } - endpwent(); - } - } - - } return res; @@ -2079,7 +2059,7 @@ void complete( const wchar_t *cmd, if( current_token && current_command && prev_token ) { - + if( on_command ) { /* Complete command filename */ @@ -2096,48 +2076,9 @@ void complete( const wchar_t *cmd, expanded. This is potentially very slow. */ - int cmd_ok = 1; - int do_file = 1; - - wchar_t *end_str = current_token; - - /* - If the command is an function, we use the - completions of the first command in the function - and hope for the best... - */ - if( function_exists(current_command ) ) - { - tokenizer tok2; - tok_init( &tok2, function_get_definition( current_command), 0 ); - wchar_t *new_cmd=0; - - switch( tok_last_type( &tok2 ) ) - { - case TOK_STRING: - new_cmd = expand_one( wcsdup(tok_last( &tok2 )), - EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES ); - break; - default: - cmd_ok = 0; - break; - } - - tok_destroy( &tok2 ); - - if( cmd_ok ) - { - do_file &= complete_param( new_cmd, - prev_token, - end_str, - comp ); - } - if( new_cmd != 0 ) - free(new_cmd); - } - // fwprintf( stderr, L"complete_param with end_str %ls\n", end_str ); - do_file &= complete_param( current_command, prev_token, end_str, comp ); + int do_file; + do_file = complete_param( current_command, prev_token, current_token, comp ); complete_param_expand( current_token, comp, do_file ); } } diff --git a/doc_src/doc.hdr b/doc_src/doc.hdr index 21041a7b9..a7096e1f5 100644 --- a/doc_src/doc.hdr +++ b/doc_src/doc.hdr @@ -857,12 +857,12 @@ directory, or install them in /etc. - Complete vi-mode key bindings - '**' wildcard for recursive wildcard matching - next-history-complete -- builtin ulimit command +- umask shellscript function - builtin wait command - More completions (for example xterm, vim, konsole, gnome-terminal, dcop, cdrecord, cron, xargs rlogin, telnet, rsync, arch, finger, nice, locate, -latex, bibtex, patch, aspell, xpdf, +bibtex, patch, aspell, xpdf, zip, compress, wine, xmms, dig, wine, batch, cron, g++, javac, java, gcj, lpr, doxygen, whois, find) - Undo support @@ -892,7 +892,6 @@ g++, javac, java, gcj, lpr, doxygen, whois, find) - show the whole list of commands on using tab on an empty commandline - Automatically move cursor to the end of the current token before completing - Map variables. (export only the values. When expanding with no key specified, expand to all values.) -- psub function/builtin to make somthing like process substitution using command substitution \subsection bugs Known bugs diff --git a/event.c b/event.c index 2ccaf619c..9a5785cfd 100644 --- a/event.c +++ b/event.c @@ -283,7 +283,7 @@ static void event_fire_internal( event_t *event, array_list_t *arguments ) for( i=0; iparam1.filename, - io->param2.flags, 0666 ))==-1 ) + io->param2.flags, umask_val ))==-1 ) { debug( 1, FILE_ERROR, @@ -471,7 +505,7 @@ static io_data_t *io_transmogrify( io_data_t * in ) { int fd; - if( (fd=wopen( in->param1.filename, in->param2.flags, 0666 ))==-1 ) + if( (fd=wopen( in->param1.filename, in->param2.flags, umask_val ))==-1 ) { debug( 1, FILE_ERROR, @@ -626,7 +660,9 @@ void exec( job_t *j ) io_data_t *tmp; io_data_t *io_buffer =0; - + + umask_val = get_umask(); + debug( 4, L"Exec job %ls with id %d", j->command, j->job_id ); if( j->first_process->type==INTERNAL_EXEC ) @@ -829,7 +865,7 @@ void exec( job_t *j ) in->filename); */ new_fd=wopen( in->param1.filename, - in->param2.flags, 0666 ); + in->param2.flags, umask_val ); if( new_fd == -1 ) { wperror( L"wopen" ); diff --git a/init/fish_function.fish b/init/fish_function.fish index 70b163e41..1615f818c 100644 --- a/init/fish_function.fish +++ b/init/fish_function.fish @@ -5,7 +5,7 @@ function _contains_help -d "Helper function for contains" -set bullet \* + set bullet \* if count $LANG >/dev/null if test (expr match $LANG ".*UTF") -gt 0 set bullet \u2022 @@ -562,7 +562,7 @@ function __bold -d "Print argument in bold" set_color normal end -function __type_help -d "Help for the type shellscript function" +function __fish_type_help -d "Help for the type shellscript function" set bullet \* if count $LANG >/dev/null @@ -601,34 +601,47 @@ function type -d "Print the type of a command" set mode normal set selection all - for i in $argv + + set -- shortopt -o tpPafh + if getopt -T >/dev/null + set longopt + else + set longopt -- -l type,path,force-path,all,no-functions,help + end + + if not getopt -n type -Q $shortopt $longopt -- $argv + return 1 + end + + set tmp -- (getopt $shortopt $longopt -- $argv) + + eval set opt -- $tmp + + for i in $opt switch $i - case -t --t --ty --typ --type + case -t --type set mode type - case -p --p --pa --pat --path + case -p --path set mode path - case -P --f --fo --for --forc --force --force- --force-p --force-pa --force-pat --force-path + case -P --force-path set mode path set selection files - case -a --a --al --all + case -a --all set selection multi - case -f --n --no --no- --no-f --no-fu --no-fun --no-func --no-funct --no-functi --no-functio --no-function --no-functions + case -f --no-functions set selection files - case -h --h --he --hel --help - __type_help + case -h --help + __fish_type_help return 0 case -- break - case '-*' - echo Unknown option $i - return 1 end end @@ -711,6 +724,203 @@ function type -d "Print the type of a command" return $status end +function __fish_umask_help + +set bullet \* +if count $LANG >/dev/null + if test (expr match $LANG ".*UTF") -gt 0 + set bullet \u2022 + end +end + +echo \tumask - Set or get the user file-creation mask +echo +echo (__bold Synopsis) +echo +echo \t(set_color $fish_color_command)umask(set_color normal) [OPTIONS] [mask] +echo +echo (__bold Description) +echo +echo \tWith no argument, the current file-creation mask is printed, if an\n\targument is specified, it is the new file creation mask. +echo +echo \t$bullet (__bold -h) or (__bold --help) print this message +echo \t$bullet (__bold -S) or (__bold --symbolic) prints the file-creation mask in symbolic\n\t\ \ form instead of octal form. Use \'(set_color $fish_color_command)man(set_color $fish_color_normal) chmod\' for more information. +echo \t$bullet (__bold -p) or (__bold --as-command) prints any output in a form that may be reused\n\t\ \ as input +echo +echo (__bold Example) +echo +echo \t\'(set_color $fish_color_command)umask(set_color normal) 600\' sets the file creation mask to read and write for the\n\towner and no permissions at all for any other users. +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 + else + set res 0 0 0 + set el (echo $argv|tr , \n) + for i in $el + switch $i + case 'u*' + set idx 1 + set i (echo $i| cut -c 2-) + + case 'g*' + set idx 2 + set i (echo $i| cut -c 2-) + + case 'o*' + set idx 3 + set i (echo $i| cut -c 2-) + + case 'a*' + set idx 1 2 3 + set i (echo $i| cut -c 2-) + + case '*' + set idx 1 2 3 + end + + switch $i + case '=*' + set mode set + set i (echo $i| cut -c 2-) + + case '+*' + set mode add + set i (echo $i| cut -c 2-) + + case '-*' + set mode remove + set i (echo $i| cut -c 2-) + + case '*' + set mode set + end + + if not echo $perm|grep -E '^(r|w|x)*$' >/dev/null + echo umask: Invalid mask $argv >&2 + return + end + + set val 0 + if echo $perm |grep 'r' >/dev/null + set val 4 + end + if echo $perm |grep 'w' >/dev/null + set val (echo $val + 2|bc) + end + if echo $perm |grep 'x' >/dev/null + set val (echo $val + 1|bc) + end + + for j in $idx + set res[$j] $val + end + end + echo $res[1]$res[2]$res[3] + end +end + +function __fish_umask_print_symbolic + set -l res "" + set -l letter u g o + + for i in 1 2 3 + set res $res,$letter[$i]= + set val (echo $umask|cut -c $i) + + if contains $val 4 5 6 7 + set res {$res}r + end + + if contains $val 2 3 6 7 + set res {$res}w + end + + if contains $val 1 3 5 7 + set res {$res}x + end + + end + + echo $res|cut -c 2- +end + +function umask -d "Set default file permission mask" + + set -l as_command 0 + set -l symbolic 0 + + set -- shortopt -o pSh + if getopt -T >/dev/null + set longopt + else + set longopt -- -l as-command,symbolic,help + end + + if not getopt -n umask -Q $shortopt $longopt -- $argv + return 1 + end + + set tmp -- (getopt $shortopt $longopt -- $argv) + + eval set opt -- $tmp + + while count $opt >/dev/null + + switch $opt[1] + case -h --help + __fish_umask_help + return 0 + + case -p --as-command + set as_command 1 + + case -S --symbolic + set symbolic 1 + + case -- + set -e opt[1] + break + + end + + set -e opt[1] + + end + + switch (count $opt) + + case 0 + if not set -q umask + set -g umask 775 + end + if test $as_command -eq 1 + echo umask $umask + else + if test $symbolic -eq 1 + __fish_umask_print_symbolic $umask + else + echo $umask + end + end + + case 1 + set parsed (__fish_umask_parse $opt) + if test (count $parsed) -eq 1 + set -g umask $parsed + end + + case '*' + echo umask: Too may arguments >&2 + + end + +end + function psub -d "Read from stdin into a file and output the filename. Remove the file when the command that calles psub exits." if not status --is-command-substitution diff --git a/output.c b/output.c index 34e8819b7..e1e2f8481 100644 --- a/output.c +++ b/output.c @@ -1,3 +1,7 @@ +/** \file output.c + Generic output functions +*/ + #include "config.h" #include @@ -82,7 +86,14 @@ static int col_idx[]= } ; +/** + Size of writestr_buff +*/ static size_t writestr_buff_sz=0; + +/** + Temp buffer used for converting from wide to narrow strings +*/ static char *writestr_buff = 0; void output_init() @@ -97,7 +108,8 @@ void output_destroy() void set_color( int c, int c2 ) { - static int last_color = FISH_COLOR_NORMAL, last_color2=FISH_COLOR_NORMAL; + static int last_color = FISH_COLOR_NORMAL; + static int last_color2 = FISH_COLOR_NORMAL; int bg_set=0, last_bg_set=0; char *fg = 0, *bg=0; @@ -147,14 +159,16 @@ void set_color( int c, int c2 ) if(bg_set && !last_bg_set) { /* - Background color changed and is set, so we enter bold mode to make reading easier + Background color changed and is set, so we enter bold + mode to make reading easier */ writembs( enter_bold_mode ); } if(!bg_set && last_bg_set) { /* - Background color changed and is no longer set, so we exit bold mode + Background color changed and is no longer set, so we + exit bold mode */ writembs( exit_attribute_mode ); /* @@ -228,9 +242,6 @@ int writembs( char *str ) return 0; } -/** - Write a wide character to fd 1. -*/ int writech( wint_t ch ) { static mbstate_t out_state; @@ -253,37 +264,50 @@ int writech( wint_t ch ) return 0; } -/** - Write a wide character string to FD 1. -*/ void writestr( const wchar_t *str ) { // while( *str ) // writech( *str++ ); + + /* + Check amount of needed space + */ + size_t len = wcstombs( 0, str, 0 ); + + if( len == (size_t)-1 ) + { + debug( 1, L"Tried to print invalid wide character string" ); + return; + } - size_t len = MAX_UTF8_BYTES*wcslen(str)+1; + len++; + /* + Reallocate if needed + */ if( writestr_buff_sz < len ) { - writestr_buff = realloc( writestr_buff, writestr_buff_sz ); + writestr_buff = realloc( writestr_buff, len ); if( !writestr_buff ) die_mem(); writestr_buff_sz = len; } + /* + Convert + */ wcstombs( writestr_buff, str, writestr_buff_sz ); + /* + Write + */ write( 1, writestr_buff, strlen( writestr_buff ) ); } -/** - Write a wide character string to FD 1. If the string is wider than - the specified maximum, truncate and ellipsize it. -*/ void writestr_ellipsis( const wchar_t *str, int max_width ) { int written=0; @@ -314,9 +338,6 @@ void writestr_ellipsis( const wchar_t *str, int max_width ) } } -/** - Escape and write a string to fd 1 -*/ int write_escaped_str( const wchar_t *str, int max_len ) { @@ -352,16 +373,10 @@ int write_escaped_str( const wchar_t *str, int max_len ) } -/** - parm_ich seems to often be undefined, so we use this - workalike. Writes the specified number of spaces. -*/ int writespace( int c ) { if( repeat_char && strlen(repeat_char) ) { - debug( 1, L"YAY" ); - writembs( tparm( repeat_char, ' ', c ) ); } else diff --git a/output.h b/output.h index 8fac423d1..6532a48bf 100644 --- a/output.h +++ b/output.h @@ -1,3 +1,6 @@ +/** \file output.h + Generic output functions +*/ /** Constants for various character classifications. Each character of a command string can be classified as one of the following types. */ @@ -81,20 +84,46 @@ void set_color( int c, int c2 ); */ int writembs( char *str ); +/** + Write a wide character to fd 1. +*/ int writech( wint_t ch ); +/** + Write a wide character string to FD 1. +*/ void writestr( const wchar_t *str ); +/** + Write a wide character string to FD 1. If the string is wider than + the specified maximum, truncate and ellipsize it. +*/ void writestr_ellipsis( const wchar_t *str, int max_width ); +/** + Escape and write a string to fd 1 +*/ int write_escaped_str( const wchar_t *str, int max_len ); +/** + parm_ich seems to often be undefined, so we use this + workalike. Writes the specified number of spaces. +*/ int writespace( int c ); +/** + Return the internal color code representing the specified color +*/ int output_color_code( const wchar_t *val ); +/** + Initialize static data +*/ void output_init(); +/** + Destroy static data +*/ void output_destroy(); #endif