mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-31 12:21:19 -03:00
Compare commits
57 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 | ||
|
|
13a7269378 | ||
|
|
fd2644ce49 | ||
|
|
508de57459 | ||
|
|
de2405b35a | ||
|
|
a7f977836a | ||
|
|
f59e4a88c6 | ||
|
|
c755bd0358 | ||
|
|
536523ffd7 | ||
|
|
ca82fc2f03 | ||
|
|
d1411c42d6 | ||
|
|
9d770af5f4 | ||
|
|
d1ff6a323a | ||
|
|
112ea1759a | ||
|
|
76bafbef2a | ||
|
|
1947ec88f1 | ||
|
|
d0956f1e43 | ||
|
|
6996c7718e | ||
|
|
45d56d8e05 | ||
|
|
53295d38b7 | ||
|
|
bd9c843fd1 | ||
|
|
f812b9b26c | ||
|
|
52851a3ba4 |
10
Makefile.in
10
Makefile.in
@@ -344,7 +344,6 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
|
|||||||
./gen_hdr.sh $*.doxygen >>$@
|
./gen_hdr.sh $*.doxygen >>$@
|
||||||
echo ");" >>$@
|
echo ");" >>$@
|
||||||
echo "}" >>$@
|
echo "}" >>$@
|
||||||
#man -- doc_src/builtin_doc/man/man1/`basename $@ .c`.1 | cat -s | ./gen_hdr2 >>$@
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# The build rules for installing/uninstalling fish
|
# The build rules for installing/uninstalling fish
|
||||||
@@ -413,7 +412,7 @@ install-force: all install-translations
|
|||||||
@echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.
|
@echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.
|
||||||
@echo
|
@echo
|
||||||
@echo Have fun!
|
@echo Have fun!
|
||||||
.PHONY: force-install
|
.PHONY: install-force
|
||||||
|
|
||||||
|
|
||||||
# Uninstall this fish version
|
# Uninstall this fish version
|
||||||
@@ -455,6 +454,7 @@ uninstall-legacy: uninstall
|
|||||||
rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions; true
|
rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions; true
|
||||||
rmdir $(DESTDIR)$(sysconfdir)/fish.d; true
|
rmdir $(DESTDIR)$(sysconfdir)/fish.d; true
|
||||||
@echo The previous fish installation has been removed.
|
@echo The previous fish installation has been removed.
|
||||||
|
.PHONY: uninstall-legacy
|
||||||
|
|
||||||
install-translations: $(TRANSLATIONS)
|
install-translations: $(TRANSLATIONS)
|
||||||
if test $(HAVE_GETTEXT) = 1; then \
|
if test $(HAVE_GETTEXT) = 1; then \
|
||||||
@@ -579,7 +579,7 @@ distclean: clean
|
|||||||
.PHONY: distclean
|
.PHONY: distclean
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o doc.h doc_src/*.doxygen doc_src/*.c builtin_help.c
|
rm -f *.o doc.h doc_src/*.doxygen doc_src/*.c builtin_help.c doc_src/*.o
|
||||||
rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt
|
rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt
|
||||||
rm -f tokenizer_test fish key_reader set_color gen_hdr2 mimedb
|
rm -f tokenizer_test fish key_reader set_color gen_hdr2 mimedb
|
||||||
rm -f fishd fish_pager count fish_tests
|
rm -f fishd fish_pager count fish_tests
|
||||||
@@ -620,7 +620,6 @@ complete.o: signal.h config.h fallback.h common.h util.h tokenizer.h
|
|||||||
complete.o: wildcard.h proc.h io.h parser.h event.h function.h complete.h
|
complete.o: wildcard.h proc.h io.h parser.h event.h function.h complete.h
|
||||||
complete.o: builtin.h env.h exec.h expand.h reader.h history.h intern.h
|
complete.o: builtin.h env.h exec.h expand.h reader.h history.h intern.h
|
||||||
complete.o: translate.h parse_util.h halloc_util.h wutil.h
|
complete.o: translate.h parse_util.h halloc_util.h wutil.h
|
||||||
dragon.o: signal.h
|
|
||||||
env.o: config.h signal.h fallback.h common.h util.h wutil.h proc.h io.h env.h
|
env.o: config.h signal.h fallback.h common.h util.h wutil.h proc.h io.h env.h
|
||||||
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
|
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
|
||||||
env.o: env_universal_common.h input_common.h translate.h complete.h
|
env.o: env_universal_common.h input_common.h translate.h complete.h
|
||||||
@@ -637,7 +636,7 @@ exec.o: halloc.h halloc_util.h parse_util.h
|
|||||||
expand.o: signal.h config.h fallback.h common.h util.h wutil.h env.h proc.h
|
expand.o: signal.h config.h fallback.h common.h util.h wutil.h env.h proc.h
|
||||||
expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
|
expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
|
||||||
expand.o: complete.h translate.h parse_util.h halloc_util.h
|
expand.o: complete.h translate.h parse_util.h halloc_util.h
|
||||||
fallback.o: config.h common.h util.h
|
fallback.o: config.h fallback.h common.h util.h
|
||||||
fishd.o: config.h signal.h fallback.h common.h util.h wutil.h
|
fishd.o: config.h signal.h fallback.h common.h util.h wutil.h
|
||||||
fishd.o: env_universal_common.h
|
fishd.o: env_universal_common.h
|
||||||
fish_pager.o: config.h signal.h fallback.h common.h util.h wutil.h complete.h
|
fish_pager.o: config.h signal.h fallback.h common.h util.h wutil.h complete.h
|
||||||
@@ -670,6 +669,7 @@ kill.o: io.h sanity.h env.h exec.h parser.h event.h
|
|||||||
main.o: config.h signal.h fallback.h common.h util.h reader.h builtin.h
|
main.o: config.h signal.h fallback.h common.h util.h reader.h builtin.h
|
||||||
main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h
|
main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h
|
||||||
main.o: event.h expand.h intern.h exec.h output.h translate.h halloc_util.h
|
main.o: event.h expand.h intern.h exec.h output.h translate.h halloc_util.h
|
||||||
|
main.o: history.h
|
||||||
mimedb.o: config.h xdgmime.h fallback.h common.h util.h
|
mimedb.o: config.h xdgmime.h fallback.h common.h util.h
|
||||||
output.o: config.h signal.h fallback.h common.h util.h wutil.h expand.h
|
output.o: config.h signal.h fallback.h common.h util.h wutil.h expand.h
|
||||||
output.o: output.h halloc_util.h highlight.h
|
output.o: output.h halloc_util.h highlight.h
|
||||||
|
|||||||
158
builtin.c
158
builtin.c
@@ -497,27 +497,24 @@ static int builtin_builtin( wchar_t **argv )
|
|||||||
if( list )
|
if( list )
|
||||||
{
|
{
|
||||||
array_list_t names;
|
array_list_t names;
|
||||||
wchar_t **names_arr;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
al_init( &names );
|
al_init( &names );
|
||||||
builtin_get_names( &names );
|
builtin_get_names( &names );
|
||||||
names_arr = list_to_char_arr( &names );
|
sort_list( &names );
|
||||||
qsort( names_arr,
|
|
||||||
al_get_count( &names ),
|
|
||||||
sizeof(wchar_t *),
|
|
||||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
|
||||||
for( i=0; i<al_get_count( &names ); i++ )
|
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;
|
continue;
|
||||||
|
|
||||||
sb_append2( sb_out,
|
sb_append2( sb_out,
|
||||||
names_arr[i],
|
el,
|
||||||
L"\n",
|
L"\n",
|
||||||
(void *)0 );
|
(void *)0 );
|
||||||
}
|
}
|
||||||
free( names_arr );
|
|
||||||
al_destroy( &names );
|
al_destroy( &names );
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -677,7 +674,6 @@ static int builtin_functions( wchar_t **argv )
|
|||||||
wchar_t *desc=0;
|
wchar_t *desc=0;
|
||||||
|
|
||||||
array_list_t names;
|
array_list_t names;
|
||||||
wchar_t **names_arr;
|
|
||||||
|
|
||||||
int argc=builtin_count_args( argv );
|
int argc=builtin_count_args( argv );
|
||||||
int list=0;
|
int list=0;
|
||||||
@@ -820,11 +816,7 @@ static int builtin_functions( wchar_t **argv )
|
|||||||
|
|
||||||
al_init( &names );
|
al_init( &names );
|
||||||
function_get_names( &names, show_hidden );
|
function_get_names( &names, show_hidden );
|
||||||
names_arr = list_to_char_arr( &names );
|
sort_list( &names );
|
||||||
qsort( names_arr,
|
|
||||||
al_get_count( &names ),
|
|
||||||
sizeof(wchar_t *),
|
|
||||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
|
||||||
if( is_screen )
|
if( is_screen )
|
||||||
{
|
{
|
||||||
string_buffer_t buff;
|
string_buffer_t buff;
|
||||||
@@ -833,12 +825,12 @@ static int builtin_functions( wchar_t **argv )
|
|||||||
for( i=0; i<al_get_count( &names ); i++ )
|
for( i=0; i<al_get_count( &names ); i++ )
|
||||||
{
|
{
|
||||||
sb_append2( &buff,
|
sb_append2( &buff,
|
||||||
names_arr[i],
|
al_get(&names, i),
|
||||||
L", ",
|
L", ",
|
||||||
(void *)0 );
|
(void *)0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
write_screen( (wchar_t *)buff.buff );
|
write_screen( (wchar_t *)buff.buff, sb_out );
|
||||||
sb_destroy( &buff );
|
sb_destroy( &buff );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -846,13 +838,12 @@ static int builtin_functions( wchar_t **argv )
|
|||||||
for( i=0; i<al_get_count( &names ); i++ )
|
for( i=0; i<al_get_count( &names ); i++ )
|
||||||
{
|
{
|
||||||
sb_append2( sb_out,
|
sb_append2( sb_out,
|
||||||
names_arr[i],
|
al_get(&names, i),
|
||||||
L"\n",
|
L"\n",
|
||||||
(void *)0 );
|
(void *)0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free( names_arr );
|
|
||||||
al_destroy( &names );
|
al_destroy( &names );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -865,16 +856,13 @@ static int builtin_functions( wchar_t **argv )
|
|||||||
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
|
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
|
||||||
al_init( &names );
|
al_init( &names );
|
||||||
function_get_names( &names, show_hidden );
|
function_get_names( &names, show_hidden );
|
||||||
names_arr = list_to_char_arr( &names );
|
sort_list( &names );
|
||||||
qsort( names_arr,
|
|
||||||
al_get_count( &names ),
|
|
||||||
sizeof(wchar_t *),
|
|
||||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
|
||||||
for( i=0; i<al_get_count( &names ); i++ )
|
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 );
|
al_destroy( &names );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1029,7 +1017,7 @@ static int builtin_function( wchar_t **argv )
|
|||||||
{
|
{
|
||||||
event_t *e;
|
event_t *e;
|
||||||
|
|
||||||
if( !wcsvarname( woptarg ) )
|
if( wcsvarname( woptarg ) )
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
_( L"%ls: Invalid variable name '%ls'\n" ),
|
_( L"%ls: Invalid variable name '%ls'\n" ),
|
||||||
@@ -1145,7 +1133,7 @@ static int builtin_function( wchar_t **argv )
|
|||||||
argc-woptind );
|
argc-woptind );
|
||||||
res=1;
|
res=1;
|
||||||
}
|
}
|
||||||
else if( !(is_binding?wcsbindingname( argv[woptind] ) : wcsvarname( argv[woptind] ) ))
|
else if( !(is_binding?wcsbindingname( argv[woptind] ) : !wcsvarname( argv[woptind] ) ))
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
_( L"%ls: Illegal function name '%ls'\n" ),
|
_( L"%ls: Illegal function name '%ls'\n" ),
|
||||||
@@ -1170,7 +1158,6 @@ static int builtin_function( wchar_t **argv )
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
array_list_t names;
|
array_list_t names;
|
||||||
wchar_t **names_arr;
|
|
||||||
int chars=0;
|
int chars=0;
|
||||||
|
|
||||||
// builtin_print_help( argv[0], sb_err );
|
// builtin_print_help( argv[0], sb_err );
|
||||||
@@ -1180,14 +1167,11 @@ static int builtin_function( wchar_t **argv )
|
|||||||
|
|
||||||
al_init( &names );
|
al_init( &names );
|
||||||
function_get_names( &names, 0 );
|
function_get_names( &names, 0 );
|
||||||
names_arr = list_to_char_arr( &names );
|
sort_list( &names );
|
||||||
qsort( names_arr,
|
|
||||||
al_get_count( &names ),
|
|
||||||
sizeof(wchar_t *),
|
|
||||||
(int (*)(const void *, const void *))&wcsfilecmp );
|
|
||||||
for( i=0; i<al_get_count( &names ); i++ )
|
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 );
|
int l = wcslen( nxt + 2 );
|
||||||
if( chars+l > common_get_width() )
|
if( chars+l > common_get_width() )
|
||||||
{
|
{
|
||||||
@@ -1198,7 +1182,6 @@ static int builtin_function( wchar_t **argv )
|
|||||||
sb_append2( sb_err,
|
sb_append2( sb_err,
|
||||||
nxt, L" ", (void *)0 );
|
nxt, L" ", (void *)0 );
|
||||||
}
|
}
|
||||||
free( names_arr );
|
|
||||||
al_destroy( &names );
|
al_destroy( &names );
|
||||||
sb_append( sb_err, L"\n" );
|
sb_append( sb_err, L"\n" );
|
||||||
|
|
||||||
@@ -1351,7 +1334,7 @@ static int builtin_read( wchar_t **argv )
|
|||||||
int exit_res=0;
|
int exit_res=0;
|
||||||
|
|
||||||
woptind=0;
|
woptind=0;
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
const static struct woption
|
const static struct woption
|
||||||
@@ -1439,7 +1422,6 @@ static int builtin_read( wchar_t **argv )
|
|||||||
case L'?':
|
case L'?':
|
||||||
builtin_print_help( argv[0], sb_err );
|
builtin_print_help( argv[0], sb_err );
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1468,20 +1450,6 @@ static int builtin_read( wchar_t **argv )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( woptind == argc )
|
|
||||||
{
|
|
||||||
sb_printf( sb_err,
|
|
||||||
BUILTIN_ERR_MISSING,
|
|
||||||
argv[0] );
|
|
||||||
|
|
||||||
sb_append2( sb_err,
|
|
||||||
parser_current_line(),
|
|
||||||
L"\n",
|
|
||||||
(void *)0 );
|
|
||||||
builtin_print_help( argv[0], sb_err );
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Verify all variable names
|
Verify all variable names
|
||||||
*/
|
*/
|
||||||
@@ -1512,10 +1480,6 @@ static int builtin_read( wchar_t **argv )
|
|||||||
*/
|
*/
|
||||||
i=woptind;
|
i=woptind;
|
||||||
|
|
||||||
ifs = env_get( L"IFS" );
|
|
||||||
if( ifs == 0 )
|
|
||||||
ifs = L"";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if we should read interactively using \c reader_readline()
|
Check if we should read interactively using \c reader_readline()
|
||||||
*/
|
*/
|
||||||
@@ -1593,20 +1557,29 @@ static int builtin_read( wchar_t **argv )
|
|||||||
sb_destroy( &sb );
|
sb_destroy( &sb );
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *state;
|
if( i != argc )
|
||||||
|
|
||||||
nxt = wcstok( buff, (i<argc-1)?ifs:L"", &state );
|
|
||||||
|
|
||||||
while( i<argc )
|
|
||||||
{
|
{
|
||||||
env_set( argv[i], nxt != 0 ? nxt: L"", place );
|
|
||||||
|
wchar_t *state;
|
||||||
|
|
||||||
i++;
|
ifs = env_get( L"IFS" );
|
||||||
if( nxt != 0 )
|
if( ifs == 0 )
|
||||||
nxt = wcstok( 0, (i<argc-1)?ifs:L"", &state);
|
ifs = L"";
|
||||||
|
|
||||||
|
nxt = wcstok( buff, (i<argc-1)?ifs:L"", &state );
|
||||||
|
|
||||||
|
while( i<argc )
|
||||||
|
{
|
||||||
|
env_set( argv[i], nxt != 0 ? nxt: L"", place );
|
||||||
|
|
||||||
|
i++;
|
||||||
|
if( nxt != 0 )
|
||||||
|
nxt = wcstok( 0, (i<argc-1)?ifs:L"", &state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free( buff );
|
free( buff );
|
||||||
|
|
||||||
return exit_res;
|
return exit_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1883,7 +1856,7 @@ static int builtin_exit( wchar_t **argv )
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
reader_exit( 1 );
|
reader_exit( 1, 0 );
|
||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2086,7 +2059,7 @@ static void make_first( job_t *j )
|
|||||||
*/
|
*/
|
||||||
static int builtin_fg( wchar_t **argv )
|
static int builtin_fg( wchar_t **argv )
|
||||||
{
|
{
|
||||||
job_t *j;
|
job_t *j=0;
|
||||||
|
|
||||||
if( argv[1] == 0 )
|
if( argv[1] == 0 )
|
||||||
{
|
{
|
||||||
@@ -2136,27 +2109,40 @@ static int builtin_fg( wchar_t **argv )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int pid = abs(wcstol( argv[1], 0, 10 ));
|
wchar_t *end;
|
||||||
j = job_get_from_pid( pid );
|
int pid = abs(wcstol( argv[1], &end, 10 ));
|
||||||
if( !j )
|
|
||||||
|
if( *end )
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
_( L"%ls: No suitable job: %d\n" ),
|
_( L"%ls: Argument must be a number: %ls\n" ),
|
||||||
argv[0],
|
argv[0],
|
||||||
pid );
|
argv[1] );
|
||||||
builtin_print_help( argv[0], sb_err );
|
builtin_print_help( argv[0], sb_err );
|
||||||
}
|
}
|
||||||
if( !j->job_control )
|
else
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
j = job_get_from_pid( pid );
|
||||||
_( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
|
if( !j || !j->constructed || job_is_completed( j ))
|
||||||
argv[0],
|
{
|
||||||
pid,
|
sb_printf( sb_err,
|
||||||
j->command );
|
_( L"%ls: No suitable job: %d\n" ),
|
||||||
builtin_print_help( argv[0], sb_err );
|
argv[0],
|
||||||
j=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 )
|
if( j )
|
||||||
@@ -2593,7 +2579,7 @@ static int builtin_for( wchar_t **argv )
|
|||||||
argv[0] );
|
argv[0] );
|
||||||
builtin_print_help( argv[0], sb_err );
|
builtin_print_help( argv[0], sb_err );
|
||||||
}
|
}
|
||||||
else if ( !wcsvarname(argv[1]) )
|
else if ( wcsvarname(argv[1]) )
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
_( L"%ls: '%ls' is not a valid variable name\n" ),
|
_( L"%ls: '%ls' is not a valid variable name\n" ),
|
||||||
|
|||||||
641
builtin_set.c
641
builtin_set.c
@@ -26,46 +26,164 @@ Functions used for implementing the set builtin.
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "translate.h"
|
#include "translate.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract the name from a destination argument of the form name[index1 index2...]
|
Error message for invalid path operations
|
||||||
*/
|
*/
|
||||||
static int parse_fill_name( string_buffer_t *name,
|
#define BUILTIN_SET_PATH_ERROR L"%ls: Could not add component %ls to %ls.\n"
|
||||||
const wchar_t *src)
|
|
||||||
|
/**
|
||||||
|
Hint for invalid path operation with a colon
|
||||||
|
*/
|
||||||
|
#define BUILTIN_SET_PATH_HINT L"%ls: Did you mean 'set %ls $%ls %ls'?\n"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Error for mismatch between index count and elements
|
||||||
|
*/
|
||||||
|
#define BUILTIN_SET_ARG_COUNT L"%ls: The number of variable indexes does not match the number of values\n"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test if the specified variable should be subject to path validation
|
||||||
|
*/
|
||||||
|
static int is_path_variable( const wchar_t *env )
|
||||||
{
|
{
|
||||||
|
return contains_str( env,
|
||||||
if (src == 0)
|
L"PATH",
|
||||||
{
|
L"CDPATH",
|
||||||
return 0;
|
(void *)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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 indexes from a destination argument of the form name[index1 index2...]
|
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)
|
if (src == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -76,16 +194,27 @@ static int parse_fill_indexes( array_list_t *indexes,
|
|||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*src == L'\0')
|
if (*src != L'[')
|
||||||
{
|
{
|
||||||
|
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), L"set" );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*src++ != L'[')
|
len = src-src_orig;
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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))
|
while (iswspace(*src))
|
||||||
{
|
{
|
||||||
src++;
|
src++;
|
||||||
@@ -98,9 +227,9 @@ static int parse_fill_indexes( array_list_t *indexes,
|
|||||||
if (end == src)
|
if (end == src)
|
||||||
{
|
{
|
||||||
sb_printf(sb_err, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", 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));
|
int *ind = (int *) calloc(1, sizeof(int));
|
||||||
*ind = (int) l_ind;
|
*ind = (int) l_ind;
|
||||||
al_push(indexes, ind);
|
al_push(indexes, ind);
|
||||||
@@ -114,7 +243,13 @@ static int parse_fill_indexes( array_list_t *indexes,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Update a list by writing the specified values at the specified indexes
|
Update a list \c list by writing copies (using wcsdup) of the
|
||||||
|
values specified by \c values to the indexes specified by \c
|
||||||
|
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
|
||||||
*/
|
*/
|
||||||
static int update_values( array_list_t *list,
|
static int update_values( array_list_t *list,
|
||||||
array_list_t *indexes,
|
array_list_t *indexes,
|
||||||
@@ -122,16 +257,12 @@ static int update_values( array_list_t *list,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
//fwprintf(stderr, L"Scan complete\n");
|
|
||||||
/* Replace values where needed */
|
/* Replace values where needed */
|
||||||
for( i = 0; i < al_get_count(indexes); i++ )
|
for( i = 0; i < al_get_count(indexes); i++ )
|
||||||
{
|
{
|
||||||
int ind = *(int *) al_get(indexes, i) - 1;
|
int ind = *(int *) al_get(indexes, i) - 1;
|
||||||
void *new = (void *) al_get(values, i);
|
void *new = (void *) al_get(values, i);
|
||||||
if (al_get(list, ind) != 0)
|
free((void *) al_get(list, ind));
|
||||||
{
|
|
||||||
free((void *) al_get(list, ind));
|
|
||||||
}
|
|
||||||
al_set(list, ind, new != 0 ? wcsdup(new) : wcsdup(L""));
|
al_set(list, ind, new != 0 ? wcsdup(new) : wcsdup(L""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +282,7 @@ static int al_contains_int( array_list_t *list,
|
|||||||
for (i = 0; i < al_get_count(list); i++)
|
for (i = 0; i < al_get_count(list); i++)
|
||||||
{
|
{
|
||||||
int *current = (int *) al_get(list, i);
|
int *current = (int *) al_get(list, i);
|
||||||
if (current != 0 && *current == val)
|
if( current != 0 && *current == val )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -164,13 +295,11 @@ static int al_contains_int( array_list_t *list,
|
|||||||
/**
|
/**
|
||||||
Erase from a list values at specified indexes
|
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;
|
int i;
|
||||||
array_list_t result;
|
array_list_t result;
|
||||||
|
|
||||||
//fwprintf(stderr, L"Starting with %d\n", al_get_count(list));
|
|
||||||
|
|
||||||
al_init(&result);
|
al_init(&result);
|
||||||
|
|
||||||
for (i = 0; i < al_get_count(list); i++)
|
for (i = 0; i < al_get_count(list); i++)
|
||||||
@@ -188,33 +317,6 @@ static int erase_values(array_list_t *list, array_list_t *indexes)
|
|||||||
al_truncate(list,0);
|
al_truncate(list,0);
|
||||||
al_push_all( list, &result );
|
al_push_all( list, &result );
|
||||||
al_destroy(&result);
|
al_destroy(&result);
|
||||||
|
|
||||||
//fwprintf(stderr, L"Remaining: %d\n", al_get_count(&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)
|
|
||||||
{
|
|
||||||
// fwprintf(stderr, L".\n");
|
|
||||||
// fwprintf(stderr, L"Collecting %ls from %d\n", v, i);
|
|
||||||
sb_append(sb, v);
|
|
||||||
}
|
|
||||||
if (i < al_get_count(list) - 1)
|
|
||||||
sb_append(sb, ARRAY_SEP_STR);
|
|
||||||
}
|
|
||||||
return al_get_count(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -254,12 +356,18 @@ static void print_variables(int include_values, int esc, int scope)
|
|||||||
al_destroy(&names);
|
al_destroy(&names);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
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 )
|
int builtin_set( wchar_t **argv )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
Variables used for parsing the argument list
|
||||||
|
*/
|
||||||
const static struct woption
|
const static struct woption
|
||||||
long_options[] =
|
long_options[] =
|
||||||
{
|
{
|
||||||
@@ -293,7 +401,7 @@ int builtin_set( wchar_t **argv )
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
wchar_t short_options[] = L"+xglenuUq";
|
const wchar_t *short_options = L"+xglenuUq";
|
||||||
|
|
||||||
int argc = builtin_count_args(argv);
|
int argc = builtin_count_args(argv);
|
||||||
|
|
||||||
@@ -309,14 +417,12 @@ int builtin_set( wchar_t **argv )
|
|||||||
Variables used for performing the actual work
|
Variables used for performing the actual work
|
||||||
*/
|
*/
|
||||||
wchar_t *dest = 0;
|
wchar_t *dest = 0;
|
||||||
array_list_t values;
|
|
||||||
string_buffer_t name_sb;
|
|
||||||
int retcode=0;
|
int retcode=0;
|
||||||
wchar_t *name;
|
int scope;
|
||||||
array_list_t indexes;
|
int slice=0;
|
||||||
int retval;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
/* Parse options to obtain the requested operation and the modifiers */
|
/* Parse options to obtain the requested operation and the modifiers */
|
||||||
woptind = 0;
|
woptind = 0;
|
||||||
while (1)
|
while (1)
|
||||||
@@ -363,6 +469,15 @@ int builtin_set( wchar_t **argv )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ok, all arguments have been parsed, let's validate them
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
If we are checking the existance of a variable (-q) we can not
|
||||||
|
also specify scope
|
||||||
|
*/
|
||||||
|
|
||||||
if( query && (erase || list || global || local || universal || export || unexport ) )
|
if( query && (erase || list || global || local || universal || export || unexport ) )
|
||||||
{
|
{
|
||||||
sb_printf(sb_err,
|
sb_printf(sb_err,
|
||||||
@@ -370,12 +485,12 @@ int builtin_set( wchar_t **argv )
|
|||||||
argv[0],
|
argv[0],
|
||||||
parser_current_line() );
|
parser_current_line() );
|
||||||
|
|
||||||
builtin_print_help( argv[0], sb_err );
|
// builtin_print_help( argv[0], sb_err );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check operation and modifiers sanity */
|
/* We can't both list and erase varaibles */
|
||||||
if( erase && list )
|
if( erase && list )
|
||||||
{
|
{
|
||||||
sb_printf(sb_err,
|
sb_printf(sb_err,
|
||||||
@@ -383,229 +498,241 @@ int builtin_set( wchar_t **argv )
|
|||||||
argv[0],
|
argv[0],
|
||||||
parser_current_line() );
|
parser_current_line() );
|
||||||
|
|
||||||
builtin_print_help( argv[0], sb_err );
|
// builtin_print_help( argv[0], sb_err );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Variables can only have one scope
|
||||||
|
*/
|
||||||
if( local + global + universal > 1 )
|
if( local + global + universal > 1 )
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
BUILTIN_ERR_GLOCAL,
|
BUILTIN_ERR_GLOCAL,
|
||||||
argv[0],
|
argv[0],
|
||||||
parser_current_line() );
|
parser_current_line() );
|
||||||
builtin_print_help( argv[0], sb_err );
|
// builtin_print_help( argv[0], sb_err );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Variables can only have one export status
|
||||||
|
*/
|
||||||
if( export && unexport )
|
if( export && unexport )
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
BUILTIN_ERR_EXPUNEXP,
|
BUILTIN_ERR_EXPUNEXP,
|
||||||
argv[0],
|
argv[0],
|
||||||
parser_current_line() );
|
parser_current_line() );
|
||||||
builtin_print_help( argv[0], sb_err );
|
// builtin_print_help( argv[0], sb_err );
|
||||||
return 1;
|
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 )
|
if( query )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Query mode. Return number of specified variables that do not exist.
|
Query mode. Return the number variables that do not exist
|
||||||
|
out of the specified variables.
|
||||||
*/
|
*/
|
||||||
int i;
|
int i;
|
||||||
for( i=woptind; i<argc; i++ )
|
for( i=woptind; i<argc; i++ )
|
||||||
{
|
{
|
||||||
if( !env_exist( argv[i] ) )
|
if( !env_exist( argv[i] ) )
|
||||||
|
{
|
||||||
retcode++;
|
retcode++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( woptind == argc )
|
||||||
/* Parse destination */
|
|
||||||
if( woptind < argc )
|
|
||||||
{
|
{
|
||||||
dest = wcsdup(argv[woptind++]);
|
/*
|
||||||
//fwprintf(stderr, L"Dest: %ls\n", dest);
|
Print values of variables
|
||||||
|
*/
|
||||||
|
|
||||||
if( !wcslen( dest ) )
|
if( erase )
|
||||||
{
|
{
|
||||||
free( dest );
|
sb_printf( sb_err,
|
||||||
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
|
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||||
return 1;
|
argv[0],
|
||||||
}
|
parser_current_line() );
|
||||||
}
|
|
||||||
|
// builtin_print_help( argv[0], sb_err );
|
||||||
/* Parse values */
|
|
||||||
// wchar_t **values = woptind < argc ? (wchar_t **) calloc(argc - woptind, sizeof(wchar_t *)) : 0;
|
|
||||||
|
|
||||||
al_init(&values);
|
|
||||||
while( woptind < argc )
|
|
||||||
{
|
|
||||||
al_push(&values, argv[woptind++]);
|
|
||||||
// fwprintf(stderr, L"Val: %ls\n", argv[woptind - 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;
|
|
||||||
//fwprintf(stderr, L"Name is %ls\n", name);
|
|
||||||
|
|
||||||
al_init(&indexes);
|
|
||||||
retval = parse_fill_indexes(&indexes, dest);
|
|
||||||
if (retval < 0)
|
|
||||||
retcode = 1;
|
retcode = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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( 1, 1, scope );
|
||||||
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 )
|
|
||||||
{
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
finished=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( !finished )
|
|
||||||
{
|
|
||||||
if( al_get_count( &values ) == 0 &&
|
|
||||||
al_get_count( &indexes ) == 0 &&
|
|
||||||
!erase &&
|
|
||||||
!list )
|
|
||||||
{
|
|
||||||
env_set( name, 0, scope );
|
|
||||||
finished = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !finished )
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( list )
|
||||||
|
{
|
||||||
|
/* 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( wcschr( dest, L'[' ) )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
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( !erase )
|
||||||
|
{
|
||||||
|
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 )
|
||||||
{
|
{
|
||||||
/* There are some arguments, we have at least a variable name */
|
/*
|
||||||
if( erase && al_get_count(&values) != 0 )
|
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 );
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
woptind++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
No slicing
|
||||||
|
*/
|
||||||
|
if( erase )
|
||||||
|
{
|
||||||
|
if( woptind != argc )
|
||||||
{
|
{
|
||||||
sb_printf( sb_err,
|
sb_printf( sb_err,
|
||||||
_(L"%ls: Values cannot be specfied with erase\n%ls\n"),
|
_(L"%ls: Values cannot be specfied with erase\n%ls\n"),
|
||||||
argv[0],
|
argv[0],
|
||||||
parser_current_line() );
|
parser_current_line() );
|
||||||
|
retcode=1;
|
||||||
builtin_print_help( argv[0], sb_err );
|
}
|
||||||
retcode = 1;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* All ok, we can alter the specified variable */
|
env_remove( dest, ENV_USER );
|
||||||
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);
|
|
||||||
env_set(name, (wchar_t *) result_sb.buff, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
update_values( &val_l,
|
|
||||||
&indexes,
|
|
||||||
&values );
|
|
||||||
|
|
||||||
fill_buffer_from_list( &result_sb,
|
|
||||||
&val_l );
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 );
|
retcode = my_env_set( dest, &val, scope );
|
||||||
al_destroy(&indexes);
|
|
||||||
|
al_destroy( &val );
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Common cleanup */
|
free( dest );
|
||||||
//fwprintf(stderr, L"Cleanup\n");
|
|
||||||
free(dest);
|
|
||||||
sb_destroy(&name_sb);
|
|
||||||
al_destroy( &values );
|
|
||||||
|
|
||||||
return retcode;
|
return retcode;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
162
common.c
162
common.c
@@ -61,17 +61,27 @@ parts of fish.
|
|||||||
#include "wildcard.h"
|
#include "wildcard.h"
|
||||||
#include "parser.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
|
The number of milliseconds to wait between polls when attempting to acquire
|
||||||
a lockfile
|
a lockfile
|
||||||
*/
|
*/
|
||||||
#define LOCKPOLLINTERVAL 10
|
#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;
|
struct termios shell_modes;
|
||||||
|
|
||||||
int error_max=1;
|
int error_max=1;
|
||||||
@@ -400,119 +410,17 @@ wchar_t **strv2wcsv( const char **in )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wchar_t *wcsvarname( wchar_t *str )
|
||||||
/*$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
size_t
|
|
||||||
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
|
||||||
{
|
|
||||||
|
|
||||||
register wchar_t *d = dst;
|
|
||||||
register const wchar_t *s = src;
|
|
||||||
register size_t n = siz;
|
|
||||||
size_t dlen;
|
|
||||||
|
|
||||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
|
||||||
while (n-- != 0 && *d != '\0')
|
|
||||||
d++;
|
|
||||||
|
|
||||||
dlen = d - dst;
|
|
||||||
n = siz - dlen;
|
|
||||||
|
|
||||||
if (n == 0)
|
|
||||||
return(dlen + wcslen(s));
|
|
||||||
|
|
||||||
while (*s != '\0')
|
|
||||||
{
|
|
||||||
if (n != 1)
|
|
||||||
{
|
|
||||||
*d++ = *s;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
*d = '\0';
|
|
||||||
|
|
||||||
return(dlen + (s - src));
|
|
||||||
/* count does not include NUL */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
size_t
|
|
||||||
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
|
||||||
{
|
|
||||||
register wchar_t *d = dst;
|
|
||||||
register const wchar_t *s = src;
|
|
||||||
register size_t n = siz;
|
|
||||||
|
|
||||||
/* Copy as many bytes as will fit */
|
|
||||||
if (n != 0 && --n != 0)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if ((*d++ = *s++) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (--n != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
|
||||||
if (n == 0)
|
|
||||||
{
|
|
||||||
if (siz != 0)
|
|
||||||
*d = '\0';
|
|
||||||
/* NUL-terminate dst */
|
|
||||||
while (*s++)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return(s - src - 1);
|
|
||||||
/* count does not include NUL */
|
|
||||||
}
|
|
||||||
|
|
||||||
int wcsvarname( wchar_t *str )
|
|
||||||
{
|
{
|
||||||
while( *str )
|
while( *str )
|
||||||
{
|
{
|
||||||
if( (!iswalnum(*str)) && (*str != L'_' ) )
|
if( (!iswalnum(*str)) && (*str != L'_' ) )
|
||||||
{
|
{
|
||||||
return 0;
|
return str;
|
||||||
}
|
}
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -597,6 +505,12 @@ int contains_str( const wchar_t *a, ... )
|
|||||||
wchar_t *arg;
|
wchar_t *arg;
|
||||||
va_list va;
|
va_list va;
|
||||||
int res = 0;
|
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 );
|
va_start( va, a );
|
||||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||||
@@ -641,23 +555,27 @@ void debug( int level, const wchar_t *msg, ... )
|
|||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
string_buffer_t sb;
|
string_buffer_t sb;
|
||||||
|
string_buffer_t sb2;
|
||||||
|
|
||||||
if( level > debug_level )
|
if( level > debug_level )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sb_init( &sb );
|
sb_init( &sb );
|
||||||
|
sb_init( &sb2 );
|
||||||
va_start( va, msg );
|
va_start( va, msg );
|
||||||
|
|
||||||
sb_printf( &sb, L"%ls: ", program_name );
|
sb_printf( &sb, L"%ls: ", program_name );
|
||||||
sb_vprintf( &sb, msg, va );
|
sb_vprintf( &sb, msg, va );
|
||||||
va_end( 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( &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;
|
const wchar_t *start, *pos;
|
||||||
int line_width = 0;
|
int line_width = 0;
|
||||||
@@ -707,8 +625,8 @@ void write_screen( const wchar_t *msg )
|
|||||||
*/
|
*/
|
||||||
wchar_t *token = wcsndup( start, pos-start );
|
wchar_t *token = wcsndup( start, pos-start );
|
||||||
if( line_width != 0 )
|
if( line_width != 0 )
|
||||||
putwc( L'\n', stderr );
|
sb_append_char( buff, L'\n' );
|
||||||
fwprintf( stderr, L"%ls-\n", token );
|
sb_printf( buff, L"%ls-\n", token );
|
||||||
free( token );
|
free( token );
|
||||||
line_width=0;
|
line_width=0;
|
||||||
}
|
}
|
||||||
@@ -720,10 +638,10 @@ void write_screen( const wchar_t *msg )
|
|||||||
wchar_t *token = wcsndup( start, pos-start );
|
wchar_t *token = wcsndup( start, pos-start );
|
||||||
if( (line_width + (line_width!=0?1:0) + tok_width) > screen_width )
|
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;
|
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 );
|
free( token );
|
||||||
line_width += (line_width!=0?1:0) + tok_width;
|
line_width += (line_width!=0?1:0) + tok_width;
|
||||||
}
|
}
|
||||||
@@ -738,9 +656,9 @@ void write_screen( const wchar_t *msg )
|
|||||||
}
|
}
|
||||||
else
|
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,
|
wchar_t *escape( const wchar_t *in,
|
||||||
@@ -934,14 +852,14 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
|||||||
int base=16;
|
int base=16;
|
||||||
|
|
||||||
int byte = 0;
|
int byte = 0;
|
||||||
int max_val = 127;
|
wchar_t max_val = ASCII_MAX;
|
||||||
|
|
||||||
switch( in[in_pos] )
|
switch( in[in_pos] )
|
||||||
{
|
{
|
||||||
case L'u':
|
case L'u':
|
||||||
{
|
{
|
||||||
chars=4;
|
chars=4;
|
||||||
max_val = 35535;
|
max_val = UCS2_MAX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,7 +878,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
|||||||
case L'X':
|
case L'X':
|
||||||
{
|
{
|
||||||
byte=1;
|
byte=1;
|
||||||
max_val = 255;
|
max_val = BYTE_MAX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,7 +904,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
|
|||||||
res=(res*base)|d;
|
res=(res*base)|d;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (res > 0) && (res <= max_val) )
|
if( (res <= max_val) )
|
||||||
{
|
{
|
||||||
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
|
||||||
}
|
}
|
||||||
|
|||||||
43
common.h
43
common.h
@@ -134,35 +134,18 @@ wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
|
|||||||
*/
|
*/
|
||||||
wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 );
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Test if the given string is a valid variable name
|
Test if the given string is a valid variable name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int wcsvarname( wchar_t *str );
|
|
||||||
|
/**
|
||||||
|
Test if the given string is a valid variable name.
|
||||||
|
|
||||||
|
\return null if this is a valid name, and a pointer to the first invalid character otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
wchar_t *wcsvarname( wchar_t *str );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,9 +181,11 @@ void error_reset();
|
|||||||
const wchar_t *wsetlocale( int category, const wchar_t *locale );
|
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
|
\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, ... );
|
int contains_str( const wchar_t *needle, ... );
|
||||||
|
|
||||||
@@ -302,10 +287,10 @@ int common_get_height();
|
|||||||
void common_handle_winch( int signal );
|
void common_handle_winch( int signal );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write paragraph of output to screen. Ignore newlines in message and
|
Write paragraph of output to the specified stringbuffer, and redo
|
||||||
perform internal line-breaking.
|
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
|
#endif
|
||||||
|
|||||||
10
complete.c
10
complete.c
@@ -1983,7 +1983,8 @@ void complete( const wchar_t *cmd,
|
|||||||
{
|
{
|
||||||
if( parser_is_subcommand( tok_last( &tok ) ) )
|
if( parser_is_subcommand( tok_last( &tok ) ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
free( current_command );
|
||||||
current_command = wcsdup( tok_last( &tok ) );
|
current_command = wcsdup( tok_last( &tok ) );
|
||||||
|
|
||||||
on_command = (pos <= tok_get_pos( &tok) + wcslen( 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;
|
error_max=old_error_max;
|
||||||
condition_cache_clear();
|
condition_cache_clear();
|
||||||
|
|
||||||
|
|||||||
22
configure.ac
22
configure.ac
@@ -1,5 +1,5 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT(fish,1.21.4,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
|
# If needed, run autoconf to regenerate the configure file
|
||||||
AC_MSG_CHECKING([if autoconf needs to be run])
|
AC_MSG_CHECKING([if autoconf needs to be run])
|
||||||
@@ -12,7 +12,7 @@ if test configure -ot configure.ac; then
|
|||||||
if autoconf; then
|
if autoconf; then
|
||||||
./configure "$@"
|
./configure "$@"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
else
|
else
|
||||||
AC_MSG_ERROR( [cannot find the autoconf program in your path.
|
AC_MSG_ERROR( [cannot find the autoconf program in your path.
|
||||||
This program needs to be run whenever the configure.ac file is modified.
|
This program needs to be run whenever the configure.ac file is modified.
|
||||||
@@ -85,7 +85,7 @@ AC_PROG_INSTALL
|
|||||||
# Check for doxygen, which is needed to build
|
# Check for doxygen, which is needed to build
|
||||||
AC_CHECK_PROG( has_doxygen, [doxygen], "true")
|
AC_CHECK_PROG( has_doxygen, [doxygen], "true")
|
||||||
|
|
||||||
if ! test $has_doxygen = "true"; then
|
if ! test "$has_doxygen" = "true"; then
|
||||||
AC_MSG_ERROR( [cannot find the Doxygen program in your path.
|
AC_MSG_ERROR( [cannot find the Doxygen program in your path.
|
||||||
This program is needed to build fish.
|
This program is needed to build fish.
|
||||||
Please install it and try again.])
|
Please install it and try again.])
|
||||||
@@ -276,7 +276,7 @@ AC_CHECK_HEADER([regex.h],
|
|||||||
# Check for presense of various functions
|
# Check for presense of various functions
|
||||||
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
|
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
|
||||||
AC_CHECK_FUNCS( futimes wcwidth wcswidth getopt_long wcstok fputwc fgetwc )
|
AC_CHECK_FUNCS( futimes wcwidth wcswidth getopt_long wcstok fputwc fgetwc )
|
||||||
AC_CHECK_FUNCS( wcstol dcgettext )
|
AC_CHECK_FUNCS( wcstol dcgettext wcslcat wcslcpy )
|
||||||
|
|
||||||
# Here follows a list of small programs used to test for various
|
# Here follows a list of small programs used to test for various
|
||||||
# features that Autoconf doesn't tell us about
|
# features that Autoconf doesn't tell us about
|
||||||
@@ -389,6 +389,20 @@ else
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
fi
|
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
|
# 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_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile etc/fish etc/fish_interactive.fish share/fish seq])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@@ -11,6 +11,22 @@ wildcarded values. The \c case statement is used together with the \c
|
|||||||
switch statement in order to determine which block should be
|
switch statement in order to determine which block should be
|
||||||
performed.
|
performed.
|
||||||
|
|
||||||
|
Each \c case command is given one or more parameter. The first \c case
|
||||||
|
command with a parameter that matches the string specified in the
|
||||||
|
switch command will be evaluated. \c case parameters may contain
|
||||||
|
wildcards. These need to be escaped or quoted in order to avoid
|
||||||
|
regular wildcard expansion using filenames.
|
||||||
|
|
||||||
|
Note that fish does not fall through on case statements. Though the
|
||||||
|
syntax may look a bit like C switch statements, it behaves more like
|
||||||
|
the case stamantes of traditional shells.
|
||||||
|
|
||||||
|
Also note that command substitutions in a case statement will be
|
||||||
|
evaluated even if it's body is not taken. This may seem
|
||||||
|
counterintuitive at first, but it is unavoidable, since it would be
|
||||||
|
impossible to know if a case command will evaluate to true before all
|
||||||
|
forms of parameter expansion have been performed for the case command.
|
||||||
|
|
||||||
\subsection case-example Example
|
\subsection case-example Example
|
||||||
|
|
||||||
If the variable \$animal contains the name of an animal, the following
|
If the variable \$animal contains the name of an animal, the following
|
||||||
@@ -27,9 +43,11 @@ switch $animal
|
|||||||
echo bird
|
echo bird
|
||||||
case shark trout stingray
|
case shark trout stingray
|
||||||
echo fish
|
echo fish
|
||||||
|
case '*'
|
||||||
|
echo I have no idea what a $animal is
|
||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If the above code was run with \$animal set to \c whale, the output would be \c mammal.
|
If the above code was run with \c \$animal set to \c whale, the output would be \c mammal.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -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
|
The reason for providing for two output file descriptors is to allow
|
||||||
separation of errors and warnings from regular program output.
|
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.
|
default through a simple mechanism called a redirection.
|
||||||
|
|
||||||
An example of a file redirection is <code> echo hello \>output.txt</code>,
|
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
|
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
|
for the variable '$USER' and not for the variable '$USERsan'. It's
|
||||||
simply a case of one syntax lending itself nicely to solving an
|
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
|
Variable expansion is the only type of expansion performed on double
|
||||||
quoted strings. There is, however, an important difference in how
|
quoted strings. There is, however, an important difference in how
|
||||||
@@ -644,7 +644,7 @@ echo $pirate
|
|||||||
\subsection variables-universal More on universal variables
|
\subsection variables-universal More on universal variables
|
||||||
|
|
||||||
Universal variables are variables that are shared between all the
|
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
|
configuration options as universal variables. This means that in order
|
||||||
to change fish settings, all you have to do is change the variable
|
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
|
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
|
\c fish also sends additional information to the user through the
|
||||||
values of certain environment variables. The user can not change 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 _, 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 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 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 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.
|
- \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
|
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
|
started by fish, those in lowercase are not exported. This rule is not
|
||||||
coding practice to use casing to distinguish between exported and
|
enforced by fish, but it is good coding practice to use casing to
|
||||||
unexported variables. \c fish also uses several variables
|
distinguish between exported and unexported variables. \c fish also
|
||||||
internally. Such variables are prefixed with the string __FISH or
|
uses several variables internally. Such variables are prefixed with
|
||||||
__fish. These should be ignored by the user.
|
the string __FISH or __fish. These should be ignored by the user.
|
||||||
|
|
||||||
\subsection variables-locale Locale variables
|
\subsection variables-locale Locale variables
|
||||||
|
|
||||||
@@ -1025,7 +1026,7 @@ Detected errors include:
|
|||||||
- Mismatched parenthesis
|
- Mismatched parenthesis
|
||||||
|
|
||||||
When the cursor is over a parenthesis or a quote, \c fish also
|
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
|
To customize the syntax highlighting, you can set the environment
|
||||||
variables \c fish_color_normal, \c fish_color_command, \c
|
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
|
If you install fish in your home directory, fish will not work
|
||||||
correctly for any other user than yourself. This is because fish needs
|
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
|
problem, either copy the initialization files to each fish users home
|
||||||
directory, or install them in /etc.
|
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
|
placeholders. These will be replaced by a value by fish at
|
||||||
runtime. You must always take care to use exactly the same
|
runtime. You must always take care to use exactly the same
|
||||||
placeholders in the same order in your translation. (Actually, there
|
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
|
introduction. See the full manual for the printf C function for more
|
||||||
information.)
|
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
|
- 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
|
- Syntax highlighting should mark cd to non-existing directories as an error
|
||||||
- wait shellscript
|
- wait shellscript
|
||||||
- Signal handler to save the history file before exiting from a signal
|
|
||||||
- Support for the screen clipboard
|
- 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
|
\subsection todo-possible Possible features
|
||||||
@@ -1284,7 +1286,7 @@ Examples:
|
|||||||
|
|
||||||
- Here documents are too similar to using echo inside of a pipeline.
|
- Here documents are too similar to using echo inside of a pipeline.
|
||||||
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
|
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
|
||||||
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish sunctions have none of the drawbacks of either syntax.
|
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish functions have none of the drawbacks of either syntax.
|
||||||
- The many Posix quoting styles are silly, especially \$''.
|
- The many Posix quoting styles are silly, especially \$''.
|
||||||
|
|
||||||
|
|
||||||
@@ -1377,14 +1379,14 @@ Examples:
|
|||||||
|
|
||||||
\subsection disc The law of discoverability
|
\subsection disc The law of discoverability
|
||||||
|
|
||||||
The shell should implement it's features in a way that makes them as
|
A program should be designed to make its features as
|
||||||
easy as possible for the user to discover for her/himself.
|
easy as possible to discover for the user.
|
||||||
|
|
||||||
Rationale:
|
Rationale:
|
||||||
|
|
||||||
A program whose features are discoverable makes a new user into an
|
A program whose features are discoverable turns a new user into an
|
||||||
expert in a shorter span of time, since the user will learn how to use
|
expert in a shorter span of time, since the user will become an expert
|
||||||
the program simply by using it.
|
on the program simply by using it.
|
||||||
|
|
||||||
The main benefit of a graphical program over a command line-based
|
The main benefit of a graphical program over a command line-based
|
||||||
program is discoverability. In a graphical program, one can discover
|
program is discoverability. In a graphical program, one can discover
|
||||||
|
|||||||
@@ -8,10 +8,13 @@
|
|||||||
The <tt>read</tt> builtin causes fish to read one line from standard
|
The <tt>read</tt> builtin causes fish to read one line from standard
|
||||||
input and store the result in one or more environment variables.
|
input and store the result in one or more environment variables.
|
||||||
|
|
||||||
|
- <tt>-c CMD</tt> or <tt>--command=CMD</tt> specifies that the initial string in the interactive mode command buffer should be CMD.
|
||||||
- <tt>-e</tt> or <tt>--export</tt> specifies that the variables will be exported to subshells.
|
- <tt>-e</tt> or <tt>--export</tt> specifies that the variables will be exported to subshells.
|
||||||
- <tt>-g</tt> or <tt>--global</tt> specifies that the variables will be made global.
|
- <tt>-g</tt> or <tt>--global</tt> specifies that the variables will be made global.
|
||||||
- <tt>-pPROMPT_CMD</tt> or <tt>--prompt=PROMPT_CMD</tt> specifies that the output of the shell command PROMPT_CMD should be used as the prompt for the interactive mode prompt. The default prompt command is <tt>set_color green; echo read; set_color normal; echo "> "</tt>.
|
- <tt>-p PROMPT_CMD</tt> or <tt>--prompt=PROMPT_CMD</tt> specifies that the output of the shell command PROMPT_CMD should be used as the prompt for the interactive mode prompt. The default prompt command is <tt>set_color green; echo read; set_color normal; echo "> "</tt>.
|
||||||
- <tt>-cCMD</tt> or <tt>--command=CMD</tt> specifies that the initial string in the interactive mode command buffer should be CMD.
|
- <code>-u</code> or <code>--unexport</code> causes the specified environment not to be exported to child processes
|
||||||
|
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be made universal. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
|
||||||
|
- <code>-x</code> or <code>--export</code> causes the specified environment variable to be exported to child processes
|
||||||
|
|
||||||
Read starts by reading a single line of input from stdin, the line is
|
Read starts by reading a single line of input from stdin, the line is
|
||||||
then tokenized using the <tt>IFS</tt> environment variable. Each variable
|
then tokenized using the <tt>IFS</tt> environment variable. Each variable
|
||||||
|
|||||||
@@ -8,7 +8,19 @@
|
|||||||
|
|
||||||
The \c switch statement is used to perform one of several blocks of
|
The \c switch statement is used to perform one of several blocks of
|
||||||
commands depending on whether a specified value equals one of several
|
commands depending on whether a specified value equals one of several
|
||||||
wildcarded values.
|
wildcarded values. The \c case statement is used together with the \c
|
||||||
|
switch statement in order to determine which block should be
|
||||||
|
performed.
|
||||||
|
|
||||||
|
Each \c case command is given one or more parameter. The first \c case
|
||||||
|
command with a parameter that matches the string specified in the
|
||||||
|
switch command will be evaluated. \c case parameters may contain
|
||||||
|
wildcards. These need to be escaped or quoted in order to avoid
|
||||||
|
regular wildcard expansion using filenames.
|
||||||
|
|
||||||
|
Note that fish does not fall through on case statements. Though the
|
||||||
|
syntax may look a bit like C switch statements, it behaves more like
|
||||||
|
the case stamantes of traditional shells.
|
||||||
|
|
||||||
\subsection switch-example Example
|
\subsection switch-example Example
|
||||||
|
|
||||||
@@ -26,12 +38,14 @@ switch $animal
|
|||||||
echo bird
|
echo bird
|
||||||
case shark trout stingray
|
case shark trout stingray
|
||||||
echo fish
|
echo fish
|
||||||
|
case '*'
|
||||||
|
echo I have no idea what a $animal is
|
||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
If the above code was run with \$animal set to \c whale, the output
|
If the above code was run with \c \$animal set to \c whale, the output
|
||||||
would be \c mammal.
|
would be \c mammal.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
17
env.c
17
env.c
@@ -104,7 +104,7 @@ typedef struct env_node
|
|||||||
typedef struct var_entry
|
typedef struct var_entry
|
||||||
{
|
{
|
||||||
int export; /**< Whether the variable should be exported */
|
int export; /**< Whether the variable should be exported */
|
||||||
wchar_t val[0]; /**< The value of the variable */
|
wchar_t val[1]; /**< The value of the variable */
|
||||||
}
|
}
|
||||||
var_entry_t;
|
var_entry_t;
|
||||||
|
|
||||||
@@ -608,9 +608,9 @@ static env_node_t *env_get_node( const wchar_t *key )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void env_set( const wchar_t *key,
|
int env_set( const wchar_t *key,
|
||||||
const wchar_t *val,
|
const wchar_t *val,
|
||||||
int var_mode )
|
int var_mode )
|
||||||
{
|
{
|
||||||
int free_val = 0;
|
int free_val = 0;
|
||||||
var_entry_t *entry;
|
var_entry_t *entry;
|
||||||
@@ -626,7 +626,7 @@ void env_set( const wchar_t *key,
|
|||||||
if( (var_mode & ENV_USER ) &&
|
if( (var_mode & ENV_USER ) &&
|
||||||
hash_get( &env_read_only, key ) )
|
hash_get( &env_read_only, key ) )
|
||||||
{
|
{
|
||||||
return;
|
return ENV_PERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wcscmp( key, L"umask" ) == 0)
|
if( wcscmp( key, L"umask" ) == 0)
|
||||||
@@ -650,7 +650,7 @@ void env_set( const wchar_t *key,
|
|||||||
/*
|
/*
|
||||||
Do not actually create a umask variable, on env_get, it will be calculated dynamically
|
Do not actually create a umask variable, on env_get, it will be calculated dynamically
|
||||||
*/
|
*/
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -749,7 +749,7 @@ void env_set( const wchar_t *key,
|
|||||||
node = top;
|
node = top;
|
||||||
while( node->next && !node->new_scope )
|
while( node->next && !node->new_scope )
|
||||||
node = node->next;
|
node = node->next;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -809,7 +809,8 @@ void env_set( const wchar_t *key,
|
|||||||
{
|
{
|
||||||
handle_locale();
|
handle_locale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
13
env.h
13
env.h
@@ -41,6 +41,11 @@
|
|||||||
*/
|
*/
|
||||||
#define ENV_UNIVERSAL 32
|
#define ENV_UNIVERSAL 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
Error code for trying to alter read-only variable
|
||||||
|
*/
|
||||||
|
#define ENV_PERM 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize environment variable data
|
Initialize environment variable data
|
||||||
*/
|
*/
|
||||||
@@ -61,9 +66,15 @@ void env_destroy();
|
|||||||
\param val The value
|
\param val The value
|
||||||
\param mode The type of the variable. Can be any combination of ENV_GLOBAL, ENV_LOCAL, ENV_EXPORT and ENV_USER. If mode is zero, the current variable space is searched and the current mode is used. If no current variable with the same name is found, ENV_LOCAL is assumed.
|
\param mode The type of the variable. Can be any combination of ENV_GLOBAL, ENV_LOCAL, ENV_EXPORT and ENV_USER. If mode is zero, the current variable space is searched and the current mode is used. If no current variable with the same name is found, ENV_LOCAL is assumed.
|
||||||
|
|
||||||
|
\returns 0 on suicess or an error code on failiure.
|
||||||
|
|
||||||
|
The current error codes are:
|
||||||
|
|
||||||
|
* ENV_PERM, can only be returned when setting as a user, e.g. ENV_USER is set. This means that the user tried to change a read-only variable.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void env_set( const wchar_t *key,
|
int env_set( const wchar_t *key,
|
||||||
const wchar_t *val,
|
const wchar_t *val,
|
||||||
int mode );
|
int mode );
|
||||||
|
|
||||||
|
|||||||
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
|
active, which is the one that new events is written to. The inactive
|
||||||
one contains the events that are currently beeing performed.
|
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
|
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;
|
event_t e;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Because of concurrency issues, env_remove does not actually free
|
Because of concurrency issues (env_remove could remove an event
|
||||||
any events - instead it simply moves all events that should be
|
that is currently being executed), env_remove does not actually
|
||||||
removed from the event list to the killme list.
|
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 )
|
if( !events )
|
||||||
@@ -617,7 +620,6 @@ void event_fire( event_t *event )
|
|||||||
|
|
||||||
void event_init()
|
void event_init()
|
||||||
{
|
{
|
||||||
sig_list[active_list].count=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_destroy()
|
void event_destroy()
|
||||||
@@ -653,3 +655,4 @@ void event_free( event_t *e )
|
|||||||
free( (void *)e->param1.variable );
|
free( (void *)e->param1.variable );
|
||||||
free( e );
|
free( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
exec.c
26
exec.c
@@ -126,7 +126,7 @@ int exec_pipe( int fd[2])
|
|||||||
|
|
||||||
if( open_fds == 0 )
|
if( open_fds == 0 )
|
||||||
{
|
{
|
||||||
open_fds = al_new();
|
open_fds = al_halloc( global_context );
|
||||||
}
|
}
|
||||||
|
|
||||||
al_push( open_fds, (void *)(long)fd[0] );
|
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
|
the redirection list io. This should make sure that there are no
|
||||||
stray opened file descriptors in the child.
|
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 )
|
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.
|
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 );
|
io_data_t *io_internal = io_transmogrify( io );
|
||||||
int is_block_old=is_block;
|
int is_block_old=is_block;
|
||||||
is_block=1;
|
is_block=1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Did the transmogrification fail - if so, set error status and return
|
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();
|
signal_unblock();
|
||||||
|
|
||||||
eval( def, io_internal, block_type );
|
eval( def, io_internal, block_type );
|
||||||
|
|
||||||
signal_block();
|
signal_block();
|
||||||
@@ -837,7 +824,7 @@ void exec( job_t *j )
|
|||||||
io_buffer = io_buffer_create();
|
io_buffer = io_buffer_create();
|
||||||
j->io = io_add( j->io, io_buffer );
|
j->io = io_add( j->io, io_buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_exec_helper( p->argv[0], TOP, j->io );
|
internal_exec_helper( p->argv[0], TOP, j->io );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -852,6 +839,7 @@ void exec( job_t *j )
|
|||||||
if( p == j->first_process )
|
if( p == j->first_process )
|
||||||
{
|
{
|
||||||
io_data_t *in = io_get( j->io, 0 );
|
io_data_t *in = io_get( j->io, 0 );
|
||||||
|
|
||||||
if( in )
|
if( in )
|
||||||
{
|
{
|
||||||
switch( in->io_mode )
|
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")
|
#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.
|
Execute the processes specified by j.
|
||||||
|
|
||||||
|
|||||||
46
expand.c
46
expand.c
@@ -421,17 +421,18 @@ static int find_process( const wchar_t *proc,
|
|||||||
{
|
{
|
||||||
|
|
||||||
int jid = wcstol( proc, 0, 10 );
|
int jid = wcstol( proc, 0, 10 );
|
||||||
|
if( jid > 0 )
|
||||||
j = job_get( jid );
|
|
||||||
if( (j != 0) && (j->command != 0 ) )
|
|
||||||
{
|
{
|
||||||
|
j = job_get( jid );
|
||||||
|
if( (j != 0) && (j->command != 0 ) )
|
||||||
{
|
{
|
||||||
result = malloc(sizeof(wchar_t)*16 );
|
|
||||||
swprintf( result, 16, L"%d", j->pgid );
|
{
|
||||||
//fwprintf( stderr, L"pid %d %ls\n", j->pgid, result );
|
result = malloc(sizeof(wchar_t)*16 );
|
||||||
al_push( out, result );
|
swprintf( result, 16, L"%d", j->pgid );
|
||||||
found = 1;
|
al_push( out, result );
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,12 +442,9 @@ static int find_process( const wchar_t *proc,
|
|||||||
|
|
||||||
for( j=first_job; j != 0; j=j->next )
|
for( j=first_job; j != 0; j=j->next )
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"..." );
|
|
||||||
if( j->command == 0 )
|
if( j->command == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// fwprintf( stderr, L"match '%ls' '%ls'\n\n\n", j->command, proc );
|
|
||||||
|
|
||||||
if( match_pid( j->command, proc, flags ) )
|
if( match_pid( j->command, proc, flags ) )
|
||||||
{
|
{
|
||||||
if( flags & ACCEPT_INCOMPLETE )
|
if( flags & ACCEPT_INCOMPLETE )
|
||||||
@@ -455,8 +453,6 @@ static int find_process( const wchar_t *proc,
|
|||||||
COMPLETE_SEP_STR,
|
COMPLETE_SEP_STR,
|
||||||
COMPLETE_JOB_DESC,
|
COMPLETE_JOB_DESC,
|
||||||
(void *)0 );
|
(void *)0 );
|
||||||
// fwprintf( stderr, L"Woot %ls\n", res );
|
|
||||||
|
|
||||||
al_push( out, res );
|
al_push( out, res );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -482,12 +478,9 @@ static int find_process( const wchar_t *proc,
|
|||||||
for( p=j->first_process; p; p=p->next )
|
for( p=j->first_process; p; p=p->next )
|
||||||
{
|
{
|
||||||
|
|
||||||
// fwprintf( stderr, L"..." );
|
|
||||||
if( p->actual_cmd == 0 )
|
if( p->actual_cmd == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// fwprintf( stderr, L"match '%ls' '%ls'\n\n\n", j->command, proc );
|
|
||||||
|
|
||||||
if( match_pid( p->actual_cmd, proc, flags ) )
|
if( match_pid( p->actual_cmd, proc, flags ) )
|
||||||
{
|
{
|
||||||
if( flags & ACCEPT_INCOMPLETE )
|
if( flags & ACCEPT_INCOMPLETE )
|
||||||
@@ -687,27 +680,22 @@ static int expand_pid( wchar_t *in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fwprintf( stderr, L"expand_pid() %ls\n", in );
|
|
||||||
int prev = al_get_count( out );
|
int prev = al_get_count( out );
|
||||||
if( !find_process( in+1, flags, out ) )
|
if( !find_process( in+1, flags, out ) )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if( prev == al_get_count( out ) )
|
if( prev == al_get_count( out ) )
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"no match\n" );
|
|
||||||
|
|
||||||
if( flags & ACCEPT_INCOMPLETE )
|
if( flags & ACCEPT_INCOMPLETE )
|
||||||
free( in );
|
free( in );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*in = L'%';
|
*in = L'%';
|
||||||
// fwprintf( stderr, L"return %ls\n", in );
|
|
||||||
al_push( out, in );
|
al_push( out, in );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// fwprintf( stderr, L"match\n" );
|
|
||||||
free( in );
|
free( in );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +955,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
wcsncpy( new_in, in, start_pos-1 );
|
wcslcpy( new_in, in, start_pos );
|
||||||
|
|
||||||
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
|
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
|
||||||
{
|
{
|
||||||
@@ -980,7 +968,6 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
|||||||
wcscat( new_in, next );
|
wcscat( new_in, next );
|
||||||
wcscat( new_in, &in[stop_pos] );
|
wcscat( new_in, &in[stop_pos] );
|
||||||
|
|
||||||
// fwprintf( stderr, L"New value %ls\n", new_in );
|
|
||||||
is_ok &= expand_variables( new_in, out, i );
|
is_ok &= expand_variables( new_in, out, i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1059,9 +1046,6 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
|||||||
wchar_t *item_begin;
|
wchar_t *item_begin;
|
||||||
int len1, len2, tot_len;
|
int len1, len2, tot_len;
|
||||||
|
|
||||||
// fwprintf( stderr, L"expand %ls\n", in );
|
|
||||||
|
|
||||||
|
|
||||||
for( pos=in;
|
for( pos=in;
|
||||||
(!bracket_end) && (*pos) && !syntax_error;
|
(!bracket_end) && (*pos) && !syntax_error;
|
||||||
pos++ )
|
pos++ )
|
||||||
@@ -1153,8 +1137,8 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
|||||||
int item_len = pos-item_begin;
|
int item_len = pos-item_begin;
|
||||||
|
|
||||||
whole_item = malloc( sizeof(wchar_t)*(tot_len + item_len + 1) );
|
whole_item = malloc( sizeof(wchar_t)*(tot_len + item_len + 1) );
|
||||||
wcsncpy( whole_item, in, len1 );
|
wcslcpy( whole_item, in, len1+1 );
|
||||||
wcsncpy( whole_item+len1, item_begin, item_len );
|
wcslcpy( whole_item+len1, item_begin, item_len+1 );
|
||||||
wcscpy( whole_item+len1+item_len, bracket_end+1 );
|
wcscpy( whole_item+len1+item_len, bracket_end+1 );
|
||||||
|
|
||||||
expand_brackets( whole_item, flags, out );
|
expand_brackets( whole_item, flags, out );
|
||||||
@@ -1234,7 +1218,7 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wcsncpy( subcmd, paran_begin+1, paran_end-paran_begin-1 );
|
wcslcpy( subcmd, paran_begin+1, paran_end-paran_begin );
|
||||||
subcmd[ paran_end-paran_begin-1]=0;
|
subcmd[ paran_end-paran_begin-1]=0;
|
||||||
|
|
||||||
if( exec_subshell( subcmd, &sub_res)==-1 )
|
if( exec_subshell( subcmd, &sub_res)==-1 )
|
||||||
@@ -1310,7 +1294,6 @@ static wchar_t * expand_tilde_internal( wchar_t *in )
|
|||||||
wchar_t *new_in=0;
|
wchar_t *new_in=0;
|
||||||
wchar_t *old_in=0;
|
wchar_t *old_in=0;
|
||||||
|
|
||||||
// fwprintf( stderr, L"Tilde expand ~%ls\n", (*ptr)+1 );
|
|
||||||
if( in[1] == '/' || in[1] == '\0' )
|
if( in[1] == '/' || in[1] == '\0' )
|
||||||
{
|
{
|
||||||
/* Current users home directory */
|
/* Current users home directory */
|
||||||
@@ -1439,7 +1422,6 @@ int expand_string( void *context,
|
|||||||
|
|
||||||
// debug( 1, L"Expand %ls", str );
|
// debug( 1, L"Expand %ls", str );
|
||||||
|
|
||||||
|
|
||||||
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
|
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
|
||||||
{
|
{
|
||||||
halloc_register( context, str );
|
halloc_register( context, str );
|
||||||
|
|||||||
118
fallback.c
118
fallback.c
@@ -818,8 +818,7 @@ wchar_t *wcsndup( const wchar_t *in, int c )
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
wcsncpy( res, in, c+1 );
|
wcslcpy( res, in, c+1 );
|
||||||
res[c] = L'\0';
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -888,6 +887,121 @@ long wcstol(const wchar_t *nptr,
|
|||||||
nptr++;
|
nptr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_WCSLCAT
|
||||||
|
|
||||||
|
/*$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||||
|
{
|
||||||
|
|
||||||
|
register wchar_t *d = dst;
|
||||||
|
register const wchar_t *s = src;
|
||||||
|
register size_t n = siz;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
|
while (n-- != 0 && *d != '\0')
|
||||||
|
d++;
|
||||||
|
|
||||||
|
dlen = d - dst;
|
||||||
|
n = siz - dlen;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return(dlen + wcslen(s));
|
||||||
|
|
||||||
|
while (*s != '\0')
|
||||||
|
{
|
||||||
|
if (n != 1)
|
||||||
|
{
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return(dlen + (s - src));
|
||||||
|
/* count does not include NUL */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_WCSLCPY
|
||||||
|
|
||||||
|
/*$OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t
|
||||||
|
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||||
|
{
|
||||||
|
register wchar_t *d = dst;
|
||||||
|
register const wchar_t *s = src;
|
||||||
|
register size_t n = siz;
|
||||||
|
|
||||||
|
/* Copy as many bytes as will fit */
|
||||||
|
if (n != 0 && --n != 0)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((*d++ = *s++) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (--n != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
if (siz != 0)
|
||||||
|
*d = '\0';
|
||||||
|
/* NUL-terminate dst */
|
||||||
|
while (*s++)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return(s - src - 1);
|
||||||
|
/* count does not include NUL */
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_BROKEN_DEL_CURTERM
|
||||||
|
|
||||||
|
int del_curterm(TERMINAL *oterm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
50
fallback.h
50
fallback.h
@@ -3,10 +3,18 @@
|
|||||||
#define FISH_FALLBACK_H
|
#define FISH_FALLBACK_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
#include <wchar.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
|
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
|
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 );
|
long convert_digit( wchar_t d, int base );
|
||||||
|
|
||||||
@@ -232,5 +241,42 @@ long wcstol(const wchar_t *nptr,
|
|||||||
int base);
|
int base);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef HAVE_WCSLCAT
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_WCSLCPY
|
||||||
|
|
||||||
|
/**
|
||||||
|
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 );
|
||||||
|
|
||||||
|
#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
|
#endif
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ static int pq_compare( void *e1, void *e2 )
|
|||||||
/**
|
/**
|
||||||
Test priority queue functionality
|
Test priority queue functionality
|
||||||
*/
|
*/
|
||||||
static int pq_test( int elements )
|
static void pq_test( int elements )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int prev;
|
int prev;
|
||||||
@@ -290,7 +290,7 @@ static int hash_test( int elements )
|
|||||||
/**
|
/**
|
||||||
Arraylist test
|
Arraylist test
|
||||||
*/
|
*/
|
||||||
static int al_test( int sz)
|
static void al_test( int sz)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
array_list_t l;
|
array_list_t l;
|
||||||
@@ -690,7 +690,6 @@ int main( int argc, char **argv )
|
|||||||
proc_init();
|
proc_init();
|
||||||
halloc_util_init();
|
halloc_util_init();
|
||||||
event_init();
|
event_init();
|
||||||
exec_init();
|
|
||||||
parser_init();
|
parser_init();
|
||||||
function_init();
|
function_init();
|
||||||
builtin_init();
|
builtin_init();
|
||||||
@@ -718,7 +717,6 @@ int main( int argc, char **argv )
|
|||||||
builtin_destroy();
|
builtin_destroy();
|
||||||
complete_destroy();
|
complete_destroy();
|
||||||
wutil_destroy();
|
wutil_destroy();
|
||||||
exec_destroy();
|
|
||||||
event_destroy();
|
event_destroy();
|
||||||
proc_destroy();
|
proc_destroy();
|
||||||
halloc_util_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);
|
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
|
Helper function for removing hidden functions
|
||||||
*/
|
*/
|
||||||
@@ -258,8 +271,25 @@ static void get_names_internal( const void *key,
|
|||||||
wchar_t *name = (wchar_t *)key;
|
wchar_t *name = (wchar_t *)key;
|
||||||
function_data_t *f = (function_data_t *)val;
|
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 );
|
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 )
|
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 );
|
autoload_names( list, get_hidden );
|
||||||
|
|
||||||
if( get_hidden )
|
if( get_hidden )
|
||||||
hash_get_keys( &function, list );
|
{
|
||||||
|
hash_foreach2( &function, &get_names_internal_all, list );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
hash_foreach2( &function, &get_names_internal, list );
|
hash_foreach2( &function, &get_names_internal, list );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,6 +202,10 @@ static void history_to_hash()
|
|||||||
{
|
{
|
||||||
history_data *d;
|
history_data *d;
|
||||||
|
|
||||||
|
if( !history_last )
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
d = (history_data *)hash_get( &history_table,
|
d = (history_data *)hash_get( &history_table,
|
||||||
mode_name );
|
mode_name );
|
||||||
|
|
||||||
|
|||||||
9
input.c
9
input.c
@@ -119,7 +119,8 @@ const wchar_t *name_arr[] =
|
|||||||
L"history-token-search-backward",
|
L"history-token-search-backward",
|
||||||
L"history-token-search-forward",
|
L"history-token-search-forward",
|
||||||
L"self-insert",
|
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 backward through list of previous commands for matching token",
|
||||||
L"Search forward 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"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_BACKWARD,
|
||||||
R_HISTORY_TOKEN_SEARCH_FORWARD,
|
R_HISTORY_TOKEN_SEARCH_FORWARD,
|
||||||
R_SELF_INSERT,
|
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
|
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_END_OF_LINE,
|
||||||
R_FORWARD_CHAR,
|
R_FORWARD_CHAR,
|
||||||
R_BACKWARD_CHAR,
|
R_BACKWARD_CHAR,
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ static wint_t readb()
|
|||||||
{
|
{
|
||||||
unsigned char arr[1];
|
unsigned char arr[1];
|
||||||
int do_loop = 0;
|
int do_loop = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
fd_set fd;
|
fd_set fd;
|
||||||
@@ -93,17 +93,21 @@ static wint_t readb()
|
|||||||
{
|
{
|
||||||
int res = interrupt_handler();
|
int res = interrupt_handler();
|
||||||
if( res )
|
if( res )
|
||||||
|
{
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
do_loop = 1;
|
do_loop = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
/*
|
||||||
wperror(L"read");
|
The teminal has been closed. Save and exit.
|
||||||
exit(1);
|
*/
|
||||||
|
return R_EOF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,17 +119,17 @@ static wint_t readb()
|
|||||||
{
|
{
|
||||||
debug( 3, L"Wake up on universal variable event" );
|
debug( 3, L"Wake up on universal variable event" );
|
||||||
env_universal_read_all();
|
env_universal_read_all();
|
||||||
debug( 3, L"Return R_NULL" );
|
do_loop = 1;
|
||||||
return R_NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( FD_ISSET( 0, &fd ) )
|
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");
|
The teminal has been closed. Save and exit.
|
||||||
exit(1);
|
*/
|
||||||
|
return R_EOF;
|
||||||
}
|
}
|
||||||
do_loop = 0;
|
do_loop = 0;
|
||||||
}
|
}
|
||||||
@@ -180,8 +184,8 @@ wchar_t input_common_readch( int timed )
|
|||||||
|
|
||||||
int sz;
|
int sz;
|
||||||
|
|
||||||
if( b == R_NULL )
|
if( (b == R_NULL) || (b == R_EOF) )
|
||||||
return R_NULL;
|
return b;
|
||||||
|
|
||||||
bb=b;
|
bb=b;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ enum
|
|||||||
requested but none could be delivered, or when an exception
|
requested but none could be delivered, or when an exception
|
||||||
happened.
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static void io_print( io_data_t *io )
|
void io_print( io_data_t *io )
|
||||||
{
|
{
|
||||||
if( !io )
|
if( !io )
|
||||||
{
|
{
|
||||||
fwprintf( stderr, L"\n" );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug( 1, L"IO fd %d, type ",
|
||||||
fwprintf( stderr, L"IO fd %d, type ",
|
|
||||||
io->fd );
|
io->fd );
|
||||||
switch( io->io_mode )
|
switch( io->io_mode )
|
||||||
{
|
{
|
||||||
case IO_PIPE:
|
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;
|
break;
|
||||||
|
|
||||||
case IO_FD:
|
case IO_FD:
|
||||||
fwprintf(stderr, L"FD, copy %d\n", io->old_fd );
|
debug( 1, L"FD, copy %d", io->param1.old_fd );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IO_BUFFER:
|
case IO_BUFFER:
|
||||||
fwprintf( stderr, L"BUFFER\n" );
|
debug( 1, L"BUFFER" );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fwprintf( stderr, L"OTHER\n" );
|
debug( 1, L"OTHER" );
|
||||||
}
|
}
|
||||||
|
|
||||||
io_print( io->next );
|
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_buffer_read( io_data_t *d );
|
||||||
|
|
||||||
|
void io_print( io_data_t *io );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
Type ^C to exit the program.
|
Type ^C to exit the program.
|
||||||
*/
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
28
main.c
28
main.c
@@ -61,7 +61,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "translate.h"
|
#include "translate.h"
|
||||||
#include "halloc_util.h"
|
#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
|
Parse init files
|
||||||
@@ -79,9 +84,9 @@ static int read_init()
|
|||||||
|
|
||||||
env_set( L"__fish_help_dir", DOCDIR, 0);
|
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 " DATADIR L"/fish 2>/dev/null; and . 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 " SYSCONFDIR L" 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
|
||||||
eval( L"builtin cd 2>/dev/null;. .fish 2>/dev/null", 0, TOP );
|
eval( L"builtin cd 2>/dev/null; and . .fish 2>/dev/null", 0, TOP );
|
||||||
|
|
||||||
if( chdir( cwd ) == -1 )
|
if( chdir( cwd ) == -1 )
|
||||||
{
|
{
|
||||||
@@ -164,14 +169,14 @@ int main( int argc, char **argv )
|
|||||||
|
|
||||||
int opt = getopt_long( argc,
|
int opt = getopt_long( argc,
|
||||||
argv,
|
argv,
|
||||||
"hilnvc:p:d:",
|
GETOPT_STRING,
|
||||||
long_options,
|
long_options,
|
||||||
&opt_index );
|
&opt_index );
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int opt = getopt( argc,
|
int opt = getopt( argc,
|
||||||
argv,
|
argv,
|
||||||
"hilnvc:p:d:" );
|
GETOPT_STRING );
|
||||||
#endif
|
#endif
|
||||||
if( opt == -1 )
|
if( opt == -1 )
|
||||||
break;
|
break;
|
||||||
@@ -258,7 +263,6 @@ int main( int argc, char **argv )
|
|||||||
|
|
||||||
proc_init();
|
proc_init();
|
||||||
event_init();
|
event_init();
|
||||||
exec_init();
|
|
||||||
wutil_init();
|
wutil_init();
|
||||||
parser_init();
|
parser_init();
|
||||||
builtin_init();
|
builtin_init();
|
||||||
@@ -266,6 +270,7 @@ int main( int argc, char **argv )
|
|||||||
env_init();
|
env_init();
|
||||||
complete_init();
|
complete_init();
|
||||||
reader_init();
|
reader_init();
|
||||||
|
history_init();
|
||||||
|
|
||||||
if( read_init() )
|
if( read_init() )
|
||||||
{
|
{
|
||||||
@@ -274,7 +279,7 @@ int main( int argc, char **argv )
|
|||||||
wchar_t *cmd_wcs = str2wcs( cmd );
|
wchar_t *cmd_wcs = str2wcs( cmd );
|
||||||
res = eval( cmd_wcs, 0, TOP );
|
res = eval( cmd_wcs, 0, TOP );
|
||||||
free(cmd_wcs);
|
free(cmd_wcs);
|
||||||
reader_exit(0);
|
reader_exit(0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -297,10 +302,10 @@ int main( int argc, char **argv )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb_init( &sb );
|
|
||||||
|
|
||||||
if( *(argv+2))
|
if( *(argv+2))
|
||||||
{
|
{
|
||||||
|
sb_init( &sb );
|
||||||
|
|
||||||
for( i=1,ptr = argv+2; *ptr; i++, ptr++ )
|
for( i=1,ptr = argv+2; *ptr; i++, ptr++ )
|
||||||
{
|
{
|
||||||
if( i != 1 )
|
if( i != 1 )
|
||||||
@@ -336,7 +341,8 @@ int main( int argc, char **argv )
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
|
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
|
||||||
|
|
||||||
|
history_destroy();
|
||||||
complete_destroy();
|
complete_destroy();
|
||||||
proc_destroy();
|
proc_destroy();
|
||||||
env_destroy();
|
env_destroy();
|
||||||
@@ -345,12 +351,12 @@ int main( int argc, char **argv )
|
|||||||
reader_destroy();
|
reader_destroy();
|
||||||
parser_destroy();
|
parser_destroy();
|
||||||
wutil_destroy();
|
wutil_destroy();
|
||||||
exec_destroy();
|
|
||||||
event_destroy();
|
event_destroy();
|
||||||
|
|
||||||
common_destroy();
|
common_destroy();
|
||||||
halloc_util_destroy();
|
halloc_util_destroy();
|
||||||
intern_free_all();
|
intern_free_all();
|
||||||
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
255
parser.c
255
parser.c
@@ -101,12 +101,12 @@ The fish parser. Contains functions for parsing code.
|
|||||||
/**
|
/**
|
||||||
Error message when a non-string token is found when expecting a command name
|
Error message when a non-string token is found when expecting a command name
|
||||||
*/
|
*/
|
||||||
#define CMD_OR_ERR_MSG _( L"Expected a command name, got token of type '%ls'. Did you mean 'COMMAND; or COMMAND'? For more information on the 'or' builtin command, see the help section for 'or' by typing 'help or'.")
|
#define CMD_OR_ERR_MSG _( L"Expected a command name, got token of type '%ls'. Did you mean 'COMMAND; or COMMAND'? See the help section for the 'or' builtin command by typing 'help or'.")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Error message when a non-string token is found when expecting a command name
|
Error message when a non-string token is found when expecting a command name
|
||||||
*/
|
*/
|
||||||
#define CMD_AND_ERR_MSG _( L"Expected a command name, got token of type '%ls'. Did you mean 'COMMAND; and COMMAND'? For more information on the 'and' builtin command, see the help section for 'and' by typing 'help and'.")
|
#define CMD_AND_ERR_MSG _( L"Expected a command name, got token of type '%ls'. Did you mean 'COMMAND; and COMMAND'? See the help section for the 'and' builtin command by typing 'help and'.")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Error message when encountering an illegal command name
|
Error message when encountering an illegal command name
|
||||||
@@ -165,7 +165,7 @@ The fish parser. Contains functions for parsing code.
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Error for wrong token type
|
Error for wrong token type
|
||||||
*/
|
*/
|
||||||
#define UNEXPECTED_TOKEN_ERR_MSG _( L"Unexpected token of type '%ls'")
|
#define UNEXPECTED_TOKEN_ERR_MSG _( L"Unexpected token of type '%ls'")
|
||||||
|
|
||||||
@@ -176,78 +176,78 @@ The fish parser. Contains functions for parsing code.
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
While block description
|
While block description
|
||||||
*/
|
*/
|
||||||
#define WHILE_BLOCK _( L"'while' block" )
|
#define WHILE_BLOCK _( L"'while' block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
For block description
|
For block description
|
||||||
*/
|
*/
|
||||||
#define FOR_BLOCK _( L"'for' block" )
|
#define FOR_BLOCK _( L"'for' block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
If block description
|
If block description
|
||||||
*/
|
*/
|
||||||
#define IF_BLOCK _( L"'if' conditional block" )
|
#define IF_BLOCK _( L"'if' conditional block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
function definition block description
|
Function definition block description
|
||||||
*/
|
*/
|
||||||
#define FUNCTION_DEF_BLOCK _( L"function definition block" )
|
#define FUNCTION_DEF_BLOCK _( L"function definition block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Function invocation block description
|
Function invocation block description
|
||||||
*/
|
*/
|
||||||
#define FUNCTION_CALL_BLOCK _( L"function invocation block" )
|
#define FUNCTION_CALL_BLOCK _( L"function invocation block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Switch block description
|
Switch block description
|
||||||
*/
|
*/
|
||||||
#define SWITCH_BLOCK _( L"'switch' block" )
|
#define SWITCH_BLOCK _( L"'switch' block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Fake block description
|
Fake block description
|
||||||
*/
|
*/
|
||||||
#define FAKE_BLOCK _( L"unexecutable block" )
|
#define FAKE_BLOCK _( L"unexecutable block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Top block description
|
Top block description
|
||||||
*/
|
*/
|
||||||
#define TOP_BLOCK _( L"global root block" )
|
#define TOP_BLOCK _( L"global root block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Command substitution block description
|
Command substitution block description
|
||||||
*/
|
*/
|
||||||
#define SUBST_BLOCK _( L"command substitution block" )
|
#define SUBST_BLOCK _( L"command substitution block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Begin block description
|
Begin block description
|
||||||
*/
|
*/
|
||||||
#define BEGIN_BLOCK _( L"'begin' unconditional block" )
|
#define BEGIN_BLOCK _( L"'begin' unconditional block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Source block description
|
Source block description
|
||||||
*/
|
*/
|
||||||
#define SOURCE_BLOCK _( L"Block created by the . builtin" )
|
#define SOURCE_BLOCK _( L"Block created by the . builtin" )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Source block description
|
Source block description
|
||||||
*/
|
*/
|
||||||
#define EVENT_BLOCK _( L"event handler block" )
|
#define EVENT_BLOCK _( L"event handler block" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Unknown block description
|
Unknown block description
|
||||||
*/
|
*/
|
||||||
#define UNKNOWN_BLOCK _( L"unknown/invalid block" )
|
#define UNKNOWN_BLOCK _( L"unknown/invalid block" )
|
||||||
|
|
||||||
@@ -724,75 +724,85 @@ wchar_t *get_filename( const wchar_t *cmd )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
path = env_get(L"PATH");
|
path = env_get(L"PATH");
|
||||||
if( path != 0 )
|
if( path == 0 )
|
||||||
{
|
{
|
||||||
/*
|
if( contains_str( PREFIX L"/bin", L"/bin", L"/usr/bin", (void *)0 ) )
|
||||||
Allocate string long enough to hold the whole command
|
|
||||||
*/
|
|
||||||
wchar_t *new_cmd = malloc( sizeof(wchar_t)*(wcslen(cmd)+wcslen(path)+2) );
|
|
||||||
/*
|
|
||||||
We tokenize a copy of the path, since strtok modifies
|
|
||||||
its arguments
|
|
||||||
*/
|
|
||||||
wchar_t *path_cpy = wcsdup( path );
|
|
||||||
wchar_t *nxt_path = path;
|
|
||||||
wchar_t *state;
|
|
||||||
|
|
||||||
if( (new_cmd==0) || (path_cpy==0) )
|
|
||||||
{
|
{
|
||||||
die_mem();
|
path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
|
|
||||||
nxt_path != 0;
|
|
||||||
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
|
|
||||||
{
|
{
|
||||||
int path_len = wcslen( nxt_path );
|
path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
|
||||||
wcscpy( new_cmd, nxt_path );
|
|
||||||
if( new_cmd[path_len-1] != L'/' )
|
|
||||||
{
|
|
||||||
new_cmd[path_len++]=L'/';
|
|
||||||
}
|
|
||||||
wcscpy( &new_cmd[path_len], cmd );
|
|
||||||
if( waccess( new_cmd, X_OK )==0 )
|
|
||||||
{
|
|
||||||
struct stat buff;
|
|
||||||
if( wstat( new_cmd, &buff )==-1 )
|
|
||||||
{
|
|
||||||
if( errno != EACCES )
|
|
||||||
{
|
|
||||||
wperror( L"stat" );
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( S_ISREG(buff.st_mode) )
|
|
||||||
{
|
|
||||||
free( path_cpy );
|
|
||||||
return new_cmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch( errno )
|
|
||||||
{
|
|
||||||
case ENOENT:
|
|
||||||
case ENAMETOOLONG:
|
|
||||||
case EACCES:
|
|
||||||
case ENOTDIR:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
debug( 1,
|
|
||||||
MISSING_COMMAND_ERR_MSG,
|
|
||||||
new_cmd );
|
|
||||||
wperror( L"access" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free( path_cpy );
|
|
||||||
free( new_cmd );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Allocate string long enough to hold the whole command
|
||||||
|
*/
|
||||||
|
wchar_t *new_cmd = malloc( sizeof(wchar_t)*(wcslen(cmd)+wcslen(path)+2) );
|
||||||
|
/*
|
||||||
|
We tokenize a copy of the path, since strtok modifies
|
||||||
|
its arguments
|
||||||
|
*/
|
||||||
|
wchar_t *path_cpy = wcsdup( path );
|
||||||
|
wchar_t *nxt_path = path;
|
||||||
|
wchar_t *state;
|
||||||
|
|
||||||
|
if( (new_cmd==0) || (path_cpy==0) )
|
||||||
|
{
|
||||||
|
die_mem();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
|
||||||
|
nxt_path != 0;
|
||||||
|
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
|
||||||
|
{
|
||||||
|
int path_len = wcslen( nxt_path );
|
||||||
|
wcscpy( new_cmd, nxt_path );
|
||||||
|
if( new_cmd[path_len-1] != L'/' )
|
||||||
|
{
|
||||||
|
new_cmd[path_len++]=L'/';
|
||||||
|
}
|
||||||
|
wcscpy( &new_cmd[path_len], cmd );
|
||||||
|
if( waccess( new_cmd, X_OK )==0 )
|
||||||
|
{
|
||||||
|
struct stat buff;
|
||||||
|
if( wstat( new_cmd, &buff )==-1 )
|
||||||
|
{
|
||||||
|
if( errno != EACCES )
|
||||||
|
{
|
||||||
|
wperror( L"stat" );
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( S_ISREG(buff.st_mode) )
|
||||||
|
{
|
||||||
|
free( path_cpy );
|
||||||
|
return new_cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch( errno )
|
||||||
|
{
|
||||||
|
case ENOENT:
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
case EACCES:
|
||||||
|
case ENOTDIR:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
debug( 1,
|
||||||
|
MISSING_COMMAND_ERR_MSG,
|
||||||
|
new_cmd );
|
||||||
|
wperror( L"access" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free( path_cpy );
|
||||||
|
free( new_cmd );
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -934,7 +944,7 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
|||||||
int do_loop=1;
|
int do_loop=1;
|
||||||
|
|
||||||
proc_push_interactive(0);
|
proc_push_interactive(0);
|
||||||
|
current_tokenizer = &tok;
|
||||||
current_tokenizer_pos = 0;
|
current_tokenizer_pos = 0;
|
||||||
|
|
||||||
tok_init( &tok, line, 0 );
|
tok_init( &tok, line, 0 );
|
||||||
@@ -1101,8 +1111,8 @@ int parser_get_lineno()
|
|||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
/* static const wchar_t *prev_str = 0;
|
/* static const wchar_t *prev_str = 0;
|
||||||
static int i=0;
|
static int i=0;
|
||||||
static int lineno=1;
|
static int lineno=1;
|
||||||
*/
|
*/
|
||||||
if( !current_tokenizer )
|
if( !current_tokenizer )
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1163,9 +1173,9 @@ wchar_t *parser_current_line()
|
|||||||
{
|
{
|
||||||
int lineno=1;
|
int lineno=1;
|
||||||
|
|
||||||
const wchar_t *file = parser_current_filename();
|
const wchar_t *file;
|
||||||
wchar_t *whole_str = tok_string( current_tokenizer );
|
wchar_t *whole_str;
|
||||||
wchar_t *line = whole_str;
|
wchar_t *line;
|
||||||
wchar_t *line_end;
|
wchar_t *line_end;
|
||||||
int i;
|
int i;
|
||||||
int offset;
|
int offset;
|
||||||
@@ -1173,6 +1183,14 @@ wchar_t *parser_current_line()
|
|||||||
const wchar_t *function_name=0;
|
const wchar_t *function_name=0;
|
||||||
int current_line_start=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 )
|
if( !line )
|
||||||
return L"";
|
return L"";
|
||||||
@@ -1241,8 +1259,8 @@ wchar_t *parser_current_line()
|
|||||||
|
|
||||||
// debug( 1, L"Current pos %d, line pos %d, file_length %d, is_interactive %d, offset %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str), is_interactive, offset);
|
// debug( 1, L"Current pos %d, line pos %d, file_length %d, is_interactive %d, offset %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str), is_interactive, offset);
|
||||||
/*
|
/*
|
||||||
Skip printing character position if we are in interactive mode
|
Skip printing character position if we are in interactive mode
|
||||||
and the error was on the first character of the line.
|
and the error was on the first character of the line.
|
||||||
*/
|
*/
|
||||||
if( !is_interactive || is_function() || (current_line_width!=0) )
|
if( !is_interactive || is_function() || (current_line_width!=0) )
|
||||||
{
|
{
|
||||||
@@ -1716,8 +1734,8 @@ static int parse_job( process_t *p,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
error( SYNTAX_ERROR,
|
error( SYNTAX_ERROR,
|
||||||
tok_get_pos( tok ),
|
tok_get_pos( tok ),
|
||||||
CMD_ERR_MSG,
|
CMD_ERR_MSG,
|
||||||
tok_get_desc( tok_last_type(tok) ) );
|
tok_get_desc( tok_last_type(tok) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1860,6 +1878,7 @@ static int parse_job( process_t *p,
|
|||||||
|
|
||||||
consumed=1;
|
consumed=1;
|
||||||
is_new_block=1;
|
is_new_block=1;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if( wcscmp( L"if", nxt ) ==0 )
|
else if( wcscmp( L"if", nxt ) ==0 )
|
||||||
{
|
{
|
||||||
@@ -1919,15 +1938,15 @@ static int parse_job( process_t *p,
|
|||||||
builtin_exists( (wchar_t *)al_get( args, 0 ) ) )
|
builtin_exists( (wchar_t *)al_get( args, 0 ) ) )
|
||||||
{
|
{
|
||||||
p->type = INTERNAL_BUILTIN;
|
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 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !p->type || (p->type == INTERNAL_EXEC) )
|
if( !p->type || (p->type == INTERNAL_EXEC) )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we are not executing the current block, allow
|
If we are not executing the current block, allow
|
||||||
non-existent commands.
|
non-existent commands.
|
||||||
*/
|
*/
|
||||||
if( current_block->skip )
|
if( current_block->skip )
|
||||||
{
|
{
|
||||||
@@ -1971,7 +1990,8 @@ static int parse_job( process_t *p,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int tmp;
|
int tmp;
|
||||||
|
wchar_t *cmd = (wchar_t *)al_get( args, 0 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We couln't find the specified command.
|
We couln't find the specified command.
|
||||||
|
|
||||||
@@ -1986,19 +2006,42 @@ static int parse_job( process_t *p,
|
|||||||
cause the job to silently not execute. We
|
cause the job to silently not execute. We
|
||||||
also print an error message.
|
also print an error message.
|
||||||
*/
|
*/
|
||||||
if( wcschr( (wchar_t *)al_get( args, 0 ), L'=' ) )
|
if( wcschr( cmd, L'=' ) )
|
||||||
{
|
{
|
||||||
debug( 0,
|
debug( 0,
|
||||||
COMMAND_ASSIGN_ERR_MSG,
|
COMMAND_ASSIGN_ERR_MSG,
|
||||||
(wchar_t *)al_get( args, 0 ) );
|
(wchar_t *)al_get( args, 0 ) );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else if(cmd[0]==L'$')
|
||||||
|
{
|
||||||
|
wchar_t *val = env_get( cmd+1 );
|
||||||
|
if( val )
|
||||||
|
{
|
||||||
|
debug( 0,
|
||||||
|
_(L"Variables may not be used as commands. Instead, define a function like 'function %ls; %ls $argv; end'. See the help section for the function command by typing 'help function'." ),
|
||||||
|
cmd+1,
|
||||||
|
val,
|
||||||
|
cmd );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug( 0,
|
||||||
|
_(L"Variables may not be used as commands. Instead, define a function. See the help section for the function command by typing 'help function'." ),
|
||||||
|
cmd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(wcschr( cmd, L'$' ))
|
||||||
{
|
{
|
||||||
|
debug( 0,
|
||||||
|
_(L"Commands may not contain variables. Use the eval builtin instead, like 'eval %ls'. See the help section for the eval command by typing 'help eval'." ),
|
||||||
|
cmd,
|
||||||
|
cmd );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
debug( 0,
|
debug( 0,
|
||||||
_(L"Unknown command '%ls'"),
|
_(L"Unknown command '%ls'"),
|
||||||
(wchar_t *)al_get( args, 0 ) );
|
cmd );
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = current_tokenizer_pos;
|
tmp = current_tokenizer_pos;
|
||||||
@@ -2033,6 +2076,7 @@ static int parse_job( process_t *p,
|
|||||||
|
|
||||||
if( !make_sub_block )
|
if( !make_sub_block )
|
||||||
{
|
{
|
||||||
|
|
||||||
tok_init( &subtok, end, 0 );
|
tok_init( &subtok, end, 0 );
|
||||||
switch( tok_last_type( &subtok ) )
|
switch( tok_last_type( &subtok ) )
|
||||||
{
|
{
|
||||||
@@ -2058,17 +2102,18 @@ static int parse_job( process_t *p,
|
|||||||
}
|
}
|
||||||
tok_destroy( &subtok );
|
tok_destroy( &subtok );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( make_sub_block )
|
if( make_sub_block )
|
||||||
{
|
{
|
||||||
|
|
||||||
int end_pos = end-tok_string( tok );
|
int end_pos = end-tok_string( tok );
|
||||||
wchar_t *sub_block= wcsndup( tok_string( tok ) + current_tokenizer_pos,
|
wchar_t *sub_block= halloc_wcsndup( j,
|
||||||
end_pos - current_tokenizer_pos);
|
tok_string( tok ) + current_tokenizer_pos,
|
||||||
|
end_pos - current_tokenizer_pos);
|
||||||
|
|
||||||
p->type = INTERNAL_BLOCK;
|
p->type = INTERNAL_BLOCK;
|
||||||
al_set( args, 0, sub_block );
|
al_set( args, 0, sub_block );
|
||||||
|
|
||||||
tok_set_pos( tok,
|
tok_set_pos( tok,
|
||||||
end_pos );
|
end_pos );
|
||||||
|
|
||||||
@@ -2482,7 +2527,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Restore previous eval state
|
Restore previous eval state
|
||||||
*/
|
*/
|
||||||
forbidden_function = prev_forbidden;
|
forbidden_function = prev_forbidden;
|
||||||
current_tokenizer=previous_tokenizer;
|
current_tokenizer=previous_tokenizer;
|
||||||
|
|||||||
4
proc.c
4
proc.c
@@ -182,7 +182,7 @@ int proc_get_last_status()
|
|||||||
|
|
||||||
job_t *job_create()
|
job_t *job_create()
|
||||||
{
|
{
|
||||||
int free_id=0;
|
int free_id=1;
|
||||||
job_t *res;
|
job_t *res;
|
||||||
|
|
||||||
while( job_get( free_id ) != 0 )
|
while( job_get( free_id ) != 0 )
|
||||||
@@ -204,7 +204,7 @@ job_t *job_create()
|
|||||||
job_t *job_get( int id )
|
job_t *job_get( int id )
|
||||||
{
|
{
|
||||||
job_t *res = first_job;
|
job_t *res = first_job;
|
||||||
if( id == -1 )
|
if( id <= 0 )
|
||||||
{
|
{
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
5
proc.h
5
proc.h
@@ -261,7 +261,7 @@ job_t *job_create();
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Return the job with the specified job id.
|
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);
|
job_t *job_get(int id);
|
||||||
|
|
||||||
@@ -328,7 +328,8 @@ void proc_update_jiffies();
|
|||||||
void proc_sanity_check();
|
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 );
|
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status );
|
||||||
|
|
||||||
|
|||||||
72
reader.c
72
reader.c
@@ -232,6 +232,11 @@ typedef struct reader_data
|
|||||||
When this is true, the reader will exit
|
When this is true, the reader will exit
|
||||||
*/
|
*/
|
||||||
int end_loop;
|
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
|
Pointer to previous reader_data
|
||||||
@@ -299,6 +304,11 @@ static void reader_save_status();
|
|||||||
static void reader_check_status();
|
static void reader_check_status();
|
||||||
static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int pos, array_list_t *error );
|
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
|
Give up control of terminal
|
||||||
@@ -370,6 +380,12 @@ static int room_for_usec(struct stat *st)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int reader_exit_forced()
|
||||||
|
{
|
||||||
|
return exit_forced;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
string_buffer used as temporary storage for the reader_readline function
|
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 )
|
if( data )
|
||||||
data->end_loop=do_exit;
|
data->end_loop=do_exit;
|
||||||
end_loop=do_exit;
|
end_loop=do_exit;
|
||||||
|
if( forced )
|
||||||
|
exit_forced = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void repaint()
|
void repaint()
|
||||||
@@ -1631,7 +1650,6 @@ static void reader_interactive_init()
|
|||||||
|
|
||||||
|
|
||||||
al_init( &prompt_list );
|
al_init( &prompt_list );
|
||||||
history_init();
|
|
||||||
|
|
||||||
common_handle_winch(0);
|
common_handle_winch(0);
|
||||||
|
|
||||||
@@ -1658,7 +1676,6 @@ static void reader_interactive_destroy()
|
|||||||
kill_destroy();
|
kill_destroy();
|
||||||
al_foreach( &prompt_list, (void (*)(const void *))&free );
|
al_foreach( &prompt_list, (void (*)(const void *))&free );
|
||||||
al_destroy( &prompt_list );
|
al_destroy( &prompt_list );
|
||||||
history_destroy();
|
|
||||||
|
|
||||||
writestr( L"\n" );
|
writestr( L"\n" );
|
||||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||||
@@ -2232,7 +2249,6 @@ int exit_status()
|
|||||||
*/
|
*/
|
||||||
static int read_i()
|
static int read_i()
|
||||||
{
|
{
|
||||||
int prev_end_loop=0;
|
|
||||||
|
|
||||||
reader_push(L"fish");
|
reader_push(L"fish");
|
||||||
reader_set_complete_function( &complete );
|
reader_set_complete_function( &complete );
|
||||||
@@ -2240,6 +2256,7 @@ static int read_i()
|
|||||||
reader_set_test_function( &shell_test );
|
reader_set_test_function( &shell_test );
|
||||||
|
|
||||||
data->prompt_width=60;
|
data->prompt_width=60;
|
||||||
|
data->prev_end_loop=0;
|
||||||
|
|
||||||
while( (!data->end_loop) && (!sanity_check()) )
|
while( (!data->end_loop) && (!sanity_check()) )
|
||||||
{
|
{
|
||||||
@@ -2256,12 +2273,7 @@ static int read_i()
|
|||||||
during evaluation.
|
during evaluation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tmp = wcsdup( reader_readline() );
|
tmp = reader_readline();
|
||||||
|
|
||||||
data->buff_pos=data->buff_len=0;
|
|
||||||
data->buff[data->buff_len]=L'\0';
|
|
||||||
reader_run_command( tmp );
|
|
||||||
free( tmp );
|
|
||||||
|
|
||||||
if( data->end_loop)
|
if( data->end_loop)
|
||||||
{
|
{
|
||||||
@@ -2277,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" ));
|
writestr(_( L"There are stopped jobs\n" ));
|
||||||
write_prompt();
|
write_prompt();
|
||||||
data->end_loop = 0;
|
data->end_loop = 0;
|
||||||
prev_end_loop=1;
|
data->prev_end_loop=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2444,6 +2463,14 @@ wchar_t *reader_readline()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case R_EOF:
|
||||||
|
{
|
||||||
|
exit_forced = 1;
|
||||||
|
data->end_loop=1;
|
||||||
|
debug( 1, L"got R_EOF" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* complete */
|
/* complete */
|
||||||
case R_COMPLETE:
|
case R_COMPLETE:
|
||||||
{
|
{
|
||||||
@@ -2835,14 +2862,17 @@ wchar_t *reader_readline()
|
|||||||
}
|
}
|
||||||
|
|
||||||
al_destroy( &comp );
|
al_destroy( &comp );
|
||||||
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
if( !reader_exit_forced() )
|
||||||
{
|
{
|
||||||
wperror(L"tcsetattr");
|
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||||
exit(1);
|
{
|
||||||
}
|
wperror(L"tcsetattr");
|
||||||
|
exit(1);
|
||||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
}
|
||||||
|
|
||||||
|
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||||
|
}
|
||||||
|
|
||||||
return data->buff;
|
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.
|
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
|
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 );
|
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
|
#endif
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
function __fish_complete_apropos
|
function __fish_complete_apropos
|
||||||
if test (commandline -ct)
|
if test (commandline -ct)
|
||||||
set str (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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,29 @@
|
|||||||
# completions are located in the completions subdirectory.
|
# 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
|
# 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
|
# 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
|
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
|
||||||
end
|
end
|
||||||
|
|
||||||
for i in $path_list
|
# Make a regular expressin that matches any component in the PATH. A
|
||||||
if not expr "$PATH" : .\*$i.\* >/dev/null
|
# trailing slash is ok. The sed call is to remove the last '\|'.
|
||||||
if test -d $i
|
|
||||||
set PATH $PATH $i
|
set -l path_regexp \\\((printf "^%s\\(\\|/\\)\$\\|" $PATH | sed -e "s/..\$//")\\\)
|
||||||
end
|
|
||||||
|
for i in (printf "%s\n" $path_list|grep -v $path_regexp)
|
||||||
|
if test -d $i
|
||||||
|
set PATH $PATH $i
|
||||||
end
|
end
|
||||||
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
|
# Don't need completions in non-interactive mode
|
||||||
#
|
#
|
||||||
@@ -43,8 +63,8 @@ end
|
|||||||
# Convenience functions
|
# Convenience functions
|
||||||
#
|
#
|
||||||
# The naming heuristic is that __fish_complete_* prints completions
|
# The naming heuristic is that __fish_complete_* prints completions
|
||||||
# and descriptions, while __fish_print_* only prints the completion,
|
# and descriptions, while __fish_print_* only prints the completions
|
||||||
# without the description
|
# and no descriptions
|
||||||
#
|
#
|
||||||
|
|
||||||
function __fish_complete_users -d "Print a list of local users, with the real user name as a description"
|
function __fish_complete_users -d "Print a list of local users, with the real user name as a description"
|
||||||
|
|||||||
@@ -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 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 "
|
complete $cmds -l sort -x -d (N_ "Sort criteria") -a "
|
||||||
extension\t'Sort by file extension'
|
extension\t'Sort by file extension'
|
||||||
none\tDon't\ sort
|
none\tDon\'t\ sort
|
||||||
size\t'Sort by size'
|
size\t'Sort by size'
|
||||||
time\t'Sort by modification time'
|
time\t'Sort by modification time'
|
||||||
version\t'Sort by version'
|
version\t'Sort by version'
|
||||||
@@ -106,4 +106,4 @@ function __fish_complete_ls -d "Compleletions for ls and it's aliases"
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
#
|
|
||||||
# This file defines various shellscript functions. Most of them are
|
|
||||||
# meant to be used directly by the user, but some of them, typically
|
|
||||||
# the ones whose name start with '__fish_', are only meant to be used
|
|
||||||
# internally by fish.
|
|
||||||
#
|
|
||||||
|
|
||||||
function contains -d (N_ "Test if a key is contained in a set of values")
|
function contains -d (N_ "Test if a key is contained in a set of values")
|
||||||
while set -q argv
|
while set -q argv
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
# string has a newline before and after, so that fish will know how
|
# string has a newline before and after, so that fish will know how
|
||||||
# long it is.
|
# 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")
|
function fish_prompt -d (N_ "Write out the prompt")
|
||||||
|
|
||||||
# Just calculate these once, to save a few cycles when displaying the prompt
|
# Just calculate these once, to save a few cycles when displaying the prompt
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
function type -d (N_ "Print the type of a command")
|
function type -d (N_ "Print the type of a command")
|
||||||
|
|
||||||
# Initialize
|
# Initialize
|
||||||
set -l status 1
|
set -l res 1
|
||||||
set -l mode normal
|
set -l mode normal
|
||||||
set -l selection all
|
set -l selection all
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ function type -d (N_ "Print the type of a command")
|
|||||||
if test $selection != files
|
if test $selection != files
|
||||||
|
|
||||||
if contains -- $i (functions -na)
|
if contains -- $i (functions -na)
|
||||||
set status 0
|
set res 0
|
||||||
set found 1
|
set found 1
|
||||||
switch $mode
|
switch $mode
|
||||||
case normal
|
case normal
|
||||||
@@ -86,7 +86,8 @@ function type -d (N_ "Print the type of a command")
|
|||||||
end
|
end
|
||||||
|
|
||||||
if contains -- $i (builtin -n)
|
if contains -- $i (builtin -n)
|
||||||
set status 0
|
|
||||||
|
set res 0
|
||||||
set found 1
|
set found 1
|
||||||
switch $mode
|
switch $mode
|
||||||
case normal
|
case normal
|
||||||
@@ -107,7 +108,7 @@ function type -d (N_ "Print the type of a command")
|
|||||||
|
|
||||||
set -l path (which $i ^/dev/null)
|
set -l path (which $i ^/dev/null)
|
||||||
if test -x (echo $path)
|
if test -x (echo $path)
|
||||||
set status 0
|
set res 0
|
||||||
set found 1
|
set found 1
|
||||||
switch $mode
|
switch $mode
|
||||||
case normal
|
case normal
|
||||||
@@ -130,6 +131,6 @@ function type -d (N_ "Print the type of a command")
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return $status
|
return $res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
112
signal.c
112
signal.c
@@ -55,143 +55,189 @@ static int block_count=0;
|
|||||||
*/
|
*/
|
||||||
static struct lookup_entry lookup[] =
|
static struct lookup_entry lookup[] =
|
||||||
{
|
{
|
||||||
|
#ifdef SIGHUP
|
||||||
{
|
{
|
||||||
SIGHUP,
|
SIGHUP,
|
||||||
L"SIGHUP",
|
L"SIGHUP",
|
||||||
N_( L"Terminal hung up" )
|
N_( L"Terminal hung up" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGINT
|
||||||
{
|
{
|
||||||
SIGINT,
|
SIGINT,
|
||||||
L"SIGINT",
|
L"SIGINT",
|
||||||
N_( L"Quit request from job control (^C)" )
|
N_( L"Quit request from job control (^C)" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGQUIT
|
||||||
{
|
{
|
||||||
SIGQUIT,
|
SIGQUIT,
|
||||||
L"SIGQUIT",
|
L"SIGQUIT",
|
||||||
N_( L"Quit request from job control with core dump (^\\)" )
|
N_( L"Quit request from job control with core dump (^\\)" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGILL
|
||||||
{
|
{
|
||||||
SIGILL,
|
SIGILL,
|
||||||
L"SIGILL",
|
L"SIGILL",
|
||||||
N_( L"Illegal instruction" )
|
N_( L"Illegal instruction" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTRAP
|
||||||
{
|
{
|
||||||
SIGTRAP,
|
SIGTRAP,
|
||||||
L"SIGTRAP",
|
L"SIGTRAP",
|
||||||
N_( L"Trace or breakpoint trap" )
|
N_( L"Trace or breakpoint trap" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGABRT
|
||||||
{
|
{
|
||||||
SIGABRT,
|
SIGABRT,
|
||||||
L"SIGABRT",
|
L"SIGABRT",
|
||||||
N_( L"Abort" )
|
N_( L"Abort" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGBUS
|
||||||
{
|
{
|
||||||
SIGBUS,
|
SIGBUS,
|
||||||
L"SIGBUS",
|
L"SIGBUS",
|
||||||
N_( L"Misaligned address error" )
|
N_( L"Misaligned address error" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGFPE
|
||||||
{
|
{
|
||||||
SIGFPE,
|
SIGFPE,
|
||||||
L"SIGFPE",
|
L"SIGFPE",
|
||||||
N_( L"Floating point exception" )
|
N_( L"Floating point exception" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGKILL
|
||||||
{
|
{
|
||||||
SIGKILL,
|
SIGKILL,
|
||||||
L"SIGKILL",
|
L"SIGKILL",
|
||||||
N_( L"Forced quit" )
|
N_( L"Forced quit" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGUSR1
|
||||||
{
|
{
|
||||||
SIGUSR1,
|
SIGUSR1,
|
||||||
L"SIGUSR1",
|
L"SIGUSR1",
|
||||||
N_( L"User defined signal 1" )
|
N_( L"User defined signal 1" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGUSR2
|
||||||
{
|
{
|
||||||
SIGUSR2, L"SIGUSR2",
|
SIGUSR2, L"SIGUSR2",
|
||||||
N_( L"User defined signal 2" )
|
N_( L"User defined signal 2" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGSEGV
|
||||||
{
|
{
|
||||||
SIGSEGV,
|
SIGSEGV,
|
||||||
L"SIGSEGV",
|
L"SIGSEGV",
|
||||||
N_( L"Address boundary error" )
|
N_( L"Address boundary error" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPIPE
|
||||||
{
|
{
|
||||||
SIGPIPE,
|
SIGPIPE,
|
||||||
L"SIGPIPE",
|
L"SIGPIPE",
|
||||||
N_( L"Broken pipe" )
|
N_( L"Broken pipe" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGALRM
|
||||||
{
|
{
|
||||||
SIGALRM,
|
SIGALRM,
|
||||||
L"SIGALRM",
|
L"SIGALRM",
|
||||||
N_( L"Timer expired" )
|
N_( L"Timer expired" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTERM
|
||||||
{
|
{
|
||||||
SIGTERM,
|
SIGTERM,
|
||||||
L"SIGTERM",
|
L"SIGTERM",
|
||||||
N_( L"Polite quit request" )
|
N_( L"Polite quit request" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGCHLD
|
||||||
{
|
{
|
||||||
SIGCHLD,
|
SIGCHLD,
|
||||||
L"SIGCHLD",
|
L"SIGCHLD",
|
||||||
N_( L"Child process status changed" )
|
N_( L"Child process status changed" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGCONT
|
||||||
{
|
{
|
||||||
SIGCONT,
|
SIGCONT,
|
||||||
L"SIGCONT",
|
L"SIGCONT",
|
||||||
N_( L"Continue previously stopped process" )
|
N_( L"Continue previously stopped process" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGSTOP
|
||||||
{
|
{
|
||||||
SIGSTOP,
|
SIGSTOP,
|
||||||
L"SIGSTOP",
|
L"SIGSTOP",
|
||||||
N_( L"Forced stop" )
|
N_( L"Forced stop" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTSTP
|
||||||
{
|
{
|
||||||
SIGTSTP,
|
SIGTSTP,
|
||||||
L"SIGTSTP",
|
L"SIGTSTP",
|
||||||
N_( L"Stop request from job control (^Z)" )
|
N_( L"Stop request from job control (^Z)" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTTIN
|
||||||
{
|
{
|
||||||
SIGTTIN,
|
SIGTTIN,
|
||||||
L"SIGTTIN",
|
L"SIGTTIN",
|
||||||
N_( L"Stop from terminal input" )
|
N_( L"Stop from terminal input" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTTOU
|
||||||
{
|
{
|
||||||
SIGTTOU,
|
SIGTTOU,
|
||||||
L"SIGTTOU",
|
L"SIGTTOU",
|
||||||
N_( L"Stop from terminal output" )
|
N_( L"Stop from terminal output" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGURG
|
||||||
{
|
{
|
||||||
SIGURG,
|
SIGURG,
|
||||||
L"SIGURG",
|
L"SIGURG",
|
||||||
N_( L"Urgent socket condition" )
|
N_( L"Urgent socket condition" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGXCPY
|
||||||
{
|
{
|
||||||
SIGXCPU,
|
SIGXCPU,
|
||||||
L"SIGXCPU",
|
L"SIGXCPU",
|
||||||
N_( L"CPU time limit exceeded" )
|
N_( L"CPU time limit exceeded" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
#ifdef SIGXFSZ
|
#ifdef SIGXFSZ
|
||||||
{
|
{
|
||||||
SIGXFSZ,
|
SIGXFSZ,
|
||||||
@@ -200,12 +246,14 @@ static struct lookup_entry lookup[] =
|
|||||||
}
|
}
|
||||||
,
|
,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SIGVTALRM
|
||||||
{
|
{
|
||||||
SIGVTALRM,
|
SIGVTALRM,
|
||||||
L"SIGVTALRM",
|
L"SIGVTALRM",
|
||||||
N_( L"Virtual timer expired" )
|
N_( L"Virtual timer expired" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
#ifdef SIGPROF
|
#ifdef SIGPROF
|
||||||
{
|
{
|
||||||
SIGPROF,
|
SIGPROF,
|
||||||
@@ -230,12 +278,14 @@ static struct lookup_entry lookup[] =
|
|||||||
}
|
}
|
||||||
,
|
,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SIGWIO
|
||||||
{
|
{
|
||||||
SIGIO,
|
SIGIO,
|
||||||
L"SIGIO",
|
L"SIGIO",
|
||||||
N_( L"I/O on asynchronous file descriptor is possible" )
|
N_( L"I/O on asynchronous file descriptor is possible" )
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
#endif
|
||||||
#ifdef SIGPWR
|
#ifdef SIGPWR
|
||||||
{
|
{
|
||||||
SIGPWR,
|
SIGPWR,
|
||||||
@@ -338,6 +388,7 @@ int wcs2sig( const wchar_t *str )
|
|||||||
const wchar_t *sig2wcs( int sig )
|
const wchar_t *sig2wcs( int sig )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for( i=0; lookup[i].desc ; i++ )
|
for( i=0; lookup[i].desc ; i++ )
|
||||||
{
|
{
|
||||||
if( lookup[i].signal == sig )
|
if( lookup[i].signal == sig )
|
||||||
@@ -345,12 +396,14 @@ const wchar_t *sig2wcs( int sig )
|
|||||||
return lookup[i].name;
|
return lookup[i].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return L"Unknown";
|
|
||||||
|
return _(L"Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t *signal_get_desc( int sig )
|
const wchar_t *signal_get_desc( int sig )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for( i=0; lookup[i].desc ; i++ )
|
for( i=0; lookup[i].desc ; i++ )
|
||||||
{
|
{
|
||||||
if( lookup[i].signal == sig )
|
if( lookup[i].signal == sig )
|
||||||
@@ -358,7 +411,8 @@ const wchar_t *signal_get_desc( int sig )
|
|||||||
return _(lookup[i].desc);
|
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)
|
static void default_handler(int signal, siginfo_t *info, void *context)
|
||||||
{
|
{
|
||||||
event_t e;
|
event_t e;
|
||||||
|
|
||||||
e.type=EVENT_SIGNAL;
|
e.type=EVENT_SIGNAL;
|
||||||
e.param1.signal = signal;
|
e.param1.signal = signal;
|
||||||
e.function_name=0;
|
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 );
|
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
|
Interactive mode ^C handler. Respond to int signal by setting
|
||||||
interrupted-flag and stopping all loops and conditionals.
|
interrupted-flag and stopping all loops and conditionals.
|
||||||
@@ -431,7 +512,7 @@ void signal_set_handlers()
|
|||||||
sigemptyset( & act.sa_mask );
|
sigemptyset( & act.sa_mask );
|
||||||
act.sa_flags=SA_SIGINFO;
|
act.sa_flags=SA_SIGINFO;
|
||||||
act.sa_sigaction = &default_handler;
|
act.sa_sigaction = &default_handler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First reset everything to a use default_handler, a function
|
First reset everything to a use default_handler, a function
|
||||||
whose sole action is to fire of an event
|
whose sole action is to fire of an event
|
||||||
@@ -479,7 +560,7 @@ void signal_set_handlers()
|
|||||||
wperror( L"sigaction" );
|
wperror( L"sigaction" );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
act.sa_flags = SA_SIGINFO;
|
act.sa_flags = SA_SIGINFO;
|
||||||
act.sa_sigaction= &handle_winch;
|
act.sa_sigaction= &handle_winch;
|
||||||
if( sigaction( SIGWINCH, &act, 0 ) )
|
if( sigaction( SIGWINCH, &act, 0 ) )
|
||||||
@@ -488,6 +569,14 @@ void signal_set_handlers()
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
act.sa_flags = SA_SIGINFO;
|
||||||
|
act.sa_sigaction= &handle_hup;
|
||||||
|
if( sigaction( SIGHUP, &act, 0 ) )
|
||||||
|
{
|
||||||
|
wperror( L"sigaction" );
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -510,12 +599,13 @@ void signal_set_handlers()
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_handle( int sig, int do_handle )
|
void signal_handle( int sig, int do_handle )
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These should always be handled
|
These should always be handled
|
||||||
*/
|
*/
|
||||||
@@ -527,15 +617,15 @@ void signal_handle( int sig, int do_handle )
|
|||||||
(sig == SIGCHLD) )
|
(sig == SIGCHLD) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sigemptyset( & act.sa_mask );
|
sigemptyset( &act.sa_mask );
|
||||||
if( do_handle )
|
if( do_handle )
|
||||||
{
|
{
|
||||||
act.sa_flags=SA_SIGINFO;
|
act.sa_flags = SA_SIGINFO;
|
||||||
act.sa_sigaction = &default_handler;
|
act.sa_sigaction = &default_handler;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
act.sa_flags=0;
|
act.sa_flags = 0;
|
||||||
act.sa_handler = SIG_DFL;
|
act.sa_handler = SIG_DFL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,16 +641,20 @@ void signal_block()
|
|||||||
sigfillset( &chldset );
|
sigfillset( &chldset );
|
||||||
sigprocmask(SIG_BLOCK, &chldset, 0);
|
sigprocmask(SIG_BLOCK, &chldset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
block_count++;
|
block_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_unblock()
|
void signal_unblock()
|
||||||
{
|
{
|
||||||
sigset_t chldset;
|
sigset_t chldset;
|
||||||
|
|
||||||
block_count--;
|
block_count--;
|
||||||
|
|
||||||
if( !block_count )
|
if( !block_count )
|
||||||
{
|
{
|
||||||
sigfillset( &chldset );
|
sigfillset( &chldset );
|
||||||
sigprocmask(SIG_UNBLOCK, &chldset, 0);
|
sigprocmask(SIG_UNBLOCK, &chldset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -611,7 +611,7 @@ void tok_next( tokenizer *tok )
|
|||||||
|
|
||||||
wchar_t *tok_string( 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 )
|
wchar_t *tok_first( const wchar_t *str )
|
||||||
|
|||||||
@@ -2,6 +2,19 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>fish user documentation</title>
|
<title>fish user documentation</title>
|
||||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
<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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|||||||
1
util.c
1
util.c
@@ -809,6 +809,7 @@ int wcsfilecmp( const wchar_t *a, const wchar_t *b )
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int secondary_diff=0;
|
int secondary_diff=0;
|
||||||
if( iswdigit( *a ) && iswdigit( *b ) )
|
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 )
|
wchar_t *wgetcwd( wchar_t *buff, size_t sz )
|
||||||
{
|
{
|
||||||
char buffc[sz*MAX_UTF8_BYTES];
|
char *buffc = malloc( sz*MAX_UTF8_BYTES);
|
||||||
char *res = getcwd( buffc, sz*MAX_UTF8_BYTES );
|
char *res;
|
||||||
if( !res )
|
wchar_t *ret = 0;
|
||||||
return 0;
|
|
||||||
|
if( !buffc )
|
||||||
if( (size_t)-1 == mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
|
|
||||||
{
|
{
|
||||||
return 0;
|
errno = ENOMEM;
|
||||||
}
|
return 0;
|
||||||
return buff;
|
}
|
||||||
|
|
||||||
|
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 )
|
int wchdir( const wchar_t * dir )
|
||||||
|
|||||||
Reference in New Issue
Block a user