Compare commits

...

30 Commits

Author SHA1 Message Date
axel
13a7269378 Bump version number
darcs-hash:20060422101024-ac50b-8cfc71d94572187d8d3a6ce890beee0a0225a09a.gz
2006-04-22 20:10:24 +10:00
axel
fd2644ce49 Tweaks to a few error messages (Thanks to Philip Ganchev)
darcs-hash:20060422100630-ac50b-18cef1e493321e8ad0cf65982dc1748965d02630.gz
2006-04-22 20:06:30 +10:00
axel
508de57459 Change setup to avoid invalid directories and warnings, also revert directory checking for fish_*_path, it makes sense to add non-empty directories to these
darcs-hash:20060421150558-ac50b-90aff08f81b3d280badba4cc14fb6a0897c39f9e.gz
2006-04-22 01:05:58 +10:00
axel
de2405b35a Add more descriptive error messages when trying to use variables in command names
darcs-hash:20060421142939-ac50b-d1809fa4687706b433d1d0a5e0a0c9d791de510f.gz
2006-04-22 00:29:39 +10:00
axel
a7f977836a Expand the switch/case documentation
darcs-hash:20060421083529-ac50b-f287424c0cc9377085b49492453d35a5512cbc90.gz
2006-04-21 18:35:29 +10:00
axel
f59e4a88c6 If PATH is unset, use a default value
darcs-hash:20060420183502-ac50b-8e746ae4ed00c354712cf61e57e0a187aa40a4fa.gz
2006-04-21 04:35:02 +10:00
axel
c755bd0358 Only allow real directories in PATH, CDPATH, etc. If user tries to use ':' instead of arrays, give a friendly pointer on how to use arrays
darcs-hash:20060420182944-ac50b-fbb5dc63c2a4d3fe3bde92ad7699b1cad972dd0f.gz
2006-04-21 04:29:44 +10:00
axel
536523ffd7 Minor comment and documentation edits
darcs-hash:20060420150206-ac50b-c5c91053ee37a6c3f763287c42b430cdc99bb45b.gz
2006-04-21 01:02:06 +10:00
axel
ca82fc2f03 Add missing documentation for the read builtin
darcs-hash:20060420150124-ac50b-71a94cea3fedb0265af71718022e54e42567d69e.gz
2006-04-21 01:01:24 +10:00
axel
d1411c42d6 Minor edits to Makefile. A mistyped .PHONY was corrected, a few stray .o files are now properly removed by make clean, and the dependency list has been updated
darcs-hash:20060420150028-ac50b-b3b6b04023f1c039d167e5f67c89cbbaa6bd0cdc.gz
2006-04-21 01:00:28 +10:00
axel
9d770af5f4 Earlier history in non-interactive mode bugfix contained a new bug causing fish to crash if read is not used in non-interactive mode
darcs-hash:20060419234211-ac50b-886a33e96cb3f95e9b2c632f03eb3b2b20a560fd.gz
2006-04-20 09:42:11 +10:00
axel
d1ff6a323a Bump version number
darcs-hash:20060419124513-ac50b-f0c4bacee786ca9e147a86004aa90f5a09c04b34.gz
2006-04-19 22:45:13 +10:00
axel
112ea1759a Minor code cleanup
darcs-hash:20060419124315-ac50b-e7e9cafe6850e1fe805bad82278d15c2de327f5d.gz
2006-04-19 22:43:15 +10:00
axel
76bafbef2a Make the read builtin accept 0 parameters and drop the input instead of showing an error message
darcs-hash:20060419100830-ac50b-50f96925481bb29ad840fb12240ef9b9b86d18c4.gz
2006-04-19 20:08:30 +10:00
axel
1947ec88f1 Remove minor memory leak on init
darcs-hash:20060419095818-ac50b-d2146525feba5f00d224bce920ab40cc023e390d.gz
2006-04-19 19:58:18 +10:00
axel
d0956f1e43 Use libc implementations of wcslcpy and wcslcat if they exist. Move internal implementations to fallback.c.
darcs-hash:20060419095628-ac50b-0e94e4205306bb99bb9dea72eec43b442520bf1b.gz
2006-04-19 19:56:28 +10:00
axel
6996c7718e Always init history on startup, to avoid destorying history multiple times when reading interactively in a non-interactive script
darcs-hash:20060419095502-ac50b-abf2fe39cf9c027bdbc69d78fe858e946f7c81f2.gz
2006-04-19 19:55:02 +10:00
axel
45d56d8e05 Drop all calls to wcsncpy
darcs-hash:20060413121851-ac50b-1f479b96b3aa1050a30e9ee0ed27cc107ce2bc45.gz
2006-04-13 22:18:51 +10:00
axel
53295d38b7 Change var_entry_t struct to be ANSI C compliant (Wastes a few hundred bytes)
darcs-hash:20060410160109-ac50b-fa8b097722f06aee5fb09095e89f6b39ff90d44b.gz
2006-04-11 02:01:09 +10:00
axel
bd9c843fd1 Add warning when trying to change read-only variable
darcs-hash:20060410153626-ac50b-700ff7687647b8aab47ba79d759d1739cbe60425.gz
2006-04-11 01:36:26 +10:00
axel
f812b9b26c Fix bug in type command causing type -f to return true even when no file was found
darcs-hash:20060410143201-ac50b-4d8a70cd9721edcddaf11324f0b575d3f8cbace8.gz
2006-04-11 00:32:01 +10:00
axel
52851a3ba4 Quote Doxygen test in configure script to remove warning - thanks to Ray Hammond for the report and the fix
darcs-hash:20060410141909-ac50b-f310b7e326ce28ae8a3bbc1a3c1d247511f3d860.gz
2006-04-11 00:19:09 +10:00
axel
b1bf115fa2 Bump version number
darcs-hash:20060408143210-ac50b-0a143a45d0510e67a75024b802a1ca677480e4c0.gz
2006-04-09 00:32:10 +10:00
axel
0f25ef365d Tiny documentation edits
darcs-hash:20060408143134-ac50b-eae8cf585d3801b51bba415955ef2aacf98baeb2.gz
2006-04-09 00:31:34 +10:00
axel
55ea4b6fc0 Documentation additions
darcs-hash:20060405132928-ac50b-d551c31d04426c75c756d513e02e34b91bfc4ad6.gz
2006-04-05 23:29:28 +10:00
axel
5ef8cccf21 Mention in the license section that fish includes the glibc wcstok implementation as a fallback for libc implementations lacking wcstok
darcs-hash:20060405125956-ac50b-9e5b51d94676868365878387cd8c7e14a1684348.gz
2006-04-05 22:59:56 +10:00
axel
5613d96001 Do not call autoconf in Makefile, since configure will automatically reconfigure itself if configure.ac has changed
darcs-hash:20060405124918-ac50b-0f45ddc7759383d930e0473a281f092566570210.gz
2006-04-05 22:49:18 +10:00
axel
5d9ba8c1a2 Delete some commented code and tweak a few comments
darcs-hash:20060405124825-ac50b-8242b2a9c788cf147f864329797b2e24a7040f0b.gz
2006-04-05 22:48:25 +10:00
axel
0de232bf54 Do not return to the shell until all processes of a job have finished (Previous behaviour was to return once the last job had exited, and could cause e.g. the jobs builtin to print out the job responsible for repainting the titlebar). Also validate that jobs have not completed in various places where the job list is examined
darcs-hash:20060404112722-ac50b-4b6a55ce7c57d39213cdd0ed0f581795a72859b7.gz
2006-04-04 21:27:22 +10:00
axel
db5b887824 PPC fix by James Vega, fixing an issue with a variable named putc, which clashed with the putc macro
darcs-hash:20060403150422-ac50b-78d5db541cb1f41bfea55deac7578c0df73605bd.gz
2006-04-04 01:04:22 +10:00
24 changed files with 633 additions and 419 deletions

View File

@@ -198,7 +198,6 @@ all: $(PROGRAMS) user_doc
.PHONY: all
configure: configure.ac
autoconf
./config.status --recheck
Makefile: Makefile.in configure
@@ -345,7 +344,6 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
./gen_hdr.sh $*.doxygen >>$@
echo ");" >>$@
echo "}" >>$@
#man -- doc_src/builtin_doc/man/man1/`basename $@ .c`.1 | cat -s | ./gen_hdr2 >>$@
#
# The build rules for installing/uninstalling fish
@@ -414,7 +412,7 @@ install-force: all install-translations
@echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.
@echo
@echo Have fun!
.PHONY: force-install
.PHONY: install-force
# Uninstall this fish version
@@ -456,6 +454,7 @@ uninstall-legacy: uninstall
rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions; true
rmdir $(DESTDIR)$(sysconfdir)/fish.d; true
@echo The previous fish installation has been removed.
.PHONY: uninstall-legacy
install-translations: $(TRANSLATIONS)
if test $(HAVE_GETTEXT) = 1; then \
@@ -580,7 +579,7 @@ distclean: clean
.PHONY: distclean
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 tokenizer_test fish key_reader set_color gen_hdr2 mimedb
rm -f fishd fish_pager count fish_tests
@@ -621,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: 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
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: 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
@@ -638,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: 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
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: env_universal_common.h
fish_pager.o: config.h signal.h fallback.h common.h util.h wutil.h complete.h
@@ -671,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: 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: history.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: output.h halloc_util.h highlight.h

View File

@@ -1029,7 +1029,7 @@ static int builtin_function( wchar_t **argv )
{
event_t *e;
if( !wcsvarname( woptarg ) )
if( wcsvarname( woptarg ) )
{
sb_printf( sb_err,
_( L"%ls: Invalid variable name '%ls'\n" ),
@@ -1145,7 +1145,7 @@ static int builtin_function( wchar_t **argv )
argc-woptind );
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,
_( L"%ls: Illegal function name '%ls'\n" ),
@@ -1468,20 +1468,6 @@ static int builtin_read( wchar_t **argv )
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
*/
@@ -1512,10 +1498,6 @@ static int builtin_read( wchar_t **argv )
*/
i=woptind;
ifs = env_get( L"IFS" );
if( ifs == 0 )
ifs = L"";
/*
Check if we should read interactively using \c reader_readline()
*/
@@ -1593,20 +1575,29 @@ static int builtin_read( wchar_t **argv )
sb_destroy( &sb );
}
wchar_t *state;
nxt = wcstok( buff, (i<argc-1)?ifs:L"", &state );
while( i<argc )
if( i != argc )
{
env_set( argv[i], nxt != 0 ? nxt: L"", place );
wchar_t *state;
i++;
if( nxt != 0 )
nxt = wcstok( 0, (i<argc-1)?ifs:L"", &state);
ifs = env_get( L"IFS" );
if( ifs == 0 )
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 );
return exit_res;
}
@@ -2503,7 +2494,7 @@ static int builtin_jobs( wchar_t **argv )
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed )
if( j->constructed && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
return 0;
@@ -2536,7 +2527,7 @@ static int builtin_jobs( wchar_t **argv )
j = job_get_from_pid( pid );
if( j )
if( j && !job_is_completed( j ) )
{
builtin_jobs_print( j, mode, !found );
}
@@ -2557,7 +2548,7 @@ static int builtin_jobs( wchar_t **argv )
/*
Ignore unconstructed jobs, i.e. ourself.
*/
if( j->constructed /*&& j->skip_notification*/ )
if( j->constructed && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
found = 1;
@@ -2593,7 +2584,7 @@ static int builtin_for( wchar_t **argv )
argv[0] );
builtin_print_help( argv[0], sb_err );
}
else if ( !wcsvarname(argv[1]) )
else if ( wcsvarname(argv[1]) )
{
sb_printf( sb_err,
_( L"%ls: '%ls' is not a valid variable name\n" ),

View File

@@ -26,6 +26,26 @@ Functions used for implementing the set builtin.
#include "parser.h"
#include "translate.h"
#define BUILTIN_SET_PATH_ERROR L"%ls: Could not add component %ls to %ls.\n"
#define BUILTIN_SET_PATH_HINT L"%ls: Did you mean 'set %ls $%ls %ls'?\n"
/**
Call env_set. On error, print a description of the problem to
stderr.
*/
static void my_env_set( const wchar_t *key, const wchar_t *val, int scope )
{
switch( env_set( key, val, scope | ENV_USER ) )
{
case ENV_PERM:
{
sb_printf( sb_err, _(L"%ls: Tried to change the read-only variable '%ls'\n"), L"set", key );
break;
}
}
}
/**
Extract the name from a destination argument of the form name[index1 index2...]
*/
@@ -114,7 +134,12 @@ 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,
array_list_t *indexes,
@@ -122,16 +147,12 @@ static int update_values( array_list_t *list,
{
int i;
//fwprintf(stderr, L"Scan complete\n");
/* Replace values where needed */
for( i = 0; i < al_get_count(indexes); i++ )
{
int ind = *(int *) al_get(indexes, i) - 1;
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""));
}
@@ -169,8 +190,6 @@ static int erase_values(array_list_t *list, array_list_t *indexes)
int i;
array_list_t result;
//fwprintf(stderr, L"Starting with %d\n", al_get_count(list));
al_init(&result);
for (i = 0; i < al_get_count(list); i++)
@@ -189,8 +208,6 @@ static int erase_values(array_list_t *list, array_list_t *indexes)
al_push_all( list, &result );
al_destroy(&result);
//fwprintf(stderr, L"Remaining: %d\n", al_get_count(&result));
return al_get_count(list);
}
@@ -207,8 +224,6 @@ static int fill_buffer_from_list(string_buffer_t *sb, array_list_t *list)
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)
@@ -254,12 +269,25 @@ static void print_variables(int include_values, int esc, int scope)
al_destroy(&names);
}
static int is_path_variable( const wchar_t *env )
{
return contains_str( env,
L"PATH",
L"CDPATH",
(void *)0 );
}
/**
The set builtin. Creates, updates and erases environment variables and environemnt variable arrays.
*/
int builtin_set( wchar_t **argv )
{
/**
Variables used for parsing the argument list
*/
const static struct woption
long_options[] =
{
@@ -293,7 +321,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);
@@ -363,6 +391,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 ) )
{
sb_printf(sb_err,
@@ -375,7 +412,7 @@ int builtin_set( wchar_t **argv )
}
/* Check operation and modifiers sanity */
/* We can't both list and erase varaibles */
if( erase && list )
{
sb_printf(sb_err,
@@ -387,6 +424,9 @@ int builtin_set( wchar_t **argv )
return 1;
}
/*
Variables can only have one scope
*/
if( local + global + universal > 1 )
{
sb_printf( sb_err,
@@ -397,6 +437,9 @@ int builtin_set( wchar_t **argv )
return 1;
}
/*
Variables can only have one export status
*/
if( export && unexport )
{
sb_printf( sb_err,
@@ -410,13 +453,16 @@ int builtin_set( wchar_t **argv )
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;
for( i=woptind; i<argc; i++ )
{
if( !env_exist( argv[i] ) )
{
retcode++;
}
}
return retcode;
@@ -427,8 +473,7 @@ int builtin_set( wchar_t **argv )
if( woptind < argc )
{
dest = wcsdup(argv[woptind++]);
//fwprintf(stderr, L"Dest: %ls\n", dest);
if( !wcslen( dest ) )
{
free( dest );
@@ -444,9 +489,82 @@ int builtin_set( wchar_t **argv )
while( woptind < argc )
{
al_push(&values, argv[woptind++]);
// fwprintf(stderr, L"Val: %ls\n", argv[woptind - 1]);
}
if( is_path_variable( dest ) )
{
int i;
int error = 0;
for( i=0; i<al_get_count( &values ); i++ )
{
int show_perror = 0;
int show_hint = 0;
struct stat buff;
wchar_t *dir = (wchar_t *)al_get( &values, i );
if( wstat( dir, &buff ) )
{
error = 1;
show_perror = 1;
}
if( !( S_IFDIR & buff.st_mode ) )
{
error = 1;
}
if( error )
{
wchar_t *colon;
sb_printf( sb_err,
_(BUILTIN_SET_PATH_ERROR),
argv[0],
dir,
dest );
colon = wcschr( dir, L':' );
if( colon && *(colon+1) )
{
show_hint = 1;
}
}
if( show_perror )
{
builtin_wperror( argv[0] );
}
if( show_hint )
{
sb_printf( sb_err,
_(BUILTIN_SET_PATH_HINT),
argv[0],
dest,
dest,
wcschr( dir, L':' )+1);
}
if( error )
{
break;
}
}
if( error )
{
al_destroy(&values);
return 1;
}
}
/* Extract variable name and indexes */
sb_init(&name_sb);
@@ -459,8 +577,7 @@ int builtin_set( wchar_t **argv )
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)
@@ -477,7 +594,7 @@ int builtin_set( wchar_t **argv )
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 */
/* Maybe we should issue an error if there are any other arguments? */
print_variables(0, 0, scope);
finished=1;
}
@@ -512,7 +629,7 @@ int builtin_set( wchar_t **argv )
!erase &&
!list )
{
env_set( name, 0, scope );
my_env_set( name, 0, scope );
finished = 1;
}
}
@@ -572,7 +689,8 @@ int builtin_set( wchar_t **argv )
else
{
fill_buffer_from_list(&result_sb, &val_l);
env_set(name, (wchar_t *) result_sb.buff, scope);
my_env_set(name, (wchar_t *) result_sb.buff, scope);
}
}
else
@@ -585,7 +703,7 @@ int builtin_set( wchar_t **argv )
fill_buffer_from_list( &result_sb,
&val_l );
env_set(name,
my_env_set(name,
(wchar_t *) result_sb.buff,
scope);
}
@@ -601,7 +719,7 @@ int builtin_set( wchar_t **argv )
}
/* Common cleanup */
//fwprintf(stderr, L"Cleanup\n");
free(dest);
sb_destroy(&name_sb);
al_destroy( &values );

108
common.c
View File

@@ -400,119 +400,17 @@ wchar_t **strv2wcsv( const char **in )
}
/*$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 )
wchar_t *wcsvarname( wchar_t *str )
{
while( *str )
{
if( (!iswalnum(*str)) && (*str != L'_' ) )
{
return 0;
return str;
}
str++;
}
return 1;
return 0;
}

View File

@@ -134,35 +134,18 @@ wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
*/
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
*/
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 );
/**

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(fish,1.21.3,fish-users@lists.sf.net)
AC_INIT(fish,1.21.6,fish-users@lists.sf.net)
# If needed, run autoconf to regenerate the configure file
AC_MSG_CHECKING([if autoconf needs to be run])
@@ -12,7 +12,7 @@ if test configure -ot configure.ac; then
if autoconf; then
./configure "$@"
fi
exit
exit
else
AC_MSG_ERROR( [cannot find the autoconf program in your path.
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
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.
This program is needed to build fish.
Please install it and try again.])
@@ -276,7 +276,7 @@ AC_CHECK_HEADER([regex.h],
# Check for presense of various functions
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
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
# features that Autoconf doesn't tell us about

View File

@@ -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
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
If the variable \$animal contains the name of an animal, the following
@@ -27,9 +43,11 @@ switch $animal
echo bird
case shark trout stingray
echo fish
case '*'
echo I have no idea what a $animal is
end
</pre>
</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>

View File

@@ -33,8 +33,9 @@ the manual page for the echo command by writing:
<code>man echo</code>
\c man is a command for displaying a manual page on a given
topic. There are manual pages for almost every command on most
\c man is a command for displaying a manual page on a given topic. The
man command takes the name of the manual page to display as an
argument. There are manual pages for almost every command on most
computers. There are also manual pages for many other things, such as
system libraries and important files.
@@ -60,6 +61,17 @@ Commands and parameters are separated by the space character
the return key) or a semicolon (;). More than one command can be
written on the same line by separating them with semicolons.
A switch is a very common special type of argument. Switches almost
always start with one or more hyphens (-) and alter the way a command
operates. For example, the \c ls command usually lists all the files
and directories in the current working directory, but by using the \c
-l switch, the behaviour of ls is changed to not only display the
filename, but also the size, permissions, owner and modification time
of each file. Switches differ between commands and are documented in
the manual page for each command. Some switches are very common
though, for example '--help' will usually display a help text, '-i'
will often turn on interactive prompting before taking action, while
'-f' will turn it off.
\subsection quotes Quotes
@@ -200,7 +212,15 @@ When you start a job in \c fish, \c fish itself will pause, and give
control of the terminal to the program just started. Sometimes, you
want to continue using the commandline, and have the job run in the
background. To create a background job, append a \& (ampersand) to
your command. This will tell fish to run the job in the background.
your command. This will tell fish to run the job in the
background. Background jobs are very useful when running programs that
have a graphical user interface.
Example:
<code>emacs \&</code>
will start the emacs text editor in the background.
\subsection syntax-job-control Job control
@@ -211,16 +231,17 @@ programs and do anything you want. If you then want to go back to the
suspended command by using the <a href="builtins.html#fg">fg</a>
command.
If you instead want to put a suspended job into the foreground, use
the <a href="builtins.html#fg">fg</a> command.
If you instead want to put a suspended job into the background, use
the <a href="builtins.html#bg">bg</a> command.
To get a listing of all currently started jobs, use the <a
href="builtins.html#jobs">jobs</a> command.
\subsection syntax-function Shellscript functions
Functions are used to group together commands and arguments
using a single name. For example, the following is a function
Functions are used to group together commands and arguments using a
single name. It can also be used to start a specific command with
additional arguments. For example, the following is a function
definition that calls the command 'ls -l' to print a detailed listing
of the contents of the current directory:
@@ -237,14 +258,14 @@ $argv</code> should be called when ll is invoked. $argv is an array
variable, which always contains all arguments sent to the function. In
the example above, these are simply passed on to the ls command. For
more information on functions, see the documentation for the <a
href='builtin.html#function'>function builtin</a>.
href='builtin.html#function'>function</a> builtin.
Functions can be defined on the commandline or in a configuration
file, but they can also be automatically loaded. Fish automatically
searches through any directories in the array variable
\$fish_function_path, and any functions defined are automatically
loaded when needed. A function definition file must have a filename
consisting of the name of the function and the suffix '.fish'.
consisting of the name of the function plus the suffix '.fish'.
The default value for \$fish_function_path is ~/.fish.d/functions,
/etc/fish.d/functions /usr/share/fish/functions. The exact path to the
@@ -259,12 +280,13 @@ functions and the last one is for default fish functions.
This is a short explanation of some of the commonly used words in fish.
- argument, a parameter given to a command
- builtin, a command that is implemented in the shell
- command, a program
- function, a block of one or more fish commands that can be called as a single command. By using functions, it is possible to string together multiple smaller commands into one more advanced command.
- builtin, a command that is implemented in the shell. Builtins are commands that are so closely tied to the shell that it is impossible to implement them as external commands.
- command, a program that the shell can run.
- function, a block of commands and arguments that can be called as if they where a single command. By using functions, it is possible to string together multiple smaller commands into one more advanced command.
- job, a running pipeline or command
- pipeline, a set of commands stringed together so that the output of one command is the input of the next command
- redirection, a operation that changes one of the input/output streams associated with a job
- switch, a special flag sent as an argument to a command that will alter the behavious of the command. A switch almost always begins with one or two hyphens.
\section help Help
@@ -1206,7 +1228,7 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
\subsection bugs Known bugs
- Completion for gcc -\#\#\# option doesn't work.
- Yanking weird characters from clipboard prints Unicode escapes
- Yanking weird characters from the clipboard prints Unicode escapes
- Suspending and then resuming pipelines containing a builtin is broken. How should this be handled?
If you think you have found a bug not described here, please send a
@@ -1262,7 +1284,7 @@ Examples:
- 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.
- 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 \$''.
@@ -1355,14 +1377,14 @@ Examples:
\subsection disc The law of discoverability
The shell should implement it's features in a way that makes them as
easy as possible for the user to discover for her/himself.
A program should be designed to make its features as
easy as possible to discover for the user.
Rationale:
A program whose features are discoverable makes a new user into an
expert in a shorter span of time, since the user will learn how to use
the program simply by using it.
A program whose features are discoverable turns a new user into an
expert in a shorter span of time, since the user will become an expert
on the program simply by using it.
The main benefit of a graphical program over a command line-based
program is discoverability. In a graphical program, one can discover
@@ -1384,8 +1406,8 @@ Examples:
/** \page license Licenses
Fish Copyright (C) 2005 Axel Liljencrantz. Fish is released under the
GNU General Public License. The license agreement is included
below.
GNU General Public License, version 2. The license agreement is
included below.
Fish contains code under the BSD license, namely versions of the
two functions strlcat and strlcpy, modified for use with wide
@@ -1394,11 +1416,16 @@ license agreement is included below.
The XSel command, written and copyrighted by Conrad Parker, is
distributed together with, and used by fish. It is released under the MIT
license. The license agreement is included below.
license. The license agreement is included below.
The xdgmime library, written and copyrighted by Red Hat, Inc, is used
by the mimedb command, which is a part of fish. It is released under
the LGPL license. The license agreement is included below.
the LGPL. The license agreement is included below.
Fish contains code from the glibc library, namely the wcstok
function. This code is licensed under the LGPL. The license agreement
is included below.
<HR>

View File

@@ -8,10 +8,13 @@
The <tt>read</tt> builtin causes fish to read one line from standard
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>-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>-cCMD</tt> or <tt>--command=CMD</tt> specifies that the initial string in the interactive mode command buffer should be CMD.
- <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>.
- <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
then tokenized using the <tt>IFS</tt> environment variable. Each variable

View File

@@ -8,7 +8,19 @@
The \c switch statement is used to perform one of several blocks of
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
@@ -26,12 +38,14 @@ switch $animal
echo bird
case shark trout stingray
echo fish
case '*'
echo I have no idea what a $animal is
end
</pre>
</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.
</p>

17
env.c
View File

@@ -104,7 +104,7 @@ typedef struct env_node
typedef struct var_entry
{
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;
@@ -608,9 +608,9 @@ static env_node_t *env_get_node( const wchar_t *key )
return 0;
}
void env_set( const wchar_t *key,
const wchar_t *val,
int var_mode )
int env_set( const wchar_t *key,
const wchar_t *val,
int var_mode )
{
int free_val = 0;
var_entry_t *entry;
@@ -626,7 +626,7 @@ void env_set( const wchar_t *key,
if( (var_mode & ENV_USER ) &&
hash_get( &env_read_only, key ) )
{
return;
return ENV_PERM;
}
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
*/
return;
return 0;
}
/*
@@ -749,7 +749,7 @@ void env_set( const wchar_t *key,
node = top;
while( node->next && !node->new_scope )
node = node->next;
}
}
}
@@ -809,7 +809,8 @@ void env_set( const wchar_t *key,
{
handle_locale();
}
return 0;
}

13
env.h
View File

@@ -41,6 +41,11 @@
*/
#define ENV_UNIVERSAL 32
/**
Error code for trying to alter read-only variable
*/
#define ENV_PERM 1
/**
Initialize environment variable data
*/
@@ -61,9 +66,15 @@ void env_destroy();
\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.
\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,
int mode );

4
exec.c
View File

@@ -1209,14 +1209,12 @@ void exec( job_t *j )
{
proc_last_bg_pid = j->pgid;
}
if( !exec_error )
{
job_continue (j, 0);
}
debug( 3, L"End of exec()" );
}
int exec_subshell( const wchar_t *cmd,

View File

@@ -429,7 +429,6 @@ static int find_process( const wchar_t *proc,
{
result = malloc(sizeof(wchar_t)*16 );
swprintf( result, 16, L"%d", j->pgid );
//fwprintf( stderr, L"pid %d %ls\n", j->pgid, result );
al_push( out, result );
found = 1;
}
@@ -441,12 +440,9 @@ static int find_process( const wchar_t *proc,
for( j=first_job; j != 0; j=j->next )
{
// fwprintf( stderr, L"..." );
if( j->command == 0 )
continue;
// fwprintf( stderr, L"match '%ls' '%ls'\n\n\n", j->command, proc );
if( match_pid( j->command, proc, flags ) )
{
if( flags & ACCEPT_INCOMPLETE )
@@ -455,8 +451,6 @@ static int find_process( const wchar_t *proc,
COMPLETE_SEP_STR,
COMPLETE_JOB_DESC,
(void *)0 );
// fwprintf( stderr, L"Woot %ls\n", res );
al_push( out, res );
}
else
@@ -482,12 +476,9 @@ static int find_process( const wchar_t *proc,
for( p=j->first_process; p; p=p->next )
{
// fwprintf( stderr, L"..." );
if( p->actual_cmd == 0 )
continue;
// fwprintf( stderr, L"match '%ls' '%ls'\n\n\n", j->command, proc );
if( match_pid( p->actual_cmd, proc, flags ) )
{
if( flags & ACCEPT_INCOMPLETE )
@@ -687,27 +678,22 @@ static int expand_pid( wchar_t *in,
}
}
// fwprintf( stderr, L"expand_pid() %ls\n", in );
int prev = al_get_count( out );
if( !find_process( in+1, flags, out ) )
return 0;
if( prev == al_get_count( out ) )
{
// fwprintf( stderr, L"no match\n" );
if( flags & ACCEPT_INCOMPLETE )
free( in );
else
{
*in = L'%';
// fwprintf( stderr, L"return %ls\n", in );
al_push( out, in );
}
}
else
{
// fwprintf( stderr, L"match\n" );
free( in );
}
@@ -967,7 +953,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
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)
{
@@ -980,7 +966,6 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
wcscat( new_in, next );
wcscat( new_in, &in[stop_pos] );
// fwprintf( stderr, L"New value %ls\n", new_in );
is_ok &= expand_variables( new_in, out, i );
}
}
@@ -1059,9 +1044,6 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
wchar_t *item_begin;
int len1, len2, tot_len;
// fwprintf( stderr, L"expand %ls\n", in );
for( pos=in;
(!bracket_end) && (*pos) && !syntax_error;
pos++ )
@@ -1153,8 +1135,8 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
int item_len = pos-item_begin;
whole_item = malloc( sizeof(wchar_t)*(tot_len + item_len + 1) );
wcsncpy( whole_item, in, len1 );
wcsncpy( whole_item+len1, item_begin, item_len );
wcslcpy( whole_item, in, len1+1 );
wcslcpy( whole_item+len1, item_begin, item_len+1 );
wcscpy( whole_item+len1+item_len, bracket_end+1 );
expand_brackets( whole_item, flags, out );
@@ -1234,7 +1216,7 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
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;
if( exec_subshell( subcmd, &sub_res)==-1 )
@@ -1310,7 +1292,6 @@ static wchar_t * expand_tilde_internal( wchar_t *in )
wchar_t *new_in=0;
wchar_t *old_in=0;
// fwprintf( stderr, L"Tilde expand ~%ls\n", (*ptr)+1 );
if( in[1] == '/' || in[1] == '\0' )
{
/* Current users home directory */
@@ -1439,7 +1420,6 @@ int expand_string( void *context,
// debug( 1, L"Expand %ls", str );
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
{
halloc_register( context, str );

View File

@@ -38,17 +38,17 @@
#include <ncurses/term.h>
#endif
#include "common.h"
#include "fallback.h"
#include "util.h"
#ifdef TPUTS_KLUDGE
int tputs(const char *str, int affcnt, int (*putc)(tputs_arg_t))
int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
{
while( *str )
{
putc( *str++ );
fish_putc( *str++ );
}
}
@@ -818,8 +818,7 @@ wchar_t *wcsndup( const wchar_t *in, int c )
{
return 0;
}
wcsncpy( res, in, c+1 );
res[c] = L'\0';
wcslcpy( res, in, c+1 );
return res;
}
#endif
@@ -888,6 +887,113 @@ long wcstol(const wchar_t *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

View File

@@ -27,7 +27,7 @@ typedef char tputs_arg_t;
Linux on PPC seems to have a tputs implementation that sometimes
behaves strangely. This fallback seems to fix things.
*/
int tputs(const char *str, int affcnt, int (*putc)(tputs_arg_t));
int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t));
#endif
@@ -231,6 +231,35 @@ long wcstol(const wchar_t *nptr,
wchar_t **endptr,
int base);
#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
#endif

View File

@@ -202,6 +202,10 @@ static void history_to_hash()
{
history_data *d;
if( !history_last )
return;
d = (history_data *)hash_get( &history_table,
mode_name );

7
main.c
View File

@@ -61,6 +61,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "output.h"
#include "translate.h"
#include "halloc_util.h"
#include "history.h"
/**
@@ -266,6 +267,7 @@ int main( int argc, char **argv )
env_init();
complete_init();
reader_init();
history_init();
if( read_init() )
{
@@ -297,10 +299,10 @@ int main( int argc, char **argv )
return 1;
}
sb_init( &sb );
if( *(argv+2))
{
sb_init( &sb );
for( i=1,ptr = argv+2; *ptr; i++, ptr++ )
{
if( i != 1 )
@@ -337,6 +339,7 @@ int main( int argc, char **argv )
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
history_destroy();
complete_destroy();
proc_destroy();
env_destroy();

223
parser.c
View File

@@ -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
*/
#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
*/
#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
@@ -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'")
@@ -176,78 +176,78 @@ The fish parser. Contains functions for parsing code.
/**
While block description
While block description
*/
#define WHILE_BLOCK _( L"'while' block" )
/**
For block description
For block description
*/
#define FOR_BLOCK _( L"'for' block" )
/**
If block description
If block description
*/
#define IF_BLOCK _( L"'if' conditional block" )
/**
function definition block description
Function definition block description
*/
#define FUNCTION_DEF_BLOCK _( L"function definition block" )
/**
Function invocation block description
Function invocation block description
*/
#define FUNCTION_CALL_BLOCK _( L"function invocation block" )
/**
Switch block description
Switch block description
*/
#define SWITCH_BLOCK _( L"'switch' block" )
/**
Fake block description
Fake block description
*/
#define FAKE_BLOCK _( L"unexecutable block" )
/**
Top block description
Top block description
*/
#define TOP_BLOCK _( L"global root block" )
/**
Command substitution block description
Command substitution block description
*/
#define SUBST_BLOCK _( L"command substitution block" )
/**
Begin block description
Begin block description
*/
#define BEGIN_BLOCK _( L"'begin' unconditional block" )
/**
Source block description
Source block description
*/
#define SOURCE_BLOCK _( L"Block created by the . builtin" )
/**
Source block description
Source block description
*/
#define EVENT_BLOCK _( L"event handler block" )
/**
Unknown block description
Unknown block description
*/
#define UNKNOWN_BLOCK _( L"unknown/invalid block" )
@@ -724,75 +724,85 @@ wchar_t *get_filename( const wchar_t *cmd )
else
{
path = env_get(L"PATH");
if( path != 0 )
if( path == 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) )
if( contains_str( PREFIX L"/bin", L"/bin", L"/usr/bin", (void *)0 ) )
{
die_mem();
path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
}
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
else
{
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" );
}
}
}
path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
}
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;
}
@@ -1101,8 +1111,8 @@ int parser_get_lineno()
int lineno;
/* static const wchar_t *prev_str = 0;
static int i=0;
static int lineno=1;
static int i=0;
static int lineno=1;
*/
if( !current_tokenizer )
return -1;
@@ -1241,8 +1251,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);
/*
Skip printing character position if we are in interactive mode
and the error was on the first character of the line.
Skip printing character position if we are in interactive mode
and the error was on the first character of the line.
*/
if( !is_interactive || is_function() || (current_line_width!=0) )
{
@@ -1716,8 +1726,8 @@ static int parse_job( process_t *p,
else
{
error( SYNTAX_ERROR,
tok_get_pos( tok ),
CMD_ERR_MSG,
tok_get_pos( tok ),
CMD_ERR_MSG,
tok_get_desc( tok_last_type(tok) ) );
}
@@ -1926,8 +1936,8 @@ static int parse_job( process_t *p,
if( !p->type || (p->type == INTERNAL_EXEC) )
{
/*
If we are not executing the current block, allow
non-existent commands.
If we are not executing the current block, allow
non-existent commands.
*/
if( current_block->skip )
{
@@ -1971,7 +1981,8 @@ static int parse_job( process_t *p,
else
{
int tmp;
wchar_t *cmd = (wchar_t *)al_get( args, 0 );
/*
We couln't find the specified command.
@@ -1986,19 +1997,42 @@ static int parse_job( process_t *p,
cause the job to silently not execute. We
also print an error message.
*/
if( wcschr( (wchar_t *)al_get( args, 0 ), L'=' ) )
if( wcschr( cmd, L'=' ) )
{
debug( 0,
COMMAND_ASSIGN_ERR_MSG,
(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,
_(L"Unknown command '%ls'"),
(wchar_t *)al_get( args, 0 ) );
cmd );
}
tmp = current_tokenizer_pos;
@@ -2482,7 +2516,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;
current_tokenizer=previous_tokenizer;
@@ -2497,7 +2531,6 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
return code;
}
int parser_test( wchar_t * buff,
int babble )
{

30
proc.c
View File

@@ -265,28 +265,12 @@ int job_is_completed( const job_t *j )
{
if (!p->completed)
{
// fwprintf( stderr, L"Process %ls not finished\n", p->argv[0] );
return 0;
}
}
return 1;
}
/**
Return true if all processes in the job have completed.
\param j the job to test
*/
static int job_last_is_completed( const job_t *j )
{
process_t *p;
for (p = j->first_process; p->next; p = p->next)
;
return p->completed;
}
/**
Store the status of the process pid that was returned by waitpid.
Return 0 if all went well, nonzero otherwise.
@@ -503,6 +487,11 @@ int job_reap( int interactive )
static int locked = 0;
locked++;
/*
job_read may fire an event handler, we do not want to call
ourselves recursively (to avoid infinite recursion).
*/
if( locked>1 )
return 0;
@@ -511,6 +500,11 @@ int job_reap( int interactive )
process_t *p;
jnext = j->next;
/*
If we are reaping only jobs who do not need status messages
sent to the console, do not consider reaping jobs that need
status messages
*/
if( (!j->skip_notification) && (!interactive) && (!j->fg))
{
continue;
@@ -915,7 +909,7 @@ void job_continue (job_t *j, int cont)
do
{
got_signal = 0;
quit = job_is_stopped( j ) || job_last_is_completed( j );
quit = job_is_stopped( j ) || job_is_completed( j );
}
while( got_signal && !quit );
if( !quit )
@@ -1039,7 +1033,7 @@ void proc_sanity_check()
/*
More than one foreground job?
*/
if( j->fg && !(job_is_stopped(j) || job_last_is_completed(j) ) )
if( j->fg && !(job_is_stopped(j) || job_is_completed(j) ) )
{
if( fg_job != 0 )
{

View File

@@ -1631,7 +1631,6 @@ static void reader_interactive_init()
al_init( &prompt_list );
history_init();
common_handle_winch(0);
@@ -1658,7 +1657,6 @@ static void reader_interactive_destroy()
kill_destroy();
al_foreach( &prompt_list, (void (*)(const void *))&free );
al_destroy( &prompt_list );
history_destroy();
writestr( L"\n" );
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
@@ -2265,7 +2263,19 @@ static int read_i()
if( data->end_loop)
{
if( !prev_end_loop && first_job != 0 )
job_t *j;
int has_job=0;
for( j=first_job; j; j=j->next )
{
if( !job_is_completed(j) )
{
has_job = 1;
break;
}
}
if( !prev_end_loop && has_job )
{
writestr(_( L"There are stopped jobs\n" ));
write_prompt();
@@ -2461,8 +2471,6 @@ wchar_t *reader_readline()
len = data->buff_pos - (data->buff - begin);
buffcpy = wcsndup( begin, len );
//fwprintf( stderr, L"String is %ls\n", buffcpy );
reader_save_status();
data->complete_func( buffcpy, &comp );
reader_check_status();
@@ -2492,7 +2500,6 @@ wchar_t *reader_readline()
repaint();
// wcscpy(data->search_buff,data->buff);
break;
}
@@ -2512,7 +2519,6 @@ wchar_t *reader_readline()
reader_super_highlight_me_plenty( data->buff, data->color, data->buff_pos, 0 );
repaint();
// wcscpy(data->search_buff,data->buff);
break;
}
@@ -2524,7 +2530,6 @@ wchar_t *reader_readline()
reader_super_highlight_me_plenty( data->buff, data->color, data->buff_pos, 0 );
repaint();
// wcscpy(data->search_buff,data->buff);
break;
}
@@ -2533,7 +2538,6 @@ wchar_t *reader_readline()
{ yank_str = kill_yank();
insert_str( yank_str );
yank = wcslen( yank_str );
// wcscpy(data->search_buff,data->buff);
break;
}
@@ -2696,6 +2700,7 @@ wchar_t *reader_readline()
/* Move left*/
case R_BACKWARD_CHAR:
{
if( data->buff_pos > 0 )
{
data->buff_pos--;
@@ -2710,8 +2715,9 @@ wchar_t *reader_readline()
}
}
break;
/* Move right*/
}
/* Move right*/
case R_FORWARD_CHAR:
{
if( data->buff_pos < data->buff_len )
@@ -2796,7 +2802,12 @@ wchar_t *reader_readline()
insert_char( c );
else
{
// Carriage returns happen. We ignore them
/*
Carriage returns happen - they are usually a
sign of an incorrectly set terminal, but there
really isn't very much we can do at this point,
so we ignore them.
*/
if( c != 13 )
debug( 0, _( L"Unknown keybinding %d" ), c );
}
@@ -2873,7 +2884,7 @@ static int read_ni( int fd )
_( L"Error while reading commands" ) );
/*
Reset buffer. We won't evaluate incomplete files.
Reset buffer on error. We won't evaluate incomplete files.
*/
acc.used=0;
break;
@@ -2894,13 +2905,10 @@ static int read_ni( int fd )
res = 1;
}
// fwprintf( stderr, L"Woot is %d chars\n", wcslen( acc.buff ) );
if( str )
{
if( !parser_test( str, 1 ) )
{
//fwprintf( stderr, L"We parse it\n" );
eval( str, 0, TOP );
}
else
@@ -2943,10 +2951,11 @@ static int read_ni( int fd )
int reader_read( int fd )
{
int res;
/*
If reader_read is called recursively through the '.' builtin,
we need to preserve is_interactive, so we save the
original state. We also update the signal handlers.
If reader_read is called recursively through the '.' builtin, we
need to preserve is_interactive. This, and signal handler setup
is handled by proc_push_interactive/proc_pop_interactive.
*/
proc_push_interactive( ((fd == 0) && isatty(STDIN_FILENO)));
@@ -2955,7 +2964,7 @@ int reader_read( int fd )
/*
If the exit command was called in a script, only exit the
script, not the program
script, not the program.
*/
if( data )
data->end_loop = 0;

View File

@@ -18,7 +18,7 @@ if test "$USER" = root
end
for i in $path_list
if not expr "$PATH" : .\*$i.\* >/dev/null
if not expr "$PATH" : "$i/*" >/dev/null
if test -d $i
set PATH $PATH $i
end
@@ -43,8 +43,8 @@ end
# Convenience functions
#
# The naming heuristic is that __fish_complete_* prints completions
# and descriptions, while __fish_print_* only prints the completion,
# without the description
# and descriptions, while __fish_print_* only prints the completions
# and no descriptions
#
function __fish_complete_users -d "Print a list of local users, with the real user name as a description"

View File

@@ -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")
while set -q argv

View File

@@ -2,7 +2,7 @@
function type -d (N_ "Print the type of a command")
# Initialize
set -l status 1
set -l res 1
set -l mode normal
set -l selection all
@@ -66,7 +66,7 @@ function type -d (N_ "Print the type of a command")
if test $selection != files
if contains -- $i (functions -na)
set status 0
set res 0
set found 1
switch $mode
case normal
@@ -86,7 +86,8 @@ function type -d (N_ "Print the type of a command")
end
if contains -- $i (builtin -n)
set status 0
set res 0
set found 1
switch $mode
case normal
@@ -107,7 +108,7 @@ function type -d (N_ "Print the type of a command")
set -l path (which $i ^/dev/null)
if test -x (echo $path)
set status 0
set res 0
set found 1
switch $mode
case normal
@@ -130,6 +131,6 @@ function type -d (N_ "Print the type of a command")
end
return $status
return $res
end