mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-10 01:21:16 -03:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aa1ab540e | ||
|
|
27c9eb8758 | ||
|
|
e6b1035ddc | ||
|
|
9f6aba38d6 | ||
|
|
b52fe0feb6 | ||
|
|
db459f869a | ||
|
|
763a6b8351 | ||
|
|
4a06821d99 | ||
|
|
22f3dcfd35 | ||
|
|
dbb66e1895 | ||
|
|
5a7a264b96 | ||
|
|
3d601bd751 | ||
|
|
c9deea2237 | ||
|
|
32e54fd719 | ||
|
|
9ebdc16be6 | ||
|
|
92ecc01baa | ||
|
|
ff1c5e058f | ||
|
|
3d192a8e93 | ||
|
|
f5c6306bde | ||
|
|
524e0aa174 | ||
|
|
94abb30f94 | ||
|
|
af8e053896 | ||
|
|
633e2f498f | ||
|
|
4932538c74 | ||
|
|
786144ba86 | ||
|
|
e3dd94f272 | ||
|
|
b110a0ae21 | ||
|
|
48d9c38d1e | ||
|
|
51f8272ebd | ||
|
|
77f35c1b41 | ||
|
|
06668bfacb | ||
|
|
df59b8498f | ||
|
|
92fde30c0c | ||
|
|
d690a15b29 | ||
|
|
445f6539cf |
105
builtin.c
105
builtin.c
@@ -497,27 +497,24 @@ static int builtin_builtin( wchar_t **argv )
|
||||
if( list )
|
||||
{
|
||||
array_list_t names;
|
||||
wchar_t **names_arr;
|
||||
int i;
|
||||
|
||||
al_init( &names );
|
||||
builtin_get_names( &names );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
||||
sort_list( &names );
|
||||
|
||||
for( i=0; i<al_get_count( &names ); i++ )
|
||||
{
|
||||
if( wcscmp( names_arr[i], L"count" ) == 0 )
|
||||
wchar_t *el = (wchar_t *)al_get( &names, i );
|
||||
|
||||
if( wcscmp( el, L"count" ) == 0 )
|
||||
continue;
|
||||
|
||||
sb_append2( sb_out,
|
||||
names_arr[i],
|
||||
el,
|
||||
L"\n",
|
||||
(void *)0 );
|
||||
}
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
}
|
||||
return 0;
|
||||
@@ -677,7 +674,6 @@ static int builtin_functions( wchar_t **argv )
|
||||
wchar_t *desc=0;
|
||||
|
||||
array_list_t names;
|
||||
wchar_t **names_arr;
|
||||
|
||||
int argc=builtin_count_args( argv );
|
||||
int list=0;
|
||||
@@ -820,11 +816,7 @@ static int builtin_functions( wchar_t **argv )
|
||||
|
||||
al_init( &names );
|
||||
function_get_names( &names, show_hidden );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
||||
sort_list( &names );
|
||||
if( is_screen )
|
||||
{
|
||||
string_buffer_t buff;
|
||||
@@ -833,12 +825,12 @@ static int builtin_functions( wchar_t **argv )
|
||||
for( i=0; i<al_get_count( &names ); i++ )
|
||||
{
|
||||
sb_append2( &buff,
|
||||
names_arr[i],
|
||||
al_get(&names, i),
|
||||
L", ",
|
||||
(void *)0 );
|
||||
}
|
||||
|
||||
write_screen( (wchar_t *)buff.buff );
|
||||
write_screen( (wchar_t *)buff.buff, sb_out );
|
||||
sb_destroy( &buff );
|
||||
}
|
||||
else
|
||||
@@ -846,13 +838,12 @@ static int builtin_functions( wchar_t **argv )
|
||||
for( i=0; i<al_get_count( &names ); i++ )
|
||||
{
|
||||
sb_append2( sb_out,
|
||||
names_arr[i],
|
||||
al_get(&names, i),
|
||||
L"\n",
|
||||
(void *)0 );
|
||||
}
|
||||
}
|
||||
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
return 0;
|
||||
}
|
||||
@@ -865,16 +856,13 @@ static int builtin_functions( wchar_t **argv )
|
||||
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
|
||||
al_init( &names );
|
||||
function_get_names( &names, show_hidden );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
||||
sort_list( &names );
|
||||
|
||||
for( i=0; i<al_get_count( &names ); i++ )
|
||||
{
|
||||
functions_def( names_arr[i] );
|
||||
functions_def( (wchar_t *)al_get( &names, i ) );
|
||||
}
|
||||
free( names_arr );
|
||||
|
||||
al_destroy( &names );
|
||||
break;
|
||||
}
|
||||
@@ -1170,7 +1158,6 @@ static int builtin_function( wchar_t **argv )
|
||||
{
|
||||
int i;
|
||||
array_list_t names;
|
||||
wchar_t **names_arr;
|
||||
int chars=0;
|
||||
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
@@ -1180,14 +1167,11 @@ static int builtin_function( wchar_t **argv )
|
||||
|
||||
al_init( &names );
|
||||
function_get_names( &names, 0 );
|
||||
names_arr = list_to_char_arr( &names );
|
||||
qsort( names_arr,
|
||||
al_get_count( &names ),
|
||||
sizeof(wchar_t *),
|
||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
||||
sort_list( &names );
|
||||
|
||||
for( i=0; i<al_get_count( &names ); i++ )
|
||||
{
|
||||
wchar_t *nxt = names_arr[i];
|
||||
wchar_t *nxt = (wchar_t *)al_get( &names, i );
|
||||
int l = wcslen( nxt + 2 );
|
||||
if( chars+l > common_get_width() )
|
||||
{
|
||||
@@ -1198,7 +1182,6 @@ static int builtin_function( wchar_t **argv )
|
||||
sb_append2( sb_err,
|
||||
nxt, L" ", (void *)0 );
|
||||
}
|
||||
free( names_arr );
|
||||
al_destroy( &names );
|
||||
sb_append( sb_err, L"\n" );
|
||||
|
||||
@@ -1351,7 +1334,7 @@ static int builtin_read( wchar_t **argv )
|
||||
int exit_res=0;
|
||||
|
||||
woptind=0;
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
const static struct woption
|
||||
@@ -1439,7 +1422,6 @@ static int builtin_read( wchar_t **argv )
|
||||
case L'?':
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1874,7 +1856,7 @@ static int builtin_exit( wchar_t **argv )
|
||||
return 1;
|
||||
|
||||
}
|
||||
reader_exit( 1 );
|
||||
reader_exit( 1, 0 );
|
||||
return ec;
|
||||
}
|
||||
|
||||
@@ -2077,7 +2059,7 @@ static void make_first( job_t *j )
|
||||
*/
|
||||
static int builtin_fg( wchar_t **argv )
|
||||
{
|
||||
job_t *j;
|
||||
job_t *j=0;
|
||||
|
||||
if( argv[1] == 0 )
|
||||
{
|
||||
@@ -2127,27 +2109,40 @@ static int builtin_fg( wchar_t **argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
int pid = abs(wcstol( argv[1], 0, 10 ));
|
||||
j = job_get_from_pid( pid );
|
||||
if( !j )
|
||||
wchar_t *end;
|
||||
int pid = abs(wcstol( argv[1], &end, 10 ));
|
||||
|
||||
if( *end )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: No suitable job: %d\n" ),
|
||||
argv[0],
|
||||
pid );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Argument must be a number: %ls\n" ),
|
||||
argv[0],
|
||||
argv[1] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
}
|
||||
if( !j->job_control )
|
||||
else
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
|
||||
argv[0],
|
||||
pid,
|
||||
j->command );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
j=0;
|
||||
j = job_get_from_pid( pid );
|
||||
if( !j || !j->constructed || job_is_completed( j ))
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: No suitable job: %d\n" ),
|
||||
argv[0],
|
||||
pid );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
j=0;
|
||||
}
|
||||
else if( !j->job_control )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
|
||||
argv[0],
|
||||
pid,
|
||||
j->command );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
j=0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( j )
|
||||
|
||||
649
builtin_set.c
649
builtin_set.c
@@ -26,66 +26,164 @@ Functions used for implementing the set builtin.
|
||||
#include "parser.h"
|
||||
#include "translate.h"
|
||||
|
||||
/**
|
||||
Error message for invalid path operations
|
||||
*/
|
||||
#define BUILTIN_SET_PATH_ERROR L"%ls: Could not add component %ls to %ls.\n"
|
||||
|
||||
/**
|
||||
Hint for invalid path operation with a colon
|
||||
*/
|
||||
#define BUILTIN_SET_PATH_HINT L"%ls: Did you mean 'set %ls $%ls %ls'?\n"
|
||||
|
||||
/**
|
||||
Call env_set. On error, print a description of the problem to
|
||||
stderr.
|
||||
Error for mismatch between index count and elements
|
||||
*/
|
||||
static void my_env_set( const wchar_t *key, const wchar_t *val, int scope )
|
||||
{
|
||||
#define BUILTIN_SET_ARG_COUNT L"%ls: The number of variable indexes does not match the number of values\n"
|
||||
|
||||
switch( env_set( key, val, scope | ENV_USER ) )
|
||||
/**
|
||||
Test if the specified variable should be subject to path validation
|
||||
*/
|
||||
static int is_path_variable( const wchar_t *env )
|
||||
{
|
||||
return contains_str( env,
|
||||
L"PATH",
|
||||
L"CDPATH",
|
||||
(void *)0 );
|
||||
}
|
||||
|
||||
/**
|
||||
Call env_set. If this is a path variable, e.g. PATH, validate the
|
||||
elements. On error, print a description of the problem to stderr.
|
||||
*/
|
||||
static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
{
|
||||
string_buffer_t sb;
|
||||
int i;
|
||||
int retcode = 0;
|
||||
wchar_t *val_str=0;
|
||||
|
||||
if( is_path_variable( key ) )
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
for( i=0; i<al_get_count( val ); i++ )
|
||||
{
|
||||
int show_perror = 0;
|
||||
int show_hint = 0;
|
||||
|
||||
struct stat buff;
|
||||
wchar_t *dir = (wchar_t *)al_get( val, i );
|
||||
|
||||
if( wstat( dir, &buff ) )
|
||||
{
|
||||
error = 1;
|
||||
show_perror = 1;
|
||||
}
|
||||
|
||||
if( !( S_IFDIR & buff.st_mode ) )
|
||||
{
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
wchar_t *colon;
|
||||
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_ERROR),
|
||||
L"set",
|
||||
dir,
|
||||
key );
|
||||
|
||||
colon = wcschr( dir, L':' );
|
||||
|
||||
if( colon && *(colon+1) )
|
||||
{
|
||||
show_hint = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( show_perror )
|
||||
{
|
||||
builtin_wperror( L"set" );
|
||||
}
|
||||
|
||||
if( show_hint )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_HINT),
|
||||
L"set",
|
||||
key,
|
||||
key,
|
||||
wcschr( dir, L':' )+1);
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sb_init( &sb );
|
||||
|
||||
if( al_get_count( val ) )
|
||||
{
|
||||
for( i=0; i<al_get_count( val ); i++ )
|
||||
{
|
||||
sb_append( &sb, (wchar_t *)al_get( val, i ) );
|
||||
if( i<al_get_count( val )-1 )
|
||||
{
|
||||
sb_append( &sb, ARRAY_SEP_STR );
|
||||
}
|
||||
}
|
||||
val_str = (wchar_t *)sb.buff;
|
||||
|
||||
}
|
||||
|
||||
switch( env_set( key, val_str, scope | ENV_USER ) )
|
||||
{
|
||||
case ENV_PERM:
|
||||
{
|
||||
sb_printf( sb_err, _(L"%ls: Tried to change the read-only variable '%ls'\n"), L"set", key );
|
||||
retcode=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sb_destroy( &sb );
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/**
|
||||
Extract the name from a destination argument of the form name[index1 index2...]
|
||||
*/
|
||||
static int parse_fill_name( string_buffer_t *name,
|
||||
const wchar_t *src)
|
||||
{
|
||||
|
||||
if (src == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (iswalnum(*src) || *src == L'_')
|
||||
{
|
||||
sb_append_char(name, *src++);
|
||||
}
|
||||
|
||||
if (*src != L'[' && *src != L'\0')
|
||||
{
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, L"set", *src );
|
||||
sb_append2(sb_err, parser_current_line(), L"\n", (void *)0 );
|
||||
// builtin_print_help( L"set", sb_err );
|
||||
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Extract indexes from a destination argument of the form name[index1 index2...]
|
||||
*/
|
||||
static int parse_fill_indexes( array_list_t *indexes,
|
||||
const wchar_t *src)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
\param indexes the list to insert the new indexes into
|
||||
\param src the source string to parse
|
||||
\param name the name of the element. Return null if the name in \c src does not match this name
|
||||
|
||||
\return the number of indexes parsed, or -1 on error
|
||||
*/
|
||||
static int parse_index( array_list_t *indexes,
|
||||
const wchar_t *src,
|
||||
const wchar_t *name )
|
||||
{
|
||||
int len;
|
||||
|
||||
int count = 0;
|
||||
const wchar_t *src_orig = src;
|
||||
|
||||
if (src == 0)
|
||||
{
|
||||
return 0;
|
||||
@@ -96,16 +194,27 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
src++;
|
||||
}
|
||||
|
||||
if (*src == L'\0')
|
||||
if (*src != L'[')
|
||||
{
|
||||
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), L"set" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*src++ != L'[')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
len = src-src_orig;
|
||||
|
||||
if( (wcsncmp( src_orig, name, len )!=0) || (wcslen(name) != (len)) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Multiple variable names specified in single call (%ls and %.*ls)\n"),
|
||||
L"set",
|
||||
name,
|
||||
len,
|
||||
src_orig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src++;
|
||||
|
||||
while (iswspace(*src))
|
||||
{
|
||||
src++;
|
||||
@@ -118,9 +227,9 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
if (end == src)
|
||||
{
|
||||
sb_printf(sb_err, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int *ind = (int *) calloc(1, sizeof(int));
|
||||
*ind = (int) l_ind;
|
||||
al_push(indexes, ind);
|
||||
@@ -139,7 +248,8 @@ static int parse_fill_indexes( array_list_t *indexes,
|
||||
indexes. The previous entries at the specidied position will be
|
||||
free'd.
|
||||
|
||||
\return The number of elements in the list after the modifications have been made
|
||||
\return The number of elements in the list after the modifications
|
||||
have been made
|
||||
*/
|
||||
static int update_values( array_list_t *list,
|
||||
array_list_t *indexes,
|
||||
@@ -172,7 +282,7 @@ static int al_contains_int( array_list_t *list,
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
{
|
||||
int *current = (int *) al_get(list, i);
|
||||
if (current != 0 && *current == val)
|
||||
if( current != 0 && *current == val )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -185,7 +295,7 @@ static int al_contains_int( array_list_t *list,
|
||||
/**
|
||||
Erase from a list values at specified indexes
|
||||
*/
|
||||
static int erase_values(array_list_t *list, array_list_t *indexes)
|
||||
static void erase_values(array_list_t *list, array_list_t *indexes)
|
||||
{
|
||||
int i;
|
||||
array_list_t result;
|
||||
@@ -207,29 +317,6 @@ static int erase_values(array_list_t *list, array_list_t *indexes)
|
||||
al_truncate(list,0);
|
||||
al_push_all( list, &result );
|
||||
al_destroy(&result);
|
||||
|
||||
return al_get_count(list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Fill a string buffer with values from a list, using ARRAY_SEP_STR to separate them
|
||||
*/
|
||||
static int fill_buffer_from_list(string_buffer_t *sb, array_list_t *list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
{
|
||||
wchar_t *v = (wchar_t *) al_get(list, i);
|
||||
if (v != 0)
|
||||
{
|
||||
sb_append(sb, v);
|
||||
}
|
||||
if (i < al_get_count(list) - 1)
|
||||
sb_append(sb, ARRAY_SEP_STR);
|
||||
}
|
||||
return al_get_count(list);
|
||||
}
|
||||
|
||||
|
||||
@@ -269,19 +356,12 @@ static void print_variables(int include_values, int esc, int scope)
|
||||
al_destroy(&names);
|
||||
}
|
||||
|
||||
static int is_path_variable( const wchar_t *env )
|
||||
{
|
||||
return contains_str( env,
|
||||
L"PATH",
|
||||
L"CDPATH",
|
||||
(void *)0 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The set builtin. Creates, updates and erases environment variables and environemnt variable arrays.
|
||||
The set builtin. Creates, updates and erases environment variables
|
||||
and environemnt variable arrays.
|
||||
*/
|
||||
|
||||
int builtin_set( wchar_t **argv )
|
||||
{
|
||||
|
||||
@@ -337,14 +417,12 @@ int builtin_set( wchar_t **argv )
|
||||
Variables used for performing the actual work
|
||||
*/
|
||||
wchar_t *dest = 0;
|
||||
array_list_t values;
|
||||
string_buffer_t name_sb;
|
||||
int retcode=0;
|
||||
wchar_t *name;
|
||||
array_list_t indexes;
|
||||
int retval;
|
||||
|
||||
|
||||
int scope;
|
||||
int slice=0;
|
||||
int i;
|
||||
|
||||
|
||||
/* Parse options to obtain the requested operation and the modifiers */
|
||||
woptind = 0;
|
||||
while (1)
|
||||
@@ -407,7 +485,7 @@ int builtin_set( wchar_t **argv )
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -420,7 +498,7 @@ int builtin_set( wchar_t **argv )
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -433,7 +511,7 @@ int builtin_set( wchar_t **argv )
|
||||
BUILTIN_ERR_GLOCAL,
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -446,10 +524,15 @@ int builtin_set( wchar_t **argv )
|
||||
BUILTIN_ERR_EXPUNEXP,
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate the scope value for variable assignement
|
||||
*/
|
||||
scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (export ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
|
||||
|
||||
if( query )
|
||||
{
|
||||
/*
|
||||
@@ -468,262 +551,188 @@ int builtin_set( wchar_t **argv )
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
/* Parse destination */
|
||||
if( woptind < argc )
|
||||
if( woptind == argc )
|
||||
{
|
||||
dest = wcsdup(argv[woptind++]);
|
||||
|
||||
if( !wcslen( dest ) )
|
||||
/*
|
||||
Print values of variables
|
||||
*/
|
||||
|
||||
if( erase )
|
||||
{
|
||||
free( dest );
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
|
||||
return 1;
|
||||
}
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
// builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_variables( 1, 1, scope );
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* Parse values */
|
||||
// wchar_t **values = woptind < argc ? (wchar_t **) calloc(argc - woptind, sizeof(wchar_t *)) : 0;
|
||||
|
||||
al_init(&values);
|
||||
while( woptind < argc )
|
||||
if( list )
|
||||
{
|
||||
al_push(&values, argv[woptind++]);
|
||||
/* Maybe we should issue an error if there are any other arguments? */
|
||||
print_variables(0, 0, scope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !(dest = wcsdup(argv[woptind])))
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
|
||||
if( is_path_variable( dest ) )
|
||||
if( wcschr( dest, L'[' ) )
|
||||
{
|
||||
int i;
|
||||
int error = 0;
|
||||
slice = 1;
|
||||
*wcschr( dest, L'[' )=0;
|
||||
}
|
||||
|
||||
if( !wcslen( dest ) )
|
||||
{
|
||||
free( dest );
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
set assignment can work in two modes, either using slices or
|
||||
using the whole array. We detect which mode is used here.
|
||||
*/
|
||||
|
||||
if( slice )
|
||||
{
|
||||
|
||||
/*
|
||||
Slice mode
|
||||
*/
|
||||
int idx_count, val_count;
|
||||
array_list_t values;
|
||||
array_list_t indexes;
|
||||
|
||||
for( i=0; i<al_get_count( &values ); i++ )
|
||||
{
|
||||
int show_perror = 0;
|
||||
int show_hint = 0;
|
||||
|
||||
struct stat buff;
|
||||
wchar_t *dir = (wchar_t *)al_get( &values, i );
|
||||
|
||||
if( wstat( dir, &buff ) )
|
||||
{
|
||||
error = 1;
|
||||
show_perror = 1;
|
||||
}
|
||||
|
||||
if( !( S_IFDIR & buff.st_mode ) )
|
||||
{
|
||||
error = 1;
|
||||
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
wchar_t *colon;
|
||||
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_ERROR),
|
||||
argv[0],
|
||||
dir,
|
||||
dest );
|
||||
colon = wcschr( dir, L':' );
|
||||
|
||||
if( colon && *(colon+1) )
|
||||
{
|
||||
show_hint = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( show_perror )
|
||||
{
|
||||
builtin_wperror( argv[0] );
|
||||
}
|
||||
|
||||
if( show_hint )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_HINT),
|
||||
argv[0],
|
||||
dest,
|
||||
dest,
|
||||
wcschr( dir, L':' )+1);
|
||||
}
|
||||
|
||||
if( error )
|
||||
al_init(&values);
|
||||
al_init(&indexes);
|
||||
|
||||
for( ; woptind<argc; woptind++ )
|
||||
{
|
||||
if( !parse_index( &indexes, argv[woptind], dest ) )
|
||||
{
|
||||
retcode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
val_count = argc-woptind-1;
|
||||
idx_count = al_get_count( &indexes );
|
||||
|
||||
if( error )
|
||||
{
|
||||
al_destroy(&values);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Extract variable name and indexes */
|
||||
|
||||
sb_init(&name_sb);
|
||||
retval = parse_fill_name(&name_sb, dest);
|
||||
|
||||
|
||||
if( retval < 0 )
|
||||
retcode=1;
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
name = (wchar_t *) name_sb.buff;
|
||||
|
||||
al_init(&indexes);
|
||||
retval = parse_fill_indexes(&indexes, dest);
|
||||
if (retval < 0)
|
||||
retcode = 1;
|
||||
}
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
|
||||
int i;
|
||||
int finished=0;
|
||||
|
||||
/* Do the actual work */
|
||||
int scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (export ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
|
||||
if( list )
|
||||
{
|
||||
/* Maybe we should issue an error if there are any other arguments? */
|
||||
print_variables(0, 0, scope);
|
||||
finished=1;
|
||||
}
|
||||
|
||||
if( (!finished ) &&
|
||||
(name == 0 || wcslen(name) == 0))
|
||||
{
|
||||
/* No arguments -- display name & value for all variables in scope */
|
||||
if( erase )
|
||||
if( !erase )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
if( val_count < idx_count )
|
||||
{
|
||||
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), argv[0] );
|
||||
retcode=1;
|
||||
break;
|
||||
}
|
||||
if( val_count == idx_count )
|
||||
{
|
||||
woptind++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
/*
|
||||
Slice indexes have been calculated, do the actual work
|
||||
*/
|
||||
|
||||
array_list_t result;
|
||||
al_init(&result);
|
||||
|
||||
expand_variable_array( env_get(dest), &result );
|
||||
if( erase )
|
||||
{
|
||||
erase_values(&result, &indexes);
|
||||
my_env_set( dest, &result, scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
array_list_t value;
|
||||
al_init(&value);
|
||||
|
||||
while( woptind < argc )
|
||||
{
|
||||
al_push(&value, argv[woptind++]);
|
||||
}
|
||||
|
||||
update_values( &result,
|
||||
&indexes,
|
||||
&value );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_variables( 1, 1, scope );
|
||||
}
|
||||
|
||||
finished=1;
|
||||
}
|
||||
|
||||
|
||||
if( !finished )
|
||||
{
|
||||
if( al_get_count( &values ) == 0 &&
|
||||
al_get_count( &indexes ) == 0 &&
|
||||
!erase &&
|
||||
!list )
|
||||
{
|
||||
my_env_set( name, 0, scope );
|
||||
finished = 1;
|
||||
}
|
||||
my_env_set(dest,
|
||||
&result,
|
||||
scope);
|
||||
|
||||
al_destroy( &value );
|
||||
|
||||
}
|
||||
al_foreach( &result, (void (*)(const void *))&free );
|
||||
al_destroy( &result );
|
||||
}
|
||||
|
||||
al_foreach( &indexes, (void (*)(const void *))&free );
|
||||
al_destroy(&indexes);
|
||||
al_destroy(&values);
|
||||
|
||||
if( !finished )
|
||||
}
|
||||
else
|
||||
{
|
||||
woptind++;
|
||||
|
||||
/*
|
||||
No slicing
|
||||
*/
|
||||
if( erase )
|
||||
{
|
||||
/* There are some arguments, we have at least a variable name */
|
||||
if( erase && al_get_count(&values) != 0 )
|
||||
if( woptind != argc )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Values cannot be specfied with erase\n%ls\n"),
|
||||
argv[0],
|
||||
parser_current_line() );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
retcode=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All ok, we can alter the specified variable */
|
||||
array_list_t val_l;
|
||||
al_init(&val_l);
|
||||
|
||||
void *old=0;
|
||||
|
||||
if (al_get_count(&indexes) == 0)
|
||||
{
|
||||
/* We will act upon the entire variable */
|
||||
|
||||
al_push( &val_l, wcsdup(L"") );
|
||||
old = val_l.arr;
|
||||
|
||||
/* Build indexes for all variable or all new values */
|
||||
int end_index = erase ? al_get_count(&val_l) : al_get_count(&values);
|
||||
for (i = 0; i < end_index; i++)
|
||||
{
|
||||
int *ind = (int *) calloc(1, sizeof(int));
|
||||
*ind = i + 1;
|
||||
al_push(&indexes, ind);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We will act upon some specific indexes */
|
||||
expand_variable_array( env_get(name), &val_l );
|
||||
}
|
||||
|
||||
string_buffer_t result_sb;
|
||||
sb_init(&result_sb);
|
||||
if (erase)
|
||||
{
|
||||
int rem = erase_values(&val_l, &indexes);
|
||||
if (rem == 0)
|
||||
{
|
||||
env_remove(name, ENV_USER);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_buffer_from_list(&result_sb, &val_l);
|
||||
|
||||
my_env_set(name, (wchar_t *) result_sb.buff, scope);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
update_values( &val_l,
|
||||
&indexes,
|
||||
&values );
|
||||
|
||||
fill_buffer_from_list( &result_sb,
|
||||
&val_l );
|
||||
|
||||
my_env_set(name,
|
||||
(wchar_t *) result_sb.buff,
|
||||
scope);
|
||||
}
|
||||
|
||||
al_foreach( &val_l, (void (*)(const void *))&free );
|
||||
al_destroy(&val_l);
|
||||
sb_destroy(&result_sb);
|
||||
{
|
||||
env_remove( dest, ENV_USER );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array_list_t val;
|
||||
al_init( &val );
|
||||
|
||||
for( i=woptind; i<argc; i++ )
|
||||
{
|
||||
al_push( &val, argv[i] );
|
||||
}
|
||||
|
||||
al_foreach( &indexes, (void (*)(const void *))&free );
|
||||
al_destroy(&indexes);
|
||||
retcode = my_env_set( dest, &val, scope );
|
||||
|
||||
al_destroy( &val );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Common cleanup */
|
||||
|
||||
free(dest);
|
||||
sb_destroy(&name_sb);
|
||||
al_destroy( &values );
|
||||
free( dest );
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
54
common.c
54
common.c
@@ -61,17 +61,27 @@ parts of fish.
|
||||
#include "wildcard.h"
|
||||
#include "parser.h"
|
||||
|
||||
/**
|
||||
The maximum number of minor errors to report. Further errors will be omitted.
|
||||
*/
|
||||
#define ERROR_MAX_COUNT 1
|
||||
|
||||
/**
|
||||
The number of milliseconds to wait between polls when attempting to acquire
|
||||
a lockfile
|
||||
*/
|
||||
#define LOCKPOLLINTERVAL 10
|
||||
|
||||
/**
|
||||
Highest legal ascii value
|
||||
*/
|
||||
#define ASCII_MAX 127u
|
||||
|
||||
/**
|
||||
Highest legal 16-bit unicode value
|
||||
*/
|
||||
#define UCS2_MAX 0xffffu
|
||||
|
||||
/**
|
||||
Highest legal byte value
|
||||
*/
|
||||
#define BYTE_MAX 0xffu
|
||||
|
||||
struct termios shell_modes;
|
||||
|
||||
int error_max=1;
|
||||
@@ -495,6 +505,12 @@ int contains_str( const wchar_t *a, ... )
|
||||
wchar_t *arg;
|
||||
va_list va;
|
||||
int res = 0;
|
||||
|
||||
if( !a )
|
||||
{
|
||||
debug( 1, L"Warning: Called contains_str with null argument. This is a bug." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_start( va, a );
|
||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||
@@ -539,23 +555,27 @@ void debug( int level, const wchar_t *msg, ... )
|
||||
{
|
||||
va_list va;
|
||||
string_buffer_t sb;
|
||||
string_buffer_t sb2;
|
||||
|
||||
if( level > debug_level )
|
||||
return;
|
||||
|
||||
sb_init( &sb );
|
||||
sb_init( &sb2 );
|
||||
va_start( va, msg );
|
||||
|
||||
sb_printf( &sb, L"%ls: ", program_name );
|
||||
sb_vprintf( &sb, msg, va );
|
||||
va_end( va );
|
||||
|
||||
write_screen( (wchar_t *)sb.buff );
|
||||
write_screen( (wchar_t *)sb.buff, &sb2 );
|
||||
fwprintf( stderr, L"%ls", sb2.buff );
|
||||
|
||||
sb_destroy( &sb );
|
||||
sb_destroy( &sb2 );
|
||||
}
|
||||
|
||||
void write_screen( const wchar_t *msg )
|
||||
void write_screen( const wchar_t *msg, string_buffer_t *buff )
|
||||
{
|
||||
const wchar_t *start, *pos;
|
||||
int line_width = 0;
|
||||
@@ -605,8 +625,8 @@ void write_screen( const wchar_t *msg )
|
||||
*/
|
||||
wchar_t *token = wcsndup( start, pos-start );
|
||||
if( line_width != 0 )
|
||||
putwc( L'\n', stderr );
|
||||
fwprintf( stderr, L"%ls-\n", token );
|
||||
sb_append_char( buff, L'\n' );
|
||||
sb_printf( buff, L"%ls-\n", token );
|
||||
free( token );
|
||||
line_width=0;
|
||||
}
|
||||
@@ -618,10 +638,10 @@ void write_screen( const wchar_t *msg )
|
||||
wchar_t *token = wcsndup( start, pos-start );
|
||||
if( (line_width + (line_width!=0?1:0) + tok_width) > screen_width )
|
||||
{
|
||||
putwc( L'\n', stderr );
|
||||
sb_append_char( buff, L'\n' );
|
||||
line_width=0;
|
||||
}
|
||||
fwprintf( stderr, L"%ls%ls", line_width?L" ":L"", token );
|
||||
sb_printf( buff, L"%ls%ls", line_width?L" ":L"", token );
|
||||
free( token );
|
||||
line_width += (line_width!=0?1:0) + tok_width;
|
||||
}
|
||||
@@ -636,9 +656,9 @@ void write_screen( const wchar_t *msg )
|
||||
}
|
||||
else
|
||||
{
|
||||
fwprintf( stderr, L"%ls", msg );
|
||||
sb_printf( buff, L"%ls", msg );
|
||||
}
|
||||
putwc( L'\n', stderr );
|
||||
sb_append_char( buff, L'\n' );
|
||||
}
|
||||
|
||||
wchar_t *escape( const wchar_t *in,
|
||||
@@ -832,14 +852,14 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
int base=16;
|
||||
|
||||
int byte = 0;
|
||||
int max_val = 127;
|
||||
wchar_t max_val = ASCII_MAX;
|
||||
|
||||
switch( in[in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
{
|
||||
chars=4;
|
||||
max_val = 35535;
|
||||
max_val = UCS2_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -858,7 +878,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
case L'X':
|
||||
{
|
||||
byte=1;
|
||||
max_val = 255;
|
||||
max_val = BYTE_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -884,7 +904,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
||||
res=(res*base)|d;
|
||||
}
|
||||
|
||||
if( (res > 0) && (res <= max_val) )
|
||||
if( (res <= max_val) )
|
||||
{
|
||||
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
||||
}
|
||||
|
||||
10
common.h
10
common.h
@@ -181,9 +181,11 @@ void error_reset();
|
||||
const wchar_t *wsetlocale( int category, const wchar_t *locale );
|
||||
|
||||
/**
|
||||
Checks if \c needle is included in the list of strings specified
|
||||
Checks if \c needle is included in the list of strings specified. A warning is printed if needle is zero.
|
||||
|
||||
\param needle the string to search for in the list
|
||||
|
||||
\return zero is needle is not found, of if needle is null, non-zero otherwise
|
||||
*/
|
||||
int contains_str( const wchar_t *needle, ... );
|
||||
|
||||
@@ -285,10 +287,10 @@ int common_get_height();
|
||||
void common_handle_winch( int signal );
|
||||
|
||||
/**
|
||||
Write paragraph of output to screen. Ignore newlines in message and
|
||||
perform internal line-breaking.
|
||||
Write paragraph of output to the specified stringbuffer, and redo
|
||||
the linebreaks to fit the current screen.
|
||||
*/
|
||||
void write_screen( const wchar_t *msg );
|
||||
void write_screen( const wchar_t *msg, string_buffer_t *buff );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
10
complete.c
10
complete.c
@@ -1983,7 +1983,8 @@ void complete( const wchar_t *cmd,
|
||||
{
|
||||
if( parser_is_subcommand( tok_last( &tok ) ) )
|
||||
break;
|
||||
|
||||
|
||||
free( current_command );
|
||||
current_command = wcsdup( tok_last( &tok ) );
|
||||
|
||||
on_command = (pos <= tok_get_pos( &tok) + wcslen( tok_last( &tok ) ) );
|
||||
@@ -2050,11 +2051,12 @@ void complete( const wchar_t *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
free( current_token );
|
||||
free( current_command );
|
||||
free( prev_token );
|
||||
}
|
||||
|
||||
free( current_token );
|
||||
free( current_command );
|
||||
free( prev_token );
|
||||
|
||||
error_max=old_error_max;
|
||||
condition_cache_clear();
|
||||
|
||||
|
||||
16
configure.ac
16
configure.ac
@@ -1,5 +1,5 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(fish,1.21.6,fish-users@lists.sf.net)
|
||||
AC_INIT(fish,1.21.7,fish-users@lists.sf.net)
|
||||
|
||||
# If needed, run autoconf to regenerate the configure file
|
||||
AC_MSG_CHECKING([if autoconf needs to be run])
|
||||
@@ -389,6 +389,20 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check if we are using basic BSD curses - in that case we redefine
|
||||
# del_curterm as a no-op, to avoid a double-free
|
||||
|
||||
AC_MSG_CHECKING([If we are using BSD curses])
|
||||
case $target_os in
|
||||
*bsd*)
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_CHECK_LIB( ncurses, del_curterm, true, [AC_DEFINE([HAVE_BROKEN_DEL_CURTERM],[1],[We are using basic BSD curses, redefine del_curterm to a no-op to avoid a double-free bug])])
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT(no)
|
||||
;;
|
||||
esac
|
||||
|
||||
# Tell the world what we know
|
||||
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile etc/fish etc/fish_interactive.fish share/fish seq])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -144,7 +144,7 @@ a number called a file descriptor (FD). These are:
|
||||
The reason for providing for two output file descriptors is to allow
|
||||
separation of errors and warnings from regular program output.
|
||||
|
||||
Any file descriptor can be directed to a different output than it's
|
||||
Any file descriptor can be directed to a different output than its
|
||||
default through a simple mechanism called a redirection.
|
||||
|
||||
An example of a file redirection is <code> echo hello \>output.txt</code>,
|
||||
@@ -488,7 +488,7 @@ becomes explicitly NOT a part of the variable name, even if it happens
|
||||
to be a legal variable name character. That's why '{$USER}san' looks
|
||||
for the variable '$USER' and not for the variable '$USERsan'. It's
|
||||
simply a case of one syntax lending itself nicely to solving an
|
||||
unrelated problem in it's spare time.
|
||||
unrelated problem in its spare time.
|
||||
|
||||
Variable expansion is the only type of expansion performed on double
|
||||
quoted strings. There is, however, an important difference in how
|
||||
@@ -644,7 +644,7 @@ echo $pirate
|
||||
\subsection variables-universal More on universal variables
|
||||
|
||||
Universal variables are variables that are shared between all the
|
||||
users fish sessions on the computer. Fish stores many of it's
|
||||
users fish sessions on the computer. Fish stores many of its
|
||||
configuration options as universal variables. This means that in order
|
||||
to change fish settings, all you have to do is change the variable
|
||||
value once, and it will be automatically updated for all sessions, and
|
||||
@@ -758,9 +758,10 @@ certain environment variables.
|
||||
|
||||
\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:
|
||||
values of most of these variables.
|
||||
|
||||
- \c _, which is the name of the currently running command.
|
||||
- \c argv, which is an array of arguments to the shell or function. \c argv is only defined when inside a function call, or if fish was invoked with a list of arguments, like 'fish myscript.fish foo bar'. This variable can be changed by the user.
|
||||
- \c history, which is an array containing the last commands that where entered.
|
||||
- \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.
|
||||
@@ -769,11 +770,11 @@ values of these variables. They are:
|
||||
- \c LANG, \c LC_ALL, \c LC_COLLATE, \c LC_CTYPE, \c LC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and \c LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
|
||||
|
||||
Variables whose name are in uppercase are exported to the commands
|
||||
started by fish. This rule is not enforced by fish, but it is good
|
||||
coding practice to use casing to distinguish between exported and
|
||||
unexported variables. \c fish also uses several variables
|
||||
internally. Such variables are prefixed with the string __FISH or
|
||||
__fish. These should be ignored by the user.
|
||||
started by fish, those in lowercase are not exported. This rule is not
|
||||
enforced by fish, but it is good coding practice to use casing to
|
||||
distinguish between exported and unexported variables. \c fish also
|
||||
uses several variables internally. Such variables are prefixed with
|
||||
the string __FISH or __fish. These should be ignored by the user.
|
||||
|
||||
\subsection variables-locale Locale variables
|
||||
|
||||
@@ -1025,7 +1026,7 @@ Detected errors include:
|
||||
- Mismatched parenthesis
|
||||
|
||||
When the cursor is over a parenthesis or a quote, \c fish also
|
||||
highlights it's matching quote or parenthesis.
|
||||
highlights its matching quote or parenthesis.
|
||||
|
||||
To customize the syntax highlighting, you can set the environment
|
||||
variables \c fish_color_normal, \c fish_color_command, \c
|
||||
@@ -1116,7 +1117,7 @@ command.
|
||||
|
||||
If you install fish in your home directory, fish will not work
|
||||
correctly for any other user than yourself. This is because fish needs
|
||||
it's initalization files to function properly. To solve this
|
||||
its initalization files to function properly. To solve this
|
||||
problem, either copy the initialization files to each fish users home
|
||||
directory, or install them in /etc.
|
||||
|
||||
@@ -1176,7 +1177,7 @@ msgstr "%ls: Inget passande jobb\n"
|
||||
placeholders. These will be replaced by a value by fish at
|
||||
runtime. You must always take care to use exactly the same
|
||||
placeholders in the same order in your translation. (Actually, there
|
||||
are ways to avoid this, but they are to complicated for this short
|
||||
are ways to avoid this, but they are too complicated for this short
|
||||
introduction. See the full manual for the printf C function for more
|
||||
information.)
|
||||
|
||||
@@ -1199,8 +1200,9 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||
- The jobs builtin should be able to give information on a specific job, such as the pids of the processes in the job
|
||||
- Syntax highlighting should mark cd to non-existing directories as an error
|
||||
- wait shellscript
|
||||
- Signal handler to save the history file before exiting from a signal
|
||||
- Support for the screen clipboard
|
||||
- The -a string sent to complete should be validated
|
||||
- Fish should detect improper variable expansion when validating, e.g. strings such as 'foo$' and 'a${}' should be detected as invalid
|
||||
|
||||
|
||||
\subsection todo-possible Possible features
|
||||
|
||||
13
event.c
13
event.c
@@ -57,7 +57,7 @@ typedef struct
|
||||
active, which is the one that new events is written to. The inactive
|
||||
one contains the events that are currently beeing performed.
|
||||
*/
|
||||
static signal_list_t sig_list[2];
|
||||
static signal_list_t sig_list[]={{0,0},{0,0}};
|
||||
|
||||
/**
|
||||
The index of sig_list that is the list of signals currently written to
|
||||
@@ -273,9 +273,12 @@ void event_remove( event_t *criterion )
|
||||
event_t e;
|
||||
|
||||
/*
|
||||
Because of concurrency issues, env_remove does not actually free
|
||||
any events - instead it simply moves all events that should be
|
||||
removed from the event list to the killme list.
|
||||
Because of concurrency issues (env_remove could remove an event
|
||||
that is currently being executed), env_remove does not actually
|
||||
free any events - instead it simply moves all events that should
|
||||
be removed from the event list to the killme list, and the ones
|
||||
that shouldn't be killed to new_list, and then drops the empty
|
||||
events-list.
|
||||
*/
|
||||
|
||||
if( !events )
|
||||
@@ -617,7 +620,6 @@ void event_fire( event_t *event )
|
||||
|
||||
void event_init()
|
||||
{
|
||||
sig_list[active_list].count=0;
|
||||
}
|
||||
|
||||
void event_destroy()
|
||||
@@ -653,3 +655,4 @@ void event_free( event_t *e )
|
||||
free( (void *)e->param1.variable );
|
||||
free( e );
|
||||
}
|
||||
|
||||
|
||||
26
exec.c
26
exec.c
@@ -126,7 +126,7 @@ int exec_pipe( int fd[2])
|
||||
|
||||
if( open_fds == 0 )
|
||||
{
|
||||
open_fds = al_new();
|
||||
open_fds = al_halloc( global_context );
|
||||
}
|
||||
|
||||
al_push( open_fds, (void *)(long)fd[0] );
|
||||
@@ -164,7 +164,8 @@ static int use_fd_in_pipe( int fd, io_data_t *io )
|
||||
the redirection list io. This should make sure that there are no
|
||||
stray opened file descriptors in the child.
|
||||
|
||||
\param io the list of io redirections for this job. Pipes mentioned here should not be closed.
|
||||
\param io the list of io redirections for this job. Pipes mentioned
|
||||
here should not be closed.
|
||||
*/
|
||||
static void close_unused_internal_pipes( io_data_t *io )
|
||||
{
|
||||
@@ -185,20 +186,6 @@ static void close_unused_internal_pipes( io_data_t *io )
|
||||
}
|
||||
}
|
||||
|
||||
void exec_init()
|
||||
{
|
||||
}
|
||||
|
||||
void exec_destroy()
|
||||
{
|
||||
if( open_fds )
|
||||
{
|
||||
al_destroy( open_fds );
|
||||
free( open_fds );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Make sure the fd used by this redirection is not used by i.e. a pipe.
|
||||
*/
|
||||
@@ -564,7 +551,7 @@ static void internal_exec_helper( const wchar_t *def,
|
||||
io_data_t *io_internal = io_transmogrify( io );
|
||||
int is_block_old=is_block;
|
||||
is_block=1;
|
||||
|
||||
|
||||
/*
|
||||
Did the transmogrification fail - if so, set error status and return
|
||||
*/
|
||||
@@ -575,7 +562,7 @@ static void internal_exec_helper( const wchar_t *def,
|
||||
}
|
||||
|
||||
signal_unblock();
|
||||
|
||||
|
||||
eval( def, io_internal, block_type );
|
||||
|
||||
signal_block();
|
||||
@@ -837,7 +824,7 @@ void exec( job_t *j )
|
||||
io_buffer = io_buffer_create();
|
||||
j->io = io_add( j->io, io_buffer );
|
||||
}
|
||||
|
||||
|
||||
internal_exec_helper( p->argv[0], TOP, j->io );
|
||||
break;
|
||||
|
||||
@@ -852,6 +839,7 @@ void exec( job_t *j )
|
||||
if( p == j->first_process )
|
||||
{
|
||||
io_data_t *in = io_get( j->io, 0 );
|
||||
|
||||
if( in )
|
||||
{
|
||||
switch( in->io_mode )
|
||||
|
||||
11
exec.h
11
exec.h
@@ -18,17 +18,6 @@
|
||||
*/
|
||||
#define PIPE_ERROR _(L"An error occurred while setting up pipe")
|
||||
|
||||
/**
|
||||
Initialize the exec library
|
||||
*/
|
||||
void exec_init();
|
||||
|
||||
/**
|
||||
Destroy dynamically allocated data and other resources used by the
|
||||
exec library
|
||||
*/
|
||||
void exec_destroy();
|
||||
|
||||
/**
|
||||
Execute the processes specified by j.
|
||||
|
||||
|
||||
18
expand.c
18
expand.c
@@ -421,16 +421,18 @@ static int find_process( const wchar_t *proc,
|
||||
{
|
||||
|
||||
int jid = wcstol( proc, 0, 10 );
|
||||
|
||||
j = job_get( jid );
|
||||
if( (j != 0) && (j->command != 0 ) )
|
||||
if( jid > 0 )
|
||||
{
|
||||
|
||||
j = job_get( jid );
|
||||
if( (j != 0) && (j->command != 0 ) )
|
||||
{
|
||||
result = malloc(sizeof(wchar_t)*16 );
|
||||
swprintf( result, 16, L"%d", j->pgid );
|
||||
al_push( out, result );
|
||||
found = 1;
|
||||
|
||||
{
|
||||
result = malloc(sizeof(wchar_t)*16 );
|
||||
swprintf( result, 16, L"%d", j->pgid );
|
||||
al_push( out, result );
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,3 +997,11 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_DEL_CURTERM
|
||||
|
||||
int del_curterm(TERMINAL *oterm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
21
fallback.h
21
fallback.h
@@ -3,10 +3,18 @@
|
||||
#define FISH_FALLBACK_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#include "common.h"
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef WCHAR_MAX
|
||||
/**
|
||||
This _should_ be defined by wchar.h, but e.g. OpenBSD doesn't.
|
||||
*/
|
||||
#define WCHAR_MAX INT_MAX
|
||||
#endif
|
||||
|
||||
/**
|
||||
Under curses, tputs expects an int (*func)(char) as its last
|
||||
@@ -213,7 +221,8 @@ wchar_t *wcsndup( const wchar_t *in, int c );
|
||||
|
||||
/**
|
||||
Converts from wide char to digit in the specified base. If d is not
|
||||
a valid digit in the specified base, return -1.
|
||||
a valid digit in the specified base, return -1. This is a helper
|
||||
function for wcstol, but it is useful itself, so it is exported.
|
||||
*/
|
||||
long convert_digit( wchar_t d, int base );
|
||||
|
||||
@@ -262,4 +271,12 @@ size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_DEL_CURTERM
|
||||
|
||||
/**
|
||||
BSD del_curterm seems to do a double-free. We redefine it as a no-op
|
||||
*/
|
||||
int del_curterm(TERMINAL *oterm);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -102,7 +102,7 @@ static int pq_compare( void *e1, void *e2 )
|
||||
/**
|
||||
Test priority queue functionality
|
||||
*/
|
||||
static int pq_test( int elements )
|
||||
static void pq_test( int elements )
|
||||
{
|
||||
int i;
|
||||
int prev;
|
||||
@@ -290,7 +290,7 @@ static int hash_test( int elements )
|
||||
/**
|
||||
Arraylist test
|
||||
*/
|
||||
static int al_test( int sz)
|
||||
static void al_test( int sz)
|
||||
{
|
||||
int i;
|
||||
array_list_t l;
|
||||
@@ -690,7 +690,6 @@ int main( int argc, char **argv )
|
||||
proc_init();
|
||||
halloc_util_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
parser_init();
|
||||
function_init();
|
||||
builtin_init();
|
||||
@@ -718,7 +717,6 @@ int main( int argc, char **argv )
|
||||
builtin_destroy();
|
||||
complete_destroy();
|
||||
wutil_destroy();
|
||||
exec_destroy();
|
||||
event_destroy();
|
||||
proc_destroy();
|
||||
halloc_util_destroy();
|
||||
|
||||
38
function.c
38
function.c
@@ -248,6 +248,19 @@ void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
||||
data->desc =wcsdup(desc);
|
||||
}
|
||||
|
||||
static int al_contains_str( array_list_t *list, const wchar_t * str )
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<al_get_count( list ); i++ )
|
||||
{
|
||||
if( wcscmp( al_get( list, i ), str) == 0 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function for removing hidden functions
|
||||
*/
|
||||
@@ -258,8 +271,25 @@ static void get_names_internal( const void *key,
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
function_data_t *f = (function_data_t *)val;
|
||||
|
||||
if( name[0] != L'_' && !f->is_binding)
|
||||
if( name[0] != L'_' && !f->is_binding && !al_contains_str( (array_list_t *)aux, name ) )
|
||||
{
|
||||
al_push( (array_list_t *)aux, name );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function for removing hidden functions
|
||||
*/
|
||||
static void get_names_internal_all( const void *key,
|
||||
const void *val,
|
||||
void *aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
|
||||
if( !al_contains_str( (array_list_t *)aux, name ) )
|
||||
{
|
||||
al_push( (array_list_t *)aux, name );
|
||||
}
|
||||
}
|
||||
|
||||
void function_get_names( array_list_t *list, int get_hidden )
|
||||
@@ -267,9 +297,13 @@ void function_get_names( array_list_t *list, int get_hidden )
|
||||
autoload_names( list, get_hidden );
|
||||
|
||||
if( get_hidden )
|
||||
hash_get_keys( &function, list );
|
||||
{
|
||||
hash_foreach2( &function, &get_names_internal_all, list );
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_foreach2( &function, &get_names_internal, list );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
9
input.c
9
input.c
@@ -119,7 +119,8 @@ const wchar_t *name_arr[] =
|
||||
L"history-token-search-backward",
|
||||
L"history-token-search-forward",
|
||||
L"self-insert",
|
||||
L"null"
|
||||
L"null",
|
||||
L"eof"
|
||||
}
|
||||
;
|
||||
|
||||
@@ -155,7 +156,8 @@ const wchar_t *desc_arr[] =
|
||||
L"Search backward through list of previous commands for matching token",
|
||||
L"Search forward through list of previous commands for matching token",
|
||||
L"Insert the pressed key",
|
||||
L"Do nothing"
|
||||
L"Do nothing",
|
||||
L"End of file"
|
||||
}
|
||||
;
|
||||
|
||||
@@ -191,7 +193,8 @@ const wchar_t code_arr[] =
|
||||
R_HISTORY_TOKEN_SEARCH_BACKWARD,
|
||||
R_HISTORY_TOKEN_SEARCH_FORWARD,
|
||||
R_SELF_INSERT,
|
||||
R_NULL
|
||||
R_NULL,
|
||||
R_EOF
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
2
input.h
2
input.h
@@ -17,7 +17,7 @@ inputrc information for key bindings.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
R_BEGINNING_OF_LINE = R_NULL+1,
|
||||
R_BEGINNING_OF_LINE = R_NULL+10, /* This give input_common ten slots for lowlevel keycodes */
|
||||
R_END_OF_LINE,
|
||||
R_FORWARD_CHAR,
|
||||
R_BACKWARD_CHAR,
|
||||
|
||||
@@ -64,7 +64,7 @@ static wint_t readb()
|
||||
{
|
||||
unsigned char arr[1];
|
||||
int do_loop = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
fd_set fd;
|
||||
@@ -93,17 +93,21 @@ static wint_t readb()
|
||||
{
|
||||
int res = interrupt_handler();
|
||||
if( res )
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
do_loop = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
||||
wperror(L"read");
|
||||
exit(1);
|
||||
/*
|
||||
The teminal has been closed. Save and exit.
|
||||
*/
|
||||
return R_EOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,17 +119,17 @@ static wint_t readb()
|
||||
{
|
||||
debug( 3, L"Wake up on universal variable event" );
|
||||
env_universal_read_all();
|
||||
debug( 3, L"Return R_NULL" );
|
||||
return R_NULL;
|
||||
do_loop = 1;
|
||||
}
|
||||
}
|
||||
if( FD_ISSET( 0, &fd ) )
|
||||
{
|
||||
if( read_blocked( 0, arr, 1 ) == -1 )
|
||||
if( read_blocked( 0, arr, 1 ) != 1 )
|
||||
{
|
||||
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
||||
wperror(L"read");
|
||||
exit(1);
|
||||
/*
|
||||
The teminal has been closed. Save and exit.
|
||||
*/
|
||||
return R_EOF;
|
||||
}
|
||||
do_loop = 0;
|
||||
}
|
||||
@@ -180,8 +184,8 @@ wchar_t input_common_readch( int timed )
|
||||
|
||||
int sz;
|
||||
|
||||
if( b == R_NULL )
|
||||
return R_NULL;
|
||||
if( (b == R_NULL) || (b == R_EOF) )
|
||||
return b;
|
||||
|
||||
bb=b;
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ enum
|
||||
requested but none could be delivered, or when an exception
|
||||
happened.
|
||||
*/
|
||||
R_NULL = INPUT_COMMON_RESERVED
|
||||
R_NULL = INPUT_COMMON_RESERVED,
|
||||
R_EOF
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
17
io.c
17
io.c
@@ -213,37 +213,34 @@ io_data_t *io_get( io_data_t *io, int fd )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
static void io_print( io_data_t *io )
|
||||
|
||||
void io_print( io_data_t *io )
|
||||
{
|
||||
if( !io )
|
||||
{
|
||||
fwprintf( stderr, L"\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fwprintf( stderr, L"IO fd %d, type ",
|
||||
debug( 1, L"IO fd %d, type ",
|
||||
io->fd );
|
||||
switch( io->io_mode )
|
||||
{
|
||||
case IO_PIPE:
|
||||
fwprintf(stderr, L"PIPE, data %d\n", io->pipe_fd[io->fd?1:0] );
|
||||
debug( 1, L"PIPE, data %d", io->param1.pipe_fd[io->fd?1:0] );
|
||||
break;
|
||||
|
||||
case IO_FD:
|
||||
fwprintf(stderr, L"FD, copy %d\n", io->old_fd );
|
||||
debug( 1, L"FD, copy %d", io->param1.old_fd );
|
||||
break;
|
||||
|
||||
case IO_BUFFER:
|
||||
fwprintf( stderr, L"BUFFER\n" );
|
||||
debug( 1, L"BUFFER" );
|
||||
break;
|
||||
|
||||
default:
|
||||
fwprintf( stderr, L"OTHER\n" );
|
||||
debug( 1, L"OTHER" );
|
||||
}
|
||||
|
||||
io_print( io->next );
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
2
io.h
2
io.h
@@ -89,4 +89,6 @@ io_data_t *io_buffer_create();
|
||||
*/
|
||||
void io_buffer_read( io_data_t *d );
|
||||
|
||||
void io_print( io_data_t *io );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
Type ^C to exit the program.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
21
main.c
21
main.c
@@ -63,6 +63,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#include "halloc_util.h"
|
||||
#include "history.h"
|
||||
|
||||
/**
|
||||
The string describing the single-character options accepted by the main fish binary
|
||||
*/
|
||||
#define GETOPT_STRING "hilnvc:p:d:"
|
||||
|
||||
/**
|
||||
Parse init files
|
||||
@@ -80,9 +84,9 @@ static int read_init()
|
||||
|
||||
env_set( L"__fish_help_dir", DOCDIR, 0);
|
||||
|
||||
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd 2>/dev/null;. .fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd 2>/dev/null; and . .fish 2>/dev/null", 0, TOP );
|
||||
|
||||
if( chdir( cwd ) == -1 )
|
||||
{
|
||||
@@ -165,14 +169,14 @@ int main( int argc, char **argv )
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
"hilnvc:p:d:",
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
#else
|
||||
int opt = getopt( argc,
|
||||
argv,
|
||||
"hilnvc:p:d:" );
|
||||
GETOPT_STRING );
|
||||
#endif
|
||||
if( opt == -1 )
|
||||
break;
|
||||
@@ -259,7 +263,6 @@ int main( int argc, char **argv )
|
||||
|
||||
proc_init();
|
||||
event_init();
|
||||
exec_init();
|
||||
wutil_init();
|
||||
parser_init();
|
||||
builtin_init();
|
||||
@@ -276,7 +279,7 @@ int main( int argc, char **argv )
|
||||
wchar_t *cmd_wcs = str2wcs( cmd );
|
||||
res = eval( cmd_wcs, 0, TOP );
|
||||
free(cmd_wcs);
|
||||
reader_exit(0);
|
||||
reader_exit(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -338,7 +341,7 @@ int main( int argc, char **argv )
|
||||
}
|
||||
|
||||
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
|
||||
|
||||
|
||||
history_destroy();
|
||||
complete_destroy();
|
||||
proc_destroy();
|
||||
@@ -348,12 +351,12 @@ int main( int argc, char **argv )
|
||||
reader_destroy();
|
||||
parser_destroy();
|
||||
wutil_destroy();
|
||||
exec_destroy();
|
||||
event_destroy();
|
||||
|
||||
common_destroy();
|
||||
halloc_util_destroy();
|
||||
intern_free_all();
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
33
parser.c
33
parser.c
@@ -944,7 +944,7 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
||||
int do_loop=1;
|
||||
|
||||
proc_push_interactive(0);
|
||||
|
||||
current_tokenizer = &tok;
|
||||
current_tokenizer_pos = 0;
|
||||
|
||||
tok_init( &tok, line, 0 );
|
||||
@@ -1173,9 +1173,9 @@ wchar_t *parser_current_line()
|
||||
{
|
||||
int lineno=1;
|
||||
|
||||
const wchar_t *file = parser_current_filename();
|
||||
wchar_t *whole_str = tok_string( current_tokenizer );
|
||||
wchar_t *line = whole_str;
|
||||
const wchar_t *file;
|
||||
wchar_t *whole_str;
|
||||
wchar_t *line;
|
||||
wchar_t *line_end;
|
||||
int i;
|
||||
int offset;
|
||||
@@ -1183,6 +1183,14 @@ wchar_t *parser_current_line()
|
||||
const wchar_t *function_name=0;
|
||||
int current_line_start=0;
|
||||
|
||||
if( !current_tokenizer )
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
file = parser_current_filename();
|
||||
whole_str = tok_string( current_tokenizer );
|
||||
line = whole_str;
|
||||
|
||||
if( !line )
|
||||
return L"";
|
||||
@@ -1870,6 +1878,7 @@ static int parse_job( process_t *p,
|
||||
|
||||
consumed=1;
|
||||
is_new_block=1;
|
||||
|
||||
}
|
||||
else if( wcscmp( L"if", nxt ) ==0 )
|
||||
{
|
||||
@@ -1929,7 +1938,7 @@ static int parse_job( process_t *p,
|
||||
builtin_exists( (wchar_t *)al_get( args, 0 ) ) )
|
||||
{
|
||||
p->type = INTERNAL_BUILTIN;
|
||||
is_new_block = parser_is_block( (wchar_t *)al_get( args, 0 ) );
|
||||
is_new_block |= parser_is_block( (wchar_t *)al_get( args, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2067,6 +2076,7 @@ static int parse_job( process_t *p,
|
||||
|
||||
if( !make_sub_block )
|
||||
{
|
||||
|
||||
tok_init( &subtok, end, 0 );
|
||||
switch( tok_last_type( &subtok ) )
|
||||
{
|
||||
@@ -2092,17 +2102,18 @@ static int parse_job( process_t *p,
|
||||
}
|
||||
tok_destroy( &subtok );
|
||||
}
|
||||
|
||||
|
||||
if( make_sub_block )
|
||||
{
|
||||
|
||||
|
||||
int end_pos = end-tok_string( tok );
|
||||
wchar_t *sub_block= wcsndup( tok_string( tok ) + current_tokenizer_pos,
|
||||
end_pos - current_tokenizer_pos);
|
||||
|
||||
wchar_t *sub_block= halloc_wcsndup( j,
|
||||
tok_string( tok ) + current_tokenizer_pos,
|
||||
end_pos - current_tokenizer_pos);
|
||||
|
||||
p->type = INTERNAL_BLOCK;
|
||||
al_set( args, 0, sub_block );
|
||||
|
||||
|
||||
tok_set_pos( tok,
|
||||
end_pos );
|
||||
|
||||
|
||||
4
proc.c
4
proc.c
@@ -182,7 +182,7 @@ int proc_get_last_status()
|
||||
|
||||
job_t *job_create()
|
||||
{
|
||||
int free_id=0;
|
||||
int free_id=1;
|
||||
job_t *res;
|
||||
|
||||
while( job_get( free_id ) != 0 )
|
||||
@@ -204,7 +204,7 @@ job_t *job_create()
|
||||
job_t *job_get( int id )
|
||||
{
|
||||
job_t *res = first_job;
|
||||
if( id == -1 )
|
||||
if( id <= 0 )
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
5
proc.h
5
proc.h
@@ -261,7 +261,7 @@ job_t *job_create();
|
||||
|
||||
/**
|
||||
Return the job with the specified job id.
|
||||
If id is -1, return the last job used.
|
||||
If id is 0 or less, return the last job used.
|
||||
*/
|
||||
job_t *job_get(int id);
|
||||
|
||||
@@ -328,7 +328,8 @@ void proc_update_jiffies();
|
||||
void proc_sanity_check();
|
||||
|
||||
/**
|
||||
Send of an process/job exit event notification. This function is a conveniance wrapper around event_fire().
|
||||
Send a process/job exit event notification. This function is a
|
||||
conveniance wrapper around event_fire().
|
||||
*/
|
||||
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status );
|
||||
|
||||
|
||||
70
reader.c
70
reader.c
@@ -232,6 +232,11 @@ typedef struct reader_data
|
||||
When this is true, the reader will exit
|
||||
*/
|
||||
int end_loop;
|
||||
/**
|
||||
If this is true, exit reader even if there are running
|
||||
jobs. This happens if we press e.g. ^D twice.
|
||||
*/
|
||||
int prev_end_loop;
|
||||
|
||||
/**
|
||||
Pointer to previous reader_data
|
||||
@@ -299,6 +304,11 @@ static void reader_save_status();
|
||||
static void reader_check_status();
|
||||
static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int pos, array_list_t *error );
|
||||
|
||||
/**
|
||||
Variable to keep track of forced exits - see \c reader_exit_forced();
|
||||
*/
|
||||
static int exit_forced;
|
||||
|
||||
|
||||
/**
|
||||
Give up control of terminal
|
||||
@@ -370,6 +380,12 @@ static int room_for_usec(struct stat *st)
|
||||
return res;
|
||||
}
|
||||
|
||||
int reader_exit_forced()
|
||||
{
|
||||
return exit_forced;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
string_buffer used as temporary storage for the reader_readline function
|
||||
*/
|
||||
@@ -869,11 +885,14 @@ void reader_destroy()
|
||||
}
|
||||
|
||||
|
||||
void reader_exit( int do_exit )
|
||||
void reader_exit( int do_exit, int forced )
|
||||
{
|
||||
if( data )
|
||||
data->end_loop=do_exit;
|
||||
end_loop=do_exit;
|
||||
if( forced )
|
||||
exit_forced = 1;
|
||||
|
||||
}
|
||||
|
||||
void repaint()
|
||||
@@ -2230,7 +2249,6 @@ int exit_status()
|
||||
*/
|
||||
static int read_i()
|
||||
{
|
||||
int prev_end_loop=0;
|
||||
|
||||
reader_push(L"fish");
|
||||
reader_set_complete_function( &complete );
|
||||
@@ -2238,6 +2256,7 @@ static int read_i()
|
||||
reader_set_test_function( &shell_test );
|
||||
|
||||
data->prompt_width=60;
|
||||
data->prev_end_loop=0;
|
||||
|
||||
while( (!data->end_loop) && (!sanity_check()) )
|
||||
{
|
||||
@@ -2254,12 +2273,7 @@ static int read_i()
|
||||
during evaluation.
|
||||
*/
|
||||
|
||||
tmp = wcsdup( reader_readline() );
|
||||
|
||||
data->buff_pos=data->buff_len=0;
|
||||
data->buff[data->buff_len]=L'\0';
|
||||
reader_run_command( tmp );
|
||||
free( tmp );
|
||||
tmp = reader_readline();
|
||||
|
||||
if( data->end_loop)
|
||||
{
|
||||
@@ -2275,17 +2289,24 @@ static int read_i()
|
||||
}
|
||||
}
|
||||
|
||||
if( !prev_end_loop && has_job )
|
||||
if( !reader_exit_forced() && !data->prev_end_loop && has_job )
|
||||
{
|
||||
writestr(_( L"There are stopped jobs\n" ));
|
||||
write_prompt();
|
||||
data->end_loop = 0;
|
||||
prev_end_loop=1;
|
||||
data->prev_end_loop=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_end_loop=0;
|
||||
tmp = wcsdup( tmp );
|
||||
|
||||
data->buff_pos=data->buff_len=0;
|
||||
data->buff[data->buff_len]=L'\0';
|
||||
reader_run_command( tmp );
|
||||
free( tmp );
|
||||
|
||||
data->prev_end_loop=0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2442,6 +2463,14 @@ wchar_t *reader_readline()
|
||||
break;
|
||||
}
|
||||
|
||||
case R_EOF:
|
||||
{
|
||||
exit_forced = 1;
|
||||
data->end_loop=1;
|
||||
debug( 1, L"got R_EOF" );
|
||||
break;
|
||||
}
|
||||
|
||||
/* complete */
|
||||
case R_COMPLETE:
|
||||
{
|
||||
@@ -2833,14 +2862,17 @@ wchar_t *reader_readline()
|
||||
}
|
||||
|
||||
al_destroy( &comp );
|
||||
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||
{
|
||||
wperror(L"tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
|
||||
if( !reader_exit_forced() )
|
||||
{
|
||||
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||
{
|
||||
wperror(L"tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
}
|
||||
|
||||
return data->buff;
|
||||
}
|
||||
|
||||
|
||||
7
reader.h
7
reader.h
@@ -21,7 +21,7 @@ int reader_read( int fd);
|
||||
/**
|
||||
Tell the shell that it should exit after the currently running command finishes.
|
||||
*/
|
||||
void reader_exit( int do_exit );
|
||||
void reader_exit( int do_exit, int force );
|
||||
|
||||
/**
|
||||
Check that the reader is in a sane state
|
||||
@@ -162,5 +162,10 @@ void reader_replace_current_token( wchar_t *new_token );
|
||||
*/
|
||||
void reader_handle_int( int signal );
|
||||
|
||||
/**
|
||||
This function returns true if fish is exiting by force, i.e. because stdin died
|
||||
*/
|
||||
int reader_exit_forced();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -4,6 +4,29 @@
|
||||
# completions are located in the completions subdirectory.
|
||||
#
|
||||
|
||||
#
|
||||
# Assign a temporary value here for performance reasons. The real value should be set in /etc/fish.
|
||||
#
|
||||
|
||||
set -g fish_function_path $PWD/functions/
|
||||
|
||||
#
|
||||
# Make sure there are no invalid entries in the PATH
|
||||
#
|
||||
|
||||
set -l erase_idx
|
||||
for idx in (seq (count $PATH))
|
||||
set i $PATH[$idx]
|
||||
if not test -d $i
|
||||
set erase_idx $erase_idx $idx
|
||||
printf (_ '%s: Warning: The directory %s has been removed from your PATH, because it does not exist\n') fish $i
|
||||
end
|
||||
end
|
||||
|
||||
if count $erase_idx >/dev/null
|
||||
set -e PATH[(echo $erase_idx)]
|
||||
end
|
||||
|
||||
#
|
||||
# Add a few common directories to path, if they exists. Note that pure
|
||||
# console programs like makedep sometimes live in /usr/X11R6/bin, so we
|
||||
@@ -17,20 +40,17 @@ if test "$USER" = root
|
||||
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
|
||||
end
|
||||
|
||||
for i in $path_list
|
||||
if not expr "$PATH" : "$i/*" >/dev/null
|
||||
if test -d $i
|
||||
set PATH $PATH $i
|
||||
end
|
||||
# Make a regular expressin that matches any component in the PATH. A
|
||||
# trailing slash is ok. The sed call is to remove the last '\|'.
|
||||
|
||||
set -l path_regexp \\\((printf "^%s\\(\\|/\\)\$\\|" $PATH | sed -e "s/..\$//")\\\)
|
||||
|
||||
for i in (printf "%s\n" $path_list|grep -v $path_regexp)
|
||||
if test -d $i
|
||||
set PATH $PATH $i
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Assign a temporary value here for performance reasons. The real value should be set in /etc/fish.
|
||||
#
|
||||
|
||||
set -g fish_function_path $PWD/functions/
|
||||
|
||||
#
|
||||
# Don't need completions in non-interactive mode
|
||||
#
|
||||
|
||||
@@ -65,7 +65,7 @@ function __fish_complete_ls -d "Compleletions for ls and it's aliases"
|
||||
complete $cmds -l quoting-style -x -a "literal locale shell shell-always c escape" -d (N_ "Select quoting style")
|
||||
complete $cmds -l sort -x -d (N_ "Sort criteria") -a "
|
||||
extension\t'Sort by file extension'
|
||||
none\tDon't\ sort
|
||||
none\tDon\'t\ sort
|
||||
size\t'Sort by size'
|
||||
time\t'Sort by modification time'
|
||||
version\t'Sort by version'
|
||||
@@ -106,4 +106,4 @@ function __fish_complete_ls -d "Compleletions for ls and it's aliases"
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
# string has a newline before and after, so that fish will know how
|
||||
# long it is.
|
||||
|
||||
# This event handler makes sure the prompt is repainted when fish_color_cwd changes value
|
||||
function __fish_repaint --on-variable fish_color_cwd -d (N_ "Event handler, repaints the prompt when fish_color_cwd changes")
|
||||
commandline -f null
|
||||
end
|
||||
|
||||
function fish_prompt -d (N_ "Write out the prompt")
|
||||
|
||||
# Just calculate these once, to save a few cycles when displaying the prompt
|
||||
|
||||
112
signal.c
112
signal.c
@@ -55,143 +55,189 @@ static int block_count=0;
|
||||
*/
|
||||
static struct lookup_entry lookup[] =
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
{
|
||||
SIGHUP,
|
||||
L"SIGHUP",
|
||||
N_( L"Terminal hung up" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
{
|
||||
SIGINT,
|
||||
L"SIGINT",
|
||||
N_( L"Quit request from job control (^C)" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
{
|
||||
SIGQUIT,
|
||||
L"SIGQUIT",
|
||||
N_( L"Quit request from job control with core dump (^\\)" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGILL
|
||||
{
|
||||
SIGILL,
|
||||
L"SIGILL",
|
||||
N_( L"Illegal instruction" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGTRAP
|
||||
{
|
||||
SIGTRAP,
|
||||
L"SIGTRAP",
|
||||
N_( L"Trace or breakpoint trap" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGABRT
|
||||
{
|
||||
SIGABRT,
|
||||
L"SIGABRT",
|
||||
N_( L"Abort" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
{
|
||||
SIGBUS,
|
||||
L"SIGBUS",
|
||||
N_( L"Misaligned address error" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
{
|
||||
SIGFPE,
|
||||
L"SIGFPE",
|
||||
N_( L"Floating point exception" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGKILL
|
||||
{
|
||||
SIGKILL,
|
||||
L"SIGKILL",
|
||||
N_( L"Forced quit" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
{
|
||||
SIGUSR1,
|
||||
L"SIGUSR1",
|
||||
N_( L"User defined signal 1" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
{
|
||||
SIGUSR2, L"SIGUSR2",
|
||||
N_( L"User defined signal 2" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGSEGV
|
||||
{
|
||||
SIGSEGV,
|
||||
L"SIGSEGV",
|
||||
N_( L"Address boundary error" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
{
|
||||
SIGPIPE,
|
||||
L"SIGPIPE",
|
||||
N_( L"Broken pipe" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGALRM
|
||||
{
|
||||
SIGALRM,
|
||||
L"SIGALRM",
|
||||
N_( L"Timer expired" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
{
|
||||
SIGTERM,
|
||||
L"SIGTERM",
|
||||
N_( L"Polite quit request" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
{
|
||||
SIGCHLD,
|
||||
L"SIGCHLD",
|
||||
N_( L"Child process status changed" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGCONT
|
||||
{
|
||||
SIGCONT,
|
||||
L"SIGCONT",
|
||||
N_( L"Continue previously stopped process" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGSTOP
|
||||
{
|
||||
SIGSTOP,
|
||||
L"SIGSTOP",
|
||||
N_( L"Forced stop" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
{
|
||||
SIGTSTP,
|
||||
L"SIGTSTP",
|
||||
N_( L"Stop request from job control (^Z)" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGTTIN
|
||||
{
|
||||
SIGTTIN,
|
||||
L"SIGTTIN",
|
||||
N_( L"Stop from terminal input" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGTTOU
|
||||
{
|
||||
SIGTTOU,
|
||||
L"SIGTTOU",
|
||||
N_( L"Stop from terminal output" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGURG
|
||||
{
|
||||
SIGURG,
|
||||
L"SIGURG",
|
||||
N_( L"Urgent socket condition" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGXCPY
|
||||
{
|
||||
SIGXCPU,
|
||||
L"SIGXCPU",
|
||||
N_( L"CPU time limit exceeded" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
{
|
||||
SIGXFSZ,
|
||||
@@ -200,12 +246,14 @@ static struct lookup_entry lookup[] =
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGVTALRM
|
||||
{
|
||||
SIGVTALRM,
|
||||
L"SIGVTALRM",
|
||||
N_( L"Virtual timer expired" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGPROF
|
||||
{
|
||||
SIGPROF,
|
||||
@@ -230,12 +278,14 @@ static struct lookup_entry lookup[] =
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGWIO
|
||||
{
|
||||
SIGIO,
|
||||
L"SIGIO",
|
||||
N_( L"I/O on asynchronous file descriptor is possible" )
|
||||
}
|
||||
,
|
||||
#endif
|
||||
#ifdef SIGPWR
|
||||
{
|
||||
SIGPWR,
|
||||
@@ -338,6 +388,7 @@ int wcs2sig( const wchar_t *str )
|
||||
const wchar_t *sig2wcs( int sig )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; lookup[i].desc ; i++ )
|
||||
{
|
||||
if( lookup[i].signal == sig )
|
||||
@@ -345,12 +396,14 @@ const wchar_t *sig2wcs( int sig )
|
||||
return lookup[i].name;
|
||||
}
|
||||
}
|
||||
return L"Unknown";
|
||||
|
||||
return _(L"Unknown");
|
||||
}
|
||||
|
||||
const wchar_t *signal_get_desc( int sig )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; lookup[i].desc ; i++ )
|
||||
{
|
||||
if( lookup[i].signal == sig )
|
||||
@@ -358,7 +411,8 @@ const wchar_t *signal_get_desc( int sig )
|
||||
return _(lookup[i].desc);
|
||||
}
|
||||
}
|
||||
return L"Unknown";
|
||||
|
||||
return _(L"Unknown");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,11 +421,16 @@ const wchar_t *signal_get_desc( int sig )
|
||||
static void default_handler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
event_t e;
|
||||
|
||||
e.type=EVENT_SIGNAL;
|
||||
e.param1.signal = signal;
|
||||
e.function_name=0;
|
||||
|
||||
event_fire( &e );
|
||||
if( event_get( &e, 0 ) )
|
||||
{
|
||||
|
||||
event_fire( &e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,6 +442,28 @@ static void handle_winch( int sig, siginfo_t *info, void *context )
|
||||
default_handler( sig, 0, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
Respond to a winch signal by checking the terminal size
|
||||
*/
|
||||
static void handle_hup( int sig, siginfo_t *info, void *context )
|
||||
{
|
||||
event_t e;
|
||||
|
||||
e.type=EVENT_SIGNAL;
|
||||
e.param1.signal = SIGHUP;
|
||||
e.function_name=0;
|
||||
|
||||
if( event_get( &e, 0 ) )
|
||||
{
|
||||
default_handler( sig, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
reader_exit( 1, 1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Interactive mode ^C handler. Respond to int signal by setting
|
||||
interrupted-flag and stopping all loops and conditionals.
|
||||
@@ -431,7 +512,7 @@ void signal_set_handlers()
|
||||
sigemptyset( & act.sa_mask );
|
||||
act.sa_flags=SA_SIGINFO;
|
||||
act.sa_sigaction = &default_handler;
|
||||
|
||||
|
||||
/*
|
||||
First reset everything to a use default_handler, a function
|
||||
whose sole action is to fire of an event
|
||||
@@ -479,7 +560,7 @@ void signal_set_handlers()
|
||||
wperror( L"sigaction" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction= &handle_winch;
|
||||
if( sigaction( SIGWINCH, &act, 0 ) )
|
||||
@@ -488,6 +569,14 @@ void signal_set_handlers()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction= &handle_hup;
|
||||
if( sigaction( SIGHUP, &act, 0 ) )
|
||||
{
|
||||
wperror( L"sigaction" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -510,12 +599,13 @@ void signal_set_handlers()
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void signal_handle( int sig, int do_handle )
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
|
||||
/*
|
||||
These should always be handled
|
||||
*/
|
||||
@@ -527,15 +617,15 @@ void signal_handle( int sig, int do_handle )
|
||||
(sig == SIGCHLD) )
|
||||
return;
|
||||
|
||||
sigemptyset( & act.sa_mask );
|
||||
sigemptyset( &act.sa_mask );
|
||||
if( do_handle )
|
||||
{
|
||||
act.sa_flags=SA_SIGINFO;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction = &default_handler;
|
||||
}
|
||||
else
|
||||
{
|
||||
act.sa_flags=0;
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = SIG_DFL;
|
||||
}
|
||||
|
||||
@@ -551,16 +641,20 @@ void signal_block()
|
||||
sigfillset( &chldset );
|
||||
sigprocmask(SIG_BLOCK, &chldset, 0);
|
||||
}
|
||||
|
||||
block_count++;
|
||||
}
|
||||
|
||||
void signal_unblock()
|
||||
{
|
||||
sigset_t chldset;
|
||||
|
||||
block_count--;
|
||||
|
||||
if( !block_count )
|
||||
{
|
||||
sigfillset( &chldset );
|
||||
sigprocmask(SIG_UNBLOCK, &chldset, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -611,7 +611,7 @@ void tok_next( tokenizer *tok )
|
||||
|
||||
wchar_t *tok_string( tokenizer *tok )
|
||||
{
|
||||
return tok->orig_buff;
|
||||
return tok?tok->orig_buff:0;
|
||||
}
|
||||
|
||||
wchar_t *tok_first( const wchar_t *str )
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
<head>
|
||||
<title>fish user documentation</title>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<!--
|
||||
Override the default doxygen stylesheet to make the difference between different header levels larger
|
||||
-->
|
||||
<style type='text/css'>
|
||||
H2
|
||||
{
|
||||
}
|
||||
|
||||
H3
|
||||
{
|
||||
padding-left:2%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
1
util.c
1
util.c
@@ -809,6 +809,7 @@ int wcsfilecmp( const wchar_t *a, const wchar_t *b )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secondary_diff=0;
|
||||
if( iswdigit( *a ) && iswdigit( *b ) )
|
||||
{
|
||||
|
||||
30
wutil.c
30
wutil.c
@@ -137,16 +137,28 @@ struct wdirent *wreaddir(DIR *dir )
|
||||
|
||||
wchar_t *wgetcwd( wchar_t *buff, size_t sz )
|
||||
{
|
||||
char buffc[sz*MAX_UTF8_BYTES];
|
||||
char *res = getcwd( buffc, sz*MAX_UTF8_BYTES );
|
||||
if( !res )
|
||||
return 0;
|
||||
|
||||
if( (size_t)-1 == mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
|
||||
char *buffc = malloc( sz*MAX_UTF8_BYTES);
|
||||
char *res;
|
||||
wchar_t *ret = 0;
|
||||
|
||||
if( !buffc )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return buff;
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = getcwd( buffc, sz*MAX_UTF8_BYTES );
|
||||
if( res )
|
||||
{
|
||||
if( (size_t)-1 != mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
|
||||
{
|
||||
ret = buff;
|
||||
}
|
||||
}
|
||||
|
||||
free( buffc );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wchdir( const wchar_t * dir )
|
||||
|
||||
Reference in New Issue
Block a user