mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-25 06:41:15 -03:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2ebc0e443 | ||
|
|
8ff66e718c | ||
|
|
2789da6a1a | ||
|
|
51c345311a | ||
|
|
4a68a34c50 | ||
|
|
9993ff07f2 | ||
|
|
fc8b56da0d | ||
|
|
02981a1750 | ||
|
|
c2e6b07b35 | ||
|
|
8fcacdd5df | ||
|
|
6bf58e44f4 | ||
|
|
bda7948719 | ||
|
|
e800fca499 | ||
|
|
eed4b75389 | ||
|
|
5974dd68b0 | ||
|
|
680c0aff05 | ||
|
|
4a2bdeebef | ||
|
|
dfa251a1ab | ||
|
|
82cb97d3e3 | ||
|
|
7d334914f7 | ||
|
|
27a60f465d | ||
|
|
279159384e | ||
|
|
d748e05cb9 | ||
|
|
d50c051eec | ||
|
|
8d58e58d7b | ||
|
|
c8c3715aac | ||
|
|
7ffcebb9f8 | ||
|
|
831d95b600 | ||
|
|
0ffeb41c28 | ||
|
|
e8d02159da | ||
|
|
b78fba810c | ||
|
|
43213ee458 | ||
|
|
da316dd588 | ||
|
|
c8bc79005c | ||
|
|
5ba0affdd7 | ||
|
|
721f616964 | ||
|
|
ef4345968e | ||
|
|
319956c26b | ||
|
|
a9bf64465c | ||
|
|
ddcb84aa07 | ||
|
|
d332293245 | ||
|
|
48afe8062e | ||
|
|
277f9b7e60 | ||
|
|
f8de9de13d | ||
|
|
ba6ad5025e |
@@ -1,3 +1,4 @@
|
||||
|
||||
2005-10-03 Netocrat <netocrat@dodo.com.au>
|
||||
|
||||
* fishd.c, common.c: Make lock-file name include hostname for increased protection on shared NFS /tmp.
|
||||
|
||||
@@ -106,7 +106,7 @@ CMD_DOC_SRC := doc_src/count.txt doc_src/dirh.txt doc_src/dirs.txt \
|
||||
doc_src/nextd.txt doc_src/open.txt doc_src/popd.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
|
||||
doc_src/umask.txt doc_src/vared.txt
|
||||
|
||||
#
|
||||
# Files generated by running doxygen on the files in $(CMD_DOC_SRC)
|
||||
|
||||
23
builtin.c
23
builtin.c
@@ -724,6 +724,9 @@ static int wcsbindingname( wchar_t *str )
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Debug function to print the current block stack
|
||||
*/
|
||||
static void print_block_stack( block_t *b )
|
||||
{
|
||||
if( !b )
|
||||
@@ -1414,6 +1417,9 @@ static int builtin_read( wchar_t **argv )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
The status builtin. Gives various status information on fish.
|
||||
*/
|
||||
static int builtin_status( wchar_t **argv )
|
||||
{
|
||||
enum
|
||||
@@ -1951,22 +1957,13 @@ static int builtin_complete( wchar_t **argv )
|
||||
}
|
||||
|
||||
/**
|
||||
The source builtin. Can be called through either 'source' or
|
||||
'.'. Evaluates the contents of a file.
|
||||
The . (dot) builtin, sometimes called source. Evaluates the contents of a file.
|
||||
*/
|
||||
static int builtin_source( wchar_t ** argv )
|
||||
{
|
||||
int fd;
|
||||
int res;
|
||||
|
||||
/*
|
||||
if( wcsstr( argv[1], L"fish_complete" ) )
|
||||
{
|
||||
fwprintf( stderr, L"Woot\n" );
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if( (argv[1] == 0) || (argv[2]!=0) )
|
||||
{
|
||||
|
||||
@@ -2458,6 +2455,9 @@ static int builtin_for( wchar_t **argv )
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
The begin builtin. Creates a nex block.
|
||||
*/
|
||||
static int builtin_begin( wchar_t **argv )
|
||||
{
|
||||
parser_push_block( BEGIN );
|
||||
@@ -2564,7 +2564,8 @@ static int builtin_end( wchar_t **argv )
|
||||
parser_get_job_pos()-current_block->tok_pos );
|
||||
|
||||
//fwprintf( stderr, L"Function: %ls\n", def );
|
||||
if( !parser_test( def, 1 ) )
|
||||
|
||||
if( !is_interactive || !parser_test( def, 1 ) )
|
||||
{
|
||||
function_add( current_block->param1.function_name,
|
||||
def,
|
||||
|
||||
30
builtin.h
30
builtin.h
@@ -17,10 +17,29 @@ enum
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Error message on missing argument
|
||||
*/
|
||||
#define BUILTIN_ERR_MISSING L": Expected argument"
|
||||
|
||||
/**
|
||||
Error message on invalid combination of options
|
||||
*/
|
||||
#define BUILTIN_ERR_COMBO L": Invalid combination of options"
|
||||
|
||||
/**
|
||||
Error message on multiple scope levels for variables
|
||||
*/
|
||||
#define BUILTIN_ERR_GLOCAL L": Variable can only be one of universal, global and local"
|
||||
|
||||
/**
|
||||
Error message for specifying both export and unexport to set/read
|
||||
*/
|
||||
#define BUILTIN_ERR_EXPUNEXP L": Variable can't be both exported and unexported"
|
||||
|
||||
/**
|
||||
Error message for unknown switch
|
||||
*/
|
||||
#define BUILTIN_ERR_UNKNOWN L": Unknown option"
|
||||
|
||||
/**
|
||||
@@ -103,8 +122,19 @@ int builtin_count_args( wchar_t **argv );
|
||||
void builtin_print_help( wchar_t *cmd, string_buffer_t *b );
|
||||
|
||||
|
||||
/**
|
||||
The set builtin, used for setting variables. Defined in builtin_set.c.
|
||||
*/
|
||||
int builtin_set(wchar_t **argv);
|
||||
|
||||
/**
|
||||
The commandline builtin, used for setting and getting the contents of the commandline. Defined in builtin_commandline.c.
|
||||
*/
|
||||
int builtin_commandline(wchar_t **argv);
|
||||
|
||||
/**
|
||||
The ulimit builtin, used for setting resource limits. Defined in builtin_ulimit.c.
|
||||
*/
|
||||
int builtin_ulimit(wchar_t **argv);
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,6 +47,14 @@ enum
|
||||
;
|
||||
|
||||
|
||||
/**
|
||||
Replace/append/insert the selection with/at/after the specified string.
|
||||
|
||||
\param begin beginning of selection
|
||||
\param end end of selection
|
||||
\param insert the string to insert
|
||||
\param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the test update is performed
|
||||
*/
|
||||
static void replace_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
wchar_t *insert,
|
||||
@@ -95,10 +103,18 @@ static void replace_part( wchar_t *begin,
|
||||
sb_destroy( &out );
|
||||
}
|
||||
|
||||
void write_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
int cut_at_cursor,
|
||||
int tokenize )
|
||||
/**
|
||||
Output the specified selection.
|
||||
|
||||
\param begin start of selection
|
||||
\param end end of selection
|
||||
\param cut_at_cursor whether printing should stop at the surrent cursor position
|
||||
\param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens
|
||||
*/
|
||||
static void write_part( wchar_t *begin,
|
||||
wchar_t *end,
|
||||
int cut_at_cursor,
|
||||
int tokenize )
|
||||
{
|
||||
tokenizer tok;
|
||||
string_buffer_t out;
|
||||
|
||||
@@ -83,7 +83,7 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (iswblank(*src))
|
||||
while (iswspace(*src))
|
||||
{
|
||||
src++;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
al_push(indexes, ind);
|
||||
src = end;
|
||||
count++;
|
||||
while (iswblank(*src)) src++;
|
||||
while (iswspace(*src)) src++;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
117
builtin_ulimit.c
117
builtin_ulimit.c
@@ -1,6 +1,6 @@
|
||||
/** \file builtin_commandline.c Functions defining the commandline builtin
|
||||
/** \file builtin_ulimit.c Functions defining the ulimit builtin
|
||||
|
||||
Functions used for implementing the commandline builtin.
|
||||
Functions used for implementing the ulimit builtin.
|
||||
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
@@ -18,76 +18,109 @@ Functions used for implementing the commandline builtin.
|
||||
#include "common.h"
|
||||
#include "wgetopt.h"
|
||||
|
||||
/**
|
||||
Struct describing a resource limit
|
||||
*/
|
||||
struct resource_t
|
||||
{
|
||||
/**
|
||||
Resource id
|
||||
*/
|
||||
int resource;
|
||||
/**
|
||||
Description of resource
|
||||
*/
|
||||
const wchar_t *desc;
|
||||
/**
|
||||
Switch used on commandline to specify resource
|
||||
*/
|
||||
wchar_t switch_char;
|
||||
/**
|
||||
The implicit multiplier used when setting getting values
|
||||
*/
|
||||
int multiplier;
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Array of resource_t structs, describing all known resource types.
|
||||
*/
|
||||
const static struct resource_t resource_arr[] =
|
||||
{
|
||||
{
|
||||
RLIMIT_CORE, L"Maximum size of core files created", L'c'
|
||||
RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd'
|
||||
RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd', 1024
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f'
|
||||
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
|
||||
}
|
||||
,
|
||||
#if HAVE_RLIMIT_MEMLOCK
|
||||
{
|
||||
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#if HAVE_RLIMIT_RSS
|
||||
{
|
||||
RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
|
||||
}
|
||||
,
|
||||
#endif
|
||||
{
|
||||
RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n', 1
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l'
|
||||
RLIMIT_STACK, L"Maximum stack size", L's', 1024
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_RSS, L"Maximum resident set size", L'm'
|
||||
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
|
||||
}
|
||||
,
|
||||
#if HAVE_RLIMIT_NPROC
|
||||
{
|
||||
RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n'
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_STACK, L"Maximum stack size", L's'
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't'
|
||||
}
|
||||
,
|
||||
{
|
||||
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u'
|
||||
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#if HAVE_RLIMIT_AS
|
||||
{
|
||||
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v'
|
||||
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
|
||||
}
|
||||
,
|
||||
#endif
|
||||
{
|
||||
0, 0
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Get the implicit multiplication factor for the specified resource limit
|
||||
*/
|
||||
static int get_multiplier( int what )
|
||||
{
|
||||
if( ( what == RLIMIT_NPROC ) ||
|
||||
( what == RLIMIT_NOFILE ) ||
|
||||
( what == RLIMIT_CPU ) )
|
||||
int i;
|
||||
|
||||
for( i=0; resource_arr[i].desc; i++ )
|
||||
{
|
||||
return 1;
|
||||
if( resource_arr[i].resource == what )
|
||||
{
|
||||
return resource_arr[i].multiplier;
|
||||
}
|
||||
}
|
||||
return 1024;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Return the value for the specified resource limit
|
||||
*/
|
||||
static rlim_t get( int resource, int hard )
|
||||
{
|
||||
struct rlimit ls;
|
||||
@@ -97,6 +130,9 @@ static rlim_t get( int resource, int hard )
|
||||
return hard ? ls.rlim_max:ls.rlim_cur;
|
||||
}
|
||||
|
||||
/**
|
||||
Print the value of the specified resource limit
|
||||
*/
|
||||
static void print( int resource, int hard )
|
||||
{
|
||||
rlim_t l = get( resource, hard );
|
||||
@@ -108,7 +144,9 @@ static void print( int resource, int hard )
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print values of all resource limits
|
||||
*/
|
||||
static void print_all( int hard )
|
||||
{
|
||||
int i;
|
||||
@@ -142,6 +180,9 @@ static void print_all( int hard )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the description for the specified resource limit
|
||||
*/
|
||||
static const wchar_t *get_desc( int what )
|
||||
{
|
||||
int i;
|
||||
@@ -156,7 +197,9 @@ static const wchar_t *get_desc( int what )
|
||||
return L"Not a resource";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set the new value of the specified resource limit
|
||||
*/
|
||||
static int set( int resource, int hard, int soft, rlim_t value )
|
||||
{
|
||||
struct rlimit ls;
|
||||
@@ -194,6 +237,9 @@ static int set( int resource, int hard, int soft, rlim_t value )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Set all resource limits
|
||||
*/
|
||||
static int set_all( int hard, int soft, rlim_t value )
|
||||
{
|
||||
int i;
|
||||
@@ -332,14 +378,17 @@ int builtin_ulimit( wchar_t ** argv )
|
||||
case L'f':
|
||||
what=RLIMIT_FSIZE;
|
||||
break;
|
||||
|
||||
#if HAVE_RLIMIT_MEMLOCK
|
||||
case L'l':
|
||||
what=RLIMIT_MEMLOCK;
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
#if HAVE_RLIMIT_RSS
|
||||
case L'm':
|
||||
what=RLIMIT_RSS;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case L'n':
|
||||
what=RLIMIT_NOFILE;
|
||||
@@ -352,10 +401,12 @@ int builtin_ulimit( wchar_t ** argv )
|
||||
case L't':
|
||||
what=RLIMIT_CPU;
|
||||
break;
|
||||
|
||||
|
||||
#if HAVE_RLIMIT_NPROC
|
||||
case L'u':
|
||||
what=RLIMIT_NPROC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAVE_RLIMIT_AS
|
||||
case L'v':
|
||||
|
||||
611
common.c
611
common.c
@@ -13,6 +13,7 @@ parts of fish.
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <wctype.h>
|
||||
@@ -26,6 +27,11 @@ parts of fish.
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef HOST_NAME_MAX
|
||||
/**
|
||||
Maximum length of hostname return. It is ok if this is too short,
|
||||
getting the actual hostname is not critical, so long as the string
|
||||
is unique in the filesystem namespace.
|
||||
*/
|
||||
#define HOST_NAME_MAX 255
|
||||
#endif
|
||||
|
||||
@@ -93,6 +99,9 @@ int debug_level=1;
|
||||
static struct winsize termsize;
|
||||
|
||||
|
||||
/**
|
||||
Number of nested calls to the block function. Unblock when this reaches 0.
|
||||
*/
|
||||
static int block_count=0;
|
||||
|
||||
void common_destroy()
|
||||
@@ -291,7 +300,7 @@ char *wcs2str( const wchar_t *in )
|
||||
in,
|
||||
MAX_UTF8_BYTES*wcslen(in)+1 );
|
||||
|
||||
res = realloc( res, strlen( res )+1 );
|
||||
// res = realloc( res, strlen( res )+1 );
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -306,8 +315,7 @@ char **wcsv2strv( const wchar_t **in )
|
||||
char **res = malloc( sizeof( char *)*(count+1));
|
||||
if( res == 0 )
|
||||
{
|
||||
die_mem();
|
||||
|
||||
die_mem();
|
||||
}
|
||||
|
||||
for( i=0; i<count; i++ )
|
||||
@@ -345,8 +353,10 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... )
|
||||
|
||||
wchar_t *res = malloc( sizeof(wchar_t)*(len +1 ));
|
||||
if( res == 0 )
|
||||
return 0;
|
||||
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
wcscpy( res, a );
|
||||
pos = wcslen(a);
|
||||
while( (arg=va_arg(va2, wchar_t *) )!= 0 )
|
||||
@@ -481,17 +491,6 @@ long wcstol(const wchar_t *nptr,
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
Appends src to string dst of size siz (unlike wcsncat, siz is the
|
||||
full size of dst, not space left). At most siz-1 characters will be
|
||||
copied. Always NUL terminates (unless siz <= wcslen(dst)). Returns
|
||||
wcslen(src) + MIN(siz, wcslen(initial dst)). If retval >= siz,
|
||||
truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcat function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
|
||||
*/
|
||||
size_t
|
||||
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
@@ -544,14 +543,6 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
Copy src to string dst of size siz. At most siz-1 characters will
|
||||
be copied. Always NUL terminates (unless siz == 0). Returns
|
||||
wcslen(src); if retval >= siz, truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcpy function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
*/
|
||||
size_t
|
||||
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
@@ -590,7 +581,6 @@ wchar_t *wcsdup( const wchar_t *in )
|
||||
if( out == 0 )
|
||||
{
|
||||
die_mem();
|
||||
|
||||
}
|
||||
|
||||
memcpy( out, in, sizeof( wchar_t)*(len+1));
|
||||
@@ -598,6 +588,9 @@ wchar_t *wcsdup( const wchar_t *in )
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Fallback implementation if missing from libc
|
||||
*/
|
||||
int wcscasecmp( const wchar_t *a, const wchar_t *b )
|
||||
{
|
||||
if( *a == 0 )
|
||||
@@ -615,6 +608,9 @@ int wcscasecmp( const wchar_t *a, const wchar_t *b )
|
||||
return wcscasecmp( a+1,b+1);
|
||||
}
|
||||
|
||||
/**
|
||||
Fallback implementation if missing from libc
|
||||
*/
|
||||
int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count )
|
||||
{
|
||||
if( count == 0 )
|
||||
@@ -689,43 +685,25 @@ int my_wcswidth( const wchar_t *c )
|
||||
|
||||
wchar_t *quote_end( const wchar_t *in )
|
||||
{
|
||||
int level=1;
|
||||
int offset = (*in != L'\"');
|
||||
|
||||
in++;
|
||||
|
||||
while(1)
|
||||
switch( *in )
|
||||
{
|
||||
/* fwprintf( stderr, L"Check %c\n", *tok->buff );*/
|
||||
switch( *in )
|
||||
case '"':
|
||||
{
|
||||
case L'\\':
|
||||
in++;
|
||||
if( *in == L'\0' )
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
in = wcschr( in+1, L'"' );
|
||||
if( !in )
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case L'\"':
|
||||
case L'\'':
|
||||
if( (((level+offset) % 2)?L'\"':L'\'') == *in )
|
||||
{
|
||||
level--;
|
||||
}
|
||||
else
|
||||
{
|
||||
level++;
|
||||
}
|
||||
|
||||
break;
|
||||
if( *(in-1) != L'\\' )
|
||||
return (wchar_t *)in;
|
||||
}
|
||||
}
|
||||
case '\'':
|
||||
{
|
||||
return wcschr( in+1, L'\'' );
|
||||
}
|
||||
if( (*in == L'\0') ||(level==0))
|
||||
break;
|
||||
|
||||
in++;
|
||||
}
|
||||
return level?0:(wchar_t *)in;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -894,7 +872,7 @@ void debug( int level, wchar_t *msg, ... )
|
||||
|
||||
}
|
||||
putwc( L'\n', stderr );
|
||||
|
||||
sb_destroy( &sb );
|
||||
}
|
||||
|
||||
wchar_t *escape( const wchar_t *in,
|
||||
@@ -980,8 +958,10 @@ wchar_t *escape( const wchar_t *in,
|
||||
}
|
||||
|
||||
|
||||
wchar_t *unescape( const wchar_t * orig, int escape_special )
|
||||
wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
{
|
||||
|
||||
int mode = 0;
|
||||
int in_pos, out_pos, len = wcslen( orig );
|
||||
int c;
|
||||
int bracket_count=0;
|
||||
@@ -990,194 +970,346 @@ wchar_t *unescape( const wchar_t * orig, int escape_special )
|
||||
if( !in )
|
||||
die_mem();
|
||||
|
||||
for( in_pos=0, out_pos=0; in_pos<len; prev=in[out_pos], out_pos++, in_pos++ )
|
||||
for( in_pos=0, out_pos=0;
|
||||
in_pos<len;
|
||||
(prev=(out_pos>=0)?in[out_pos]:0), out_pos++, in_pos++ )
|
||||
{
|
||||
c = in[in_pos];
|
||||
if( c == L'\\' )
|
||||
switch( mode )
|
||||
{
|
||||
switch( in[++in_pos] )
|
||||
|
||||
/*
|
||||
Mode 0 means unquoted string
|
||||
*/
|
||||
case 0:
|
||||
{
|
||||
case L'\0':
|
||||
free(in);
|
||||
return 0;
|
||||
|
||||
case L'n':
|
||||
in[out_pos]=L'\n';
|
||||
break;
|
||||
|
||||
case L'r':
|
||||
in[out_pos]=L'\r';
|
||||
break;
|
||||
|
||||
case L't':
|
||||
in[out_pos]=L'\t';
|
||||
break;
|
||||
|
||||
case L'b':
|
||||
in[out_pos]=L'\b';
|
||||
break;
|
||||
|
||||
case L'e':
|
||||
in[out_pos]=L'\e';
|
||||
break;
|
||||
|
||||
case L'u':
|
||||
case L'U':
|
||||
case L'x':
|
||||
case L'o':
|
||||
if( c == L'\\' )
|
||||
{
|
||||
int i;
|
||||
wchar_t res=0;
|
||||
int chars=2;
|
||||
int base=16;
|
||||
|
||||
switch( in[in_pos] )
|
||||
switch( in[++in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
base=16;
|
||||
chars=4;
|
||||
break;
|
||||
|
||||
case L'U':
|
||||
base=16;
|
||||
chars=8;
|
||||
break;
|
||||
|
||||
case L'x':
|
||||
base=16;
|
||||
chars=2;
|
||||
break;
|
||||
|
||||
case L'o':
|
||||
base=8;
|
||||
chars=3;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
for( i=0; i<chars; i++ )
|
||||
{
|
||||
int d = convert_digit( in[++in_pos],base);
|
||||
if( d < 0 )
|
||||
case L'\0':
|
||||
{
|
||||
in_pos--;
|
||||
free(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case L'n':
|
||||
{
|
||||
in[out_pos]=L'\n';
|
||||
break;
|
||||
}
|
||||
|
||||
res=(res*base)|d;
|
||||
case L'r':
|
||||
{
|
||||
in[out_pos]=L'\r';
|
||||
break;
|
||||
}
|
||||
|
||||
case L't':
|
||||
{
|
||||
in[out_pos]=L'\t';
|
||||
break;
|
||||
}
|
||||
|
||||
case L'b':
|
||||
{
|
||||
in[out_pos]=L'\b';
|
||||
break;
|
||||
}
|
||||
|
||||
case L'e':
|
||||
{
|
||||
in[out_pos]=L'\e';
|
||||
break;
|
||||
}
|
||||
|
||||
case L'u':
|
||||
case L'U':
|
||||
case L'x':
|
||||
case L'o':
|
||||
{
|
||||
int i;
|
||||
wchar_t res=0;
|
||||
int chars=2;
|
||||
int base=16;
|
||||
|
||||
switch( in[in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
{
|
||||
base=16;
|
||||
chars=4;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'U':
|
||||
{
|
||||
base=16;
|
||||
chars=8;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'x':
|
||||
{
|
||||
base=16;
|
||||
chars=2;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'o':
|
||||
{
|
||||
base=8;
|
||||
chars=3;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for( i=0; i<chars; i++ )
|
||||
{
|
||||
int d = convert_digit( in[++in_pos],base);
|
||||
if( d < 0 )
|
||||
{
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
res=(res*base)|d;
|
||||
|
||||
}
|
||||
|
||||
in[out_pos] = res;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( in[in_pos]){
|
||||
case L'~':
|
||||
{
|
||||
if( unescape_special && (in_pos == 0) )
|
||||
{
|
||||
in[out_pos]=HOME_DIRECTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos] = L'~';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'%':
|
||||
{
|
||||
if( unescape_special && (in_pos == 0) )
|
||||
{
|
||||
in[out_pos]=PROCESS_EXPAND;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'*':
|
||||
{
|
||||
if( unescape_special )
|
||||
{
|
||||
if( out_pos > 0 && in[out_pos-1]==ANY_STRING )
|
||||
{
|
||||
out_pos--;
|
||||
in[out_pos] = ANY_STRING_RECURSIVE;
|
||||
}
|
||||
else
|
||||
in[out_pos]=ANY_STRING;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'?':
|
||||
{
|
||||
if( unescape_special )
|
||||
{
|
||||
in[out_pos]=ANY_CHAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'$':
|
||||
{
|
||||
if( unescape_special )
|
||||
{
|
||||
in[out_pos]=VARIABLE_EXPAND;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'{':
|
||||
{
|
||||
if( unescape_special )
|
||||
{
|
||||
bracket_count++;
|
||||
in[out_pos]=BRACKET_BEGIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'}':
|
||||
{
|
||||
if( unescape_special )
|
||||
{
|
||||
bracket_count--;
|
||||
in[out_pos]=BRACKET_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L',':
|
||||
{
|
||||
if( unescape_special && bracket_count && prev!=BRACKET_SEP)
|
||||
{
|
||||
in[out_pos]=BRACKET_SEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case L'\'':
|
||||
{
|
||||
mode = 1;
|
||||
out_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
case L'\"':
|
||||
{
|
||||
mode = 2;
|
||||
out_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
in[out_pos] = in[in_pos];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Mode 1 means single quoted string, i.e 'foo'
|
||||
*/
|
||||
case 1:
|
||||
{
|
||||
if( c == L'\'' )
|
||||
{
|
||||
out_pos--;
|
||||
mode = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
in[out_pos] = in[in_pos];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Mode 2 means double quoted string, i.e. "foo"
|
||||
*/
|
||||
case 2:
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case '"':
|
||||
{
|
||||
mode = 0;
|
||||
out_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
case '\\':
|
||||
{
|
||||
switch( in[++in_pos] )
|
||||
{
|
||||
case L'\0':
|
||||
{
|
||||
free(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case L'$':
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
in[out_pos++] = L'\\';
|
||||
in[out_pos] = in[in_pos];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
in[out_pos] = res;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( in[in_pos]){
|
||||
case L'~':
|
||||
if( escape_special && (in_pos == 0) )
|
||||
in[out_pos]=HOME_DIRECTORY;
|
||||
else
|
||||
in[out_pos] = L'~';
|
||||
break;
|
||||
case L'%':
|
||||
if( escape_special && (in_pos == 0) )
|
||||
in[out_pos]=PROCESS_EXPAND;
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
case L'*':
|
||||
if( escape_special )
|
||||
case '$':
|
||||
{
|
||||
if( out_pos > 0 && in[out_pos-1]==ANY_STRING )
|
||||
if( unescape_special )
|
||||
{
|
||||
out_pos--;
|
||||
in[out_pos] = ANY_STRING_RECURSIVE;
|
||||
in[out_pos]=VARIABLE_EXPAND_SINGLE;
|
||||
}
|
||||
else
|
||||
in[out_pos]=ANY_STRING;
|
||||
{
|
||||
in[out_pos]=in[in_pos];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
case L'?':
|
||||
if( escape_special )
|
||||
in[out_pos]=ANY_CHAR;
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
case L'$':
|
||||
if( escape_special )
|
||||
in[out_pos]=VARIABLE_EXPAND;
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
case L'{':
|
||||
if( escape_special )
|
||||
|
||||
default:
|
||||
{
|
||||
bracket_count++;
|
||||
in[out_pos]=BRACKET_BEGIN;
|
||||
in[out_pos] = in[in_pos];
|
||||
break;
|
||||
}
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
case L'}':
|
||||
if( escape_special )
|
||||
{
|
||||
bracket_count--;
|
||||
in[out_pos]=BRACKET_END;
|
||||
}
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
|
||||
case L',':
|
||||
if( escape_special && bracket_count && prev!=BRACKET_SEP)
|
||||
{
|
||||
in[out_pos]=BRACKET_SEP;
|
||||
}
|
||||
else
|
||||
in[out_pos]=in[in_pos];
|
||||
break;
|
||||
|
||||
case L'\'':
|
||||
case L'\"':
|
||||
{
|
||||
wchar_t *end = quote_end( &in[in_pos] );
|
||||
int len;
|
||||
|
||||
if( end == 0 )
|
||||
{
|
||||
free(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = end- &in[in_pos]-1;
|
||||
|
||||
if( escape_special)
|
||||
in[out_pos++]=INTERNAL_SEPARATOR;
|
||||
|
||||
memmove( &in[out_pos], &in[in_pos+1], sizeof(wchar_t)*(len) );
|
||||
in_pos += len+1;
|
||||
out_pos += len-1;
|
||||
|
||||
if( escape_special)
|
||||
in[++out_pos]=INTERNAL_SEPARATOR;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
in[out_pos] = in[in_pos];
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in[out_pos]=L'\0';
|
||||
return in;
|
||||
@@ -1254,8 +1386,8 @@ static int sprint_rand_digits( char *str, int maxlen )
|
||||
|
||||
/**
|
||||
Generate a filename unique in an NFS namespace by creating a copy of str and
|
||||
appending .<hostname>.<pid> to it. If gethostname() fails then a pseudo-
|
||||
random string is substituted for <hostname> - the randomness of the string
|
||||
appending .{hostname}.{pid} to it. If gethostname() fails then a pseudo-
|
||||
random string is substituted for {hostname} - the randomness of the string
|
||||
should be strong enough across different machines. The main assumption
|
||||
though is that gethostname will not fail and this is just a "safe enough"
|
||||
fallback.
|
||||
@@ -1293,25 +1425,16 @@ static char *gen_unique_nfs_filename( const char *filename )
|
||||
pidlen = sprint_pid_t( getpid(), newname + orglen + 1 + hnlen + 1 );
|
||||
newname[orglen + 1 + hnlen + 1 + pidlen] = '\0';
|
||||
/* debug( 1, L"gen_unique_nfs_filename returning with: newname = \"%s\"; "
|
||||
L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
|
||||
L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
|
||||
newname, (int)HOST_NAME_MAX, hnlen, orglen,
|
||||
(int)sizeof(pid_t),
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
|
||||
(int)(orglen + 1 + hnlen + 1 +
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
|
||||
L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
|
||||
L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
|
||||
newname, (int)HOST_NAME_MAX, hnlen, orglen,
|
||||
(int)sizeof(pid_t),
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
|
||||
(int)(orglen + 1 + hnlen + 1 +
|
||||
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
|
||||
return newname;
|
||||
}
|
||||
|
||||
/**
|
||||
Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
|
||||
milliseconds between polls and timing out after timeout seconds,
|
||||
thereafter forcibly attempting to obtain the lock if force is non-zero.
|
||||
Returns 1 on success, 0 on failure.
|
||||
To release the lock the lockfile must be unlinked.
|
||||
A unique temporary file named by appending characters to the lockfile name
|
||||
is used; any pre-existing file of the same name is subject to deletion.
|
||||
*/
|
||||
int acquire_lock_file( const char *lockfile, const int timeout, int force )
|
||||
{
|
||||
int fd, timed_out = 0;
|
||||
|
||||
132
common.h
132
common.h
@@ -3,6 +3,9 @@
|
||||
*/
|
||||
|
||||
#ifndef FISH_COMMON_H
|
||||
/**
|
||||
Header guard
|
||||
*/
|
||||
#define FISH_COMMON_H
|
||||
|
||||
#include <wchar.h>
|
||||
@@ -11,7 +14,10 @@
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
Under curses, tputs expects an int (*func)(char) as its last parameter, but in ncurses, tputs expects a int (*func)(int) as its last parameter. tputs_arg_t is defined to always be what tputs expects. Hopefully.
|
||||
Under curses, tputs expects an int (*func)(char) as its last
|
||||
parameter, but in ncurses, tputs expects a int (*func)(int) as its
|
||||
last parameter. tputs_arg_t is defined to always be what tputs
|
||||
expects. Hopefully.
|
||||
*/
|
||||
|
||||
#ifdef NCURSES_VERSION
|
||||
@@ -21,7 +27,7 @@ typedef char tputs_arg_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
Maximum number of bytes in a utf-8 character
|
||||
Maximum number of bytes used by a single utf-8 character
|
||||
*/
|
||||
#define MAX_UTF8_BYTES 6
|
||||
|
||||
@@ -36,11 +42,14 @@ typedef char tputs_arg_t;
|
||||
*/
|
||||
#define FISH_COLOR_RESET -2
|
||||
|
||||
/** Save the shell mode on startup so we can restore them on exit */
|
||||
/**
|
||||
Save the shell mode on startup so we can restore them on exit
|
||||
*/
|
||||
extern struct termios shell_modes;
|
||||
|
||||
/**
|
||||
The character to use where the text has been truncated. Is an ellipsis on unicode system and a $ on other systems.
|
||||
The character to use where the text has been truncated. Is an
|
||||
ellipsis on unicode system and a $ on other systems.
|
||||
*/
|
||||
extern wchar_t ellipsis_char;
|
||||
|
||||
@@ -64,8 +73,10 @@ extern char *profile;
|
||||
debug function.
|
||||
*/
|
||||
extern wchar_t *program_name;
|
||||
|
||||
/**
|
||||
Take an array_list_t containing wide strings and converts them to a wchar_t **.
|
||||
Take an array_list_t containing wide strings and converts them to a
|
||||
single null-terminated wchar_t **.
|
||||
*/
|
||||
wchar_t **list_to_char_arr( array_list_t *l );
|
||||
|
||||
@@ -83,22 +94,26 @@ wchar_t **list_to_char_arr( array_list_t *l );
|
||||
int fgetws2( wchar_t **buff, int *len, FILE *f );
|
||||
|
||||
/**
|
||||
Sorts a list of wide strings according to the wcsfilecmp-function from the util library
|
||||
Sorts a list of wide strings according to the wcsfilecmp-function
|
||||
from the util library
|
||||
*/
|
||||
void sort_list( array_list_t *comp );
|
||||
|
||||
/**
|
||||
Returns a newly allocated wide character string equivalent of the specified multibyte character string
|
||||
Returns a newly allocated wide character string equivalent of the
|
||||
specified multibyte character string
|
||||
*/
|
||||
wchar_t *str2wcs( const char *in );
|
||||
|
||||
/**
|
||||
Returns a newly allocated multibyte character string equivalent of the specified wide character string
|
||||
Returns a newly allocated multibyte character string equivalent of
|
||||
the specified wide character string
|
||||
*/
|
||||
char *wcs2str( const wchar_t *in );
|
||||
|
||||
/**
|
||||
Returns a newly allocated wide character string array equivalent of the specified multibyte character string array
|
||||
Returns a newly allocated wide character string array equivalent of
|
||||
the specified multibyte character string array
|
||||
*/
|
||||
char **wcsv2strv( const wchar_t **in );
|
||||
|
||||
@@ -108,17 +123,22 @@ char **wcsv2strv( const wchar_t **in );
|
||||
wchar_t **strv2wcsv( const char **in );
|
||||
|
||||
/**
|
||||
Returns a newly allocated concatenation of the specified wide character strings
|
||||
Returns a newly allocated concatenation of the specified wide
|
||||
character strings
|
||||
*/
|
||||
wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
|
||||
|
||||
/**
|
||||
Returns a newly allocated concatenation of the specified wide character strings. The last argument must be a null pointer.
|
||||
Returns a newly allocated concatenation of the specified wide
|
||||
character strings. The last argument must be a null pointer.
|
||||
*/
|
||||
wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||
|
||||
/**
|
||||
Returns a newly allocated wide character string wich is a copy of the string in, but of length c or shorter. The returned string is always null terminated, and the null is not included in the string length.
|
||||
Returns a newly allocated wide character string wich is a copy of
|
||||
the string in, but of length c or shorter. The returned string is
|
||||
always null terminated, and the null is not included in the string
|
||||
length.
|
||||
*/
|
||||
wchar_t *wcsndup( const wchar_t *in, int c );
|
||||
|
||||
@@ -140,14 +160,32 @@ long wcstol(const wchar_t *nptr,
|
||||
wchar_t **endptr,
|
||||
int base);
|
||||
|
||||
size_t
|
||||
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz);
|
||||
/**
|
||||
Appends src to string dst of size siz (unlike wcsncat, siz is the
|
||||
full size of dst, not space left). At most siz-1 characters will be
|
||||
copied. Always NUL terminates (unless siz <= wcslen(dst)). Returns
|
||||
wcslen(src) + MIN(siz, wcslen(initial dst)). If retval >= siz,
|
||||
truncation occurred.
|
||||
|
||||
size_t
|
||||
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz);
|
||||
This is the OpenBSD strlcat function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
|
||||
*/
|
||||
size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
/**
|
||||
Create a dublicate string. Wide string version of strdup.
|
||||
Copy src to string dst of size siz. At most siz-1 characters will
|
||||
be copied. Always NUL terminates (unless siz == 0). Returns
|
||||
wcslen(src); if retval >= siz, truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcpy function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
*/
|
||||
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
/**
|
||||
Create a dublicate string. Wide string version of strdup. Will
|
||||
automatically exit if out of memory.
|
||||
*/
|
||||
wchar_t *wcsdup(const wchar_t *in);
|
||||
|
||||
@@ -159,9 +197,22 @@ wchar_t *wcsdup(const wchar_t *in);
|
||||
esoteric locales where uppercase and lowercase do not cleanly
|
||||
transform between each other. Hopefully this should be fine since
|
||||
fish only uses this function with one of the strings supplied by
|
||||
fish and guaranteed to be a sane, english word.
|
||||
fish and guaranteed to be a sane, english word. Using wcscasecmp on
|
||||
a user-supplied string should be considered a bug.
|
||||
*/
|
||||
int wcscasecmp( const wchar_t *a, const wchar_t *b );
|
||||
|
||||
/**
|
||||
Case insensitive string compare function. Wide string version of
|
||||
strncasecmp.
|
||||
|
||||
This implementation of wcsncasecmp does not take into account
|
||||
esoteric locales where uppercase and lowercase do not cleanly
|
||||
transform between each other. Hopefully this should be fine since
|
||||
fish only uses this function with one of the strings supplied by
|
||||
fish and guaranteed to be a sane, english word. Using wcsncasecmp on
|
||||
a user-supplied string should be considered a bug.
|
||||
*/
|
||||
int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count );
|
||||
|
||||
/**
|
||||
@@ -184,7 +235,11 @@ int wcwidth( wchar_t c );
|
||||
int my_wcswidth( const wchar_t *c );
|
||||
|
||||
/**
|
||||
This functions returns the end of a quoted substring. It can handle nested single and double quotes.
|
||||
This functions returns the end of the quoted substring beginning at
|
||||
\c in. It can handle both single and double quotes. Returns 0 on
|
||||
error.
|
||||
|
||||
\param in the position of the opening quote
|
||||
*/
|
||||
wchar_t *quote_end( const wchar_t *in );
|
||||
|
||||
@@ -201,7 +256,7 @@ void error_reset();
|
||||
/**
|
||||
Set the locale, also change the ellipsis character
|
||||
*/
|
||||
void fish_setlocale(int category, const wchar_t *locale);
|
||||
void fish_setlocale( int category, const wchar_t *locale );
|
||||
|
||||
/**
|
||||
Checks if \c needle is included in the list of strings specified
|
||||
@@ -223,6 +278,9 @@ int read_blocked(int fd, void *buf, size_t count);
|
||||
*/
|
||||
int writeb( tputs_arg_t b );
|
||||
|
||||
/**
|
||||
Exit program at once, leaving an error message about running out of memory
|
||||
*/
|
||||
void die_mem();
|
||||
|
||||
/**
|
||||
@@ -236,7 +294,7 @@ void common_destroy();
|
||||
program_name, followed by a colon and a whitespace.
|
||||
|
||||
\param level the priority of the message. Lower number means higher priority. Messages with a priority_number higher than \c debug_level will be ignored..
|
||||
\param the message format string.
|
||||
\param msg the message format string.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -258,11 +316,39 @@ void debug( int level, wchar_t *msg, ... );
|
||||
wchar_t *escape( const wchar_t *in,
|
||||
int escape_all );
|
||||
|
||||
wchar_t *unescape( const wchar_t * in, int escape_special );
|
||||
/**
|
||||
Expand backslashed escapes and substitute them with their unescaped
|
||||
counterparts. Also optionally change the wildcards, the tilde
|
||||
character and a few more into constants which are defined in a
|
||||
private use area of Unicode. This assumes wchar_t is a unicode
|
||||
character set.
|
||||
|
||||
The result must be free()d. The original string is not modified. If
|
||||
an invalid sequence is specified, 0 is returned.
|
||||
|
||||
*/
|
||||
wchar_t *unescape( const wchar_t * in,
|
||||
int escape_special );
|
||||
|
||||
/**
|
||||
Block SIGCHLD. Calls to block/unblock may be nested, and only once the nest count reaches zero wiull the block be removed.
|
||||
*/
|
||||
void block();
|
||||
|
||||
/**
|
||||
undo call to block().
|
||||
*/
|
||||
void unblock();
|
||||
|
||||
/**
|
||||
Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
|
||||
milliseconds between polls and timing out after timeout seconds,
|
||||
thereafter forcibly attempting to obtain the lock if force is non-zero.
|
||||
Returns 1 on success, 0 on failure.
|
||||
To release the lock the lockfile must be unlinked.
|
||||
A unique temporary file named by appending characters to the lockfile name
|
||||
is used; any pre-existing file of the same name is subject to deletion.
|
||||
*/
|
||||
int acquire_lock_file( const char *lockfile, const int timeout, int force );
|
||||
|
||||
/**
|
||||
@@ -282,7 +368,7 @@ int common_get_width();
|
||||
*/
|
||||
int common_get_height();
|
||||
|
||||
/*
|
||||
/**
|
||||
Handle a window change event by looking up the new window size and
|
||||
saving it in an internal variable used by common_get_wisth and
|
||||
common_get_height().
|
||||
|
||||
15
complete.c
15
complete.c
@@ -309,7 +309,9 @@ static void clear_hash_entry( const void *key, const void *data )
|
||||
free( (void *)data );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Free hash value, but not hash key
|
||||
*/
|
||||
static void clear_hash_value( const void *key, const void *data )
|
||||
{
|
||||
free( (void *)data );
|
||||
@@ -1763,10 +1765,10 @@ static void complete_param_expand( wchar_t *str,
|
||||
}
|
||||
else
|
||||
comp_str = str;
|
||||
|
||||
// fwprintf( stderr, L"expand_string( \"%ls\", [list], ACCEPT_INCOMPLETE | %ls )\n", comp_str, do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
|
||||
|
||||
expand_string( wcsdup(comp_str), comp_out, ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) );
|
||||
// fwprintf( stderr, L"expand_string( \"%ls\", [list], EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls )\n", comp_str, do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
|
||||
|
||||
expand_string( wcsdup(comp_str), comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2094,6 +2096,11 @@ void complete( const wchar_t *cmd,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Print the GNU longopt style switch \c opt, and the argument \c
|
||||
argument to the specified stringbuffer, but only if arguemnt is
|
||||
non-null and longer than 0 characters.
|
||||
*/
|
||||
static void append_switch( string_buffer_t *out,
|
||||
const wchar_t *opt,
|
||||
const wchar_t *argument )
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
*/
|
||||
|
||||
#ifndef FISH_COMPLETE_H
|
||||
/**
|
||||
Header guard
|
||||
*/
|
||||
#define FISH_COMPLETE_H
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
97
config.h.in
97
config.h.in
@@ -1,97 +0,0 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* CPU type */
|
||||
#undef CPU
|
||||
|
||||
/* Documentation directory */
|
||||
#undef DOCDIR
|
||||
|
||||
/* Define to 1 if you have the `futimes' function. */
|
||||
#undef HAVE_FUTIMES
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#undef HAVE_GETOPT_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
#undef HAVE_LIBRT
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
#undef HAVE_LIBSOCKET
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <ncurses.h> header file. */
|
||||
#undef HAVE_NCURSES_H
|
||||
|
||||
/* Define to 1 if HAVE_RLIMIT_AS is defined in <sys/resource.h>. */
|
||||
#undef HAVE_RLIMIT_AS
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/resource.h> header file. */
|
||||
#undef HAVE_SYS_RESOURCE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <termio.h> header file. */
|
||||
#undef HAVE_TERMIO_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `wcswidth' function. */
|
||||
#undef HAVE_WCSWIDTH
|
||||
|
||||
/* Define to 1 if you have the `wcwidth' function. */
|
||||
#undef HAVE_WCWIDTH
|
||||
|
||||
/* Define to 1 if you have the `wprintf' function. */
|
||||
#undef HAVE_WPRINTF
|
||||
|
||||
/* Define to 1 if you have the file `AC_File'. */
|
||||
#undef HAVE__PROC_SELF_STAT
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Installation directory */
|
||||
#undef PREFIX
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* System configuration directory */
|
||||
#undef SYSCONFDIR
|
||||
|
||||
/* Evil kludge to get Power based machines to work */
|
||||
#undef TPUTS_KLUDGE
|
||||
51
configure.ac
51
configure.ac
@@ -1,5 +1,5 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(fish,1.16.0,axel@liljencrantz.se)
|
||||
AC_INIT(fish,1.17.0,axel@liljencrantz.se)
|
||||
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
@@ -36,20 +36,14 @@ else
|
||||
fi
|
||||
|
||||
if [[ "$prefix" = NONE ]]; then
|
||||
AC_DEFINE_UNQUOTED( [PREFIX], L"/usr/local", [Installation directory])
|
||||
AC_DEFINE_UNQUOTED( [PREFIX], L"/usr/local", [Installation directory])
|
||||
AC_SUBST( PREFIX, /usr/local)
|
||||
AC_SUBST(sysconfdir,[/etc])
|
||||
export prefix=/usr/local
|
||||
else
|
||||
AC_DEFINE_UNQUOTED( [PREFIX], L"$prefix", [Installation directory])
|
||||
AC_SUBST( PREFIX, [$prefix])
|
||||
AC_SUBST(sysconfdir,[/etc])
|
||||
fi
|
||||
|
||||
if echo $prefix | grep \^$HOME >/dev/null; then
|
||||
AC_SUBST(sysconfdir,[$HOME/etc])
|
||||
AC_MSG_NOTICE(["Install in $HOME"])
|
||||
fi
|
||||
AC_SUBST(fishdir,[/fish.d])
|
||||
AC_SUBST(fishfile,[/fish])
|
||||
AC_SUBST(fishinputfile,[/fish_inputrc])
|
||||
@@ -61,7 +55,7 @@ if test -z $docdir; then
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED( DOCDIR, [L"$(eval echo $docdir)"], [Documentation directory] )
|
||||
AC_DEFINE_UNQUOTED( SYSCONFDIR, [L"$sysconfdir"], [System configuration directory] )
|
||||
AC_DEFINE_UNQUOTED( SYSCONFDIR, [L"$(eval echo $sysconfdir)"], [System configuration directory] )
|
||||
|
||||
# See if Linux procfs is present
|
||||
AC_CHECK_FILES([/proc/self/stat])
|
||||
@@ -70,7 +64,7 @@ AC_CHECK_FILES([/proc/self/stat])
|
||||
AC_CHECK_FILE([/usr/pkg/lib],[AC_SUBST(LIBDIR,[-L/usr/pkg/lib\ -R/usr/pkg/lib])])
|
||||
AC_CHECK_FILE([/usr/pkg/include],[AC_SUBST(INCLUDEDIR,[-I/usr/pkg/include])])
|
||||
|
||||
AC_CHECK_FUNCS( [wprintf futimes wcwidth wcswidth] )
|
||||
AC_CHECK_FUNCS( [wprintf futimes wcwidth wcswidth getopt_long] )
|
||||
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h])
|
||||
|
||||
# Check for RLIMIT_AS in sys/resource.h.
|
||||
@@ -85,6 +79,43 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_MEMLOCK in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_MEMLOCK in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_MEMLOCK;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_MEMLOCK], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_MEMLOCK is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_RSS in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_RSS in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_RSS;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_RSS], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_RSS is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for RLIMIT_NPROC in sys/resource.h.
|
||||
AC_MSG_CHECKING([for RLIMIT_NPROC in sys/resource.h])
|
||||
AC_TRY_COMPILE([#include <sys/resource.h>],
|
||||
[int tmp; tmp=RLIMIT_NPROC;], have_rlimit_as=yes, have_rlimit_as=no)
|
||||
if test "$have_rlimit_as" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_RLIMIT_NPROC], [1],
|
||||
[Define to 1 if HAVE_RLIMIT_NPROC is defined in <sys/resource.h>.])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
|
||||
AC_CHECK_LIB(socket, connect)
|
||||
AC_CHECK_LIB(rt, nanosleep)
|
||||
|
||||
|
||||
@@ -503,7 +503,7 @@ inherited by any commands started by fish. It is convention that
|
||||
exported variables are in uppercase and unexported variables are in
|
||||
lowercase.
|
||||
|
||||
Variables can be explicitly set to be exportes with the \c -x or \c
|
||||
Variables can be explicitly set to be exported with the \c -x or \c
|
||||
--export switch, or not exported with the \c -u or \c --unexport
|
||||
switch. The exporting rules when creating or updating a variable are
|
||||
identical to the scoping rules for variables:
|
||||
@@ -557,24 +557,28 @@ echo $smurf
|
||||
\subsection variables-special Special variables
|
||||
|
||||
The user can change the settings of \c fish by changing the values of
|
||||
certain environment variables.These are:
|
||||
certain environment variables.
|
||||
|
||||
- \c BROWSER, which is the users preferred web browser. If this variable is set, fish will use the specified browser instead of the system default browser to display the fish documentation.
|
||||
- \c CDPATH, which is an array of directories in which to search for the new directory for the \c cd builtin.
|
||||
- \c fish_color_normal, \c fish_color_command, \c fish_color_substitution, \c fish_color_redirection, \c fish_color_end, \c fish_color_error, \c fish_color_param, \c fish_color_comment, \c fish_color_match, \c fish_color_search_match, \c fish_color_cwd, \c fish_pager_color_prefix, \c fish_pager_color_completion, \c fish_pager_color_description and \c fish_pager_color_progress are used to change the color of various elements in \c fish. These variables are universal, i.e. when changing them, their new value will be used by all running fish sessions. The new value will also be retained when restarting fish.
|
||||
- \c PATH, which is an array of directories in which to search for commands
|
||||
- \c umask, which is the current file creation mask. The preffered way to change the umask variable is through the <a href="commands.html#umask">umask shellscript function</a>. An attempt to set umask to an invalid value will always fail.
|
||||
|
||||
\c fish also sends additional information to the user through the
|
||||
values of certain environment variables. The user can not change the values of these variables. They are:
|
||||
|
||||
- \c _, which is the name of the currently running command.
|
||||
- \c history, which is an array containing the last commands that where entered
|
||||
- \c HOME, which is the users home directory. This variable can be changed by the root user.
|
||||
- \c HOME, which is the users home directory. This variable can only be changed by the root user.
|
||||
- \c PWD, which is the current working directory.
|
||||
- \c status, which is the exit status of the last foreground job to exit. If a job contains pipelines, the status of the last command in the pipeline is the status for the job.
|
||||
- \c USER, which is the username. This variable can only be changed by the root user.
|
||||
|
||||
\c fish also uses several variables internally. Such variables are
|
||||
prefixed with the string __FISH or __fish. These should be ignored by the user.
|
||||
Variables whose name are in uppercase are exported to the commands
|
||||
started by fish. \c fish also uses several variables internally. Such
|
||||
variables are prefixed with the string __FISH or __fish. These should
|
||||
be ignored by the user.
|
||||
|
||||
\section builtin-overview Builtins
|
||||
|
||||
@@ -632,6 +636,7 @@ builtins or shellscript functions, and can only be used inside fish.
|
||||
- <a href="builtins.html#switch">switch</a>, conditionally execute a block of commands
|
||||
- <a href="commands.html#tokenize">tokenize</a>, split a string up into multiple tokens
|
||||
- <a href="builtins.html#ulimit">ulimit</a>, set or get the shells resurce usage limits
|
||||
- <a href="commandss.html#umask">umask</a>, set or get the file creation mask
|
||||
- <a href="builtins.html#while">while</a>, perform a block of commands while a condition is met
|
||||
|
||||
For more information about these commands, use the <tt>--help</tt>
|
||||
|
||||
@@ -10,11 +10,13 @@ Change the foreground and/or background color of the terminal.
|
||||
COLOR is one of black, red, green, brown, yellow, blue, magenta,
|
||||
purple, cyan, white and normal.
|
||||
|
||||
- \c -c, \c --print-colors Prints a list of all valid color names
|
||||
- \c -b, \c --background Set the background color
|
||||
- \c -o, \c --bold Set bold or extra bright mode
|
||||
- \c -h, \c --help Display help message and exit
|
||||
- \c -v, \c --version Display version and exit
|
||||
|
||||
|
||||
Calling <tt>set_color normal</tt> will set the terminal color to
|
||||
whatever is the default color of the terminal.
|
||||
|
||||
|
||||
@@ -10,9 +10,30 @@ With no argument, the current file-creation mask is printed, if an
|
||||
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.
|
||||
file permissions any new files will have.
|
||||
|
||||
If a symbolic mask is specified, the actual file permission bits, and
|
||||
not the inverse, should be specified. A symbolic mask is a comma
|
||||
separated list of rights. Each right consists of three parts:
|
||||
|
||||
- The first part specifies to whom this set of right applies, and can
|
||||
be one of \c u, \c g, \c o or \c a, where \c u specifies the user who
|
||||
owns the file, \c g specifies the group owner of the file, \c o
|
||||
specifiec other users rights and \c a specifies all three should be
|
||||
changed.
|
||||
- The second part of a right specifies the mode, and can be one of \c
|
||||
=, \c + or \c -, where \c = specifies that the rights should be set to
|
||||
the new value, \c + specifies that the specified right should be added
|
||||
to those previously specified and \c - specifies that the specified
|
||||
rights should be removed from those previously specified.
|
||||
- The third part of a right specifies what rights should be changed
|
||||
and can be any compination of \c r, \c w and \c x, representing
|
||||
read, write and execute rights.
|
||||
|
||||
If the first and second parts are skipped, they are assumed to be \c a
|
||||
and \c =, respectively. As an example, <code>r,u+w</code> means all
|
||||
users should have read access and the file owner should also have
|
||||
write access.
|
||||
|
||||
- <code>-h</code> or <code>--help</code> print this message
|
||||
- <code>-S</code> or <code>--symbolic</code> prints the file-creation mask in symbolic form instead of octal form. Use <code>man chmod</code> for more information.
|
||||
|
||||
15
doc_src/vared.txt
Normal file
15
doc_src/vared.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
\section vared vared - Interactively edit the value of an environment variable
|
||||
|
||||
\subsection vared-synopsis Synopsis
|
||||
<tt>vared VARIABLE_NAME</tt>
|
||||
|
||||
\subsection vared-description Description
|
||||
|
||||
vared is used to interactively edit the value of an environment
|
||||
variable. Array variables as a whole can not be edited using vared,
|
||||
but individual array elements can.
|
||||
|
||||
\subsection vared-example Example
|
||||
|
||||
<code>vared PATH[3]</code> edits the third element of the PATH array
|
||||
189
env.c
189
env.c
@@ -45,8 +45,11 @@
|
||||
/**
|
||||
Command used to start fishd
|
||||
*/
|
||||
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fish.%s.log; end"
|
||||
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fishd.%s.log; end"
|
||||
|
||||
/**
|
||||
Value denoting a null string
|
||||
*/
|
||||
#define ENV_NULL L"\x1d"
|
||||
|
||||
/**
|
||||
@@ -116,6 +119,11 @@ static hash_table_t *global;
|
||||
*/
|
||||
static hash_table_t env_read_only;
|
||||
|
||||
/**
|
||||
Table of variables whose value is dynamically calculated, such as umask, status, etc
|
||||
*/
|
||||
static hash_table_t env_electric;
|
||||
|
||||
/**
|
||||
Exported variable array used by execv
|
||||
*/
|
||||
@@ -194,6 +202,21 @@ static void start_fishd()
|
||||
sb_destroy( &cmd );
|
||||
}
|
||||
|
||||
/**
|
||||
Return the current umask value.
|
||||
*/
|
||||
static mode_t get_umask()
|
||||
{
|
||||
mode_t res;
|
||||
res = umask( 0 );
|
||||
umask( res );
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Universal variable callback function. This function makes sure the
|
||||
proper events are triggered when an event occurs.
|
||||
*/
|
||||
static void universal_callback( int type,
|
||||
const wchar_t *name,
|
||||
const wchar_t *val )
|
||||
@@ -234,6 +257,8 @@ static void universal_callback( int type,
|
||||
void env_init()
|
||||
{
|
||||
char **p;
|
||||
struct passwd *pw;
|
||||
wchar_t *uname, *path;
|
||||
|
||||
sb_init( &dyn_var );
|
||||
|
||||
@@ -253,11 +278,22 @@ void env_init()
|
||||
hash_put( &env_read_only, L"PWD", L"" );
|
||||
|
||||
/*
|
||||
HOME should be writeable by root, since this is often a
|
||||
Names of all dynamically calculated variables
|
||||
*/
|
||||
hash_init( &env_electric, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_put( &env_electric, L"history", L"" );
|
||||
hash_put( &env_electric, L"status", L"" );
|
||||
hash_put( &env_electric, L"umask", L"" );
|
||||
|
||||
/*
|
||||
HOME and USER should be writeable by root, since this can be a
|
||||
convenient way to install software.
|
||||
*/
|
||||
if( getuid() != 0 )
|
||||
{
|
||||
hash_put( &env_read_only, L"HOME", L"" );
|
||||
hash_put( &env_read_only, L"USER", L"" );
|
||||
}
|
||||
|
||||
top = malloc( sizeof(env_node_t) );
|
||||
top->next = 0;
|
||||
@@ -266,7 +302,7 @@ void env_init()
|
||||
hash_init( &top->env, &hash_wcs_func, &hash_wcs_cmp );
|
||||
global_env = top;
|
||||
global = &top->env;
|
||||
|
||||
|
||||
/*
|
||||
Import environment variables
|
||||
*/
|
||||
@@ -276,12 +312,13 @@ void env_init()
|
||||
wchar_t *pos;
|
||||
|
||||
key = str2wcs(*p);
|
||||
|
||||
|
||||
if( !key )
|
||||
continue;
|
||||
|
||||
val = wcschr( key, L'=' );
|
||||
|
||||
|
||||
if( val == 0 )
|
||||
env_set( key, L"", ENV_EXPORT );
|
||||
else
|
||||
@@ -296,12 +333,91 @@ void env_init()
|
||||
*pos = ARRAY_SEP;
|
||||
pos++;
|
||||
}
|
||||
|
||||
|
||||
env_set( key, val, ENV_EXPORT | ENV_GLOBAL );
|
||||
}
|
||||
free(key);
|
||||
}
|
||||
}
|
||||
|
||||
path = env_get( L"PATH" );
|
||||
if( !path )
|
||||
{
|
||||
env_set( L"PATH", L"/bin" ARRAY_SEP_STR L"/usr/bin", ENV_EXPORT | ENV_GLOBAL );
|
||||
path = env_get( L"PATH" );
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, j;
|
||||
array_list_t l;
|
||||
|
||||
al_init( &l );
|
||||
expand_variable_array( path, &l );
|
||||
|
||||
debug( 3, L"PATH is %ls", path );
|
||||
|
||||
|
||||
const wchar_t *path_el[] =
|
||||
{
|
||||
L"/bin",
|
||||
L"/usr/bin",
|
||||
PREFIX L"/bin",
|
||||
0
|
||||
}
|
||||
;
|
||||
|
||||
for( j=0; path_el[j]; j++ )
|
||||
{
|
||||
int has_el=0;
|
||||
|
||||
debug( 3, L"Check directory %ls", path_el[j] );
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( &l); i++ )
|
||||
{
|
||||
wchar_t * el = (wchar_t *)al_get( &l, i );
|
||||
size_t len = wcslen( el );
|
||||
while( (len > 0) && (el[len-1]==L'/') )
|
||||
len--;
|
||||
if( (wcslen( path_el[j] ) == len) && (wcsncmp( el, path_el[j], len)==0) )
|
||||
{
|
||||
has_el = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( !has_el )
|
||||
{
|
||||
string_buffer_t b;
|
||||
debug( 3, L"directory %ls was missing", path_el[j] );
|
||||
sb_init( &b );
|
||||
sb_append2( &b, path,
|
||||
ARRAY_SEP_STR,
|
||||
path_el[j],
|
||||
(void *)0 );
|
||||
|
||||
env_set( L"PATH", (wchar_t *)b.buff, ENV_GLOBAL | ENV_EXPORT );
|
||||
sb_destroy( &b );
|
||||
path = env_get( L"PATH" );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
debug( 3, L"After: PATH is %ls", path );
|
||||
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_destroy( &l );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
pw = getpwuid( getuid() );
|
||||
if( pw )
|
||||
{
|
||||
uname = str2wcs( pw->pw_name );
|
||||
env_set( L"USER", uname, ENV_GLOBAL | ENV_EXPORT );
|
||||
free( uname );
|
||||
}
|
||||
|
||||
env_universal_init( env_get( L"FISHD_SOKET_DIR"),
|
||||
env_get( L"USER" ),
|
||||
&start_fishd,
|
||||
@@ -321,6 +437,8 @@ void env_destroy()
|
||||
env_pop();
|
||||
|
||||
hash_destroy( &env_read_only );
|
||||
|
||||
hash_destroy( &env_electric );
|
||||
|
||||
hash_foreach( global, &clear_hash_entry );
|
||||
hash_destroy( global );
|
||||
@@ -389,17 +507,24 @@ void env_set( const wchar_t *key,
|
||||
{
|
||||
wchar_t *end;
|
||||
int mask;
|
||||
|
||||
|
||||
/*
|
||||
Set the new umask
|
||||
*/
|
||||
if( val && wcslen(val) )
|
||||
{
|
||||
errno=0;
|
||||
mask = wcstol( val, &end, 8 );
|
||||
|
||||
if( !errno && !*end )
|
||||
if( !errno && (!*end) && (mask <= 0777) && (mask >= 0) )
|
||||
{
|
||||
umask( mask );
|
||||
}
|
||||
}
|
||||
/*
|
||||
Do not actually create a umask variable, on env_get, it will be calculated dynamically
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -467,8 +592,11 @@ void env_set( const wchar_t *key,
|
||||
else
|
||||
{
|
||||
if( !proc_had_barrier)
|
||||
{
|
||||
proc_had_barrier=1;
|
||||
env_universal_barrier();
|
||||
|
||||
}
|
||||
|
||||
if( env_universal_get( key ) )
|
||||
{
|
||||
int export = 0;
|
||||
@@ -656,6 +784,12 @@ wchar_t *env_get( const wchar_t *key )
|
||||
sb_printf( &dyn_var, L"%d", proc_get_last_status() );
|
||||
return (wchar_t *)dyn_var.buff;
|
||||
}
|
||||
else if( wcscmp( key, L"umask" )==0 )
|
||||
{
|
||||
sb_clear( &dyn_var );
|
||||
sb_printf( &dyn_var, L"0%0.3o", get_umask() );
|
||||
return (wchar_t *)dyn_var.buff;
|
||||
}
|
||||
|
||||
while( env != 0 )
|
||||
{
|
||||
@@ -677,7 +811,11 @@ wchar_t *env_get( const wchar_t *key )
|
||||
env = env->next;
|
||||
}
|
||||
if( !proc_had_barrier)
|
||||
{
|
||||
proc_had_barrier=1;
|
||||
env_universal_barrier();
|
||||
}
|
||||
|
||||
item = env_universal_get( key );
|
||||
|
||||
if( !item || (wcscmp( item, ENV_NULL )==0))
|
||||
@@ -694,7 +832,7 @@ int env_exist( const wchar_t *key )
|
||||
env_node_t *env = top;
|
||||
wchar_t *item;
|
||||
|
||||
if( hash_get( &env_read_only, key ) )
|
||||
if( hash_get( &env_read_only, key ) || hash_get( &env_electric, key ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -714,12 +852,19 @@ int env_exist( const wchar_t *key )
|
||||
env = env->next;
|
||||
}
|
||||
if( !proc_had_barrier)
|
||||
{
|
||||
proc_had_barrier=1;
|
||||
env_universal_barrier();
|
||||
}
|
||||
|
||||
item = env_universal_get( key );
|
||||
|
||||
return item != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the specified scope or any non-shadowed non-global subscopes contain an exported variable.
|
||||
*/
|
||||
static int local_scope_exports( env_node_t *n )
|
||||
{
|
||||
|
||||
@@ -791,6 +936,9 @@ static void add_key_to_hash( const void *key,
|
||||
hash_put( (hash_table_t *)aux, key, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
Add key to hashtable
|
||||
*/
|
||||
static void add_to_hash( const void *k, void *aux )
|
||||
{
|
||||
hash_put( (hash_table_t *)aux,
|
||||
@@ -798,6 +946,16 @@ static void add_to_hash( const void *k, void *aux )
|
||||
0 );
|
||||
}
|
||||
|
||||
/**
|
||||
Add key to list
|
||||
*/
|
||||
static void add_key_to_list( const void * key,
|
||||
const void * val,
|
||||
void *aux )
|
||||
{
|
||||
al_push( (array_list_t *)aux, key );
|
||||
}
|
||||
|
||||
|
||||
void env_get_names( array_list_t *l, int flags )
|
||||
{
|
||||
@@ -844,11 +1002,9 @@ void env_get_names( array_list_t *l, int flags )
|
||||
hash_foreach2( &global_env->env,
|
||||
add_key_to_hash,
|
||||
&names );
|
||||
|
||||
if( get_names_show_unexported )
|
||||
{
|
||||
al_push( l, L"history" );
|
||||
al_push( l, L"status" );
|
||||
}
|
||||
hash_foreach2( &env_electric, &add_key_to_list, l );
|
||||
|
||||
if( get_names_show_exported )
|
||||
{
|
||||
@@ -934,8 +1090,11 @@ static void export_func2( const void *k, const void *v, void *aux )
|
||||
char **env_export_arr( int recalc)
|
||||
{
|
||||
if( recalc && !proc_had_barrier)
|
||||
{
|
||||
proc_had_barrier=1;
|
||||
env_universal_barrier();
|
||||
|
||||
}
|
||||
|
||||
if( has_changed )
|
||||
{
|
||||
array_list_t uni;
|
||||
|
||||
@@ -117,19 +117,16 @@ static int get_socket( int fork_ok )
|
||||
if( connect( s, (struct sockaddr *)&local, len) == -1 )
|
||||
{
|
||||
close( s );
|
||||
if( fork_ok )
|
||||
if( fork_ok && start_fishd )
|
||||
{
|
||||
debug( 2, L"Could not connect to socket %d, starting fishd", s );
|
||||
|
||||
if( start_fishd )
|
||||
{
|
||||
start_fishd();
|
||||
}
|
||||
|
||||
start_fishd();
|
||||
|
||||
return get_socket( 0 );
|
||||
}
|
||||
|
||||
debug( 3, L"Could not connect to socket %d, already tried forking, giving up", s );
|
||||
debug( 2, L"Could not connect to socket %d, already tried manual restart (or no command supplied), giving up", s );
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -174,7 +171,7 @@ static void check_connection()
|
||||
|
||||
if( env_universal_server.killme )
|
||||
{
|
||||
debug( 2, L"Lost connection to universal variable server." );
|
||||
debug( 3, L"Lost connection to universal variable server." );
|
||||
close( env_universal_server.fd );
|
||||
env_universal_server.fd = -1;
|
||||
env_universal_server.killme=0;
|
||||
@@ -193,7 +190,7 @@ static void reconnect()
|
||||
if( get_socket_count >= RECONNECT_COUNT )
|
||||
return;
|
||||
|
||||
debug( 2, L"Get new fishd connection" );
|
||||
debug( 3, L"Get new fishd connection" );
|
||||
|
||||
init = 0;
|
||||
env_universal_server.fd = get_socket(1);
|
||||
@@ -262,6 +259,8 @@ int env_universal_read_all()
|
||||
if( !init)
|
||||
return 0;
|
||||
|
||||
debug( 3, L"env_universal_read_all()" );
|
||||
|
||||
if( env_universal_server.fd == -1 )
|
||||
{
|
||||
reconnect();
|
||||
@@ -290,11 +289,13 @@ wchar_t *env_universal_get( const wchar_t *name )
|
||||
if( !name )
|
||||
return 0;
|
||||
|
||||
debug( 3, L"env_universal_get( \"%ls\" )", name );
|
||||
return env_universal_common_get( name );
|
||||
}
|
||||
|
||||
int env_universal_get_export( const wchar_t *name )
|
||||
{
|
||||
debug( 3, L"env_universal_get_export()" );
|
||||
return env_universal_common_get_export( name );
|
||||
}
|
||||
|
||||
@@ -305,7 +306,7 @@ void env_universal_barrier()
|
||||
|
||||
if( !init || ( env_universal_server.fd == -1 ))
|
||||
return;
|
||||
|
||||
|
||||
barrier_reply = 0;
|
||||
|
||||
/*
|
||||
@@ -330,6 +331,7 @@ void env_universal_barrier()
|
||||
if( env_universal_server.fd == -1 )
|
||||
{
|
||||
reconnect();
|
||||
debug( 2, L"barrier interrupted, exiting" );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -347,6 +349,7 @@ void env_universal_barrier()
|
||||
if( env_universal_server.fd == -1 )
|
||||
{
|
||||
reconnect();
|
||||
debug( 2, L"barrier interrupted, exiting (2)" );
|
||||
return;
|
||||
}
|
||||
FD_ZERO( &fds );
|
||||
@@ -365,7 +368,7 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
if( !init )
|
||||
return;
|
||||
|
||||
debug( 3, L"env_universal_set( %ls, %ls )", name, value );
|
||||
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value );
|
||||
|
||||
msg = create_message( export?SET_EXPORT:SET,
|
||||
name,
|
||||
@@ -388,8 +391,8 @@ void env_universal_remove( const wchar_t *name )
|
||||
if( !init )
|
||||
return;
|
||||
|
||||
debug( 2,
|
||||
L"env_universal_remove( %ls )",
|
||||
debug( 3,
|
||||
L"env_universal_remove( \"%ls\" )",
|
||||
name );
|
||||
|
||||
msg= create_message( ERASE, name, 0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** \file env_universl.h
|
||||
/** \file env_universal.h
|
||||
Universal variable client library
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@ extern connection_t env_universal_server;
|
||||
Initialize the envuni library
|
||||
*/
|
||||
void env_universal_init();
|
||||
/*
|
||||
/**
|
||||
Free memory used by envuni
|
||||
*/
|
||||
void env_universal_destroy();
|
||||
|
||||
@@ -65,12 +65,12 @@
|
||||
should be exported. Obviously, it needs to be allocated large
|
||||
enough to fit the value string.
|
||||
*/
|
||||
typedef struct var_entry
|
||||
typedef struct var_uni_entry
|
||||
{
|
||||
int export; /**< Whether the variable should be exported */
|
||||
wchar_t val[0]; /**< The value of the variable */
|
||||
}
|
||||
var_entry_t;
|
||||
var_uni_entry_t;
|
||||
|
||||
|
||||
static void parse_message( wchar_t *msg,
|
||||
@@ -81,6 +81,9 @@ static void parse_message( wchar_t *msg,
|
||||
*/
|
||||
hash_table_t env_universal_var;
|
||||
|
||||
/**
|
||||
Callback function, should be called on all events
|
||||
*/
|
||||
void (*callback)( int type,
|
||||
const wchar_t *key,
|
||||
const wchar_t *val );
|
||||
@@ -105,6 +108,9 @@ void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const w
|
||||
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
/**
|
||||
Free both key and data
|
||||
*/
|
||||
static void erase( const void *key,
|
||||
const void *data )
|
||||
{
|
||||
@@ -186,6 +192,9 @@ void read_message( connection_t *src )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Remove variable with specified name
|
||||
*/
|
||||
static void remove_entry( wchar_t *name )
|
||||
{
|
||||
void *k, *v;
|
||||
@@ -197,6 +206,9 @@ static void remove_entry( wchar_t *name )
|
||||
free( v );
|
||||
}
|
||||
|
||||
/**
|
||||
Test if the message msg contains the command cmd
|
||||
*/
|
||||
static int match( const wchar_t *msg, const wchar_t *cmd )
|
||||
{
|
||||
size_t len = wcslen( cmd );
|
||||
@@ -209,7 +221,9 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse message msg
|
||||
*/
|
||||
static void parse_message( wchar_t *msg,
|
||||
connection_t *src )
|
||||
{
|
||||
@@ -239,8 +253,8 @@ static void parse_message( wchar_t *msg,
|
||||
|
||||
val = unescape( val, 0 );
|
||||
|
||||
var_entry_t *entry =
|
||||
malloc( sizeof(var_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
|
||||
var_uni_entry_t *entry =
|
||||
malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
|
||||
if( !entry )
|
||||
die_mem();
|
||||
entry->export=export;
|
||||
@@ -307,8 +321,13 @@ static void parse_message( wchar_t *msg,
|
||||
}
|
||||
}
|
||||
|
||||
int try_send( message_t *msg,
|
||||
int fd )
|
||||
/**
|
||||
Attempt to send the specified message to the specified file descriptor
|
||||
|
||||
\return 1 on sucess, 0 if the message could not be sent without blocking and -1 on error
|
||||
*/
|
||||
static int try_send( message_t *msg,
|
||||
int fd )
|
||||
{
|
||||
|
||||
debug( 3,
|
||||
@@ -478,7 +497,7 @@ static void add_key_to_hash( const void *key,
|
||||
const void *data,
|
||||
void *aux )
|
||||
{
|
||||
var_entry_t *e = (var_entry_t *)data;
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)data;
|
||||
if( ( e->export && get_names_show_exported) ||
|
||||
( !e->export && get_names_show_unexported) )
|
||||
al_push( (array_list_t *)aux, key );
|
||||
@@ -498,7 +517,7 @@ void env_universal_common_get_names( array_list_t *l,
|
||||
|
||||
wchar_t *env_universal_common_get( const wchar_t *name )
|
||||
{
|
||||
var_entry_t *e = (var_entry_t *)hash_get( &env_universal_var, name );
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name );
|
||||
if( e )
|
||||
return e->val;
|
||||
return 0;
|
||||
@@ -506,18 +525,28 @@ wchar_t *env_universal_common_get( const wchar_t *name )
|
||||
|
||||
int env_universal_common_get_export( const wchar_t *name )
|
||||
{
|
||||
var_entry_t *e = (var_entry_t *)hash_get( &env_universal_var, name );
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name );
|
||||
if( e )
|
||||
return e->export;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a variable creation message about the specified variable to
|
||||
the specified queue. The function signature is non-obvious since
|
||||
this function is used together with hash_foreach2, which requires
|
||||
the specified function signature.
|
||||
|
||||
\param k the variable name
|
||||
\param v the variable value
|
||||
\param q the queue to add the message to
|
||||
*/
|
||||
static void enqueue( const void *k,
|
||||
const void *v,
|
||||
void *q)
|
||||
{
|
||||
const wchar_t *key = (const wchar_t *)k;
|
||||
const var_entry_t *val = (const var_entry_t *)v;
|
||||
const var_uni_entry_t *val = (const var_uni_entry_t *)v;
|
||||
dyn_queue_t *queue = (dyn_queue_t *)q;
|
||||
|
||||
message_t *msg = create_message( val->export?SET_EXPORT:SET, key, val->val );
|
||||
|
||||
@@ -88,7 +88,13 @@ typedef struct connection
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
Number of queues that contain this message. Once this reaches zero, the message should be deleted
|
||||
*/
|
||||
int count;
|
||||
/**
|
||||
Message body. The message must be allocated using enough memory to actually contain the message.
|
||||
*/
|
||||
char body[0];
|
||||
}
|
||||
message_t;
|
||||
@@ -136,6 +142,9 @@ wchar_t *env_universal_common_get( const wchar_t *name );
|
||||
*/
|
||||
int env_universal_common_get_export( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Add messages about all existing variables to the specified connection
|
||||
*/
|
||||
void enqueue_all( connection_t *c );
|
||||
|
||||
|
||||
|
||||
15
event.c
15
event.c
@@ -1,6 +1,6 @@
|
||||
/** \file function.c
|
||||
/** \file event.c
|
||||
|
||||
Functions for storing and retrieving function information.
|
||||
Functions for handling event triggers
|
||||
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
@@ -31,13 +31,22 @@
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
Number of delivered signals
|
||||
*/
|
||||
int count;
|
||||
/**
|
||||
Whether signals have been skipped
|
||||
*/
|
||||
int overflow;
|
||||
/**
|
||||
Array of signal events
|
||||
*/
|
||||
int signal[SIG_UNHANDLED_MAX];
|
||||
}
|
||||
signal_list_t;
|
||||
|
||||
/*
|
||||
/**
|
||||
The signal event list. Actually two separate lists. One which is
|
||||
active, which is the one that new events is written to. The inactive
|
||||
one contains the events that are currently beeing performed.
|
||||
|
||||
2
event.h
2
event.h
@@ -1,6 +1,6 @@
|
||||
/** \file event.h
|
||||
|
||||
Event handling library
|
||||
Functions for handling event triggers
|
||||
|
||||
*/
|
||||
#ifndef FISH_EVENT_H
|
||||
|
||||
106
exec.c
106
exec.c
@@ -40,7 +40,7 @@
|
||||
/**
|
||||
Prototype for the getpgid library function. The prototype for this
|
||||
function seems to be missing in glibc, at least I've not found any
|
||||
combination of #includes, macros and compiler switches that will
|
||||
combination of includes, macros and compiler switches that will
|
||||
include it.
|
||||
*/
|
||||
pid_t getpgid( pid_t pid );
|
||||
@@ -103,7 +103,7 @@ void exec_close( int fd )
|
||||
int exec_pipe( int fd[2])
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
while( ( res=pipe( fd ) ) )
|
||||
{
|
||||
if( errno != EINTR )
|
||||
@@ -111,23 +111,18 @@ int exec_pipe( int fd[2])
|
||||
wperror(L"pipe");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug( 4, L"Created pipe using fds %d and %d", fd[0], fd[1]);
|
||||
|
||||
if( open_fds == 0 )
|
||||
{
|
||||
open_fds = malloc( sizeof( array_list_t ) );
|
||||
if(!open_fds )
|
||||
die_mem();
|
||||
al_init( open_fds );
|
||||
open_fds = al_new();
|
||||
}
|
||||
|
||||
if( res != -1 )
|
||||
{
|
||||
debug( 4, L"Created pipe using fds %d and %d", fd[0], fd[1]);
|
||||
|
||||
al_push( open_fds, (void *)(long)fd[0] );
|
||||
al_push( open_fds, (void *)(long)fd[1] );
|
||||
}
|
||||
al_push( open_fds, (void *)(long)fd[0] );
|
||||
al_push( open_fds, (void *)(long)fd[1] );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -183,7 +178,6 @@ static void close_unused_internal_pipes( io_data_t *io )
|
||||
|
||||
void exec_init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void exec_destroy()
|
||||
@@ -267,17 +261,13 @@ static void handle_child_io( io_data_t *io )
|
||||
free_fd( io, io->fd );
|
||||
}
|
||||
|
||||
/*
|
||||
We don't mind if this fails, it is just a speculative close
|
||||
to make sure no unexpected untracked fd causes us to fail
|
||||
*/
|
||||
close(io->fd);
|
||||
|
||||
switch( io->io_mode )
|
||||
{
|
||||
case IO_CLOSE:
|
||||
close(io->fd);
|
||||
break;
|
||||
case IO_FILE:
|
||||
{
|
||||
if( (tmp=wopen( io->param1.filename,
|
||||
io->param2.flags, 0777 ) )==-1 )
|
||||
{
|
||||
@@ -290,6 +280,8 @@ static void handle_child_io( io_data_t *io )
|
||||
}
|
||||
else if( tmp != io->fd)
|
||||
{
|
||||
close(io->fd);
|
||||
|
||||
if(dup2( tmp, io->fd ) == -1 )
|
||||
{
|
||||
debug( 1,
|
||||
@@ -301,7 +293,11 @@ static void handle_child_io( io_data_t *io )
|
||||
exec_close( tmp );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IO_FD:
|
||||
{
|
||||
close(io->fd);
|
||||
/* debug( 3, L"Redirect fd %d in process %ls (%d) from fd %d",
|
||||
io->fd,
|
||||
p->actual_cmd,
|
||||
@@ -317,10 +313,12 @@ static void handle_child_io( io_data_t *io )
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case IO_BUFFER:
|
||||
case IO_PIPE:
|
||||
{
|
||||
close(io->fd);
|
||||
|
||||
/* debug( 3, L"Pipe fd %d in process %ls (%d) (Through fd %d)",
|
||||
io->fd,
|
||||
@@ -672,7 +670,7 @@ void exec( job_t *j )
|
||||
pipe_write.io_mode=IO_PIPE;
|
||||
pipe_read.next=0;
|
||||
pipe_write.next=0;
|
||||
pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=0;
|
||||
pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1;
|
||||
|
||||
//fwprintf( stderr, L"Run command %ls\n", j->command );
|
||||
|
||||
@@ -696,7 +694,7 @@ void exec( job_t *j )
|
||||
The loop also has to handle pipelining between the jobs.
|
||||
*/
|
||||
|
||||
for (p = j->first_process; p; p = p->next)
|
||||
for( p=j->first_process; p; p = p->next )
|
||||
{
|
||||
mypipe[1]=-1;
|
||||
skip_fork=0;
|
||||
@@ -722,9 +720,11 @@ void exec( job_t *j )
|
||||
j->io = io_add( j->io, &pipe_read );
|
||||
}
|
||||
|
||||
if (p->next)
|
||||
if( p->next )
|
||||
{
|
||||
if (exec_pipe( mypipe ) == -1)
|
||||
// debug( 1, L"%ls|%ls" , p->argv[0], p->next->argv[0]);
|
||||
|
||||
if( exec_pipe( mypipe ) == -1 )
|
||||
{
|
||||
debug( 1, PIPE_ERROR );
|
||||
wperror (L"pipe");
|
||||
@@ -775,7 +775,7 @@ void exec( job_t *j )
|
||||
{
|
||||
sb_init( &sb );
|
||||
|
||||
for( i=1,arg = p->argv+1; *arg; i++, arg++ )
|
||||
for( i=1, arg=p->argv+1; *arg; i++, arg++ )
|
||||
{
|
||||
if( i != 1 )
|
||||
sb_append( &sb, ARRAY_SEP_STR );
|
||||
@@ -941,15 +941,23 @@ void exec( job_t *j )
|
||||
case INTERNAL_FUNCTION:
|
||||
{
|
||||
int status = proc_get_last_status();
|
||||
|
||||
|
||||
/*
|
||||
Handle output from a block or function. This usually
|
||||
means do nothing, but in the case of pipes, we have
|
||||
to buffer such io, since otherwisethe internal pipe
|
||||
to buffer such io, since otherwise the internal pipe
|
||||
buffer might overflow.
|
||||
*/
|
||||
if( !io_buffer)
|
||||
if( !io_buffer )
|
||||
{
|
||||
/*
|
||||
No buffer, se we exit directly. This means we
|
||||
have to manually set the exit status.
|
||||
*/
|
||||
if( p->next == 0 )
|
||||
{
|
||||
proc_set_last_status( j->negate?(status?0:1):status);
|
||||
}
|
||||
p->completed = 1;
|
||||
break;
|
||||
}
|
||||
@@ -960,10 +968,8 @@ void exec( job_t *j )
|
||||
|
||||
if( io_buffer->param2.out_buffer->used != 0 )
|
||||
{
|
||||
|
||||
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
pid = fork();
|
||||
if( pid == 0 )
|
||||
{
|
||||
/*
|
||||
This is the child process. Write out the contents of the pipeline.
|
||||
@@ -975,7 +981,7 @@ void exec( job_t *j )
|
||||
io_buffer->param2.out_buffer->used );
|
||||
exit( status );
|
||||
}
|
||||
else if (pid < 0)
|
||||
else if( pid < 0 )
|
||||
{
|
||||
/* The fork failed. */
|
||||
debug( 0, FORK_ERROR );
|
||||
@@ -1024,7 +1030,7 @@ void exec( job_t *j )
|
||||
|
||||
io_data_t *io = io_get( j->io, 1 );
|
||||
int buffer_stdout = io && io->io_mode == IO_BUFFER;
|
||||
|
||||
|
||||
if( ( !sb_err->used ) &&
|
||||
( !p->next ) &&
|
||||
( sb_out->used ) &&
|
||||
@@ -1044,16 +1050,14 @@ void exec( job_t *j )
|
||||
{
|
||||
debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status );
|
||||
|
||||
proc_set_last_status( p->status );
|
||||
proc_set_last_status( j->negate?(p->status?0:1):p->status );
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
pid = fork();
|
||||
if( pid == 0 )
|
||||
{
|
||||
/*
|
||||
This is the child process.
|
||||
@@ -1068,7 +1072,7 @@ void exec( job_t *j )
|
||||
exit( p->status );
|
||||
|
||||
}
|
||||
else if (pid < 0)
|
||||
else if( pid < 0 )
|
||||
{
|
||||
/* The fork failed. */
|
||||
debug( 0, FORK_ERROR );
|
||||
@@ -1094,11 +1098,8 @@ void exec( job_t *j )
|
||||
|
||||
case EXTERNAL:
|
||||
{
|
||||
|
||||
// fwprintf( stderr,
|
||||
// L"fork on %ls\n", j->command );
|
||||
pid = fork ();
|
||||
if (pid == 0)
|
||||
pid = fork();
|
||||
if( pid == 0 )
|
||||
{
|
||||
/*
|
||||
This is the child process.
|
||||
@@ -1111,12 +1112,12 @@ void exec( job_t *j )
|
||||
launch_process _never_ returns...
|
||||
*/
|
||||
}
|
||||
else if (pid < 0)
|
||||
else if( pid < 0 )
|
||||
{
|
||||
/* The fork failed. */
|
||||
debug( 0, FORK_ERROR );
|
||||
wperror (L"fork");
|
||||
exit (1);
|
||||
wperror( L"fork" );
|
||||
exit( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1138,11 +1139,10 @@ void exec( job_t *j )
|
||||
}
|
||||
|
||||
|
||||
if(p->type == INTERNAL_BUILTIN)
|
||||
if( p->type == INTERNAL_BUILTIN )
|
||||
builtin_pop_io();
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Close the pipe the current process uses to read from the previous process_t
|
||||
*/
|
||||
@@ -1223,7 +1223,7 @@ int exec_subshell( const wchar_t *cmd,
|
||||
b_append( io_buffer->param2.out_buffer, &z, 1 );
|
||||
|
||||
begin=end=io_buffer->param2.out_buffer->buff;
|
||||
|
||||
|
||||
if( l )
|
||||
{
|
||||
while( 1 )
|
||||
|
||||
5
exec.h
5
exec.h
@@ -3,6 +3,9 @@
|
||||
*/
|
||||
|
||||
#ifndef FISH_EXEC_H
|
||||
/**
|
||||
Header guard
|
||||
*/
|
||||
#define FISH_EXEC_H
|
||||
|
||||
#include <wchar.h>
|
||||
@@ -20,7 +23,7 @@
|
||||
*/
|
||||
void exec_init();
|
||||
|
||||
/*
|
||||
/**
|
||||
Destroy dynamically allocated data and other resources used by the
|
||||
exec library
|
||||
*/
|
||||
|
||||
374
expand.c
374
expand.c
@@ -78,13 +78,55 @@ parameter expansion.
|
||||
#define LAST_STR L"last"
|
||||
|
||||
/**
|
||||
Return the environment variable value for the string starting at in
|
||||
Characters which make a string unclean if they are the first
|
||||
character of the string. See \c is_clean().
|
||||
*/
|
||||
#define UNCLEAN_FIRST L"~%"
|
||||
/**
|
||||
Unclean characters. See \c is_clean().
|
||||
*/
|
||||
#define UNCLEAN L"$*?\\\"'({})"
|
||||
|
||||
/**
|
||||
Test if the specified argument is clean, i.e. it does not contain
|
||||
any tokens which need to be expanded or otherwise altered. Clean
|
||||
strings can be passed through expand_string and expand_one without
|
||||
changing them. About 90% of all strings are clean, so skipping
|
||||
expantion on them actually does save a small amount of time, since
|
||||
it avoids multiple memory allocations during the expantion process.
|
||||
*/
|
||||
static int is_clean( const wchar_t *in )
|
||||
{
|
||||
|
||||
const wchar_t * str = in;
|
||||
|
||||
/*
|
||||
Test characters that have a special meaning in the first character position
|
||||
*/
|
||||
if( wcschr( UNCLEAN_FIRST, *str ) )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
Test characters that have a special meaning in any character position
|
||||
*/
|
||||
while( *str )
|
||||
{
|
||||
if( wcschr( UNCLEAN, *str ) )
|
||||
return 0;
|
||||
str++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the environment variable value for the string starting at \c in.
|
||||
*/
|
||||
static wchar_t *expand_var( wchar_t *in )
|
||||
{
|
||||
if( !in )
|
||||
return 0;
|
||||
return (in[0] == VARIABLE_EXPAND )? env_get( expand_var(in+1) ) : env_get( in );
|
||||
return env_get( in );
|
||||
}
|
||||
|
||||
void expand_variable_array( const wchar_t *val, array_list_t *out )
|
||||
@@ -97,7 +139,6 @@ void expand_variable_array( const wchar_t *val, array_list_t *out )
|
||||
if( !cpy )
|
||||
{
|
||||
die_mem();
|
||||
|
||||
}
|
||||
|
||||
for( start=pos=cpy; *pos; pos++ )
|
||||
@@ -110,7 +151,7 @@ void expand_variable_array( const wchar_t *val, array_list_t *out )
|
||||
}
|
||||
}
|
||||
al_push( out, wcsdup(start) );
|
||||
|
||||
|
||||
free(cpy);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +201,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
switch( al_get_count( &l) )
|
||||
{
|
||||
case 0:
|
||||
sb_append( &buff, L"\'\'");
|
||||
sb_append( &buff, L"''");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@@ -170,9 +211,9 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
if( wcschr( el, L' ' ) && is_quotable( el ) )
|
||||
{
|
||||
sb_append2( &buff,
|
||||
L"\'",
|
||||
L"'",
|
||||
el,
|
||||
L"\'",
|
||||
L"'",
|
||||
(void *)0 );
|
||||
}
|
||||
else
|
||||
@@ -196,9 +237,9 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
if( is_quotable( el ) )
|
||||
{
|
||||
sb_append2( &buff,
|
||||
L"\'",
|
||||
L"'",
|
||||
el,
|
||||
L"\'",
|
||||
L"'",
|
||||
(void *)0 );
|
||||
}
|
||||
else
|
||||
@@ -299,7 +340,8 @@ static int match_pid( const wchar_t *cmd,
|
||||
Searches for a job with the specified job id, or a job or process
|
||||
which has the string \c proc as a prefix of its commandline.
|
||||
|
||||
If accept_incomplete is true, the remaining string for any matches are inserted.
|
||||
If accept_incomplete is true, the remaining string for any matches
|
||||
are inserted.
|
||||
|
||||
If accept_incomplete is false, any job matching the specified
|
||||
string is matched, and the job pgid is returned. If no job
|
||||
@@ -322,8 +364,6 @@ static int find_process( const wchar_t *proc,
|
||||
wchar_t *result;
|
||||
|
||||
job_t *j;
|
||||
|
||||
|
||||
|
||||
if( iswnumeric(proc) || (wcslen(proc)==0) )
|
||||
{
|
||||
@@ -657,11 +697,10 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
int is_ok= 1;
|
||||
int empty=0;
|
||||
|
||||
|
||||
for( i=wcslen(in)-1; (i>=0) && is_ok && !empty; i-- )
|
||||
{
|
||||
c = in[i];
|
||||
if( c == VARIABLE_EXPAND )
|
||||
if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
|
||||
{
|
||||
int start_pos = i+1;
|
||||
int stop_pos;
|
||||
@@ -670,15 +709,8 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
wchar_t * var_val;
|
||||
wchar_t * new_in;
|
||||
array_list_t l;
|
||||
|
||||
|
||||
|
||||
// fwprintf( stderr, L"Expand %ls\n", in );
|
||||
|
||||
|
||||
// while (in[stop_pos]==VARIABLE_EXPAND)
|
||||
// stop_pos++;
|
||||
|
||||
int is_single = (c==VARIABLE_EXPAND_SINGLE);
|
||||
|
||||
stop_pos = start_pos;
|
||||
|
||||
while( 1 )
|
||||
@@ -700,95 +732,122 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
else
|
||||
{
|
||||
wcsncpy( var_name, &in[start_pos], var_len );
|
||||
var_name[var_len]='\0';
|
||||
wcsncpy( var_name, &in[start_pos], var_len );
|
||||
var_name[var_len]='\0';
|
||||
/* printf( "Variable name is %s, len is %d\n", var_name, var_len );*/
|
||||
wchar_t *var_val_orig = expand_var( var_name );
|
||||
wchar_t *var_val_orig = expand_var( var_name );
|
||||
|
||||
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) )
|
||||
{
|
||||
int all_vars=1;
|
||||
array_list_t idx;
|
||||
al_init( &idx );
|
||||
al_init( &l );
|
||||
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) )
|
||||
{
|
||||
int all_vars=1;
|
||||
array_list_t idx;
|
||||
al_init( &idx );
|
||||
al_init( &l );
|
||||
|
||||
if( in[stop_pos] == L'[' )
|
||||
{
|
||||
wchar_t *end;
|
||||
if( in[stop_pos] == L'[' )
|
||||
{
|
||||
wchar_t *end;
|
||||
|
||||
all_vars = 0;
|
||||
all_vars = 0;
|
||||
|
||||
stop_pos++;
|
||||
while( 1 )
|
||||
stop_pos++;
|
||||
while( 1 )
|
||||
{
|
||||
int tmp;
|
||||
|
||||
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
|
||||
stop_pos++;
|
||||
|
||||
|
||||
if( in[stop_pos] == L']' )
|
||||
{
|
||||
int tmp;
|
||||
|
||||
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
|
||||
stop_pos++;
|
||||
|
||||
|
||||
if( in[stop_pos] == L']' )
|
||||
{
|
||||
stop_pos++;
|
||||
break;
|
||||
}
|
||||
stop_pos++;
|
||||
break;
|
||||
}
|
||||
|
||||
errno=0;
|
||||
tmp = wcstol( &in[stop_pos], &end, 10 );
|
||||
if( ( errno ) || ( end == &in[stop_pos] ) )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
L"Expected integer or \']\'",
|
||||
-1 );
|
||||
is_ok = 0;
|
||||
break;
|
||||
}
|
||||
al_push( &idx, (void *)tmp );
|
||||
stop_pos = end-in;
|
||||
errno=0;
|
||||
tmp = wcstol( &in[stop_pos], &end, 10 );
|
||||
if( ( errno ) || ( end == &in[stop_pos] ) )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
L"Expected integer or \']\'",
|
||||
-1 );
|
||||
is_ok = 0;
|
||||
break;
|
||||
}
|
||||
al_push( &idx, (void *)tmp );
|
||||
stop_pos = end-in;
|
||||
}
|
||||
}
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
expand_variable_array( var_val, &l );
|
||||
if( !all_vars )
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<al_get_count( &idx ); j++)
|
||||
if( is_ok )
|
||||
{
|
||||
expand_variable_array( var_val, &l );
|
||||
if( !all_vars )
|
||||
{
|
||||
int j;
|
||||
for( j=0; j<al_get_count( &idx ); j++)
|
||||
{
|
||||
int tmp = (int)al_get( &idx, j );
|
||||
if( tmp < 1 || tmp > al_get_count( &l ) )
|
||||
{
|
||||
int tmp = (int)al_get( &idx, j );
|
||||
if( tmp < 1 || tmp > al_get_count( &l ) )
|
||||
{
|
||||
error( SYNTAX_ERROR, L"Array index out of bounds", -1 );
|
||||
is_ok=0;
|
||||
al_truncate( &idx, j );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move string from list l to list idx */
|
||||
al_set( &idx, j, al_get( &l, tmp-1 ) );
|
||||
al_set( &l, tmp-1, 0 );
|
||||
}
|
||||
error( SYNTAX_ERROR, L"Array index out of bounds", -1 );
|
||||
is_ok=0;
|
||||
al_truncate( &idx, j );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move string from list l to list idx */
|
||||
al_set( &idx, j, al_get( &l, tmp-1 ) );
|
||||
al_set( &l, tmp-1, 0 );
|
||||
}
|
||||
/* Free remaining strings in list l and truncate it */
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_truncate( &l, 0 );
|
||||
/* Add items from list idx back to list l */
|
||||
al_push_all( &l, &idx );
|
||||
}
|
||||
free( var_val );
|
||||
}
|
||||
/* Free remaining strings in list l and truncate it */
|
||||
al_foreach( &l, (void (*)(const void *))&free );
|
||||
al_truncate( &l, 0 );
|
||||
/* Add items from list idx back to list l */
|
||||
al_push_all( &l, &idx );
|
||||
}
|
||||
free( var_val );
|
||||
}
|
||||
|
||||
if( is_single )
|
||||
{
|
||||
string_buffer_t res;
|
||||
sb_init( &res );
|
||||
|
||||
in[i]=0;
|
||||
|
||||
sb_append( &res, in );
|
||||
|
||||
for( j=0; j<al_get_count( &l); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &l, j );
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
if( j != 0 )
|
||||
sb_append( &res, L" " );
|
||||
sb_append( &res, next );
|
||||
}
|
||||
free( next );
|
||||
}
|
||||
sb_append( &res, &in[stop_pos] );
|
||||
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
|
||||
|
||||
sb_destroy( &res );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for( j=0; j<al_get_count( &l); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &l, j );
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
|
||||
|
||||
new_len = wcslen(in) - (stop_pos-start_pos+1) + wcslen( next) +2;
|
||||
|
||||
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
|
||||
@@ -817,21 +876,54 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
}
|
||||
}
|
||||
free( next );
|
||||
}
|
||||
al_destroy( &l );
|
||||
al_destroy( &idx );
|
||||
free(in);
|
||||
free(var_name );
|
||||
return is_ok;
|
||||
}
|
||||
}
|
||||
|
||||
al_destroy( &l );
|
||||
al_destroy( &idx );
|
||||
free(in);
|
||||
free(var_name );
|
||||
return is_ok;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Expand a non-existing variable
|
||||
*/
|
||||
if( c == VARIABLE_EXPAND )
|
||||
{
|
||||
/*
|
||||
Regular expantion, i.e. expand this argument to nothing
|
||||
*/
|
||||
empty = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
empty = 1;
|
||||
/*
|
||||
Expantion to single argument.
|
||||
*/
|
||||
string_buffer_t res;
|
||||
sb_init( &res );
|
||||
|
||||
in[i]=0;
|
||||
|
||||
sb_append( &res, in );
|
||||
|
||||
sb_append( &res, &in[stop_pos] );
|
||||
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
|
||||
|
||||
sb_destroy( &res );
|
||||
free(in);
|
||||
free(var_name );
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
free(var_name );
|
||||
}
|
||||
|
||||
free(var_name );
|
||||
|
||||
}
|
||||
|
||||
prev_char = c;
|
||||
}
|
||||
|
||||
@@ -1085,9 +1177,7 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
len1 = (paran_begin-in);
|
||||
len2 = wcslen(paran_end)-1;
|
||||
@@ -1111,10 +1201,10 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
free( subcmd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
al_init( &tail_expand );
|
||||
expand_subshell( wcsdup(paran_end+1), &tail_expand );
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( &sub_res ); i++ )
|
||||
{
|
||||
wchar_t *sub_item, *sub_item2;
|
||||
@@ -1122,20 +1212,20 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
sub_item2 = expand_escape( sub_item, 1 );
|
||||
free(sub_item);
|
||||
int item_len = wcslen( sub_item2 );
|
||||
|
||||
|
||||
for( j=0; j<al_get_count( &tail_expand ); j++ )
|
||||
{
|
||||
string_buffer_t whole_item;
|
||||
wchar_t *tail_item = (wchar_t *)al_get( &tail_expand, j );
|
||||
|
||||
|
||||
sb_init( &whole_item );
|
||||
|
||||
|
||||
sb_append_substring( &whole_item, in, len1 );
|
||||
sb_append_char( &whole_item, INTERNAL_SEPARATOR );
|
||||
sb_append_substring( &whole_item, sub_item2, item_len );
|
||||
sb_append_char( &whole_item, INTERNAL_SEPARATOR );
|
||||
sb_append( &whole_item, tail_item );
|
||||
|
||||
|
||||
al_push( out, whole_item.buff );
|
||||
}
|
||||
|
||||
@@ -1147,7 +1237,7 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
||||
|
||||
al_foreach( &tail_expand, (void (*)(const void *))&free );
|
||||
al_destroy( &tail_expand );
|
||||
|
||||
|
||||
free( subcmd );
|
||||
return 1;
|
||||
}
|
||||
@@ -1163,20 +1253,19 @@ wchar_t *expand_unescape( const wchar_t * in, int escape_special )
|
||||
|
||||
/**
|
||||
Attempts tilde expansion. Of the string specified. If tilde
|
||||
expansion is performed, the argument is freed and a new string is
|
||||
allocated in its place. Horrible call signature. Should be
|
||||
altered. Fugly!
|
||||
expansion is performed, the original string is freed and a new
|
||||
string allocated using malloc is returned, otherwise, the original
|
||||
string is returned.
|
||||
*/
|
||||
static int tilde_expand( wchar_t **ptr )
|
||||
static wchar_t * expand_tilde_internal( wchar_t *in )
|
||||
{
|
||||
wchar_t *in = *ptr;
|
||||
|
||||
if( in[0] == HOME_DIRECTORY )
|
||||
{
|
||||
int tilde_error = 0;
|
||||
wchar_t *home=0;
|
||||
wchar_t *new_in;
|
||||
wchar_t *old_in;
|
||||
wchar_t *new_in=0;
|
||||
wchar_t *old_in=0;
|
||||
|
||||
// fwprintf( stderr, L"Tilde expand ~%ls\n", (*ptr)+1 );
|
||||
if( in[1] == '/' || in[1] == '\0' )
|
||||
@@ -1210,7 +1299,7 @@ static int tilde_expand( wchar_t **ptr )
|
||||
old_in = name_end;
|
||||
|
||||
char *name_str = wcs2str( name );
|
||||
|
||||
|
||||
struct passwd *userinfo =
|
||||
getpwnam( name_str );
|
||||
|
||||
@@ -1233,26 +1322,23 @@ static int tilde_expand( wchar_t **ptr )
|
||||
free(name);
|
||||
}
|
||||
|
||||
if( !tilde_error )
|
||||
if( !tilde_error && home && old_in )
|
||||
{
|
||||
new_in = wcsdupcat( home, old_in );
|
||||
free( in );
|
||||
in = new_in;
|
||||
free(home);
|
||||
*ptr = in;
|
||||
}
|
||||
|
||||
}
|
||||
free(home);
|
||||
free( in );
|
||||
return new_in;
|
||||
}
|
||||
return 1;
|
||||
return in;
|
||||
}
|
||||
|
||||
wchar_t *expand_tilde(wchar_t *in)
|
||||
wchar_t *expand_tilde( wchar_t *in)
|
||||
{
|
||||
if( in[0] == L'~' )
|
||||
{
|
||||
in[0] = HOME_DIRECTORY;
|
||||
tilde_expand( &in );
|
||||
return in;
|
||||
return expand_tilde_internal( in );
|
||||
}
|
||||
return in;
|
||||
}
|
||||
@@ -1266,8 +1352,6 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
wchar_t *in = (wchar_t *)s;
|
||||
wchar_t *out=in;
|
||||
|
||||
// int changed=0;
|
||||
|
||||
while( *in )
|
||||
{
|
||||
switch( *in )
|
||||
@@ -1291,16 +1375,11 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
}
|
||||
}
|
||||
*out=0;
|
||||
/* if( changed )
|
||||
{
|
||||
fwprintf( stderr, L" -> %ls\n", s );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The real expansion function. All other expansion functions are wrappers to this one.
|
||||
The real expantion function. expand_one is just a wrapper around this one.
|
||||
*/
|
||||
int expand_string( wchar_t *str,
|
||||
array_list_t *end_out,
|
||||
@@ -1311,7 +1390,13 @@ int expand_string( wchar_t *str,
|
||||
|
||||
int i;
|
||||
int subshell_ok = 1;
|
||||
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
|
||||
{
|
||||
al_push( end_out, str );
|
||||
return 1;
|
||||
}
|
||||
|
||||
al_init( &list1 );
|
||||
al_init( &list2 );
|
||||
|
||||
@@ -1328,6 +1413,7 @@ int expand_string( wchar_t *str,
|
||||
if( (pos == str) || ( *(pos-1) != L'\\' ) )
|
||||
{
|
||||
error( SUBSHELL_ERROR, L"Subshells not allowed", -1 );
|
||||
free( str );
|
||||
al_destroy( &list1 );
|
||||
al_destroy( &list2 );
|
||||
return 0;
|
||||
@@ -1354,12 +1440,12 @@ int expand_string( wchar_t *str,
|
||||
for( i=0; i<al_get_count( in ); i++ )
|
||||
{
|
||||
wchar_t *next;
|
||||
|
||||
|
||||
next = expand_unescape( (wchar_t *)al_get( in, i ),
|
||||
1);
|
||||
|
||||
free( (void *)al_get( in, i ) );
|
||||
|
||||
|
||||
if( !next )
|
||||
continue;
|
||||
|
||||
@@ -1406,7 +1492,7 @@ int expand_string( wchar_t *str,
|
||||
for( i=0; i<al_get_count( in ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( in, i );
|
||||
if(!tilde_expand( &next ))
|
||||
if( !(next=expand_tilde_internal( next ) ) )
|
||||
{
|
||||
al_destroy( in );
|
||||
al_destroy( out );
|
||||
@@ -1500,12 +1586,14 @@ wchar_t *expand_one( wchar_t *string, int flags )
|
||||
array_list_t l;
|
||||
int res;
|
||||
wchar_t *one;
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) )
|
||||
return string;
|
||||
|
||||
al_init( &l );
|
||||
res = expand_string( string, &l, flags );
|
||||
if( !res )
|
||||
{
|
||||
free( string );
|
||||
one = 0;
|
||||
}
|
||||
else
|
||||
@@ -1520,7 +1608,7 @@ wchar_t *expand_one( wchar_t *string, int flags )
|
||||
al_set( &l, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
al_foreach( &l, (void(*)(const void *))&free );
|
||||
al_destroy( &l );
|
||||
return one;
|
||||
|
||||
18
expand.h
18
expand.h
@@ -10,6 +10,9 @@
|
||||
*/
|
||||
|
||||
#ifndef FISH_EXPAND_H
|
||||
/**
|
||||
Header guard
|
||||
*/
|
||||
#define FISH_EXPAND_H
|
||||
|
||||
#include <wchar.h>
|
||||
@@ -51,7 +54,7 @@
|
||||
|
||||
#define DIRECTORIES_ONLY 32
|
||||
|
||||
/*
|
||||
/**
|
||||
Use unencoded private-use keycodes for internal characters
|
||||
*/
|
||||
#define EXPAND_RESERVED 0xf000
|
||||
@@ -67,6 +70,9 @@ enum
|
||||
/** Character representing variable expantion */
|
||||
VARIABLE_EXPAND,
|
||||
|
||||
/** Character rpresenting variable expantion into a single element*/
|
||||
VARIABLE_EXPAND_SINGLE,
|
||||
|
||||
/** Character representing the start of a bracket expantion */
|
||||
BRACKET_BEGIN,
|
||||
|
||||
@@ -122,11 +128,9 @@ wchar_t *expand_one( wchar_t *in, int flag );
|
||||
/**
|
||||
Expand backslashed escapes and substitute them with their unescaped
|
||||
counterparts. Also optionally change the wildcards, the tilde
|
||||
character and a few more into constants which are defined to be
|
||||
outside of the valid character space, but still inside the valid
|
||||
space for a wchar_t. This assumes that a wchar_t is at least 32
|
||||
bits long AND that the characterset is UCS4 or some other 31-bit
|
||||
character set.
|
||||
character and a few more into constants which are defined in a
|
||||
private use area of Unicode. This assumes wchar_t is a unicode
|
||||
character. character set.
|
||||
|
||||
The result must be free()d. The original string is not modified. If
|
||||
an invalid sequence is specified, 0 is returned.
|
||||
@@ -161,7 +165,7 @@ wchar_t *expand_escape_variable( const wchar_t *in );
|
||||
wchar_t *expand_tilde(wchar_t *in);
|
||||
|
||||
/**
|
||||
Locate the last subshell in the specified string.
|
||||
Locate the first subshell in the specified string.
|
||||
|
||||
\param in the string to search for subshells
|
||||
\param begin the starting paranthesis of the subshell
|
||||
|
||||
@@ -69,6 +69,9 @@ fi
|
||||
%config %_sysconfdir/fish.d/completions/*.fish
|
||||
|
||||
%changelog
|
||||
* Tue Nov 29 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.17.0-0
|
||||
- 1.17.0
|
||||
|
||||
* Sat Sep 24 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.14.0-0
|
||||
- 1.14.0
|
||||
|
||||
|
||||
70
fish_tests.c
70
fish_tests.c
@@ -1,4 +1,4 @@
|
||||
/** \file main.c
|
||||
/** \file fish_tests.c
|
||||
Various bug and feature tests. Compiled and run by make test.
|
||||
*/
|
||||
|
||||
@@ -38,11 +38,23 @@
|
||||
#include "expand.h"
|
||||
#include "parser.h"
|
||||
#include "tokenizer.h"
|
||||
#include "output.h"
|
||||
#include "exec.h"
|
||||
#include "event.h"
|
||||
|
||||
/**
|
||||
Number of laps to run performance testing loop
|
||||
*/
|
||||
#define LAPS 50
|
||||
|
||||
/**
|
||||
Number of encountered errors
|
||||
*/
|
||||
static int err_count=0;
|
||||
|
||||
/**
|
||||
Print formatted output
|
||||
*/
|
||||
static void say( wchar_t *blah, ... )
|
||||
{
|
||||
va_list va;
|
||||
@@ -52,6 +64,9 @@ static void say( wchar_t *blah, ... )
|
||||
wprintf( L"\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
Print formatted error string
|
||||
*/
|
||||
static void err( wchar_t *blah, ... )
|
||||
{
|
||||
va_list va;
|
||||
@@ -64,16 +79,25 @@ static void err( wchar_t *blah, ... )
|
||||
wprintf( L"\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
Print ok message
|
||||
*/
|
||||
static void ok()
|
||||
{
|
||||
wprintf( L"OK\n" );
|
||||
}
|
||||
|
||||
/**
|
||||
Compare two pointers
|
||||
*/
|
||||
static int pq_compare( void *e1, void *e2 )
|
||||
{
|
||||
return e1-e2;
|
||||
}
|
||||
|
||||
/**
|
||||
Test priority queue functionality
|
||||
*/
|
||||
static int pq_test( int elements )
|
||||
{
|
||||
int i;
|
||||
@@ -114,7 +138,9 @@ static int pq_test( int elements )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test stack functionality
|
||||
*/
|
||||
static int stack_test( int elements )
|
||||
{
|
||||
int i;
|
||||
@@ -160,7 +186,9 @@ static int stack_test( int elements )
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Hash function for pointers
|
||||
*/
|
||||
static int hash_func( const void *data )
|
||||
{
|
||||
/* srand( (int)data );
|
||||
@@ -170,12 +198,18 @@ static int hash_func( const void *data )
|
||||
return 127*((foo^0xefc7e214)) ^(foo<<11);
|
||||
}
|
||||
|
||||
/**
|
||||
Pointer hash comparison function
|
||||
*/
|
||||
static int compare_func( const void *key1, const void *key2 )
|
||||
{
|
||||
return key1==key2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Hashtable test
|
||||
*/
|
||||
static int hash_test( int elements )
|
||||
{
|
||||
int i;
|
||||
@@ -249,6 +283,9 @@ static int hash_test( int elements )
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Arraylist test
|
||||
*/
|
||||
static int al_test( int sz)
|
||||
{
|
||||
int i;
|
||||
@@ -280,6 +317,9 @@ static int al_test( int sz)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Stringbuffer test
|
||||
*/
|
||||
static void sb_test()
|
||||
{
|
||||
string_buffer_t b;
|
||||
@@ -299,7 +339,9 @@ static void sb_test()
|
||||
say( (wchar_t *)b.buff );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Performs all tests of the util library
|
||||
*/
|
||||
static void test_util()
|
||||
{
|
||||
int i;
|
||||
@@ -346,8 +388,9 @@ static void test_util()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Test the tokenizer
|
||||
*/
|
||||
static void test_tok()
|
||||
{
|
||||
tokenizer t;
|
||||
@@ -412,6 +455,9 @@ static void test_tok()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Test the parser
|
||||
*/
|
||||
static void test_parser()
|
||||
{
|
||||
say( L"Testing parser" );
|
||||
@@ -514,7 +560,9 @@ static int expand_test( const wchar_t *in, int flags, ... )
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test globbing and other parameter expantion
|
||||
*/
|
||||
static void test_expand()
|
||||
{
|
||||
say( L"Testing parameter expantion" );
|
||||
@@ -536,7 +584,9 @@ static void test_expand()
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test speed of completion calculations
|
||||
*/
|
||||
void perf_complete()
|
||||
{
|
||||
wchar_t c;
|
||||
@@ -607,7 +657,9 @@ void perf_complete()
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Main test
|
||||
*/
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
|
||||
|
||||
71
fishd.c
71
fishd.c
@@ -70,6 +70,11 @@ static connection_t *conn;
|
||||
*/
|
||||
static int sock;
|
||||
|
||||
/**
|
||||
Set to one when fishd should save and exit
|
||||
*/
|
||||
static int quit=0;
|
||||
|
||||
/**
|
||||
Constructs the fish socket filename
|
||||
*/
|
||||
@@ -110,6 +115,15 @@ static char *get_socket_filename()
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
Signal handler for the term signal.
|
||||
*/
|
||||
static void handle_term( int signal )
|
||||
{
|
||||
quit=1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Acquire the lock for the socket
|
||||
Returns the name of the lock file if successful or
|
||||
@@ -268,26 +282,37 @@ static void daemonize()
|
||||
|
||||
case 0:
|
||||
{
|
||||
/*
|
||||
Make fishd ignore the HUP signal.
|
||||
*/
|
||||
struct sigaction act;
|
||||
sigemptyset( & act.sa_mask );
|
||||
act.sa_flags=0;
|
||||
act.sa_handler=SIG_IGN;
|
||||
sigaction( SIGHUP, &act, 0);
|
||||
|
||||
/*
|
||||
Make fishd save and exit on the TERM signal.
|
||||
*/
|
||||
sigfillset( & act.sa_mask );
|
||||
act.sa_flags=0;
|
||||
act.sa_handler=&handle_term;
|
||||
sigaction( SIGTERM, &act, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
debug( 0, L"Parent calling exit" );
|
||||
debug( 0, L"Parent process exiting (This is normal)" );
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Put ourself in out own processing group
|
||||
*/
|
||||
setsid();
|
||||
|
||||
|
||||
/*
|
||||
Close stdin and stdout. We only use stderr, anyway.
|
||||
*/
|
||||
@@ -350,12 +375,17 @@ void load_or_save( int save)
|
||||
close( c.fd );
|
||||
}
|
||||
|
||||
/**
|
||||
Load variables from disk
|
||||
*/
|
||||
static void load()
|
||||
{
|
||||
load_or_save(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Save variables to disk
|
||||
*/
|
||||
static void save()
|
||||
{
|
||||
load_or_save(1);
|
||||
@@ -376,11 +406,14 @@ static void init()
|
||||
load();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Main function for fishd
|
||||
*/
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
int child_socket, t;
|
||||
int child_socket;
|
||||
struct sockaddr_un remote;
|
||||
socklen_t t;
|
||||
int max_fd;
|
||||
int update_count=0;
|
||||
|
||||
@@ -409,15 +442,27 @@ int main( int argc, char ** argv )
|
||||
FD_SET( c->fd, &write_fd );
|
||||
}
|
||||
}
|
||||
|
||||
res=select( max_fd, &read_fd, &write_fd, 0, 0 );
|
||||
|
||||
if( res==-1 )
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
wperror( L"select" );
|
||||
exit(1);
|
||||
res=select( max_fd, &read_fd, &write_fd, 0, 0 );
|
||||
|
||||
if( quit )
|
||||
{
|
||||
save();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if( res != -1 )
|
||||
break;
|
||||
|
||||
if( errno != EINTR )
|
||||
{
|
||||
wperror( L"select" );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( FD_ISSET( sock, &read_fd ) )
|
||||
{
|
||||
if( (child_socket =
|
||||
|
||||
@@ -58,7 +58,7 @@ void function_set_desc( const wchar_t *name, const wchar_t *desc );
|
||||
/**
|
||||
Returns true if the function witrh the name name exists.
|
||||
*/
|
||||
int function_exists( const wchar_t *name);
|
||||
int function_exists( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Insert all function names into l. These are not copies of the strings and should not be freed after use.
|
||||
|
||||
@@ -357,7 +357,7 @@ void highlight_shell( wchar_t * buff,
|
||||
/*
|
||||
Locate and syntax highlight subshells recursively
|
||||
*/
|
||||
|
||||
|
||||
wchar_t *buffcpy = wcsdup( buff );
|
||||
wchar_t *subpos=buffcpy;
|
||||
int done=0;
|
||||
@@ -386,8 +386,9 @@ void highlight_shell( wchar_t * buff,
|
||||
break;
|
||||
|
||||
subpos = end+1;
|
||||
|
||||
}
|
||||
free( buffcpy );
|
||||
free( buffcpy);
|
||||
|
||||
|
||||
last_val=0;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
|
||||
function __fish_complete_apropos
|
||||
if test (commandline -ct)
|
||||
set str (commandline -ct)
|
||||
apropos $str|sed -e 's/^\(.*'$str'\([^ ]*\).*\)$/'$str'\2\t\1/'
|
||||
apropos $str|sed -e "s/^\(.*$str\([^ ]*\).*\)$/$str\2\t\1/"
|
||||
end
|
||||
end
|
||||
|
||||
complete -xc apropos -a "(__fish_complete_apropos)" -d "Whatis entry"
|
||||
complete -xc apropos -a '(__fish_complete_apropos)' -d "Whatis entry"
|
||||
|
||||
complete -c apropos -s h -l help -d "apropos command help"
|
||||
complete -f -c apropos -s d -l debug -d "print debugging info"
|
||||
@@ -14,7 +15,7 @@ complete -f -c apropos -s r -l regex -d "keyword as regex"
|
||||
complete -f -c apropos -s w -l wildcard -d "keyword as wildwards"
|
||||
complete -f -c apropos -s e -l exact -d "keyword as exactly match"
|
||||
complete -x -c apropos -s m -l system -d "search for other system"
|
||||
complete -x -c apropos -s M -l manpath -a "(echo $MANPATH)" -d "specify man path"
|
||||
complete -x -c apropos -s M -l manpath -a '(echo $MANPATH)' -d "specify man path"
|
||||
complete -x -c apropos -s C -l config-file -d "specify a conf file"
|
||||
complete -f -c apropos -s V -l version -d "Display version"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#completion for apt-get
|
||||
|
||||
function __fish_apt_no_subcommand -d "test if apt has yet to be given the subcommand"
|
||||
function __fish_apt_no_subcommand -d 'test if apt has yet to be given the subcommand'
|
||||
for i in (commandline -opc)
|
||||
if contains -- $i update upgrade dselect-upgrade dist-upgrade install remove source build-dep check clean autoclean
|
||||
return 1
|
||||
@@ -9,7 +9,7 @@ function __fish_apt_no_subcommand -d "test if apt has yet to be given the subcom
|
||||
return 0
|
||||
end
|
||||
|
||||
function __fish_apt_use_package -d "Test if apt command should have packages as potential completion"
|
||||
function __fish_apt_use_package -d 'Test if apt command should have packages as potential completion'
|
||||
for i in (commandline -opc)
|
||||
if contains -- $i contains install remove build-dep
|
||||
return 0
|
||||
@@ -18,47 +18,47 @@ function __fish_apt_use_package -d "Test if apt command should have packages as
|
||||
return 1
|
||||
end
|
||||
|
||||
complete -c apt-get -n "__fish_apt_use_package" -a "(__fish_print_packages)" -d "Package"
|
||||
complete -c apt-get -n '__fish_apt_use_package' -a '(__fish_print_packages)' -d 'Package'
|
||||
|
||||
complete -c apt-get -s h -l help -d "apt-get command help"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "update" -d "update sources"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "upgrade" -d "upgrade or install newest packages"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "dselect-upgrade" -d "use with dselect front-end"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "dist-upgrade" -d "distro upgrade"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "install" -d "install one or more packages"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "remove" -d "remove one or more packages"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "source" -d "fetch source packages"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "build-dep" -d "install/remove packages for dependencies"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "check" -d "update cache and check dep"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "clean" -d "clean local caches and packages"
|
||||
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "autoclean" -d "clean packages no longer be downloaded"
|
||||
complete -c apt-get -s d -l download-only -d "Download Only"
|
||||
complete -c apt-get -s f -l fix-broken -d "correct broken deps"
|
||||
complete -c apt-get -s m -l fix-missing -d "ignore missing packages"
|
||||
complete -c apt-get -l no-download -d "Disable downloading packages"
|
||||
complete -c apt-get -s q -l quiet -d "quiet output"
|
||||
complete -c apt-get -s s -l simulate -d "perform a siulation"
|
||||
complete -c apt-get -s y -l assume-yes -d "automatic yes to prompts"
|
||||
complete -c apt-get -s u -l show-upgraded -d "show upgraded packages"
|
||||
complete -c apt-get -s V -l verbose-versions -d "show full versions for packages"
|
||||
complete -c apt-get -s b -l compile -d "compile source packages"
|
||||
complete -c apt-get -s b -l build -d "compile source packages"
|
||||
complete -c apt-get -l ignore-hold -d "ignore package Holds"
|
||||
complete -c apt-get -l no-upgrade -d "Do not upgrade packages"
|
||||
complete -c apt-get -l force-yes -d "Force yes"
|
||||
complete -c apt-get -l print-uris -d "print the URIs"
|
||||
complete -c apt-get -l purge -d "use purge instead of remove"
|
||||
complete -c apt-get -l reinstall -d "reinstall packages"
|
||||
complete -c apt-get -l list-cleanup -d "erase obsolete files"
|
||||
complete -c apt-get -s t -l target-release -d "control default input to the policy engine"
|
||||
complete -c apt-get -l trivial-only -d "only perform operations that are trivial"
|
||||
complete -c apt-get -l no-remove -d "abort if any packages are to be removed"
|
||||
complete -c apt-get -l only-source -d "only accept source packages"
|
||||
complete -c apt-get -l diff-only -d "download only diff file"
|
||||
complete -c apt-get -l tar-only -d "download only tar file"
|
||||
complete -c apt-get -l arch-only -d "only process arch-dep build-deps"
|
||||
complete -c apt-get -l allow-unauthenticated -d "ignore non-authenticated packages"
|
||||
complete -c apt-get -s v -l version -d "show program version"
|
||||
complete -r -c apt-get -s c -l config-file -d "specify a config file"
|
||||
complete -r -c apt-get -s o -l option -d "set a config option"
|
||||
complete -c apt-get -s h -l help -d 'apt-get command help'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'update' -d 'update sources'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'upgrade' -d 'upgrade or install newest packages'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'dselect-upgrade' -d 'use with dselect front-end'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'dist-upgrade' -d 'distro upgrade'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'install' -d 'install one or more packages'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'remove' -d 'remove one or more packages'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'source' -d 'fetch source packages'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'build-dep' -d 'install/remove packages for dependencies'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'check' -d 'update cache and check dep'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'clean' -d 'clean local caches and packages'
|
||||
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'autoclean' -d 'clean packages no longer be downloaded'
|
||||
complete -c apt-get -s d -l download-only -d 'Download Only'
|
||||
complete -c apt-get -s f -l fix-broken -d 'correct broken deps'
|
||||
complete -c apt-get -s m -l fix-missing -d 'ignore missing packages'
|
||||
complete -c apt-get -l no-download -d 'Disable downloading packages'
|
||||
complete -c apt-get -s q -l quiet -d 'quiet output'
|
||||
complete -c apt-get -s s -l simulate -d 'perform a siulation'
|
||||
complete -c apt-get -s y -l assume-yes -d 'automatic yes to prompts'
|
||||
complete -c apt-get -s u -l show-upgraded -d 'show upgraded packages'
|
||||
complete -c apt-get -s V -l verbose-versions -d 'show full versions for packages'
|
||||
complete -c apt-get -s b -l compile -d 'compile source packages'
|
||||
complete -c apt-get -s b -l build -d 'compile source packages'
|
||||
complete -c apt-get -l ignore-hold -d 'ignore package Holds'
|
||||
complete -c apt-get -l no-upgrade -d 'Do not upgrade packages'
|
||||
complete -c apt-get -l force-yes -d 'Force yes'
|
||||
complete -c apt-get -l print-uris -d 'print the URIs'
|
||||
complete -c apt-get -l purge -d 'use purge instead of remove'
|
||||
complete -c apt-get -l reinstall -d 'reinstall packages'
|
||||
complete -c apt-get -l list-cleanup -d 'erase obsolete files'
|
||||
complete -c apt-get -s t -l target-release -d 'control default input to the policy engine'
|
||||
complete -c apt-get -l trivial-only -d 'only perform operations that are trivial'
|
||||
complete -c apt-get -l no-remove -d 'abort if any packages are to be removed'
|
||||
complete -c apt-get -l only-source -d 'only accept source packages'
|
||||
complete -c apt-get -l diff-only -d 'download only diff file'
|
||||
complete -c apt-get -l tar-only -d 'download only tar file'
|
||||
complete -c apt-get -l arch-only -d 'only process arch-dep build-deps'
|
||||
complete -c apt-get -l allow-unauthenticated -d 'ignore non-authenticated packages'
|
||||
complete -c apt-get -s v -l version -d 'show program version'
|
||||
complete -r -c apt-get -s c -l config-file -d 'specify a config file'
|
||||
complete -r -c apt-get -s o -l option -d 'set a config option'
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#apt-proxy-import
|
||||
complete -c apt-proxy-import -s h -l help -d "apt-proxy-import command help"
|
||||
complete -f -c apt-proxy-import -s V -l version -d "print version"
|
||||
complete -f -c apt-proxy-import -s v -l verbose -d "verbose info"
|
||||
complete -f -c apt-proxy-import -s q -l quiet -d "no message to STDOUT"
|
||||
complete -f -c apt-proxy-import -s r -l recursive -d "recurse into subdir"
|
||||
complete -r -c apt-proxy-import -s i -l import-dir -a "(ls -Fp|grep /$)" -d "dir to import"
|
||||
complete -r -c apt-proxy-import -s u -l user -a "(__fish_complete_users)" -d "change to user"
|
||||
complete -r -c apt-proxy-import -s d -l debug -d "debug level[default 0]"
|
||||
complete -c apt-proxy-import -s h -l help -d 'apt-proxy-import command help'
|
||||
complete -f -c apt-proxy-import -s V -l version -d 'print version'
|
||||
complete -f -c apt-proxy-import -s v -l verbose -d 'verbose info'
|
||||
complete -f -c apt-proxy-import -s q -l quiet -d 'no message to STDOUT'
|
||||
complete -f -c apt-proxy-import -s r -l recursive -d 'recurse into subdir'
|
||||
complete -r -c apt-proxy-import -s i -l import-dir -a '(ls -Fp|grep /$)' -d 'dir to import'
|
||||
complete -r -c apt-proxy-import -s u -l user -a '(__fish_complete_users)' -d 'change to user'
|
||||
complete -r -c apt-proxy-import -s d -l debug -d 'debug level[default 0]'
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#apt-show-source
|
||||
complete -c apt-show-source -s h -l help -d "apt-show-source command help"
|
||||
complete -r -c apt-show-source -l status-file -d "read pkg from FILE" -f
|
||||
complete -r -c apt-show-source -o stf -d "read pkg from FILE" -f
|
||||
complete -r -c apt-show-source -l list-dir -a "(ls -Fp .|grep /$) /var/lib/apt/lists" -d "specify APT list dir"
|
||||
complete -r -c apt-show-source -o ld -a "(ls -Fp .|grep /$) /var/lib/apt/lists" -d "specify APT list dir"
|
||||
complete -r -c apt-show-source -s p -l package -a "(apt-cache pkgnames)" -d "list PKG info"
|
||||
complete -f -c apt-show-source -l version-only -d "print version only"
|
||||
complete -f -c apt-show-source -s a -l all -d "print all src pkgs with version"
|
||||
complete -f -c apt-show-source -s v -l verbose -d "verbose message"
|
||||
complete -c apt-show-source -s h -l help -d 'apt-show-source command help'
|
||||
complete -r -c apt-show-source -l status-file -d 'read pkg from FILE' -f
|
||||
complete -r -c apt-show-source -o stf -d 'read pkg from FILE' -f
|
||||
complete -r -c apt-show-source -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d 'specify APT list dir'
|
||||
complete -r -c apt-show-source -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d 'specify APT list dir'
|
||||
complete -r -c apt-show-source -s p -l package -a '(apt-cache pkgnames)' -d 'list PKG info'
|
||||
complete -f -c apt-show-source -l version-only -d 'print version only'
|
||||
complete -f -c apt-show-source -s a -l all -d 'print all src pkgs with version'
|
||||
complete -f -c apt-show-source -s v -l verbose -d 'verbose message'
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#apt-show-versions
|
||||
complete -c apt-show-source -s h -l help -d "apt-show-versions command help"
|
||||
complete -r -c apt-show-versions -s p -l packages -a "(apt-cache pkgnames)" -d "print PKG versions"
|
||||
complete -f -c apt-show-versions -s r -l regex -d "using regex"
|
||||
complete -f -c apt-show-versions -s u -l upgradeable -d "print only upgradeable pkgs"
|
||||
complete -f -c apt-show-versions -s a -l allversions -d "print all versions"
|
||||
complete -f -c apt-show-versions -s b -l brief -d "print pkg name/distro"
|
||||
complete -f -c apt-show-versions -s v -l verbose -d "print verbose info"
|
||||
complete -f -c apt-show-versions -s i -l initialize -d "init or update cache only"
|
||||
complete -r -c apt-show-versions -l status-file -d "read pkg from FILE"
|
||||
complete -r -c apt-show-versions -o stf -d "read pkg from FILE"
|
||||
complete -r -c apt-show-versions -l list-dir -a "(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists" -d "specify APT list dir"
|
||||
complete -r -c apt-show-versions -o ld -a "(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists" -d "specify APT list dir"
|
||||
complete -c apt-show-source -s h -l help -d 'apt-show-versions command help'
|
||||
complete -r -c apt-show-versions -s p -l packages -a '(apt-cache pkgnames)' -d 'print PKG versions'
|
||||
complete -f -c apt-show-versions -s r -l regex -d 'using regex'
|
||||
complete -f -c apt-show-versions -s u -l upgradeable -d 'print only upgradeable pkgs'
|
||||
complete -f -c apt-show-versions -s a -l allversions -d 'print all versions'
|
||||
complete -f -c apt-show-versions -s b -l brief -d 'print pkg name/distro'
|
||||
complete -f -c apt-show-versions -s v -l verbose -d 'print verbose info'
|
||||
complete -f -c apt-show-versions -s i -l initialize -d 'init or update cache only'
|
||||
complete -r -c apt-show-versions -l status-file -d 'read pkg from FILE'
|
||||
complete -r -c apt-show-versions -o stf -d 'read pkg from FILE'
|
||||
complete -r -c apt-show-versions -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d 'specify APT list dir'
|
||||
complete -r -c apt-show-versions -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d 'specify APT list dir'
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
complete -c cat -s A -l show-all -d "Escape all non-printing characters"
|
||||
complete -c cat -s b -l number-nonblank -d "Number nonblank lines"
|
||||
complete -c cat -s e -d "Escape non-printing characters except tab"
|
||||
complete -c cat -s E -l show-ends -d "Display $ at end of line"
|
||||
complete -c cat -s n -l number -d "Number all lines"
|
||||
complete -c cat -s s -l squeeze-blank -d "Never more than single blank line"
|
||||
complete -c cat -s t -d "Escape non-printing characters except newline"
|
||||
complete -c cat -s T -l show-tabs -d "Escape tab"
|
||||
complete -c cat -s v -d "Escape non-printing except newline and tab"
|
||||
complete -c cat -l help -d "Display help and exit"
|
||||
complete -c cat -l version -d "Display version and exit"
|
||||
complete -c cat -s A -l show-all -d 'Escape all non-printing characters'
|
||||
complete -c cat -s b -l number-nonblank -d 'Number nonblank lines'
|
||||
complete -c cat -s e -d 'Escape non-printing characters except tab'
|
||||
complete -c cat -s E -l show-ends -d 'Display $ at end of line'
|
||||
complete -c cat -s n -l number -d 'Number all lines'
|
||||
complete -c cat -s s -l squeeze-blank -d 'Never more than single blank line'
|
||||
complete -c cat -s t -d 'Escape non-printing characters except newline'
|
||||
complete -c cat -s T -l show-tabs -d 'Escape tab'
|
||||
complete -c cat -s v -d 'Escape non-printing except newline and tab'
|
||||
complete -c cat -l help -d 'Display help and exit'
|
||||
complete -c cat -l version -d 'Display version and exit'
|
||||
|
||||
|
||||
@@ -2,52 +2,52 @@
|
||||
# I don't use CVS, so these completions are probably not all that good.
|
||||
#
|
||||
|
||||
complete -c cvs -x -a "add" -d "Add a new file/directory to the repository"
|
||||
complete -c cvs -x -a "admin" -d "Administration front end for rcs"
|
||||
complete -c cvs -x -a "annotate" -d "Show last revision where each line was modified"
|
||||
complete -c cvs -x -a "checkout" -d "Checkout sources for editing"
|
||||
complete -c cvs -x -a "commit" -d "Check files into the repository"
|
||||
complete -c cvs -x -a "diff" -d "Show differences between revisions"
|
||||
complete -c cvs -x -a "edit" -d "Get ready to edit a watched file"
|
||||
complete -c cvs -x -a "editors" -d "See who is editing a watched file"
|
||||
complete -c cvs -x -a "export" -d "Export sources from CVS, similar to checkout"
|
||||
complete -c cvs -x -a "history" -d "Show repository access history"
|
||||
complete -c cvs -x -a "import" -d "Import sources into CVS, using vendor branches"
|
||||
complete -c cvs -x -a "init" -d "Create a CVS repository if it doesnt exist"
|
||||
complete -c cvs -x -a "kserver" -d "Kerberos server mode"
|
||||
complete -c cvs -x -a "log" -d "Print out history information for files"
|
||||
complete -c cvs -x -a "login" -d "Prompt for password for authenticating server"
|
||||
complete -c cvs -x -a "logout" -d "Removes entry in .cvspass for remote repository"
|
||||
complete -c cvs -x -a "pserver" -d "Password server mode"
|
||||
complete -c cvs -x -a "rannotate" -d "Show last revision where each line of module was modified"
|
||||
complete -c cvs -x -a "rdiff" -d "Create 'patch' format diffs between releases"
|
||||
complete -c cvs -x -a "release" -d "Indicate that a Module is no longer in use"
|
||||
complete -c cvs -x -a "remove" -d "Remove an entry from the repository"
|
||||
complete -c cvs -x -a "rlog" -d "Print out history information for a module"
|
||||
complete -c cvs -x -a "rtag" -d "Add a symbolic tag to a module"
|
||||
complete -c cvs -x -a "server" -d "Server mode"
|
||||
complete -c cvs -x -a "status" -d "Display status information on checked out files"
|
||||
complete -c cvs -x -a "tag" -d "Add a symbolic tag to checked out version of files"
|
||||
complete -c cvs -x -a "unedit" -d "Undo an edit command"
|
||||
complete -c cvs -x -a "update" -d "Bring work tree in sync with repository"
|
||||
complete -c cvs -x -a "version" -d "Show current CVS version(s)"
|
||||
complete -c cvs -x -a "watch" -d "Set watches"
|
||||
complete -c cvs -x -a "watchers" -d "See who is watching a file"
|
||||
complete -c cvs -x -a 'add' -d 'Add a new file/directory to the repository'
|
||||
complete -c cvs -x -a 'admin' -d 'Administration front end for rcs'
|
||||
complete -c cvs -x -a 'annotate' -d 'Show last revision where each line was modified'
|
||||
complete -c cvs -x -a 'checkout' -d 'Checkout sources for editing'
|
||||
complete -c cvs -x -a 'commit' -d 'Check files into the repository'
|
||||
complete -c cvs -x -a 'diff' -d 'Show differences between revisions'
|
||||
complete -c cvs -x -a 'edit' -d 'Get ready to edit a watched file'
|
||||
complete -c cvs -x -a 'editors' -d 'See who is editing a watched file'
|
||||
complete -c cvs -x -a 'export' -d 'Export sources from CVS, similar to checkout'
|
||||
complete -c cvs -x -a 'history' -d 'Show repository access history'
|
||||
complete -c cvs -x -a 'import' -d 'Import sources into CVS, using vendor branches'
|
||||
complete -c cvs -x -a 'init' -d 'Create a CVS repository if it doesnt exist'
|
||||
complete -c cvs -x -a 'kserver' -d 'Kerberos server mode'
|
||||
complete -c cvs -x -a 'log' -d 'Print out history information for files'
|
||||
complete -c cvs -x -a 'login' -d 'Prompt for password for authenticating server'
|
||||
complete -c cvs -x -a 'logout' -d 'Removes entry in .cvspass for remote repository'
|
||||
complete -c cvs -x -a 'pserver' -d 'Password server mode'
|
||||
complete -c cvs -x -a 'rannotate' -d 'Show last revision where each line of module was modified'
|
||||
complete -c cvs -x -a 'rdiff' -d 'Create "patch" format diffs between releases'
|
||||
complete -c cvs -x -a 'release' -d 'Indicate that a Module is no longer in use'
|
||||
complete -c cvs -x -a 'remove' -d 'Remove an entry from the repository'
|
||||
complete -c cvs -x -a 'rlog' -d 'Print out history information for a module'
|
||||
complete -c cvs -x -a 'rtag' -d 'Add a symbolic tag to a module'
|
||||
complete -c cvs -x -a 'server' -d 'Server mode'
|
||||
complete -c cvs -x -a 'status' -d 'Display status information on checked out files'
|
||||
complete -c cvs -x -a 'tag' -d 'Add a symbolic tag to checked out version of files'
|
||||
complete -c cvs -x -a 'unedit' -d 'Undo an edit command'
|
||||
complete -c cvs -x -a 'update' -d 'Bring work tree in sync with repository'
|
||||
complete -c cvs -x -a 'version' -d 'Show current CVS version(s)'
|
||||
complete -c cvs -x -a 'watch' -d 'Set watches'
|
||||
complete -c cvs -x -a 'watchers' -d 'See who is watching a file'
|
||||
|
||||
complete -c cvs -x -s H -d "Displays usage information for command"
|
||||
complete -c cvs -x -s Q -d "Cause CVS to be really quiet"
|
||||
complete -c cvs -x -s q -d "Cause CVS to be somewhat quiet"
|
||||
complete -c cvs -x -s r -d "Make checked-out files read-only"
|
||||
complete -c cvs -x -s w -d "Make checked-out files read-write (default)"
|
||||
complete -c cvs -x -s n -d "Do not execute anything that will change the disk"
|
||||
complete -c cvs -x -s t -d "Show trace of program execution -- try with -n"
|
||||
complete -c cvs -x -s v -d "CVS version and copyright"
|
||||
complete -c cvs -x -s T -r -d "Use 'tmpdir' for temporary files"
|
||||
complete -c cvs -x -s e -r -d "Use 'editor' for editing log information"
|
||||
complete -c cvs -x -s d -r -d "Overrides $CVSROOT as the root of the CVS tree"
|
||||
complete -c cvs -x -s f -d "Do not use the ~/.cvsrc file"
|
||||
complete -c cvs -x -s z -d "Compression level for net traffic" -x -a "1 2 3 4 5 6 7 8 9"
|
||||
complete -c cvs -x -s x -d "Encrypt all net traffic"
|
||||
complete -c cvs -x -s a -d "Authenticate all net traffic"
|
||||
complete -c cvs -x -s s -d "Set CVS user variable" -x
|
||||
complete -c cvs -x -s H -d 'Displays usage information for command'
|
||||
complete -c cvs -x -s Q -d 'Cause CVS to be really quiet'
|
||||
complete -c cvs -x -s q -d 'Cause CVS to be somewhat quiet'
|
||||
complete -c cvs -x -s r -d 'Make checked-out files read-only'
|
||||
complete -c cvs -x -s w -d 'Make checked-out files read-write (default)'
|
||||
complete -c cvs -x -s n -d 'Do not execute anything that will change the disk'
|
||||
complete -c cvs -x -s t -d 'Show trace of program execution -- try with -n'
|
||||
complete -c cvs -x -s v -d 'CVS version and copyright'
|
||||
complete -c cvs -x -s T -r -d 'Use "tmpdir" for temporary files'
|
||||
complete -c cvs -x -s e -r -d 'Use "editor" for editing log information'
|
||||
complete -c cvs -x -s d -r -d 'Overrides $CVSROOT as the root of the CVS tree'
|
||||
complete -c cvs -x -s f -d 'Do not use the ~/.cvsrc file'
|
||||
complete -c cvs -x -s z -d 'Compression level for net traffic' -x -a '1 2 3 4 5 6 7 8 9'
|
||||
complete -c cvs -x -s x -d 'Encrypt all net traffic'
|
||||
complete -c cvs -x -s a -d 'Authenticate all net traffic'
|
||||
complete -c cvs -x -s s -d 'Set CVS user variable' -x
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# The gcc completion list is incomplete. There are just so many of them...
|
||||
#
|
||||
|
||||
complete -c gcc -s x -d "Language" -x -a "
|
||||
complete -c gcc -s x -d 'Language' -x -a '
|
||||
c
|
||||
c-header
|
||||
cpp-output
|
||||
@@ -19,17 +19,17 @@ complete -c gcc -s x -d "Language" -x -a "
|
||||
java
|
||||
treelang
|
||||
none
|
||||
"
|
||||
complete -c gcc -o pass-exit-codes -d "Pass program exit codes"
|
||||
complete -c gcc -s c -d "Stop after assembler"
|
||||
complete -c gcc -s S -d "Stop after compile"
|
||||
complete -c gcc -s E -d "Stop after preprocesswor"
|
||||
complete -c gcc -s o -r -d "Output file"
|
||||
complete -c gcc -s v -d "Print commands to stderr"
|
||||
complete -c gcc -o \#\#\# -d "Print quoted commands to stderr, do not run"
|
||||
complete -c gcc -o pipe -d "Use pipes"
|
||||
complete -c gcc -o ansi -d "Use ansi mode"
|
||||
complete -c gcc -o std -d "Standard mode" -x -a '
|
||||
'
|
||||
complete -c gcc -o pass-exit-codes -d 'Pass program exit codes'
|
||||
complete -c gcc -s c -d 'Stop after assembler'
|
||||
complete -c gcc -s S -d 'Stop after compile'
|
||||
complete -c gcc -s E -d 'Stop after preprocesswor'
|
||||
complete -c gcc -s o -r -d 'Output file'
|
||||
complete -c gcc -s v -d 'Print commands to stderr'
|
||||
complete -c gcc -o \#\#\# -d 'Print quoted commands to stderr, do not run'
|
||||
complete -c gcc -o pipe -d 'Use pipes'
|
||||
complete -c gcc -o ansi -d 'Use ansi mode'
|
||||
complete -c gcc -o std -d 'Standard mode' -x -a '
|
||||
c89\t"ISO C90"
|
||||
iso9899:1990\t"ISO C90"
|
||||
iso9899:199409\t"ISO C90 as modified in amendment 1"
|
||||
@@ -43,54 +43,54 @@ complete -c gcc -o std -d "Standard mode" -x -a '
|
||||
c++98\t"ISO C++98"
|
||||
gnu++98\t"ISO C++98 plus GNU extentions"
|
||||
'
|
||||
complete -c gcc -o aux-info -r -d "Write prototypes to file"
|
||||
complete -c gcc -o fno-asm -d "Do not recognize asm, inline or typeof keywords"
|
||||
complete -c gcc -o fno-builtin -d "Do not use builtin functions"
|
||||
complete -c gcc -o fhosted -d "Assert hosted environment"
|
||||
complete -c gcc -o ffreestanding -d "Assert freestanding environment"
|
||||
complete -c gcc -o fms-extensions -d "Use Microsoft extensions"
|
||||
complete -c gcc -o trigraphs -d "Use ANSI trigraphs"
|
||||
complete -c gcc -o no-integrated-cpp -d "Do not use integrated preprocessor"
|
||||
complete -c gcc -o funsigned-char -d "char is unsigned"
|
||||
complete -c gcc -o fsigned-char -d "char is signed"
|
||||
complete -c gcc -o funsigned-bitfields -d "bifield is unsigned"
|
||||
complete -c gcc -o fsigned-bitfields -d "bifield is signed"
|
||||
complete -c gcc -o fno-unsigned-bitfields -d "All bifields are signed"
|
||||
complete -c gcc -o fno-signed-bitfields -d "All bifield are signed"
|
||||
complete -c gcc -o fwritable-strings -d "String constants are not const"
|
||||
complete -c gcc -o fabi-version -d "C++ ABI version" -r -x -a "1 0"
|
||||
complete -c gcc -o fno-access-control -d "Turn off access checking"
|
||||
complete -c gcc -o fcheck-new -d "Check pointer returned by new"
|
||||
complete -c gcc -o fconserve-space -d "Put globals in the common segment"
|
||||
complete -c gcc -o fno-const-strings -d "String constants are not const"
|
||||
complete -c gcc -o fdollars-in-identifiers -d "Accept $ in identifiers"
|
||||
complete -c gcc -o fno-dollars-in-identifiers -d "Reject $ in identifiers"
|
||||
complete -c gcc -o fno-elide-constructors -d "Do not omit unneeded temporarys"
|
||||
complete -c gcc -o fno-enforce-eh-specs -d "Allow exception violations"
|
||||
complete -c gcc -o ffor-scope -d "Do not extend for-loop scope"
|
||||
complete -c gcc -o fno-for-scope -d "Extend for-loop scope"
|
||||
complete -c gcc -o fno-gnu-keywords -d "Do not recognize typeof as keyword"
|
||||
complete -c gcc -o fno-implicit-templates -d "Do not emit code for implicit templates"
|
||||
complete -c gcc -o fno-implicit-inline-templates -d "Do not emit code for implicit inline templates"
|
||||
complete -c gcc -o fno-implement-inlines -d "Do not emit out-of-line code for inline functions"
|
||||
complete -c gcc -o fms-extensions -d "Disable warnings about MFC"
|
||||
complete -c gcc -o fno-nonansi-builtins -d "Disable some built-in functions"
|
||||
complete -c gcc -o fno-operator-names -d "Disable operator keywords"
|
||||
complete -c gcc -o fno-optional-diags -d "Disable optional diagnostics"
|
||||
complete -c gcc -o fpermissive -d "Downgrade some errors to warnings"
|
||||
complete -c gcc -o frepo -d "Enable automatic template instantiation at link time"
|
||||
complete -c gcc -o fno-rtti -d "Disable generation of C++ runtime type information"
|
||||
#complete -c gcc -o fstats -d "Emit front-end usage statistics"
|
||||
complete -c gcc -o aux-info -r -d 'Write prototypes to file'
|
||||
complete -c gcc -o fno-asm -d 'Do not recognize asm, inline or typeof keywords'
|
||||
complete -c gcc -o fno-builtin -d 'Do not use builtin functions'
|
||||
complete -c gcc -o fhosted -d 'Assert hosted environment'
|
||||
complete -c gcc -o ffreestanding -d 'Assert freestanding environment'
|
||||
complete -c gcc -o fms-extensions -d 'Use Microsoft extensions'
|
||||
complete -c gcc -o trigraphs -d 'Use ANSI trigraphs'
|
||||
complete -c gcc -o no-integrated-cpp -d 'Do not use integrated preprocessor'
|
||||
complete -c gcc -o funsigned-char -d 'char is unsigned'
|
||||
complete -c gcc -o fsigned-char -d 'char is signed'
|
||||
complete -c gcc -o funsigned-bitfields -d 'bifield is unsigned'
|
||||
complete -c gcc -o fsigned-bitfields -d 'bifield is signed'
|
||||
complete -c gcc -o fno-unsigned-bitfields -d 'All bifields are signed'
|
||||
complete -c gcc -o fno-signed-bitfields -d 'All bifield are signed'
|
||||
complete -c gcc -o fwritable-strings -d 'String constants are not const'
|
||||
complete -c gcc -o fabi-version -d 'C++ ABI version' -r -x -a '1 0'
|
||||
complete -c gcc -o fno-access-control -d 'Turn off access checking'
|
||||
complete -c gcc -o fcheck-new -d 'Check pointer returned by new'
|
||||
complete -c gcc -o fconserve-space -d 'Put globals in the common segment'
|
||||
complete -c gcc -o fno-const-strings -d 'String constants are not const'
|
||||
complete -c gcc -o fdollars-in-identifiers -d 'Accept $ in identifiers'
|
||||
complete -c gcc -o fno-dollars-in-identifiers -d 'Reject $ in identifiers'
|
||||
complete -c gcc -o fno-elide-constructors -d 'Do not omit unneeded temporarys'
|
||||
complete -c gcc -o fno-enforce-eh-specs -d 'Allow exception violations'
|
||||
complete -c gcc -o ffor-scope -d 'Do not extend for-loop scope'
|
||||
complete -c gcc -o fno-for-scope -d 'Extend for-loop scope'
|
||||
complete -c gcc -o fno-gnu-keywords -d 'Do not recognize typeof as keyword'
|
||||
complete -c gcc -o fno-implicit-templates -d 'Do not emit code for implicit templates'
|
||||
complete -c gcc -o fno-implicit-inline-templates -d 'Do not emit code for implicit inline templates'
|
||||
complete -c gcc -o fno-implement-inlines -d 'Do not emit out-of-line code for inline functions'
|
||||
complete -c gcc -o fms-extensions -d 'Disable warnings about MFC'
|
||||
complete -c gcc -o fno-nonansi-builtins -d 'Disable some built-in functions'
|
||||
complete -c gcc -o fno-operator-names -d 'Disable operator keywords'
|
||||
complete -c gcc -o fno-optional-diags -d 'Disable optional diagnostics'
|
||||
complete -c gcc -o fpermissive -d 'Downgrade some errors to warnings'
|
||||
complete -c gcc -o frepo -d 'Enable automatic template instantiation at link time'
|
||||
complete -c gcc -o fno-rtti -d 'Disable generation of C++ runtime type information'
|
||||
#complete -c gcc -o fstats -d 'Emit front-end usage statistics'
|
||||
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17;
|
||||
complete -c gcc -o ftemplate-depth-1 -d Set\ maximum\ template\ depth\ to\ $i;
|
||||
end;
|
||||
|
||||
complete -c gcc -o fno-threadsafe-statistics -d "Do not emit code for thread-safe initialization of local statics"
|
||||
complete -c gcc -o fuse-cxa-atexit -d "Use __cxa_atexit for destructors"
|
||||
complete -c gcc -o fvisibility-inlines-hidden -d "Hides inline methods from export table"
|
||||
complete -c gcc -o fno-weak -d "Do not use weak symbol support"
|
||||
complete -c gcc -o fno-threadsafe-statistics -d 'Do not emit code for thread-safe initialization of local statics'
|
||||
complete -c gcc -o fuse-cxa-atexit -d 'Use __cxa_atexit for destructors'
|
||||
complete -c gcc -o fvisibility-inlines-hidden -d 'Hides inline methods from export table'
|
||||
complete -c gcc -o fno-weak -d 'Do not use weak symbol support'
|
||||
# gcc completion listing is incomplete.
|
||||
#complete -c gcc -o -d ""
|
||||
#complete -c gcc -o -d ''
|
||||
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ else
|
||||
|
||||
complete -c kill -s l -d "List codes and names of available signals"
|
||||
|
||||
for i in (kill -l|tr \ \t \n|grep "^[A-Z][A-Z0-9]*$")
|
||||
for i in (kill -l|tr \ \t \n|grep '^[A-Z][A-Z0-9]*$')
|
||||
complete -c kill -o $i -d Send\ $i\ signal
|
||||
complete -c kill -o s -x -a $i\tSend\ $i\ signal -d "Send specified signal"
|
||||
end
|
||||
end
|
||||
|
||||
complete -c kill -xa "(__fish_complete_pids)"
|
||||
complete -c kill -xa '(__fish_complete_pids)'
|
||||
complete -c kill -s l -d "List names of available signals"
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ complete -c less -s I -l IGNORE-CASE -d "Search ignores all case"
|
||||
complete -c less -s j -l jump-target -d "Target line" -r -a "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19"
|
||||
complete -c less -s J -l status-column -d "Display status column"
|
||||
complete -c less -s k -l lesskey-file -d "Specify key bindings file" -r
|
||||
complete -c less -s L -l no-lessopen -d "Ignore $LESSOPEN"
|
||||
complete -c less -s L -l no-lessopen -d 'Ignore $LESSOPEN'
|
||||
complete -c less -s m -l long-prompt -d "Prompt with percentage"
|
||||
complete -c less -s M -l LONG-PROMPT -d "Verbose prompt"
|
||||
complete -c less -s n -l line-numbers -d "Display line number"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
#Completions for make
|
||||
complete -x -c make -a "(grep -h -E '^[^#%=\t$][^#%=$]*:([^=]|$)' Makefile makefile GNUmakefile | cut -d ":" -f 1 | sed -r 's/^ *//;s/ *$//;s/ +/\n/g' ^/dev/null)" -d "Target"
|
||||
|
||||
function __fish_print_make_targets
|
||||
set files Makefile makefile GNUmakefile
|
||||
grep -h -E '^[^#%=$[:space:]][^#%=$]*:([^=]|$)' $files | cut -d ":" -f 1 | sed -r 's/^ *//;s/ *$//;s/ +/\n/g' ^/dev/null
|
||||
end
|
||||
|
||||
complete -x -c make -a "(__fish_print_make_targets)" -d "Target"
|
||||
complete -r -c make -s f -d "Use file as makefile" -r
|
||||
complete -x -c make -s C -x -a "(__fish_complete_directory (commandline -ct))" -d "Change directory"
|
||||
complete -c make -s d -d "Debug"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# A list of all known filesystem types, used by various completions,
|
||||
# including mount and df
|
||||
|
||||
set -g __fish_filesystems "
|
||||
set -g __fish_filesystems '
|
||||
adfs
|
||||
affs
|
||||
autofs
|
||||
@@ -39,29 +39,29 @@ set -g __fish_filesystems "
|
||||
xenix
|
||||
xfs
|
||||
xiafs
|
||||
"
|
||||
'
|
||||
|
||||
# Completions for mount
|
||||
complete -x -c mount -a "(cat /etc/fstab|sed -e 's/^\([^ \t]*\)[ \t]*\([^ \t]*\).*/\1\n\2/'|grep '^/')" -d "Mount point"
|
||||
complete -c mount -s V -d "Display version and exit"
|
||||
complete -c mount -s h -d "Display help and exit"
|
||||
complete -c mount -s v -d "Verbose mode"
|
||||
complete -c mount -s a -d "Mount filesystems in fstab"
|
||||
complete -c mount -s F -d "Fork process for each mount"
|
||||
complete -c mount -s f -d "Fake mounting"
|
||||
complete -c mount -s l -d "Add label to output"
|
||||
complete -c mount -s n -d "Do not write mtab"
|
||||
complete -c mount -s s -d "Tolerate sloppy mount options"
|
||||
complete -c mount -s r -d "Read only"
|
||||
complete -c mount -s w -d "Read/Write mode"
|
||||
complete -x -c mount -s L -d "Mount partition with specified label"
|
||||
complete -x -c mount -s U -d "Mount partition with specified UID"
|
||||
complete -c mount -s O -x -d "Exclude filesystems"
|
||||
complete -c mount -l bind -f -d "Remount a subtree to a second position"
|
||||
complete -c mount -l move -f -d "Move a subtree to a new position"
|
||||
complete -c mount -x -s t -d "Filesystem" -a $__fish_filesystems
|
||||
complete -x -c mount -a '(cat /etc/fstab|sed -e "s/^\([^ \t]*\)[ \t]*\([^ \t]*\).*/\1\n\2/"|grep "^/")' -d 'Mount point'
|
||||
complete -c mount -s V -d 'Display version and exit'
|
||||
complete -c mount -s h -d 'Display help and exit'
|
||||
complete -c mount -s v -d 'Verbose mode'
|
||||
complete -c mount -s a -d 'Mount filesystems in fstab'
|
||||
complete -c mount -s F -d 'Fork process for each mount'
|
||||
complete -c mount -s f -d 'Fake mounting'
|
||||
complete -c mount -s l -d 'Add label to output'
|
||||
complete -c mount -s n -d 'Do not write mtab'
|
||||
complete -c mount -s s -d 'Tolerate sloppy mount options'
|
||||
complete -c mount -s r -d 'Read only'
|
||||
complete -c mount -s w -d 'Read/Write mode'
|
||||
complete -x -c mount -s L -d 'Mount partition with specified label'
|
||||
complete -x -c mount -s U -d 'Mount partition with specified UID'
|
||||
complete -c mount -s O -x -d 'Exclude filesystems'
|
||||
complete -c mount -l bind -f -d 'Remount a subtree to a second position'
|
||||
complete -c mount -l move -f -d 'Move a subtree to a new position'
|
||||
complete -c mount -x -s t -d 'Filesystem' -a $__fish_filesystems
|
||||
|
||||
complete -c mount -x -s o -d "Mount option" -a "(__fish_append ',' $__fish_mount_opts)"
|
||||
complete -c mount -x -s o -d 'Mount option' -a '(__fish_append , $__fish_mount_opts)'
|
||||
|
||||
set -g __fish_mount_opts async\tUse\ asynchronous\ I/O atime\tUpdate\ time\ on\ each\ access auto\tMounted\ with\ -a defaults\tUse\ default\ options dev\tInterpret\ character/block\ special\ devices exec\tPermit\ executables _netdev\tFilesystem\ uses\network noatime\tDo\ not\ update\ time\ on\ each\ access noauto\tNot\ mounted\ by\ -a nodev\tDo\ not\ interpret\ character/block\ special\ devices noexec\tDo\ not\ permit\ executables nosuid\tIgnore\ suid\ bits nouser\tOnly\ root\ may\ mount remount\tRemount\ read-only\ filesystem ro\tMount\ read-only rw\tMount\ read-write suid\tAllow\ suid\ bits sync\tUse\ synchronous\ I/O dirsync\tUse\ synchronous\ directory\ operations user\tAny\ user\ may\ mount users\tAny\ user\ may\ mount\ and\ unmount
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
complete -c perl -s 0 -d "Specify record separator"
|
||||
complete -c perl -s a -d "Feed input to split"
|
||||
complete -c perl -s c -d "Check syntax"
|
||||
complete -c perl -s d -d "Debugger"
|
||||
complete -c perl -s D -x -d "Debug option"
|
||||
complete -c perl -s e -x -d "Execute command"
|
||||
complete -c perl -s F -d "Set regexp used to split input"
|
||||
complete -c perl -s i -d "Edit files in-place"
|
||||
complete -c perl -s I -d "Include path"
|
||||
complete -c perl -s l -d "Line ending processing"
|
||||
complete -c perl -s n -d "Loop script"
|
||||
complete -c perl -s p -d "Loop script, print $_"
|
||||
complete -c perl -s P -d "Invoke CPP"
|
||||
complete -c perl -s s -d "Define custom switches"
|
||||
complete -c perl -s S -d "Search $PATH for script"
|
||||
complete -c perl -s T -d "Taint checking"
|
||||
complete -c perl -s U -d "Unsafe mode"
|
||||
complete -c perl -s v -d "Display version"
|
||||
complete -c perl -s x -d "Extract script"
|
||||
complete -c perl -s 0 -d 'Specify record separator'
|
||||
complete -c perl -s a -d 'Feed input to split'
|
||||
complete -c perl -s c -d 'Check syntax'
|
||||
complete -c perl -s d -d 'Debugger'
|
||||
complete -c perl -s D -x -d 'Debug option'
|
||||
complete -c perl -s e -x -d 'Execute command'
|
||||
complete -c perl -s F -d 'Set regexp used to split input'
|
||||
complete -c perl -s i -d 'Edit files in-place'
|
||||
complete -c perl -s I -d 'Include path'
|
||||
complete -c perl -s l -d 'Line ending processing'
|
||||
complete -c perl -s n -d 'Loop script'
|
||||
complete -c perl -s p -d 'Loop script, print $_'
|
||||
complete -c perl -s P -d 'Invoke CPP'
|
||||
complete -c perl -s s -d 'Define custom switches'
|
||||
complete -c perl -s S -d 'Search $PATH for script'
|
||||
complete -c perl -s T -d 'Taint checking'
|
||||
complete -c perl -s U -d 'Unsafe mode'
|
||||
complete -c perl -s v -d 'Display version'
|
||||
complete -c perl -s x -d 'Extract script'
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ complete $rpm_erase -l repackage -d 'Re-package the files before erasing'
|
||||
complete $rpm_erase -l test -d 'Dont really uninstall anything, just go through the motions'
|
||||
set -e rpm_erase
|
||||
|
||||
set -- rpm_mode -c rpm -n "__fish_contains_opt -s e -s i -s F -s V -s U -s q erase install freshen verify upgrade query; if test $status = 0; false; else; true; end"
|
||||
set -- rpm_mode -c rpm -n '__fish_contains_opt -s e -s i -s F -s V -s U -s q erase install freshen verify upgrade query; if test $status = 0; false; else; true; end'
|
||||
complete $rpm_mode -s i -l install -d 'Install new package'
|
||||
complete $rpm_mode -s U -l upgrade -d 'Upgrade existing package'
|
||||
complete $rpm_mode -s F -l freshen -d 'Upgrade package if already installed'
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#Completions for ruby
|
||||
complete -c ruby -s 0 -d "Specify record separator"
|
||||
complete -c ruby -s a -d "Feed input to split"
|
||||
complete -c ruby -s c -d "Check syntax"
|
||||
complete -c ruby -s K -d "Kanji code-set"
|
||||
complete -c ruby -s d -l debug -d "Debugger"
|
||||
complete -c ruby -s e -x -d "Execute command"
|
||||
complete -c ruby -s h -l help -d "Display help"
|
||||
complete -c ruby -s F -d "Set regexp used to split input"
|
||||
complete -c ruby -s i -d "Edit files in-place"
|
||||
complete -c ruby -s I -d "Include path"
|
||||
complete -c ruby -s l -d "Line ending processing"
|
||||
complete -c ruby -s n -d "Loop script"
|
||||
complete -c ruby -s p -d "Loop script, print $_"
|
||||
complete -c ruby -s r -r -d "Require file"
|
||||
complete -c ruby -s s -d "Define custom switches"
|
||||
complete -c ruby -s S -d "Search $PATH for script"
|
||||
complete -c ruby -s T -d "Taint checking"
|
||||
complete -c ruby -s v -l verbose -d "Verbose mode"
|
||||
complete -c ruby -s w -d "Verbose mode without message"
|
||||
complete -c ruby -l version -d "Display version"
|
||||
complete -c ruby -s x -d "Extract script"
|
||||
complete -c ruby -s X -x -a "(__fish_complete_directory (commandline -ct))" -d "Directory"
|
||||
complete -c ruby -s y -l yydebug -d "Compiler debug mode"
|
||||
complete -c ruby -s 0 -d 'Specify record separator'
|
||||
complete -c ruby -s a -d 'Feed input to split'
|
||||
complete -c ruby -s c -d 'Check syntax'
|
||||
complete -c ruby -s K -d 'Kanji code-set'
|
||||
complete -c ruby -s d -l debug -d 'Debugger'
|
||||
complete -c ruby -s e -x -d 'Execute command'
|
||||
complete -c ruby -s h -l help -d 'Display help'
|
||||
complete -c ruby -s F -d 'Set regexp used to split input'
|
||||
complete -c ruby -s i -d 'Edit files in-place'
|
||||
complete -c ruby -s I -d 'Include path'
|
||||
complete -c ruby -s l -d 'Line ending processing'
|
||||
complete -c ruby -s n -d 'Loop script'
|
||||
complete -c ruby -s p -d 'Loop script, print $_'
|
||||
complete -c ruby -s r -r -d 'Require file'
|
||||
complete -c ruby -s s -d 'Define custom switches'
|
||||
complete -c ruby -s S -d 'Search $PATH for script'
|
||||
complete -c ruby -s T -d 'Taint checking'
|
||||
complete -c ruby -s v -l verbose -d 'Verbose mode'
|
||||
complete -c ruby -s w -d 'Verbose mode without message'
|
||||
complete -c ruby -l version -d 'Display version'
|
||||
complete -c ruby -s x -d 'Extract script'
|
||||
complete -c ruby -s X -x -a '(__fish_complete_directory (commandline -ct))' -d 'Directory'
|
||||
complete -c ruby -s y -l yydebug -d 'Compiler debug mode'
|
||||
|
||||
|
||||
@@ -3,35 +3,35 @@ function __fish_complete_screen -d "Print a list of running screen sessions"
|
||||
end
|
||||
|
||||
complete -c screen -x
|
||||
complete -c screen -s a -d "Include all capabilitys"
|
||||
complete -c screen -s A -d "Adapt window size"
|
||||
complete -c screen -s c -r -d "Specify init file"
|
||||
complete -c screen -s d -d "Detach screen" -a "(__fish_complete_screen)"
|
||||
complete -c screen -s D -d "Detach screen" -a "(__fish_complete_screen)"
|
||||
complete -c screen -s r -d "Reattach session" -a "(__fish_complete_screen)"
|
||||
complete -c screen -s R -d "Reattach/create session"
|
||||
complete -c screen -o RR -d "Reattach/create any session"
|
||||
complete -c screen -s e -x -d "Escape character"
|
||||
complete -c screen -s f -d "Flow control on"
|
||||
complete -c screen -o fn -d "Flow control off"
|
||||
complete -c screen -o fa -d "Flow control automatic"
|
||||
complete -c screen -s h -x -d "History length"
|
||||
complete -c screen -s i -d "Interrupt display on C-c"
|
||||
complete -c screen -s l -d "Login on"
|
||||
complete -c screen -o ln -d "Login off"
|
||||
complete -c screen -o ls -d "List sessions"
|
||||
complete -c screen -o list -d "List sessions"
|
||||
complete -c screen -s L -d "Log on"
|
||||
complete -c screen -s m -d "Ignore $STY"
|
||||
complete -c screen -s O -d "Optimal output"
|
||||
complete -c screen -s p -d "Preselect window"
|
||||
complete -c screen -s q -d "Quiet mode"
|
||||
complete -c screen -s s -r -d "Set shell"
|
||||
complete -c screen -s S -x -d "Session name"
|
||||
complete -c screen -s t -x -d "Session title"
|
||||
complete -c screen -s U -d "UTF-8 mode"
|
||||
complete -c screen -s v -d "Display version"
|
||||
complete -c screen -o wipe -d "Wipe dead sessions"
|
||||
complete -c screen -s x -d "Multi attach"
|
||||
complete -c screen -s X -r -d "Send command"
|
||||
complete -c screen -s a -d 'Include all capabilitys'
|
||||
complete -c screen -s A -d 'Adapt window size'
|
||||
complete -c screen -s c -r -d 'Specify init file'
|
||||
complete -c screen -s d -d 'Detach screen' -a '(__fish_complete_screen)'
|
||||
complete -c screen -s D -d 'Detach screen' -a '(__fish_complete_screen)'
|
||||
complete -c screen -s r -d 'Reattach session' -a '(__fish_complete_screen)'
|
||||
complete -c screen -s R -d 'Reattach/create session'
|
||||
complete -c screen -o RR -d 'Reattach/create any session'
|
||||
complete -c screen -s e -x -d 'Escape character'
|
||||
complete -c screen -s f -d 'Flow control on'
|
||||
complete -c screen -o fn -d 'Flow control off'
|
||||
complete -c screen -o fa -d 'Flow control automatic'
|
||||
complete -c screen -s h -x -d 'History length'
|
||||
complete -c screen -s i -d 'Interrupt display on C-c'
|
||||
complete -c screen -s l -d 'Login on'
|
||||
complete -c screen -o ln -d 'Login off'
|
||||
complete -c screen -o ls -d 'List sessions'
|
||||
complete -c screen -o list -d 'List sessions'
|
||||
complete -c screen -s L -d 'Log on'
|
||||
complete -c screen -s m -d 'Ignore $STY'
|
||||
complete -c screen -s O -d 'Optimal output'
|
||||
complete -c screen -s p -d 'Preselect window'
|
||||
complete -c screen -s q -d 'Quiet mode'
|
||||
complete -c screen -s s -r -d 'Set shell'
|
||||
complete -c screen -s S -x -d 'Session name'
|
||||
complete -c screen -s t -x -d 'Session title'
|
||||
complete -c screen -s U -d 'UTF-8 mode'
|
||||
complete -c screen -s v -d 'Display version'
|
||||
complete -c screen -o wipe -d 'Wipe dead sessions'
|
||||
complete -c screen -s x -d 'Multi attach'
|
||||
complete -c screen -s X -r -d 'Send command'
|
||||
|
||||
|
||||
@@ -43,4 +43,4 @@ function __fish_set_is_color -d 'Test if We are specifying a color value for the
|
||||
end
|
||||
end
|
||||
|
||||
complete -c set -n '__fish_set_is_color' -x -a '$__fish_colors' -d Color
|
||||
complete -c set -n '__fish_set_is_color' -x -a '(set_color --print-colors)' -d Color
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
set -g __fish_colors black red green brown blue magenta cyan white normal
|
||||
|
||||
complete -c set_color -x -d "Color" -a '$__fish_colors'
|
||||
complete -c set_color -s b -l background -x -a '$__fish_colors' -d "Change background color"
|
||||
complete -c set_color -x -d "Color" -a '(set_color --print-colors)'
|
||||
complete -c set_color -s b -l background -x -a '(set_color --print-colors)' -d "Change background color"
|
||||
complete -c set_color -s o -l bold -d 'Make font bold'
|
||||
|
||||
22
init/fish.in
22
init/fish.in
@@ -7,8 +7,7 @@
|
||||
# Set default field separators
|
||||
#
|
||||
|
||||
set IFS \ \t\n
|
||||
|
||||
set -g IFS \ \t\n
|
||||
|
||||
#
|
||||
# Add a few common directories to path, if they exists. Note that pure
|
||||
@@ -17,9 +16,8 @@ set IFS \ \t\n
|
||||
#
|
||||
|
||||
for i in /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin
|
||||
if test -d $i
|
||||
if echo $PATH|grep $i >/dev/null
|
||||
else
|
||||
if not expr "$PATH" : .\*$i.\* >/dev/null
|
||||
if test -d $i
|
||||
set PATH $PATH $i
|
||||
end
|
||||
end
|
||||
@@ -31,7 +29,7 @@ end
|
||||
#
|
||||
|
||||
if status --is-login
|
||||
if not count $LANG >/dev/null
|
||||
if not set -q LANG >/dev/null
|
||||
set -gx LANG en_US.UTF-8
|
||||
end
|
||||
end
|
||||
@@ -42,13 +40,9 @@ end
|
||||
# situation as well?
|
||||
#
|
||||
|
||||
if count $LANG >/dev/null
|
||||
if test (expr match $LANG ".*UTF") -gt 0
|
||||
if count $TERM >/dev/null
|
||||
if test linux = $TERM
|
||||
unicode_start ^/dev/null
|
||||
end
|
||||
end
|
||||
if expr match "$LANG" ".*UTF" >/dev/null
|
||||
if test linux = "$TERM"
|
||||
unicode_start ^/dev/null
|
||||
end
|
||||
end
|
||||
|
||||
@@ -59,7 +53,7 @@ end
|
||||
#
|
||||
|
||||
for i in DISPLAY
|
||||
if test (count $$i) -gt 1
|
||||
if set -q $i
|
||||
set -- $i (printf ":%s" $$i|cut -c 2-)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,10 +42,10 @@ function __fish_complete_suffix -d "Complete using files"
|
||||
set -- desc $argv[3]
|
||||
|
||||
set -- base (echo $comp |sed -e 's/\.[a-zA-Z0-9]*$//')
|
||||
eval "set -- files "$base"*"$suff
|
||||
eval "set -- files $base*$suff"
|
||||
|
||||
if test $files[1]
|
||||
printf "%s\t"$desc"\n" $files
|
||||
printf "%s\t$desc\n" $files
|
||||
end
|
||||
|
||||
#
|
||||
@@ -74,7 +74,7 @@ function __fish_complete_directory -d "Complete using directories"
|
||||
eval "set -- dirs "$comp"*/"
|
||||
|
||||
if test $dirs[1]
|
||||
printf "%s\t"$desc"\n" $dirs
|
||||
printf "%s\t$desc\n" $dirs
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
function _contains_help -d "Helper function for contains"
|
||||
|
||||
set bullet \*
|
||||
if count $LANG >/dev/null
|
||||
if test (expr match $LANG ".*UTF") -gt 0
|
||||
set bullet \u2022
|
||||
end
|
||||
if expr match "$LANG" ".*UTF" >/dev/null
|
||||
set bullet \u2022
|
||||
end
|
||||
|
||||
echo \tcontains - Test if a word is present in a list\n
|
||||
@@ -32,7 +30,7 @@ function _contains_help -d "Helper function for contains"
|
||||
end
|
||||
|
||||
function contains -d "Test if a key is contained in a set of values"
|
||||
while count $argv >/dev/null
|
||||
while set -q argv
|
||||
switch $argv[1]
|
||||
case '-h' '--h' '--he' '--hel' '--help'
|
||||
_contains_help
|
||||
@@ -56,8 +54,7 @@ function contains -d "Test if a key is contained in a set of values"
|
||||
set -e argv[1]
|
||||
end
|
||||
|
||||
if count $argv >/dev/null
|
||||
else
|
||||
if not set -q argv
|
||||
echo "contains: Key not specified"
|
||||
return 1
|
||||
end
|
||||
@@ -223,11 +220,9 @@ function prompt_pwd -d "Print the current working directory, ellipsise it if it
|
||||
if test $len -gt $max_width
|
||||
#Write ellipsis character if known to be using UTF
|
||||
#else use $
|
||||
set -l ellipsis "$" #default
|
||||
if count $LANG >/dev/null
|
||||
if test (expr match $LANG ".*UTF") -gt 0
|
||||
set ellipsis \u2026
|
||||
end
|
||||
set -l ellipsis '$' #default
|
||||
if expr match "$LANG" ".*UTF" >/dev/null
|
||||
set ellipsis \u2026
|
||||
end
|
||||
printf %s%s $ellipsis (echo $wd|cut -c (echo $len-$max_width-1|bc)- ^/dev/null )
|
||||
else
|
||||
@@ -288,18 +283,18 @@ function vared -d "Edit variable value"
|
||||
else
|
||||
|
||||
printf "vared: %s is an array variable. Use " $argv
|
||||
set_color $FISH_COLOR_COMMAND
|
||||
set_color $fish_color_command
|
||||
printf vared
|
||||
set_color $FISH_COLOR_NORMAL
|
||||
set_color $fish_color_normal
|
||||
printf " %s[n] to edit the n:th element of %s\n" $argv $argv
|
||||
|
||||
end
|
||||
end
|
||||
else
|
||||
printf "vared: Expected exactly one argument, got %s.\n\nSynopsis:\n\t" (count $argv)
|
||||
set_color $FISH_COLOR_COMMAND
|
||||
set_color $fish_color_command
|
||||
printf vared
|
||||
set_color $FISH_COLOR_NORMAL
|
||||
set_color $fish_color_normal
|
||||
printf " VARIABLE\n"
|
||||
end
|
||||
end
|
||||
@@ -565,10 +560,8 @@ end
|
||||
function __fish_type_help -d "Help for the type shellscript function"
|
||||
|
||||
set bullet \*
|
||||
if count $LANG >/dev/null
|
||||
if test (expr match $LANG ".*UTF") -gt 0
|
||||
set bullet \u2022
|
||||
end
|
||||
if expr match "$LANG" ".*UTF" >/dev/null
|
||||
set bullet \u2022
|
||||
end
|
||||
|
||||
echo \ttype - Indicate how a name would be interpreted if used as a \n\tcommand name
|
||||
@@ -724,36 +717,6 @@ 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, and pad it with zeros
|
||||
if echo $argv | grep -E '^(0|)[0-7]{1,3}$' >/dev/null
|
||||
@@ -768,19 +731,6 @@ function __fish_umask_parse -d "Parses a file permission specification as into a
|
||||
|
||||
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
|
||||
@@ -875,19 +825,6 @@ function __fish_umask_print_symbolic
|
||||
set -l res ""
|
||||
set -l letter a u g o
|
||||
|
||||
# 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)
|
||||
@@ -933,7 +870,7 @@ function umask -d "Set default file permission mask"
|
||||
|
||||
switch $opt[1]
|
||||
case -h --help
|
||||
__fish_umask_help
|
||||
help umask
|
||||
return 0
|
||||
|
||||
case -p --as-command
|
||||
@@ -984,6 +921,9 @@ end
|
||||
|
||||
function psub -d "Read from stdin into a file and output the filename. Remove the file when the command that calles psub exits."
|
||||
|
||||
set -l filename
|
||||
set -l funcname
|
||||
|
||||
if count $argv >/dev/null
|
||||
switch $argv[1]
|
||||
case '-h*' --h --he --hel --help
|
||||
@@ -998,7 +938,7 @@ function psub -d "Read from stdin into a file and output the filename. Remove th
|
||||
end
|
||||
|
||||
if not status --is-command-substitution
|
||||
echo psub: Not inside of command substitution
|
||||
echo psub: Not inside of command substitution >&2
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -53,10 +53,15 @@ end
|
||||
# Set various color values
|
||||
#
|
||||
|
||||
function set_default -d "Set an universal variable, unless it has already been set"
|
||||
function set_default_color -d "Set an universal variable, unless it has already been set. If set, verify that it is a valid color name"
|
||||
if not set -q $argv[1]
|
||||
set -U -- $argv
|
||||
return
|
||||
end
|
||||
if contains -- $$argv[1] (set_color -c)
|
||||
return
|
||||
end
|
||||
set -U -- $argv
|
||||
end
|
||||
|
||||
function set_exported_default -d "Set an exported universal variable, unless it has already been set"
|
||||
@@ -67,28 +72,28 @@ end
|
||||
|
||||
|
||||
# Regular syntax highlighting colors
|
||||
set_default fish_color_normal normal
|
||||
set_default fish_color_command green
|
||||
set_default fish_color_redirection normal
|
||||
set_default fish_color_comment brown
|
||||
set_default fish_color_error red
|
||||
set_default_color fish_color_normal normal
|
||||
set_default_color fish_color_command green
|
||||
set_default_color fish_color_redirection normal
|
||||
set_default_color fish_color_comment brown
|
||||
set_default_color fish_color_error red
|
||||
|
||||
set_default fish_color_cwd green
|
||||
set_default_color fish_color_cwd green
|
||||
|
||||
# Background color for matching quotes and parenthesis
|
||||
set_default fish_color_match cyan
|
||||
set_default_color fish_color_match cyan
|
||||
|
||||
# Background color for search matches
|
||||
set_default fish_color_search_match purple
|
||||
set_default_color fish_color_search_match purple
|
||||
|
||||
# Pager colors
|
||||
set_default fish_pager_color_prefix cyan
|
||||
set_default fish_pager_color_completion normal
|
||||
set_default fish_pager_color_description normal
|
||||
set_default fish_pager_color_progress cyan
|
||||
set_default_color fish_pager_color_prefix cyan
|
||||
set_default_color fish_pager_color_completion normal
|
||||
set_default_color fish_pager_color_description normal
|
||||
set_default_color fish_pager_color_progress cyan
|
||||
|
||||
# Directory history colors
|
||||
set_default fish_color_history_current cyan
|
||||
set_default_color fish_color_history_current cyan
|
||||
|
||||
|
||||
#
|
||||
@@ -115,5 +120,5 @@ if command ls --color=auto --help 1>/dev/null 2>/dev/null
|
||||
end
|
||||
|
||||
|
||||
functions -e set_default
|
||||
functions -e set_default_color
|
||||
functions -e set_exported_default
|
||||
|
||||
35
input.c
35
input.c
@@ -49,6 +49,7 @@ implementation in fish is as of yet incomplete.
|
||||
#include "parser.h"
|
||||
#include "env.h"
|
||||
#include "expand.h"
|
||||
#include "event.h"
|
||||
|
||||
static void input_read_inputrc( wchar_t *fn );
|
||||
|
||||
@@ -263,6 +264,9 @@ void input_set_application( wchar_t *name )
|
||||
current_application_mappings = (array_list_t *)hash_get( &all_mappings, name );
|
||||
}
|
||||
|
||||
/**
|
||||
Get the mapping with the specified name
|
||||
*/
|
||||
static array_list_t *get_mapping( const wchar_t *mode )
|
||||
{
|
||||
|
||||
@@ -694,7 +698,7 @@ static wchar_t *input_expand_sequence( const wchar_t *in )
|
||||
}
|
||||
debug( 1, L"Invalid sequence - Control-nothing?\n" );
|
||||
error = 1;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1109,6 +1113,9 @@ static void add_terminfo_mapping( const wchar_t *mode,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Call input_expand_sequence on seq, and add the result as a mapping
|
||||
*/
|
||||
static void add_escaped_mapping( const wchar_t *mode,
|
||||
const wchar_t *seq,
|
||||
const wchar_t *desc,
|
||||
@@ -1122,7 +1129,9 @@ static void add_escaped_mapping( const wchar_t *mode,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add bindings common to emacs and vi
|
||||
*/
|
||||
static void add_common_bindings()
|
||||
{
|
||||
static const wchar_t *name[] =
|
||||
@@ -1204,6 +1213,9 @@ static void add_common_bindings()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Add emacs-specific bindings
|
||||
*/
|
||||
static void add_emacs_bindings()
|
||||
{
|
||||
add_escaped_mapping( L"emacs", (L"\\C-a"), L"Control-a", L"beginning-of-line" );
|
||||
@@ -1216,6 +1228,9 @@ static void add_emacs_bindings()
|
||||
add_terminfo_mapping( L"emacs", (key_npage), L"Page Down", L"end-of-history" );
|
||||
}
|
||||
|
||||
/**
|
||||
Add vi-specific bindings
|
||||
*/
|
||||
static void add_vi_bindings()
|
||||
{
|
||||
add_mapping( L"vi", L"\e", L"Escape", L"bind -M vi-command" );
|
||||
@@ -1246,8 +1261,16 @@ static void add_vi_bindings()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Handle interruptions to key reading by reaping finshed jobs and
|
||||
propagating the interrupt to the reader.
|
||||
*/
|
||||
static int interrupt_handler()
|
||||
{
|
||||
/*
|
||||
Fire any pending events
|
||||
*/
|
||||
event_fire( 0, 0 );
|
||||
if( job_reap( 1 ) )
|
||||
repaint();
|
||||
if( reader_interupted() )
|
||||
@@ -1313,6 +1336,9 @@ int input_init()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Free memory used by the specified mapping
|
||||
*/
|
||||
static void destroy_mapping( const void *key, const void *val )
|
||||
{
|
||||
int i;
|
||||
@@ -1344,7 +1370,9 @@ void input_destroy()
|
||||
del_curterm( cur_term );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Perform the action of the specified binding
|
||||
*/
|
||||
static wint_t input_exec_binding( mapping *m, const wchar_t *seq )
|
||||
{
|
||||
// fwprintf( stderr, L"Binding %ls\n", m->command );
|
||||
@@ -1398,7 +1426,6 @@ static wint_t input_exec_binding( mapping *m, const wchar_t *seq )
|
||||
/**
|
||||
Try reading the specified function mapping
|
||||
*/
|
||||
|
||||
static wint_t input_try_mapping( mapping *m)
|
||||
{
|
||||
int j, k;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** \file input_common.h
|
||||
/** \file input_common.c
|
||||
|
||||
Implementation file for the low level input library
|
||||
|
||||
|
||||
6
intern.c
6
intern.c
@@ -17,6 +17,9 @@
|
||||
hash_table_t *intern_table=0;
|
||||
hash_table_t *intern_static_table=0;
|
||||
|
||||
/**
|
||||
Load static strings that are universally common. Currently only loads the empty string.
|
||||
*/
|
||||
static void intern_load_common_static()
|
||||
{
|
||||
intern_static( L"" );
|
||||
@@ -94,6 +97,9 @@ const wchar_t *intern_static( const wchar_t *in )
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the specified key/value pair. Should only be called by intern_free_all at shutdown
|
||||
*/
|
||||
static void clear_value( const void *key, const void *data )
|
||||
{
|
||||
debug( 3, L"interned string: '%ls'", data );
|
||||
|
||||
6
intern.h
6
intern.h
@@ -12,7 +12,7 @@
|
||||
/**
|
||||
Return an identical copy of the specified string from a pool of unique strings. If the string was not in the pool, add a copy.
|
||||
|
||||
\param The string to return an interned copy of
|
||||
\param in the string to return an interned copy of
|
||||
*/
|
||||
const wchar_t *intern( const wchar_t *in );
|
||||
|
||||
@@ -20,11 +20,13 @@ const wchar_t *intern( const wchar_t *in );
|
||||
Insert the specified string literal into the pool of unique
|
||||
strings. The string will not first be copied, and it will not be
|
||||
free'd on exit.
|
||||
|
||||
\param in the string to add to the interned pool
|
||||
*/
|
||||
const wchar_t *intern_static( const wchar_t *in );
|
||||
|
||||
/**
|
||||
Free all interned strings
|
||||
Free all interned strings. Only call this at shutdown.
|
||||
*/
|
||||
void intern_free_all();
|
||||
|
||||
|
||||
1
io.c
1
io.c
@@ -95,7 +95,6 @@ io_data_t *io_buffer_create()
|
||||
b_init( buffer_redirect->param2.out_buffer );
|
||||
buffer_redirect->fd=1;
|
||||
|
||||
|
||||
if( exec_pipe( buffer_redirect->param1.pipe_fd ) == -1 )
|
||||
{
|
||||
debug( 1, PIPE_ERROR );
|
||||
|
||||
7
io.h
7
io.h
@@ -17,7 +17,9 @@ typedef struct io_data
|
||||
int io_mode;
|
||||
/** FD to redirect */
|
||||
int fd;
|
||||
/** parameter for redirection */
|
||||
/**
|
||||
Type-specific parameter for redirection
|
||||
*/
|
||||
union
|
||||
{
|
||||
/** Fds for IO_PIPE and for IO_BUFFER */
|
||||
@@ -28,6 +30,9 @@ typedef struct io_data
|
||||
int old_fd;
|
||||
} param1
|
||||
;
|
||||
/**
|
||||
Second type-specific paramter for redirection
|
||||
*/
|
||||
union
|
||||
{
|
||||
/** file creation flags to send to open for IO_FILE */
|
||||
|
||||
13
main.c
13
main.c
@@ -111,7 +111,7 @@ int main( int argc, char **argv )
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
@@ -202,25 +202,26 @@ int main( int argc, char **argv )
|
||||
is_interactive_session &= (cmd == 0);
|
||||
is_interactive_session &= (my_optind == argc);
|
||||
is_interactive_session &= isatty(STDIN_FILENO);
|
||||
|
||||
|
||||
// fwprintf( stderr, L"%d %d %d\n", cmd==0, my_optind == argc, isatty(STDIN_FILENO) );
|
||||
|
||||
if( force_interactive )
|
||||
is_interactive_session=1;
|
||||
|
||||
|
||||
proc_init();
|
||||
output_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
wutil_init();
|
||||
parser_init();
|
||||
builtin_init();
|
||||
function_init();
|
||||
env_init();
|
||||
complete_init();
|
||||
reader_init();
|
||||
|
||||
reader_init();
|
||||
|
||||
reader_push_current_filename( L"(internal)" );
|
||||
|
||||
|
||||
if( read_init() )
|
||||
{
|
||||
if( cmd != 0 )
|
||||
|
||||
2
mimedb.c
2
mimedb.c
@@ -1018,7 +1018,7 @@ int main (int argc, char *argv[])
|
||||
*/
|
||||
while( 1 )
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
|
||||
33
parser.c
33
parser.c
@@ -51,6 +51,10 @@ The fish parser. Contains functions for parsing code.
|
||||
*/
|
||||
#define MAX_RECURSION_DEPTH 128
|
||||
|
||||
/**
|
||||
Message about reporting bugs, used on weird internal error to
|
||||
hopefully get them to report stuff.
|
||||
*/
|
||||
#define BUGREPORT_MSG L"If this error can be reproduced, please send a bug report to %s."
|
||||
|
||||
/**
|
||||
@@ -147,7 +151,25 @@ static int parse_job( process_t *p,
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int exec, parse, level, skipped;
|
||||
/**
|
||||
Time spent executing the specified command, including parse time for nested blocks
|
||||
*/
|
||||
int exec;
|
||||
/**
|
||||
Time spent parsing the specified command, incvluding execution time for command substitutions
|
||||
*/
|
||||
int parse;
|
||||
/**
|
||||
The block level of the specified command
|
||||
*/
|
||||
int level;
|
||||
/**
|
||||
If the execution of this command was skipped
|
||||
*/
|
||||
int skipped;
|
||||
/**
|
||||
The command string
|
||||
*/
|
||||
wchar_t *cmd;
|
||||
} profile_element_t;
|
||||
|
||||
@@ -1685,7 +1707,6 @@ static void eval_job( tokenizer *tok )
|
||||
|
||||
current_block->job = j;
|
||||
|
||||
proc_had_barrier=0;
|
||||
|
||||
if( is_interactive )
|
||||
{
|
||||
@@ -1741,7 +1762,15 @@ static void eval_job( tokenizer *tok )
|
||||
|
||||
if(!skip )
|
||||
{
|
||||
int was_builtin = 0;
|
||||
// if( j->first_process->type==INTERNAL_BUILTIN && !j->first_process->next)
|
||||
// was_builtin = 1;
|
||||
|
||||
exec( j );
|
||||
|
||||
/* Only external commands require a new fishd barrier */
|
||||
if( !was_builtin )
|
||||
proc_had_barrier=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
1
proc.c
1
proc.c
@@ -486,7 +486,6 @@ static void fire_process_event( const wchar_t *msg, int type, pid_t pid, int sta
|
||||
{
|
||||
static event_t ev;
|
||||
event_t e;
|
||||
|
||||
|
||||
e.function_name=0;
|
||||
|
||||
|
||||
55
reader.c
55
reader.c
@@ -93,7 +93,7 @@ commence.
|
||||
|
||||
/**
|
||||
The maximum number of characters to read from the keyboard without
|
||||
repainting. Note that this readahead wil only occur if new
|
||||
repainting. Note that this readahead will only occur if new
|
||||
characters are avaialble for reading, fish will never block for
|
||||
more input without repainting.
|
||||
*/
|
||||
@@ -1007,12 +1007,13 @@ static int insert_str(wchar_t *str)
|
||||
}
|
||||
else
|
||||
{
|
||||
int old_len = data->buff_len;
|
||||
|
||||
data->buff_len += len;
|
||||
check_size();
|
||||
|
||||
/* Insert space for extra character at the right position */
|
||||
if( data->buff_pos < data->buff_len )
|
||||
/* Insert space for extra characters at the right position */
|
||||
if( data->buff_pos < old_len )
|
||||
{
|
||||
memmove( &data->buff[data->buff_pos+len],
|
||||
&data->buff[data->buff_pos],
|
||||
@@ -1548,9 +1549,9 @@ void reader_sanity_check()
|
||||
|
||||
void reader_current_subshell_extent( wchar_t **a, wchar_t **b )
|
||||
{
|
||||
wchar_t *buffcpy = wcsdup( data->buff );
|
||||
wchar_t *begin, *end;
|
||||
|
||||
wchar_t *pos;
|
||||
|
||||
if( a )
|
||||
*a=0;
|
||||
if( b )
|
||||
@@ -1559,35 +1560,41 @@ void reader_current_subshell_extent( wchar_t **a, wchar_t **b )
|
||||
if( !data )
|
||||
return;
|
||||
|
||||
pos = data->buff;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
int bc, ec;
|
||||
|
||||
if( expand_locate_subshell( buffcpy,
|
||||
|
||||
if( expand_locate_subshell( pos,
|
||||
&begin,
|
||||
&end,
|
||||
1 ) <= 0)
|
||||
{
|
||||
begin=buffcpy;
|
||||
end = buffcpy + wcslen(data->buff);
|
||||
begin=data->buff;
|
||||
end = data->buff + wcslen(data->buff);
|
||||
break;
|
||||
}
|
||||
bc = begin-buffcpy;
|
||||
ec = end-buffcpy;
|
||||
|
||||
if( !end )
|
||||
{
|
||||
end = data->buff + wcslen(data->buff);
|
||||
}
|
||||
|
||||
bc = begin-data->buff;
|
||||
ec = end-data->buff;
|
||||
|
||||
if(( bc < data->buff_pos ) && (ec >= data->buff_pos) )
|
||||
{
|
||||
begin++;
|
||||
|
||||
//fwprintf( stderr, L"Subshell!\n" );
|
||||
break;
|
||||
}
|
||||
*begin=0;
|
||||
pos = end+1;
|
||||
}
|
||||
if( a )
|
||||
*a = data->buff + (begin-buffcpy);
|
||||
*a = begin;
|
||||
if( b )
|
||||
*b = data->buff + (end-buffcpy);
|
||||
free( buffcpy );
|
||||
*b = end;
|
||||
}
|
||||
|
||||
static void reader_current_job_or_process_extent( wchar_t **a,
|
||||
@@ -2383,14 +2390,12 @@ static int read_i()
|
||||
*/
|
||||
static int can_read( int fd )
|
||||
{
|
||||
struct pollfd pfd[] =
|
||||
{
|
||||
{
|
||||
fd, POLLIN, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
return poll( pfd, 1, 0 ) == 1;
|
||||
struct timeval can_read_timeout = { 0, 0 };
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
return select(fd + 1, &fds, 0, 0, &can_read_timeout) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
25
set_color.c
25
set_color.c
@@ -96,16 +96,25 @@ int translate_color( char *str )
|
||||
|
||||
}
|
||||
|
||||
void print_colors()
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<COLORS; i++ )
|
||||
{
|
||||
printf( "%s\n", col[i] );
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
char *bgcolor=0;
|
||||
char *fgcolor=0;
|
||||
int fg, bg;
|
||||
int bold=0;
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
@@ -125,6 +134,10 @@ int main( int argc, char **argv )
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
"print-colors", no_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
@@ -135,13 +148,13 @@ int main( int argc, char **argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"b:hvo",
|
||||
"b:hvoc",
|
||||
long_options,
|
||||
&opt_index );
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"b:hvo" );
|
||||
"b:hvoc" );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -166,6 +179,10 @@ int main( int argc, char **argv )
|
||||
fprintf( stderr, "set_color, version %s\n", PACKAGE_VERSION );
|
||||
exit( 0 );
|
||||
|
||||
case 'c':
|
||||
print_colors();
|
||||
exit(0);
|
||||
|
||||
case '?':
|
||||
return 1;
|
||||
|
||||
|
||||
2
signal.c
2
signal.c
@@ -500,5 +500,3 @@ void signal_unblock()
|
||||
|
||||
sigprocmask(SIG_UNBLOCK, &chldset, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ int main( int argc, char **argv )
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
|
||||
21
tokenizer.c
21
tokenizer.c
@@ -46,7 +46,7 @@
|
||||
/**
|
||||
Characters that separate tokens. They are ordered by frequency of occurrence to increase parsing speed.
|
||||
*/
|
||||
#define SEP L" \n;|#\t\r<>^&"
|
||||
#define SEP L" \n|\t;#\r<>^&"
|
||||
/**
|
||||
Tests if the tokenizer buffer is large enough to hold contents of
|
||||
the specified length, and if not, reallocates the tokenizer buffer.
|
||||
@@ -192,8 +192,18 @@ static int is_string_char( wchar_t c )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
/**
|
||||
Quick test to catch the most common 'non-magical' characters, makes
|
||||
read_string slightly faster by adding a fast path for the most
|
||||
common characters. This is obviously not a suitable replacement for
|
||||
iswalpha.
|
||||
*/
|
||||
static int myal( wchar_t c )
|
||||
{
|
||||
return (c>=L'a' && c<=L'z') || (c>=L'A'&&c<=L'Z');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,6 +222,11 @@ static void read_string( tokenizer *tok )
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
|
||||
if( !myal( *tok->buff ) )
|
||||
{
|
||||
// debug(1, L"%lc", *tok->buff );
|
||||
|
||||
if( *tok->buff == L'\\' )
|
||||
{
|
||||
tok->buff++;
|
||||
@@ -338,6 +353,8 @@ static void read_string( tokenizer *tok )
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !do_loop )
|
||||
break;
|
||||
|
||||
57
util.c
57
util.c
@@ -27,11 +27,16 @@
|
||||
#include "wutil.h"
|
||||
|
||||
/**
|
||||
Minimum allocated size for data structures. Used to avoid excessive
|
||||
memory allocations for lists, hash tables, etc, which are nearly
|
||||
empty.
|
||||
Minimum allocated size for data structures. Used to avoid excessive
|
||||
memory allocations for lists, hash tables, etc, which are nearly
|
||||
empty.
|
||||
*/
|
||||
#define MIN_SIZE 128
|
||||
#define MIN_SIZE 32
|
||||
|
||||
/**
|
||||
Minimum size for hash tables
|
||||
*/
|
||||
#define HASH_MIN_SIZE 7
|
||||
|
||||
/**
|
||||
Maximum number of characters that can be inserted using a single
|
||||
@@ -191,7 +196,11 @@ void hash_init( hash_table_t *h,
|
||||
int (*hash_func)(const void *key),
|
||||
int (*compare_func)(const void *key1, const void *key2) )
|
||||
{
|
||||
hash_init2( h, hash_func, compare_func, 31 );
|
||||
h->arr = 0;
|
||||
h->size = 0;
|
||||
h->count=0;
|
||||
h->hash_func = hash_func;
|
||||
h->compare_func = compare_func;
|
||||
}
|
||||
|
||||
|
||||
@@ -207,8 +216,11 @@ void hash_destroy( hash_table_t *h )
|
||||
static int hash_search( hash_table_t *h,
|
||||
const void *key )
|
||||
{
|
||||
int hv = h->hash_func( key );
|
||||
int pos = abs(hv) % h->size;
|
||||
int hv;
|
||||
int pos;
|
||||
|
||||
hv = h->hash_func( key );
|
||||
pos = abs(hv) % h->size;
|
||||
while(1)
|
||||
{
|
||||
if( (h->arr[pos].key == 0 ) ||
|
||||
@@ -229,13 +241,13 @@ static int hash_realloc( hash_table_t *h,
|
||||
{
|
||||
|
||||
/* Avoid reallocating when using pathetically small tables */
|
||||
if( ( sz < h->size ) && (h->size < MIN_SIZE))
|
||||
if( ( sz < h->size ) && (h->size < HASH_MIN_SIZE))
|
||||
return 1;
|
||||
sz = maxi( sz, MIN_SIZE );
|
||||
|
||||
sz = maxi( sz, HASH_MIN_SIZE );
|
||||
|
||||
hash_struct_t *old_arr = h->arr;
|
||||
int old_size = h->size;
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
h->arr = malloc( sizeof( hash_struct_t) * sz );
|
||||
@@ -294,7 +306,10 @@ int hash_put( hash_table_t *h,
|
||||
const void *hash_get( hash_table_t *h,
|
||||
const void *key )
|
||||
{
|
||||
int pos = hash_search( h, key );
|
||||
if( !h->count )
|
||||
return 0;
|
||||
|
||||
int pos = hash_search( h, key );
|
||||
if( h->arr[pos].key == 0 )
|
||||
return 0;
|
||||
else
|
||||
@@ -303,7 +318,10 @@ const void *hash_get( hash_table_t *h,
|
||||
|
||||
const void *hash_get_key( hash_table_t *h,
|
||||
const void *key )
|
||||
{
|
||||
{
|
||||
if( !h->count )
|
||||
return 0;
|
||||
|
||||
int pos = hash_search( h, key );
|
||||
if( h->arr[pos].key == 0 )
|
||||
return 0;
|
||||
@@ -321,6 +339,16 @@ void hash_remove( hash_table_t *h,
|
||||
const void **old_key,
|
||||
const void **old_val )
|
||||
{
|
||||
if( !h->count )
|
||||
{
|
||||
|
||||
if( old_key != 0 )
|
||||
*old_key = 0;
|
||||
if( old_val != 0 )
|
||||
*old_val = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = hash_search( h, key );
|
||||
int next_pos;
|
||||
|
||||
@@ -377,6 +405,9 @@ void hash_remove( hash_table_t *h,
|
||||
int hash_contains( hash_table_t *h,
|
||||
const void *key )
|
||||
{
|
||||
if( !h->count )
|
||||
return 0;
|
||||
|
||||
int pos = hash_search( h, key );
|
||||
return h->arr[pos].key != 0;
|
||||
}
|
||||
|
||||
77
util.h
77
util.h
@@ -136,14 +136,17 @@ typedef buffer_t string_buffer_t;
|
||||
Returns the larger of two ints
|
||||
*/
|
||||
int maxi( int a, int b );
|
||||
|
||||
/**
|
||||
Returns the smaller of two ints
|
||||
*/
|
||||
int mini( int a, int b );
|
||||
|
||||
/**
|
||||
Returns the larger of two floats
|
||||
*/
|
||||
float maxf( float a, float b );
|
||||
|
||||
/**
|
||||
Returns the smaller of two floats
|
||||
*/
|
||||
@@ -161,14 +164,19 @@ float minf( float a, float b );
|
||||
returned.
|
||||
*/
|
||||
void q_init( dyn_queue_t *q );
|
||||
|
||||
/** Destroy the queue */
|
||||
void q_destroy( dyn_queue_t *q );
|
||||
|
||||
/** Insert element into queue */
|
||||
int q_put( dyn_queue_t *q, void *e );
|
||||
|
||||
/** Remove and return next element from queue */
|
||||
void *q_get( dyn_queue_t *q);
|
||||
|
||||
/** Return next element from queue without removing it */
|
||||
void *q_peek( dyn_queue_t *q);
|
||||
|
||||
/** Returns 1 if the queue is empty, 0 otherwise */
|
||||
int q_empty( dyn_queue_t *q );
|
||||
|
||||
@@ -224,6 +232,7 @@ void hash_remove( hash_table_t *h,
|
||||
const void *key,
|
||||
const void **old_key,
|
||||
const void **old_data );
|
||||
|
||||
/**
|
||||
Checks whether the specified key is in the hash table
|
||||
*/
|
||||
@@ -235,16 +244,23 @@ int hash_contains( hash_table_t *h,
|
||||
*/
|
||||
void hash_get_keys( hash_table_t *h,
|
||||
array_list_t *arr );
|
||||
|
||||
/**
|
||||
Appends all data elements in the table to the specified list
|
||||
*/
|
||||
void hash_get_data( hash_table_t *h,
|
||||
array_list_t *arr );
|
||||
/** Call the function func for each key/data pair in the table*/
|
||||
|
||||
/**
|
||||
Call the function func for each key/data pair in the table
|
||||
*/
|
||||
void hash_foreach( hash_table_t *h,
|
||||
void (*func)( const void *, const void * ) );
|
||||
/** Same as hash_foreach, but the function func takes an additional
|
||||
* argument, which is provided by the caller in the variable aux */
|
||||
|
||||
/**
|
||||
Same as hash_foreach, but the function func takes an additional
|
||||
argument, which is provided by the caller in the variable aux
|
||||
*/
|
||||
void hash_foreach2( hash_table_t *h, void (*func)( const void *,
|
||||
const void *,
|
||||
void *),
|
||||
@@ -269,10 +285,11 @@ int hash_wcs_func( const void *data );
|
||||
*/
|
||||
int hash_wcs_cmp( const void *a, const void *b );
|
||||
|
||||
/** Initialize the priority queue
|
||||
|
||||
\param q the queue to initialize
|
||||
\param compare a comparison function that can compare two entries in the queue
|
||||
/**
|
||||
Initialize the priority queue
|
||||
|
||||
\param q the queue to initialize
|
||||
\param compare a comparison function that can compare two entries in the queue
|
||||
*/
|
||||
void pq_init( priority_queue_t *q,
|
||||
int (*compare)(void *e1, void *e2) );
|
||||
@@ -289,6 +306,7 @@ int pq_put( priority_queue_t *q,
|
||||
Removes and returns the last entry in the priority queue
|
||||
*/
|
||||
void *pq_get( priority_queue_t *q );
|
||||
|
||||
/**
|
||||
Returns the last entry in the priority queue witout removing it.
|
||||
*/
|
||||
@@ -314,10 +332,16 @@ void pq_destroy( priority_queue_t *q );
|
||||
*/
|
||||
array_list_t *al_new();
|
||||
|
||||
/** Initialize the list. */
|
||||
/**
|
||||
Initialize the list.
|
||||
*/
|
||||
void al_init( array_list_t *l );
|
||||
/** Destroy the list and free memory used by it.*/
|
||||
|
||||
/**
|
||||
Destroy the list and free memory used by it.
|
||||
*/
|
||||
void al_destroy( array_list_t *l );
|
||||
|
||||
/**
|
||||
Append element to list
|
||||
|
||||
@@ -327,6 +351,7 @@ void al_destroy( array_list_t *l );
|
||||
\return 1 if succesfull, 0 otherwise
|
||||
*/
|
||||
int al_push( array_list_t *l, const void *o );
|
||||
|
||||
/**
|
||||
Append all elements of a list to another
|
||||
|
||||
@@ -335,6 +360,7 @@ int al_push( array_list_t *l, const void *o );
|
||||
\return 1 if succesfull, 0 otherwise
|
||||
*/
|
||||
int al_push_all( array_list_t *a, array_list_t *b );
|
||||
|
||||
/**
|
||||
Sets the element at the specified index
|
||||
|
||||
@@ -343,6 +369,7 @@ int al_push_all( array_list_t *a, array_list_t *b );
|
||||
\param o The element
|
||||
*/
|
||||
int al_set( array_list_t *l, int pos, const void *o );
|
||||
|
||||
/**
|
||||
Returns the element at the specified index
|
||||
|
||||
@@ -351,26 +378,37 @@ int al_set( array_list_t *l, int pos, const void *o );
|
||||
\return The element
|
||||
*/
|
||||
const void *al_get( array_list_t *l, int pos );
|
||||
|
||||
/**
|
||||
Truncates the list to new_sz items.
|
||||
*/
|
||||
void al_truncate( array_list_t *l, int new_sz );
|
||||
|
||||
/**
|
||||
Removes and returns the last entry in the list
|
||||
*/
|
||||
const void *al_pop( array_list_t *l );
|
||||
|
||||
/**
|
||||
Returns the number of elements in the list
|
||||
*/
|
||||
int al_get_count( array_list_t *l );
|
||||
|
||||
/**
|
||||
Returns the last entry in the list witout removing it.
|
||||
*/
|
||||
const void *al_peek( array_list_t *l );
|
||||
/** Returns 1 if the list is empty, 0 otherwise*/
|
||||
|
||||
/**
|
||||
Returns 1 if the list is empty, 0 otherwise
|
||||
*/
|
||||
int al_empty( array_list_t *l);
|
||||
/** Call the function func for each entry in the list*/
|
||||
|
||||
/**
|
||||
Call the function func for each entry in the list
|
||||
*/
|
||||
void al_foreach( array_list_t *l, void (*func)(const void * ));
|
||||
|
||||
/**
|
||||
Same as al_foreach, but the function func takes an additional
|
||||
argument, which is provided by the caller in the variable aux
|
||||
@@ -400,7 +438,9 @@ void al_foreach2( array_list_t *l, void (*func)(const void *, void *), void *aux
|
||||
|
||||
Which most people would find more intuitive.
|
||||
|
||||
The system breaks down if the user is using numbers of a base larger than 10.
|
||||
This won't return the optimum results for numbers in bases higher
|
||||
than ten, such as hexadecimal, but at least a stable sort order
|
||||
will result.
|
||||
*/
|
||||
int wcsfilecmp( const wchar_t *a, const wchar_t *b );
|
||||
|
||||
@@ -432,19 +472,21 @@ void sb_append_char( string_buffer_t *, wchar_t );
|
||||
Append a null terminated list of strings to the buffer.
|
||||
Example:
|
||||
|
||||
sb_append2( my_buff, L"foo", L"bar", 0 );
|
||||
sb_append2( my_buff, L"foo", L"bar", (void *)0 );
|
||||
|
||||
Do not forget to cast the last 0 to (void *), or you might encounter errors on 64-bit platforms!
|
||||
*/
|
||||
void sb_append2( string_buffer_t *, ... );
|
||||
|
||||
/**
|
||||
Append formated string data to the buffer. This function internally
|
||||
relies on \c vswprintf, so any filter options supported by that
|
||||
function is also supported by this function
|
||||
function is also supported by this function.
|
||||
*/
|
||||
int sb_printf( string_buffer_t *buffer, const wchar_t *format, ... );
|
||||
|
||||
/**
|
||||
Vararg version of sb_printf
|
||||
Vararg version of sb_printf.
|
||||
*/
|
||||
int sb_vprintf( string_buffer_t *buffer, const wchar_t *format, va_list va_orig );
|
||||
|
||||
@@ -454,15 +496,16 @@ int sb_vprintf( string_buffer_t *buffer, const wchar_t *format, va_list va_orig
|
||||
void sb_destroy( string_buffer_t * );
|
||||
|
||||
/**
|
||||
Truncate the buffer.
|
||||
Truncate the buffer. This will not deallocate the memory used, it will only set the contents of the string to L"\0".
|
||||
*/
|
||||
void sb_clear( string_buffer_t * );
|
||||
|
||||
|
||||
/**
|
||||
Initialize the specified buffer_t
|
||||
*/
|
||||
*/
|
||||
void b_init( buffer_t *b);
|
||||
|
||||
/**
|
||||
Destroy the specified buffer_t
|
||||
*/
|
||||
|
||||
19
wgetopt.c
19
wgetopt.c
@@ -1,3 +1,22 @@
|
||||
/** \file wgetopt.c
|
||||
A version of the getopt library for use with wide character strings.
|
||||
|
||||
This is simply the gnu getopt library, but converted for use with
|
||||
wchar_t instead of char. This is not usually useful since the argv
|
||||
array is always defined to be of type char**, but in fish, all
|
||||
internal commands use wide characters and hence this library is
|
||||
useful.
|
||||
|
||||
If you want to use this version of getopt in your program, simply
|
||||
copy wgetopt.c and wgetopt.h into your program, include wgetopt.h,
|
||||
and use all the regular getopt functions, prefixing every
|
||||
function, global variable and structure with a 'w', and use only
|
||||
wide character strings. There are no other functional changes in
|
||||
this version of getopt besides using wide character strings.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Getopt for GNU.
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
|
||||
|
||||
85
wgetopt.h
85
wgetopt.h
@@ -1,7 +1,19 @@
|
||||
/** \file wgetopt.h
|
||||
The getopt librar for wide character strings.
|
||||
A version of the getopt library for use with wide character strings.
|
||||
|
||||
This is simply the gnu getopt library, but converted for use with
|
||||
wchar_t instead of char. This is not usually useful since the argv
|
||||
array is always defined to be of type char**, but in fish, all
|
||||
internal commands use wide characters and hence this library is
|
||||
useful.
|
||||
|
||||
If you want to use this version of getopt in your program, simply
|
||||
copy wgetopt.c and wgetopt.h into your program, include wgetopt.h,
|
||||
and use all the regular getopt functions, prefixing every
|
||||
function, global variable and structure with a 'w', and use only
|
||||
wide character strings. There are no other functional changes in
|
||||
this version of getopt besides using wide character strings.
|
||||
|
||||
This is simply the gnu getopt library, but converted for use with wchar_t instead of char. This is not usually useful since the argv array is always defined to be of type char**, but in fish, all internal commands use wide characters and hence this library is usefull.
|
||||
*/
|
||||
|
||||
|
||||
@@ -52,7 +64,7 @@ extern wchar_t *woptarg;
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
Otherwise, `woptind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int woptind;
|
||||
@@ -89,54 +101,99 @@ extern int woptopt;
|
||||
|
||||
struct woption
|
||||
{
|
||||
/**
|
||||
long name for switch
|
||||
*/
|
||||
#if defined (__STDC__) && __STDC__
|
||||
const wchar_t *name;
|
||||
#else
|
||||
wchar_t *name;
|
||||
#endif
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
/**
|
||||
Must be one of no_argument, required_argument and
|
||||
optional_argument.
|
||||
|
||||
has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int.
|
||||
*/
|
||||
int has_arg;
|
||||
|
||||
/**
|
||||
If non-null, the flag whose value should be set if this switch is encountered
|
||||
*/
|
||||
int *flag;
|
||||
|
||||
/**
|
||||
If \c flag is non-null, this is the value that flag will be set
|
||||
to. Otherwise, this is the return-value of the function call.
|
||||
*/
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
/**
|
||||
Specifies that a switch does not accept an argument
|
||||
*/
|
||||
#define no_argument 0
|
||||
/**
|
||||
Specifies that a switch requires an argument
|
||||
*/
|
||||
#define required_argument 1
|
||||
/**
|
||||
Specifies that a switch accepts an optional argument
|
||||
*/
|
||||
#define optional_argument 2
|
||||
|
||||
#if defined (__STDC__) && __STDC__
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Get options from argument list */
|
||||
/**
|
||||
Get options from argument list. See the glibc manual for information on how to use this function.
|
||||
*/
|
||||
extern int wgetopt (int argc, wchar_t *const *argv, const wchar_t *shortopts);
|
||||
#else /* not __GNU_LIBRARY__ */
|
||||
/* Get options from argument list */
|
||||
|
||||
extern int wgetopt ();
|
||||
#endif /* __GNU_LIBRARY__ */
|
||||
/* Get options from argument list */
|
||||
/**
|
||||
Get options from argument list. See the glibc manual for information on how to use this function.
|
||||
*/
|
||||
extern int wgetopt_long (int argc, wchar_t *const *argv, const wchar_t *shortopts,
|
||||
const struct woption *longopts, int *longind);
|
||||
/* Get options from argument list */
|
||||
/**
|
||||
Get options from argument list. See the glibc manual for information on how to use this function.
|
||||
*/
|
||||
extern int wgetopt_long_only (int argc, wchar_t *const *argv,
|
||||
const wchar_t *shortopts,
|
||||
const struct woption *longopts, int *longind);
|
||||
|
||||
/** Internal only. Users should not call this directly. */
|
||||
/**
|
||||
Internal only. Users should not call this directly.
|
||||
*/
|
||||
extern int _wgetopt_internal (int argc, wchar_t *const *argv,
|
||||
const wchar_t *shortopts,
|
||||
const struct woption *longopts, int *longind,
|
||||
int long_only);
|
||||
#else /* not __STDC__ */
|
||||
/* Get options from argument list */
|
||||
|
||||
/**
|
||||
Get options from argument list. See the glibc manual for information on how to use this function.
|
||||
*/
|
||||
extern int wgetopt ();
|
||||
/* Get options from argument list */
|
||||
|
||||
/**
|
||||
Get options from argument list. See the glibc manual for information on how to use this function.
|
||||
*/
|
||||
extern int wgetopt_long ();
|
||||
/* Get options from argument list */
|
||||
|
||||
/**
|
||||
Get options from argument list. See the glibc manual for information on how to use this function.
|
||||
*/
|
||||
extern int wgetopt_long_only ();
|
||||
|
||||
/* Get options from argument list */
|
||||
/**
|
||||
Internal only. Users should not call this directly.
|
||||
*/
|
||||
extern int _wgetopt_internal ();
|
||||
#endif /* __STDC__ */
|
||||
|
||||
|
||||
327
wildcard.c
327
wildcard.c
@@ -1,6 +1,8 @@
|
||||
/** \file wildcard.c
|
||||
My own globbing implementation. Needed to implement this to
|
||||
support tab-expansion of globbed parameters.
|
||||
|
||||
Fish needs it's own globbing implementation to support
|
||||
tab-expansion of globbed parameters. Also provides recursive
|
||||
wildcards using **.
|
||||
|
||||
*/
|
||||
|
||||
@@ -25,6 +27,19 @@
|
||||
#include "reader.h"
|
||||
#include "expand.h"
|
||||
|
||||
/**
|
||||
This flag is set in the flags parameter of wildcard_expand if the
|
||||
call is part of a recursiv wildcard search. It is used to make sure
|
||||
that the contents of subdirectories are only searched once.
|
||||
*/
|
||||
#define WILDCARD_RECURSIVE 64
|
||||
|
||||
/**
|
||||
The maximum length of a filename token. This is a fallback value,
|
||||
an attempt to find the true value using patchconf is always made.
|
||||
*/
|
||||
#define MAX_FILE_LENGTH 1024
|
||||
|
||||
int wildcard_has( const wchar_t *str, int internal )
|
||||
{
|
||||
wchar_t prev=0;
|
||||
@@ -72,7 +87,9 @@ static int wildcard_match2( const wchar_t *str,
|
||||
{
|
||||
/* Ignore hidden file */
|
||||
if( is_first && *str == L'.' )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try all submatches */
|
||||
do
|
||||
@@ -83,8 +100,16 @@ static int wildcard_match2( const wchar_t *str,
|
||||
while( *(str++) != 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( *wc == ANY_CHAR )
|
||||
{
|
||||
if( is_first && *str == L'.' )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return wildcard_match2( str+1, wc+1, 0 );
|
||||
}
|
||||
|
||||
if( *wc == *str )
|
||||
return wildcard_match2( str+1, wc+1, 0 );
|
||||
@@ -205,15 +230,13 @@ static wchar_t *make_path( const wchar_t *base_dir, const wchar_t *name )
|
||||
int base_len = wcslen( base_dir );
|
||||
if( !(long_name= malloc( sizeof(wchar_t)*(base_len+wcslen(name)+1) )))
|
||||
{
|
||||
|
||||
return 0;
|
||||
die_mem();
|
||||
}
|
||||
wcscpy( long_name, base_dir );
|
||||
wcscpy(&long_name[base_len], name );
|
||||
return long_name;
|
||||
}
|
||||
|
||||
|
||||
void get_desc( wchar_t *fn, string_buffer_t *sb, int is_cmd )
|
||||
{
|
||||
const wchar_t *desc;
|
||||
@@ -282,6 +305,11 @@ void get_desc( wchar_t *fn, string_buffer_t *sb, int is_cmd )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Test if the file specified by the given filename matches the
|
||||
expantion flags specified. flags can be a combination of
|
||||
EXECUTABLES_ONLY and DIRECTORIES_ONLY.
|
||||
*/
|
||||
static int test_flags( wchar_t *filename,
|
||||
int flags )
|
||||
{
|
||||
@@ -306,11 +334,37 @@ int wildcard_expand( const wchar_t *wc,
|
||||
int flags,
|
||||
array_list_t *out )
|
||||
{
|
||||
|
||||
/* Points to the end of the current wildcard segment */
|
||||
wchar_t *wc_end;
|
||||
|
||||
/* Variables for traversing a directory */
|
||||
struct dirent *next;
|
||||
DIR *dir;
|
||||
|
||||
/* The result returned */
|
||||
int res = 0;
|
||||
|
||||
/* Length of the directory to search in */
|
||||
int base_len;
|
||||
|
||||
/* Variables for testing for presense of recursive wildcards */
|
||||
wchar_t *wc_recursive;
|
||||
int is_recursive;
|
||||
|
||||
/* Sligtly mangled version of base_dir */
|
||||
const wchar_t *dir_string;
|
||||
|
||||
/* Description for completions */
|
||||
string_buffer_t sb_desc;
|
||||
|
||||
// debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
/* Avoid excessive number of returned matches for wc ending with a * */
|
||||
/*
|
||||
Avoid excessive number of returned matches for wc ending with a *
|
||||
*/
|
||||
int len = wcslen(wc);
|
||||
if( len && (wc[len-1]==ANY_STRING) )
|
||||
{
|
||||
@@ -321,50 +375,58 @@ int wildcard_expand( const wchar_t *wc,
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
struct dirent *next;
|
||||
wchar_t *wc_end = wcschr(wc,L'/');
|
||||
DIR *dir;
|
||||
|
||||
int res = 0;
|
||||
int base_len = wcslen( base_dir );
|
||||
|
||||
wchar_t *wc_recursive = wcschr( wc, ANY_STRING_RECURSIVE );
|
||||
int is_recursive = is_recursive = ( wc_recursive && (!wc_end || wc_recursive < wc_end));
|
||||
/*
|
||||
Initialize various variables
|
||||
*/
|
||||
|
||||
const wchar_t *dir_string = base_dir[0]==L'\0'?L".":base_dir;
|
||||
|
||||
string_buffer_t sb_desc;
|
||||
|
||||
sb_init( &sb_desc );
|
||||
// if( accept_incomplete )
|
||||
// wprintf( L"Glob %ls in '%ls'\n", wc, base_dir );//[0]==L'\0'?L".":base_dir );
|
||||
|
||||
/*
|
||||
Test for recursive match string in current segment
|
||||
*/
|
||||
dir_string = base_dir[0]==L'\0'?L".":base_dir;
|
||||
|
||||
if( !(dir = wopendir( dir_string )))
|
||||
{
|
||||
// if( errno != EACCES && errno != ENOENT )
|
||||
// wperror( L"opendir" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Is this segment of the wildcard the last?
|
||||
*/
|
||||
if( wc_end == 0 )
|
||||
wc_end = wcschr(wc,L'/');
|
||||
base_len = wcslen( base_dir );
|
||||
|
||||
/*
|
||||
Test for recursive match string in current segment
|
||||
*/
|
||||
wc_recursive = wcschr( wc, ANY_STRING_RECURSIVE );
|
||||
is_recursive = ( wc_recursive && (!wc_end || wc_recursive < wc_end));
|
||||
|
||||
/*
|
||||
This makes sure that the base
|
||||
directory of the recursive search is
|
||||
also searched for matching files.
|
||||
*/
|
||||
if( is_recursive && (wc_end==(wc+1)) && !(flags & WILDCARD_RECURSIVE ) )
|
||||
{
|
||||
wildcard_expand( wc_end + 1,
|
||||
base_dir,
|
||||
flags,
|
||||
out );
|
||||
}
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
sb_init( &sb_desc );
|
||||
|
||||
/*
|
||||
Is this segment of the wildcard the last?
|
||||
*/
|
||||
if( !wc_end && !is_recursive )
|
||||
{
|
||||
/*
|
||||
Wildcard segment is the last segment
|
||||
Wildcard segment is the last segment,
|
||||
|
||||
Insert all matching files/directories
|
||||
*/
|
||||
if( wc[0]=='\0' )
|
||||
{
|
||||
/*
|
||||
The last wildcard segment is empty. Insert everything if completing, the directory itself otherwise.
|
||||
The last wildcard segment is empty. Insert everything if
|
||||
completing, the directory itself otherwise.
|
||||
*/
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
@@ -375,20 +437,10 @@ int wildcard_expand( const wchar_t *wc,
|
||||
wchar_t *name = str2wcs(next->d_name);
|
||||
if( name == 0 )
|
||||
{
|
||||
/* closedir( dir );*/
|
||||
/* return -1; */
|
||||
continue;
|
||||
}
|
||||
wchar_t *long_name = make_path( base_dir, name );
|
||||
|
||||
if( long_name == 0 )
|
||||
{
|
||||
wperror( L"malloc" );
|
||||
closedir( dir );
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( test_flags( long_name, flags ) )
|
||||
{
|
||||
get_desc( long_name,
|
||||
@@ -407,7 +459,7 @@ int wildcard_expand( const wchar_t *wc,
|
||||
else
|
||||
{
|
||||
res = 1;
|
||||
al_push( out, wcsdup( base_dir ) );
|
||||
al_push_check( out, wcsdup( base_dir ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -423,22 +475,13 @@ int wildcard_expand( const wchar_t *wc,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* wprintf( L"Filen heter %s\n\n\n", next->d_name );*/
|
||||
/* wprintf( L"Match %ls (%s) against %ls\n\n\n", name, "tjo", wc );*/
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
/* wprintf( L"match %ls to %ls\n", name, wc );*/
|
||||
|
||||
wchar_t *long_name = make_path( base_dir, name );
|
||||
if( long_name == 0 )
|
||||
{
|
||||
wperror( L"malloc" );
|
||||
closedir( dir );
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Test for matches before stating file, so as to minimize the number of stat calls
|
||||
Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
|
||||
*/
|
||||
if( wildcard_complete( name,
|
||||
wc,
|
||||
@@ -446,8 +489,6 @@ int wildcard_expand( const wchar_t *wc,
|
||||
0,
|
||||
0 ) )
|
||||
{
|
||||
|
||||
|
||||
if( test_flags( long_name, flags ) )
|
||||
{
|
||||
get_desc( long_name,
|
||||
@@ -470,15 +511,8 @@ int wildcard_expand( const wchar_t *wc,
|
||||
if( wildcard_match2( name, wc, 1 ) )
|
||||
{
|
||||
wchar_t *long_name = make_path( base_dir, name );
|
||||
if( long_name == 0 )
|
||||
{
|
||||
wperror( L"malloc" );
|
||||
closedir( dir );
|
||||
free(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
al_push( out, long_name );
|
||||
al_push_check( out, long_name );
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
@@ -489,34 +523,52 @@ int wildcard_expand( const wchar_t *wc,
|
||||
else
|
||||
{
|
||||
/*
|
||||
Wilcard segment is not the last segment.
|
||||
Recursively call wildcard_expand for all matching subdirectories.
|
||||
Wilcard segment is not the last segment. Recursively call
|
||||
wildcard_expand for all matching subdirectories.
|
||||
*/
|
||||
|
||||
/*
|
||||
wc_str is the part of the wildcarded string from the
|
||||
beginning to the first slash
|
||||
*/
|
||||
wchar_t *wc_str;
|
||||
|
||||
/*
|
||||
new_dir is a scratch area containing the full path to a
|
||||
file/directory we are iterating over
|
||||
*/
|
||||
wchar_t *new_dir;
|
||||
static size_t ln=1024;
|
||||
|
||||
/*
|
||||
The maximum length of a file element
|
||||
*/
|
||||
static size_t ln=MAX_FILE_LENGTH;
|
||||
char * narrow_dir_string = wcs2str( dir_string );
|
||||
|
||||
if( narrow_dir_string )
|
||||
{
|
||||
ln = pathconf( narrow_dir_string, _PC_NAME_MAX ); /* Find out how long the filename can be in a worst case scenario */
|
||||
/*
|
||||
Find out how long the filename can be in a worst case
|
||||
scenario
|
||||
*/
|
||||
ln = pathconf( narrow_dir_string, _PC_NAME_MAX );
|
||||
|
||||
/*
|
||||
If not specified, use som large number as fallback
|
||||
*/
|
||||
if( ln < 0 )
|
||||
ln = 1024;
|
||||
ln = MAX_FILE_LENGTH;
|
||||
free( narrow_dir_string );
|
||||
}
|
||||
new_dir= malloc( sizeof(wchar_t)*(base_len+ln+2) );
|
||||
|
||||
wc_str = wcsndup(wc, wc_end-wc);
|
||||
wc_str = wc_end?wcsndup(wc, wc_end-wc):wcsdup(wc);
|
||||
|
||||
if( (!new_dir) || (!wc_str) )
|
||||
{
|
||||
if( new_dir )
|
||||
free( new_dir );
|
||||
if( wc_str )
|
||||
free( wc_str );
|
||||
wperror( L"malloc" );
|
||||
closedir( dir );
|
||||
return 0;
|
||||
die_mem();
|
||||
}
|
||||
|
||||
wcscpy( new_dir, base_dir );
|
||||
|
||||
while( (next=readdir(dir))!=0 )
|
||||
@@ -526,56 +578,103 @@ int wildcard_expand( const wchar_t *wc,
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
Test if the file/directory name matches the whole
|
||||
wildcard element, i.e. regular matching.
|
||||
*/
|
||||
int whole_match = wildcard_match2( name, wc_str, 1 );
|
||||
int partial_match = 0;
|
||||
|
||||
if( wildcard_match2( name, wc_str, 1 ) )
|
||||
/*
|
||||
If we are doing recursive matching, also check if this
|
||||
directory matches the part up to the recusrive
|
||||
wildcard, if so, then we can search all subdirectories
|
||||
for matches.
|
||||
*/
|
||||
if( is_recursive )
|
||||
{
|
||||
wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE );
|
||||
wchar_t *wc_sub = wcsndup( wc, end-wc+1);
|
||||
partial_match = wildcard_match2( name, wc_sub, 1 );
|
||||
free( wc_sub );
|
||||
}
|
||||
|
||||
if( whole_match || partial_match )
|
||||
{
|
||||
int new_len;
|
||||
struct stat buf;
|
||||
wcscpy(&new_dir[base_len], name );
|
||||
free(name);
|
||||
char *dir_str = wcs2str( new_dir );
|
||||
char *dir_str;
|
||||
int stat_res;
|
||||
|
||||
if( !dir_str )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
stat_res= stat( dir_str, &buf );
|
||||
free( dir_str );
|
||||
|
||||
if( stat_res )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( buf.st_mode & S_IFDIR )
|
||||
wcscpy(&new_dir[base_len], name );
|
||||
dir_str = wcs2str( new_dir );
|
||||
|
||||
if( dir_str )
|
||||
{
|
||||
new_len = wcslen( new_dir );
|
||||
new_dir[new_len] = L'/';
|
||||
new_dir[new_len+1] = L'\0';
|
||||
switch( wildcard_expand( wc_end + 1, new_dir, flags, out ) )
|
||||
stat_res = stat( dir_str, &buf );
|
||||
free( dir_str );
|
||||
|
||||
if( !stat_res )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
res = 1;
|
||||
break;
|
||||
if( buf.st_mode & S_IFDIR )
|
||||
{
|
||||
new_len = wcslen( new_dir );
|
||||
new_dir[new_len] = L'/';
|
||||
new_dir[new_len+1] = L'\0';
|
||||
|
||||
/*
|
||||
Regular matching
|
||||
*/
|
||||
if( whole_match )
|
||||
{
|
||||
res |= wildcard_expand( wc_end?wc_end + 1:L"",
|
||||
new_dir,
|
||||
flags,
|
||||
out );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Recursive matching
|
||||
*/
|
||||
if( partial_match )
|
||||
{
|
||||
res |= wildcard_expand( wcschr( wc, ANY_STRING_RECURSIVE ),
|
||||
new_dir,
|
||||
flags | WILDCARD_RECURSIVE,
|
||||
out );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
|
||||
free( wc_str );
|
||||
free( new_dir );
|
||||
}
|
||||
closedir( dir );
|
||||
|
||||
sb_destroy( &sb_desc );
|
||||
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
sb_destroy( &sb_desc );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void al_push_check( array_list_t *l, const wchar_t *new )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < al_get_count(l); i++ )
|
||||
{
|
||||
if( !wcscmp( al_get(l, i), new ) )
|
||||
{
|
||||
free( new );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
al_push( l, new );
|
||||
}
|
||||
|
||||
12
wildcard.h
12
wildcard.h
@@ -8,6 +8,9 @@
|
||||
*/
|
||||
|
||||
#ifndef FISH_WILDCARD_H
|
||||
/**
|
||||
Header guard
|
||||
*/
|
||||
#define FISH_WILDCARD_H
|
||||
|
||||
#include <wchar.h>
|
||||
@@ -20,6 +23,9 @@
|
||||
|
||||
#define WILDCARD_RESERVED 0xf400
|
||||
|
||||
/**
|
||||
Enumeration of all wildcard types
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/** Character representing any character except '/' */
|
||||
@@ -87,4 +93,10 @@ int wildcard_complete( const wchar_t *str,
|
||||
const wchar_t *(*desc_func)(const wchar_t *),
|
||||
array_list_t *out );
|
||||
|
||||
/**
|
||||
Push string if not already in list
|
||||
*/
|
||||
void al_push_check( array_list_t *l, const wchar_t *str );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
40
wutil.c
40
wutil.c
@@ -22,28 +22,49 @@
|
||||
#include "common.h"
|
||||
#include "wutil.h"
|
||||
|
||||
#define TMP_LEN_MIN 256
|
||||
|
||||
/**
|
||||
Buffer for converting wide arguments to narrow arguments, used by
|
||||
the \c wutil_wcs2str() function.
|
||||
*/
|
||||
static char *tmp=0;
|
||||
/**
|
||||
Length of the \c tmp buffer.
|
||||
*/
|
||||
static size_t tmp_len=0;
|
||||
|
||||
int c = 0;
|
||||
/**
|
||||
Counts the number of calls to the wutil wrapper functions
|
||||
*/
|
||||
static int wutil_calls = 0;
|
||||
|
||||
void wutil_init()
|
||||
{
|
||||
}
|
||||
|
||||
void wutil_destroy()
|
||||
{
|
||||
free( tmp );
|
||||
tmp=0;
|
||||
tmp_len=0;
|
||||
debug( 3, L"wutil functions called %d times", c );
|
||||
debug( 3, L"wutil functions called %d times", wutil_calls );
|
||||
}
|
||||
|
||||
/**
|
||||
Convert the specified wide aharacter string to a narrow character
|
||||
string. This function uses an internal temporary buffer for storing
|
||||
the result so subsequent results will overwrite previous results.
|
||||
*/
|
||||
static char *wutil_wcs2str( const wchar_t *in )
|
||||
{
|
||||
c++;
|
||||
wutil_calls++;
|
||||
|
||||
size_t new_sz =MAX_UTF8_BYTES*wcslen(in)+1;
|
||||
if( tmp_len < new_sz )
|
||||
{
|
||||
free( tmp );
|
||||
tmp = malloc( new_sz );
|
||||
new_sz = maxi( new_sz, TMP_LEN_MIN );
|
||||
tmp = realloc( tmp, new_sz );
|
||||
if( !tmp )
|
||||
{
|
||||
die_mem();
|
||||
@@ -109,14 +130,17 @@ int wopen(const wchar_t *pathname, int flags, ...)
|
||||
|
||||
if( tmp )
|
||||
{
|
||||
va_start( argp, flags );
|
||||
|
||||
if( ! (flags & O_CREAT) )
|
||||
{
|
||||
res = open(tmp, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
va_start( argp, flags );
|
||||
res = open(tmp, flags, va_arg(argp, int) );
|
||||
|
||||
va_end( argp );
|
||||
va_end( argp );
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
Reference in New Issue
Block a user