diff --git a/Makefile.in b/Makefile.in
index d2f04b6ea..da1a08816 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -54,10 +54,6 @@ CFLAGS=@CFLAGS@ $(MACROS)
CPPFLAGS=@CPPFLAGS@
LDFLAGS= @LIBS@ @LDFLAGS@
-
-#etc files to install
-ETC_DIR_INSTALL = etc/fish_interactive.fish
-
# Set to 1 if we have gettext
HAVE_GETTEXT=@HAVE_GETTEXT@
@@ -71,6 +67,7 @@ FISH_OBJS := function.o builtin.o complete.o env.o exec.o \
sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \
output.o intern.o env_universal.o env_universal_common.o \
input_common.o event.o signal.o io.o parse_util.o common.o screen.o\
+ path.o
# Additional files used by builtin.o
BUILTIN_FILES := builtin_help.c builtin_set.c builtin_commandline.c \
@@ -153,11 +150,11 @@ MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
main.c fish_pager.c fishd.c seq.in
# Files in ./etc/
-ETC_DIR_FILES :=etc/fish.in etc/fish_inputrc \
- etc/fish_interactive.fish.in
+ETC_DIR_FILES :=etc/config.fish.in etc/fish_inputrc
+
# Files in ./share/
-SHARE_DIR_FILES :=share/fish.in
+SHARE_DIR_FILES :=share/config.fish.in share/config_interactive.fish.in
# Files in ./tests/
TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \
@@ -185,7 +182,7 @@ TRANSLATIONS_SRC := $(wildcard po/*.po)
TRANSLATIONS := $(TRANSLATIONS_SRC:.po=.gmo)
#Make everything needed for installing fish
-all: $(PROGRAMS) user_doc etc/fish share/fish etc/fish_interactive.fish $(TRANSLATIONS)
+all: $(PROGRAMS) user_doc etc/config.fish share/config.fish share/config_interactive.fish $(TRANSLATIONS)
@echo fish has now been built.
@echo Use \'make install\' to install fish.
.PHONY: all
@@ -409,22 +406,20 @@ install-force: all install-translations
for i in $(PROGRAMS); do\
$(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \
done;
- $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish.d
+ $(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
- $(INSTALL) -m 644 etc/fish $(DESTDIR)$(sysconfdir)/fish
- $(INSTALL) -m 644 share/fish $(DESTDIR)$(datadir)/fish
- for i in $(ETC_DIR_INSTALL); do \
- $(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)/fish.d; \
- done;
+ $(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/
+ $(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/
+ $(INSTALL) -m 644 share/config_interactive.fish $(DESTDIR)$(datadir)/fish/
for i in $(COMPLETIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \
done;
for i in $(FUNCTIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \
done;
- $(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish_inputrc;
+ $(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish/fish_inputrc;
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
for i in user_doc/html/* ChangeLog; do \
if test -f $$i; then \
@@ -453,11 +448,9 @@ uninstall: uninstall-translations
rm -f $(DESTDIR)$(bindir)/$$i; \
done;
rm -f $(DESTDIR)$(bindir)/xsel
- rm -f $(DESTDIR)$(sysconfdir)/fish
- rm -f $(DESTDIR)$(sysconfdir)/fish_inputrc
- if test -f $(DESTDIR)$(sysconfdir)/fish.d/fish_interactive.fish; then \
- rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_interactive.fish; \
- fi
+ rm -f $(DESTDIR)$(sysconfdir)/fish/config.fish
+ rm -f $(DESTDIR)$(sysconfdir)/fish/fish_inputrc
+ rmdir $(DESTDIR)$(sysconfdir)/fish; true
if test -d $(DESTDIR)$(datadir)/fish; then \
rm -r $(DESTDIR)$(datadir)/fish; \
fi
@@ -533,7 +526,7 @@ count: count.o
$(CC) count.o -o $@
set_color: set_color.o doc_src/set_color.o common.o
- $(CC) set_color.o doc_src/set_color.o common.o $(LDFLAGS) -o $@
+ $(CC) set_color.o doc_src/set_color.o common.o wutil.o $(LDFLAGS) -o $@
# Test program for the tokenizer library
tokenizer_test: tokenizer.c tokenizer.h wutil.o common.o
@@ -638,7 +631,7 @@ clean:
builtin.o: config.h fallback.h util.h wutil.h builtin.h function.h complete.h
builtin.o: proc.h io.h parser.h event.h reader.h env.h common.h wgetopt.h
builtin.o: sanity.h tokenizer.h wildcard.h input_common.h input.h intern.h
-builtin.o: signal.h halloc.h halloc_util.h parse_util.h expand.h
+builtin.o: signal.h halloc.h halloc_util.h parse_util.h expand.h path.h
builtin.o: builtin_help.c builtin_set.c builtin_commandline.c
builtin.o: builtin_complete.c builtin_ulimit.c builtin_jobs.c
builtin_commandline.o: config.h signal.h fallback.h util.h wutil.h builtin.h
@@ -660,7 +653,7 @@ common.o: fallback.c
complete.o: config.h signal.h fallback.h util.h tokenizer.h wildcard.h proc.h
complete.o: io.h parser.h event.h function.h complete.h builtin.h env.h
complete.o: exec.h expand.h common.h reader.h history.h intern.h parse_util.h
-complete.o: halloc.h halloc_util.h wutil.h
+complete.o: halloc.h halloc_util.h wutil.h path.h
count.o: config.h
env.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h env.h
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
@@ -680,14 +673,13 @@ expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
expand.o: complete.h parse_util.h halloc.h halloc_util.h
fallback.o: config.h fallback.h util.h
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
-fishd.o: env_universal_common.h
+fishd.o: env_universal_common.h halloc.h halloc_util.h path.h
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h
fish_pager.o: halloc.h halloc_util.h
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
fish_tests.o: reader.h builtin.h function.h complete.h wutil.h env.h expand.h
fish_tests.o: parser.h event.h tokenizer.h output.h exec.h halloc_util.h
-foo.o: config.h signal.h
function.o: config.h signal.h wutil.h fallback.h util.h function.h proc.h
function.o: io.h parser.h event.h common.h intern.h reader.h parse_util.h
function.o: env.h expand.h
@@ -696,9 +688,9 @@ halloc_util.o: config.h fallback.h util.h common.h halloc.h
highlight.o: config.h signal.h fallback.h util.h wutil.h highlight.h
highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h builtin.h
highlight.o: function.h env.h expand.h sanity.h common.h complete.h output.h
-highlight.o: halloc.h halloc_util.h wildcard.h
+highlight.o: halloc.h halloc_util.h wildcard.h path.h
history.o: config.h fallback.h util.h wutil.h history.h common.h reader.h
-history.o: env.h sanity.h signal.h halloc.h halloc_util.h
+history.o: env.h sanity.h signal.h halloc.h halloc_util.h path.h
input.o: config.h signal.h fallback.h util.h wutil.h reader.h proc.h io.h
input.o: common.h sanity.h input_common.h input.h parser.h event.h env.h
input.o: expand.h output.h intern.h
@@ -708,10 +700,11 @@ intern.o: config.h fallback.h util.h wutil.h common.h intern.h
io.o: config.h fallback.h util.h wutil.h exec.h proc.h io.h common.h halloc.h
key_reader.o: config.h fallback.h input_common.h
kill.o: config.h signal.h fallback.h util.h wutil.h kill.h proc.h io.h
-kill.o: sanity.h common.h env.h exec.h parser.h event.h halloc.h
+kill.o: sanity.h common.h env.h exec.h halloc.h path.h
main.o: config.h signal.h fallback.h util.h common.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 halloc_util.h history.h
+main.o: event.h expand.h intern.h exec.h output.h halloc.h halloc_util.h
+main.o: history.h path.h
mimedb.o: config.h xdgmime.h fallback.h util.h
output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h
output.o: output.h halloc_util.h highlight.h
@@ -719,9 +712,12 @@ parser.o: config.h signal.h fallback.h util.h common.h wutil.h proc.h io.h
parser.o: parser.h event.h tokenizer.h exec.h wildcard.h function.h builtin.h
parser.o: env.h expand.h reader.h sanity.h env_universal.h
parser.o: env_universal_common.h intern.h parse_util.h halloc.h halloc_util.h
+parser.o: path.h
parse_util.o: config.h fallback.h util.h wutil.h common.h tokenizer.h
parse_util.o: parse_util.h expand.h intern.h exec.h proc.h io.h env.h
parse_util.o: wildcard.h halloc_util.h
+path.o: config.h fallback.h util.h common.h env.h wutil.h halloc.h
+path.o: halloc_util.h path.h expand.h
proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h
proc.o: reader.h sanity.h env.h parser.h event.h halloc.h halloc_util.h
proc.o: output.h
diff --git a/builtin.c b/builtin.c
index d6ab7db0a..bc25929d3 100644
--- a/builtin.c
+++ b/builtin.c
@@ -65,6 +65,7 @@
#include "halloc_util.h"
#include "parse_util.h"
#include "expand.h"
+#include "path.h"
@@ -2076,7 +2077,7 @@ static int builtin_cd( wchar_t **argv )
else
dir_in = argv[1];
- dir = parser_cdpath_get( context, dir_in );
+ dir = path_get_cdpath( context, dir_in );
if( !dir )
{
diff --git a/common.c b/common.c
index 34d64f930..dcd618d9a 100644
--- a/common.c
+++ b/common.c
@@ -1557,3 +1557,42 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out )
}
+int create_directory( wchar_t *d )
+{
+ int ok = 0;
+ struct stat buf;
+ int stat_res = 0;
+
+ while( (stat_res = wstat(d, &buf ) ) != 0 )
+ {
+ if( errno != EAGAIN )
+ break;
+ }
+
+ if( stat_res == 0 )
+ {
+ if( S_ISDIR( buf.st_mode ) )
+ {
+ ok = 1;
+ }
+ }
+ else
+ {
+ if( errno == ENOENT )
+ {
+ wchar_t *dir = wcsdup( d );
+ dir = wdirname( dir );
+ if( !create_directory( dir ) )
+ {
+ if( !wmkdir( d, 0700 ) )
+ {
+ ok = 1;
+ }
+ }
+ free(dir);
+ }
+ }
+
+ return ok?0:-1;
+}
+
diff --git a/common.h b/common.h
index 84aa22c0a..d9c7cc274 100644
--- a/common.h
+++ b/common.h
@@ -358,5 +358,12 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff );
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
+/**
+ Make sure the specified direcotry exists. If no, try to create it.
+
+ \return 0 if the directory exists, -1 otherwise.
+*/
+int create_directory( wchar_t *d );
+
#endif
diff --git a/complete.c b/complete.c
index f332c2bde..69c7748f0 100644
--- a/complete.c
+++ b/complete.c
@@ -45,6 +45,7 @@
#include "halloc.h"
#include "halloc_util.h"
#include "wutil.h"
+#include "path.h"
/*
@@ -407,7 +408,7 @@ void complete_add( const wchar_t *cmd,
complete_entry_opt *opt;
CHECK( cmd, );
-
+
complete_init();
c = complete_find_exact_entry( cmd, cmd_type );
@@ -581,7 +582,7 @@ static void parse_cmd_string( void *context,
wchar_t *cmd, *path;
/* Get the path of the command */
- path = parser_get_filename( context, str );
+ path = path_get_path( context, str );
if( path == 0 )
{
/**
diff --git a/doc_src/doc.hdr b/doc_src/doc.hdr
index caad3fac2..e18e22f63 100644
--- a/doc_src/doc.hdr
+++ b/doc_src/doc.hdr
@@ -279,8 +279,8 @@ automatically loaded when needed. A function definition file must have
a filename consisting of the name of the function plus the suffix
'.fish'.
-The default value for \$fish_function_path is \c ~/.fish.d/functions
-\c /etc/fish.d/functions \c /usr/share/fish/functions. The exact path
+The default value for \$fish_function_path is \c ~/.config/fish/functions
+\c /etc/fish/functions \c /usr/share/fish/functions. The exact path
to the last two of these may be slighly different depending on what
install path prefix was chosen at configuration time. The rationale
behind having three different directories is that the first one is for
@@ -404,8 +404,8 @@ searches through any directories in the array variable
loaded when needed. A completion file must have a filename consisting
of the name of the command to complete and the suffix '.fish'.
-The default value for \$fish_complete_path is ~/.fish.d/completions,
-/etc/fish.d/completions and /usr/share/fish/completions. The exact
+The default value for \$fish_complete_path is ~/.config/fish/completions,
+/etc/fish/completions and /usr/share/fish/completions. The exact
path to the last two of these may be slighly different depending on
what install path prefix was chosen at configuration time. If a
suitable file is found in one of these directories, it will be
@@ -972,8 +972,8 @@ Here are some of the commands available in the editor:
- Alt-p adds the string '| less;' to the end of the job under the cursor. The result is that the output of the command will be paged.
You can change these key bindings by making an inputrc file. To do
-this, copy the file /etc/fish_inputrc to your home directory and
-rename it to '.fish_inputrc'. Now you can edit the file .fish_inputrc,
+this, copy the file /etc/fish/fish_inputrc to your home directory and
+rename it to '.config/fish/fish_inputrc'. Now you can edit the file
to change your key bindings. The fileformat of this file is described
in the manual page for readline. Use the command man readline
to read up on this syntax. Please note that the list of key binding
@@ -1041,7 +1041,7 @@ cursor when the search began.
History searches can be aborted by pressing the escape key.
-The history is stored in the file '.fish_history'. It is automatically
+The history is stored in the file '~/.config/fish/fish_history'. It is automatically
read on startup and merged on program exit.
Example:
@@ -1065,20 +1065,23 @@ which the user can change fish
's behaviour.
\section initialization Initialization files
-On startup, \c fish evaluates the files /usr/share/fish/fish,
-/etc/fish (Or ~/etc/fish if you installed fish in your home directory)
-and ~/.fish, in that order. The first file should not be directly
-edited, the second one is meant for systemwide configuration and the
-last one is meant for user configuration. If you want to run a command
-only on starting an interactive shell, use the exit status of the
-command 'status --is-interactive' to determine if the shell is
-interactive. If you want to run a command only when using a login
-shell, use 'status --is-login' instead.
+On startup, \c fish evaluates the files /usr/share/fish/config.fish
+(Or /usr/local/fish... if you installed fish in /usr/local),
+/etc/fish/config.fish (Or ~/etc/fish/... if you installed fish in your
+home directory) and ~/.config/fish/config.fish (Or any other directory
+specified by the \$XDG_CONFIG_HOME variable), in that order. The first
+file should not be directly edited, the second one is meant for
+systemwide configuration and the last one is meant for user
+configuration. If you want to run a command only on starting an
+interactive shell, use the exit status of the command 'status
+--is-interactive' to determine if the shell is interactive. If you
+want to run a command only when using a login shell, use 'status
+--is-login' instead.
Examples:
If you want to add the directory ~/linux/bin to your PATH variable
-when using a login shell, add the following to your ~/.fish file:
+when using a login shell, add the following to your ~/.config/fish/config.fish file:
if status --is-login
set PATH $PATH ~/linux/bin
@@ -1093,7 +1096,7 @@ shell:
end
Universal variables are stored in
-the file .fishd.HOSTNAME, where HOSTNAME is the name of your
+the file .config/fish/fishd.HOSTNAME, where HOSTNAME is the name of your
computer. Do not edit this file directly, edit them through fish
scripts or by using fish interactively instead.
@@ -1302,7 +1305,7 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
- With a bit of tweakage, quite a few of the readline key-binding functions could be implemented in shellscript.
- Highlight beginning/end of block when moving over a block command
- Inclusion guards for the init files to make them evaluate only once, even if the user has installed fish both in /etc and in $HOME
-- Do not actually load/parse .fish_history, only mmap it and use some clever string handling. Should save ~150 kB of memory permanently, but is very hard to implement.
+- Do not actually load/parse fish_history, only mmap it and use some clever string handling. Should save ~150 kB of memory permanently, but is very hard to implement.
- command specific wildcarding (use case * instead of case '*', etc.)
- Map variables. (export only the values. When expanding with no key specified, expand to all values.)
- Descriptions for variables using 'set -d'.
diff --git a/etc/fish.in b/etc/config.fish.in
similarity index 94%
rename from etc/fish.in
rename to etc/config.fish.in
index 1c85fb287..648fcac91 100644
--- a/etc/fish.in
+++ b/etc/config.fish.in
@@ -59,6 +59,8 @@ end
# Load additional initialization files
#
-for i in fish.d/*.fish
- . $i
-end
+if test -d include
+ for i in include/*.fish
+ . $i
+ end
+end
\ No newline at end of file
diff --git a/etc/fish_interactive.fish.in b/etc/fish_interactive.fish.in
deleted file mode 100644
index 4e96daba6..000000000
--- a/etc/fish_interactive.fish.in
+++ /dev/null
@@ -1,103 +0,0 @@
-#
-# Initializations that should only be performed when in interactive mode
-#
-# @configure_input@
-
-if not status --is-interactive
- exit
-end
-
-#
-# Set exit message
-#
-
-function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
- printf (_ "Good bye\n")
-end
-
-#
-# Set INPUTRC to something nice
-#
-# We override INPUTRC if already set, since it may be set by a shell
-# other than fish, which may use a different file. The new value should
-# be exported, since the fish inputrc file plays nice with other files
-# by including them when found.
-# Give priority to the default file installed with fish in
-# @sysconfdir@/fish_inputrc.
-#
-
-for i in ~/.fish_inputrc @sysconfdir@/fish_inputrc ~/.inputrc /etc/inputrc
- if test -f $i
- set -xg INPUTRC $i
- break
- end
-end
-
-
-#
-# Set various defaults using these throwaway functions
-#
-
-function set_default -d "Set an universal variable, unless it has already been set"
- if not set -q $argv[1]
- set -U -- $argv
- end
- if not set -q $argv[1]
- set -g -- $argv
- end
-end
-
-function set_exported_default -d "Set an exported universal variable, unless it has already been set"
- if not set -q $argv[1]
- set -Ux -- $argv
- end
- if not set -q $argv[1]
- set -gx -- $argv
- end
-end
-
-
-# Regular syntax highlighting colors
-set_default fish_color_normal normal
-set_default fish_color_command green
-set_default fish_color_redirection normal
-set_default fish_color_comment red
-set_default fish_color_error red --bold
-set_default fish_color_escape cyan
-set_default fish_color_operator cyan
-set_default fish_color_quote brown
-set_default fish_color_valid_path --underline
-
-set_default fish_color_cwd green
-
-# Background color for matching quotes and parenthesis
-set_default fish_color_match cyan
-
-# Background color for search matches
-set_default fish_color_search_match purple
-
-# Pager colors
-set_default fish_pager_color_prefix cyan
-set_default fish_pager_color_completion normal
-set_default fish_pager_color_description normal
-set_default fish_pager_color_progress cyan
-
-#
-# Directory history colors
-#
-
-set_default fish_color_history_current cyan
-
-
-#
-# Setup the CDPATH variable
-#
-
-set_default CDPATH . ~
-
-#
-# Remove temporary functions for setting default variable values
-#
-
-functions -e set_exported_default
-functions -e set_default
diff --git a/fish.spec.in b/fish.spec.in
index 34a5205c2..f2b26b7fc 100644
--- a/fish.spec.in
+++ b/fish.spec.in
@@ -133,14 +133,14 @@ fi
%attr(0755,root,root) %_bindir/count
# Configuration files
-%config %_sysconfdir/fish
-%config %_sysconfdir/fish_inputrc
-%dir %_sysconfdir/fish.d
-%config %_sysconfdir/fish.d/fish_*.fish
+%config %_sysconfdir/fish/config.fish
+%config %_sysconfdir/fish/fish_inputrc
+%dir %_sysconfdir/fish
# Non-configuration initialization files
%dir %_datadir/fish
-%_datadir/fish/fish
+%_datadir/fish/config.fish
+%_datadir/fish/config_interactive.fish
# Program specific tab-completions
%dir %_datadir/fish/completions
@@ -155,6 +155,9 @@ fi
%changelog
+* Sat Oct 14 2006 Axel Liljencrantz 1.22.0-0
+- Update names of various configuration files
+
* Fri Aug 4 2006 Axel Liljencrantz 1.21.10-4
- Add better translation finding code from fedora spec to main spec. Thank you to Michael Schwendt.
- Add missing dependency libXext-devel.
diff --git a/fishd.c b/fishd.c
index ea26b9135..998b6550e 100644
--- a/fishd.c
+++ b/fishd.c
@@ -70,6 +70,9 @@ time the original barrier request was sent have been received.
#include "common.h"
#include "wutil.h"
#include "env_universal_common.h"
+#include "halloc.h"
+#include "halloc_util.h"
+#include "path.h"
/**
Maximum length of socket filename
@@ -100,7 +103,7 @@ time the original barrier request was sent have been received.
/**
The name of the save file. The hostname is appended to this.
*/
-#define FILE ".fishd."
+#define FILE "fishd."
/**
Maximum length of hostname. Longer hostnames are truncated
@@ -388,24 +391,108 @@ static void daemonize()
}
+/**
+ Get environment variable value. The resulting string needs to be free'd.
+*/
+static wchar_t *fishd_env_get( wchar_t *key )
+{
+ char *nres, *nkey;
+ wchar_t *res;
+
+ nkey = wcs2str( key );
+ nres = getenv( nkey );
+ free( nkey );
+ if( nres )
+ {
+ return str2wcs( nres );
+ }
+ else
+ {
+ res = env_universal_common_get( key );
+ if( res )
+ res = wcsdup( res );
+
+ return env_universal_common_get( key );
+ }
+}
+
+/**
+ Get the configuration directory. The resulting string needs to be
+ free'd. This is mostly the same code as path_get_config(), but had
+ to be rewritten to avoid dragging in additional library
+ dependencies.
+*/
+static wchar_t *fishd_get_config()
+{
+ wchar_t *xdg_dir, *home;
+ int done = 0;
+ wchar_t *res = 0;
+
+ xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
+ if( xdg_dir )
+ {
+ res = wcsdupcat( xdg_dir, L"/fish" );
+ if( !create_directory( res ) )
+ {
+ done = 1;
+ }
+ else
+ {
+ free( res );
+ }
+ free( xdg_dir );
+ }
+ else
+ {
+ home = fishd_env_get( L"HOME" );
+ if( home )
+ {
+ res = wcsdupcat( home, L"/.config/fish" );
+ if( !create_directory( res ) )
+ {
+ done = 1;
+ }
+ else
+ {
+ free( res );
+ }
+ free( home );
+ }
+ }
+
+ if( done )
+ {
+ return res;
+ }
+ else
+ {
+ debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
+ return 0;
+ }
+
+}
+
/**
Load or save all variables
*/
static void load_or_save( int save)
{
- struct passwd *pw;
char *name;
- char *dir = getenv( "HOME" );
+ wchar_t *wdir = fishd_get_config();
+ char *dir;
char hostname[HOSTNAME_LEN];
connection_t c;
int fd;
- if( !dir )
+ if( !wdir )
{
- pw = getpwuid( getuid() );
- dir = pw->pw_dir;
+ return;
}
+ dir = wcs2str( wdir );
+
+ free( wdir );
+
gethostname( hostname, HOSTNAME_LEN );
name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 );
@@ -413,6 +500,9 @@ static void load_or_save( int save)
strcat( name, "/" );
strcat( name, FILE );
strcat( name, hostname );
+
+ free( dir );
+
debug( 4, L"Open file for %s: '%s'",
save?"saving":"loading",
@@ -485,6 +575,8 @@ int main( int argc, char ** argv )
int update_count=0;
fd_set read_fd, write_fd;
+
+ halloc_util_init();
program_name=L"fishd";
wsetlocale( LC_ALL, L"" );
@@ -685,10 +777,10 @@ int main( int argc, char ** argv )
debug( 0, L"No more clients. Quitting" );
save();
env_universal_common_destroy();
- exit(0);
- c=c->next;
+ break;
}
}
+ halloc_util_destroy();
}
diff --git a/highlight.c b/highlight.c
index 471065555..506348b27 100644
--- a/highlight.c
+++ b/highlight.c
@@ -33,6 +33,7 @@
#include "halloc.h"
#include "halloc_util.h"
#include "wildcard.h"
+#include "path.h"
/**
Number of elements in the highlight_var array
@@ -588,7 +589,7 @@ void highlight_shell( wchar_t * buff,
EXPAND_SKIP_CMDSUBST );
if( dir )
{
- if( !parser_cdpath_get( context, dir ) )
+ if( !path_get_cdpath( context, dir ) )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
}
@@ -671,13 +672,13 @@ void highlight_shell( wchar_t * buff,
/*
Check if this is a regular command
*/
- is_cmd |= !!(tmp=parser_get_filename( context, cmd ));
+ is_cmd |= !!(tmp=path_get_path( context, cmd ));
/*
Could not find the command. Maybe it is
a path for a implicit cd command.
*/
- is_cmd |= !!(tmp=parser_cdpath_get( context, cmd ));
+ is_cmd |= !!(tmp=path_get_cdpath( context, cmd ));
if( is_cmd )
{
diff --git a/history.c b/history.c
index cb595d7e2..f98ddaff6 100644
--- a/history.c
+++ b/history.c
@@ -25,6 +25,7 @@
#include "signal.h"
#include "halloc.h"
#include "halloc_util.h"
+#include "path.h"
/*
The history is implemented using a linked list. Searches are done
@@ -230,6 +231,19 @@ static wchar_t *history_unescape_newlines( wchar_t *in )
return (wchar_t *)out->buff;
}
+static wchar_t *history_file_name( void *context )
+{
+ wchar_t *path = path_get_config( context );
+ wchar_t *res;
+
+ if( !path )
+ return 0;
+
+ res = wcsdupcat2( path, L"/", mode_name, L"_history", (void *)0 );
+ halloc_register_function( context, &free, res );
+ return res;
+}
+
/**
Read a complete histor entry from the specified FILE.
*/
@@ -310,12 +324,15 @@ static int history_load()
FILE *in_stream;
hash_table_t used;
int res = 0;
+ void *context;
if( !mode_name )
{
return -1;
}
+ context = halloc( 0, 0 );
+
is_loaded = 1;
signal_block();
@@ -324,8 +341,10 @@ static int history_load()
&hash_wcs_cmp,
4096 );
- fn = wcsdupcat2( env_get(L"HOME"), L"/.", mode_name, L"_history", (void *)0 );
-
+ fn = history_file_name( context );
+ if( fn )
+ {
+
in_stream = wfopen( fn, "r" );
if( in_stream != 0 )
@@ -374,15 +393,15 @@ static int history_load()
res = -1;
}
-
- }
+ }
+
+ last_loaded = history_last;
+ }
hash_destroy( &used );
-
- free( fn );
- last_loaded = history_last;
signal_unblock();
+ halloc_free( context );
return res;
}
@@ -549,24 +568,29 @@ static void history_save()
/* Save the global history */
{
- fn = wcsdupcat2( env_get(L"HOME"), L"/.", mode_name, L"_history", (void *)0 );
-
- out_stream = wfopen( fn, "w" );
- if( out_stream )
+ void *context = halloc( 0, 0 );
+ fn = history_file_name( context );
+ if( fn )
{
- history_save_node( history_last, out_stream );
- if( fclose( out_stream ) )
+ out_stream = wfopen( fn, "w" );
+
+ if( out_stream )
+ {
+ history_save_node( history_last, out_stream );
+ if( fclose( out_stream ) )
+ {
+ debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn );
+ wperror( L"fopen" );
+ }
+ }
+ else
{
debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn );
wperror( L"fopen" );
- }
+ }
}
- else
- {
- debug( 1, L"The following non-fatal error occurred while saving command history to \'%ls\':", fn );
- wperror( L"fopen" );
- }
- free( fn );
+
+ halloc_free( context );
}
}
diff --git a/kill.c b/kill.c
index 050c909da..ff480a0ae 100644
--- a/kill.c
+++ b/kill.c
@@ -29,8 +29,8 @@
#include "common.h"
#include "env.h"
#include "exec.h"
-#include "parser.h"
#include "halloc.h"
+#include "path.h"
/**
Maximum entries in killring
@@ -50,7 +50,7 @@ static wchar_t *cut_buffer=0;
static int has_xsel()
{
void *context = halloc(0, 0);
- wchar_t *path = parser_get_filename( context, L"xsel" );
+ wchar_t *path = path_get_path( context, L"xsel" );
int res = !!path;
halloc_free( context );
return res;
diff --git a/main.c b/main.c
index a19c47ec4..9eabe247b 100644
--- a/main.c
+++ b/main.c
@@ -58,9 +58,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "exec.h"
#include "event.h"
#include "output.h"
-
+#include "halloc.h"
#include "halloc_util.h"
#include "history.h"
+#include "path.h"
/**
The string describing the single-character options accepted by the main fish binary
@@ -75,23 +76,42 @@ static int read_init()
char cwd[4096];
wchar_t *wcwd;
+ wchar_t *config_dir;
+ wchar_t *config_dir_escaped;
+ void *context;
+ string_buffer_t *eval_buff;
+
if( !getcwd( cwd, 4096 ) )
{
wperror( L"getcwd" );
return 0;
}
- eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and builtin . fish 2>/dev/null", 0, TOP );
- eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; and builtin . fish 2>/dev/null", 0, TOP );
- eval( L"builtin cd 2>/dev/null; and builtin . .fish 2>/dev/null", 0, TOP );
-
+ eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and builtin . config.fish 2>/dev/null", 0, TOP );
+ eval( L"builtin cd " SYSCONFDIR L"/fish 2>/dev/null; and builtin . config.fish 2>/dev/null", 0, TOP );
+
+ /*
+ We need to get the configuration directory before we can source the user configuration file
+ */
+ context = halloc( 0, 0 );
+ eval_buff = sb_halloc( context );
+ config_dir = path_get_config( context );
+ config_dir_escaped = escape( config_dir, 1 );
+ sb_printf( eval_buff, L"builtin cd %ls 2>/dev/null; and builtin . config.fish 2>/dev/null", config_dir_escaped );
+ eval( (wchar_t *)eval_buff->buff, 0, TOP );
+
+ halloc_free( context );
+ free( config_dir_escaped );
+
if( chdir( cwd ) == -1 )
{
/*
- If we can't change back to previos directory, we'll stay in
+ If we can't change back to previos directory, we go to
~. Should be a sane default behavior.
*/
+ eval( L"builtin cd", 0, TOP );
}
+
wcwd = str2wcs( cwd );
if( wcwd )
{
@@ -281,6 +301,7 @@ int main( int argc, char **argv )
reader_init();
history_init();
+
if( read_init() )
{
if( cmd != 0 )
diff --git a/parser.c b/parser.c
index 635c6bc0a..9d0f38b30 100644
--- a/parser.c
+++ b/parser.c
@@ -37,11 +37,11 @@ The fish parser. Contains functions for parsing code.
#include "sanity.h"
#include "env_universal.h"
#include "event.h"
-
#include "intern.h"
#include "parse_util.h"
#include "halloc.h"
#include "halloc_util.h"
+#include "path.h"
/**
Maximum number of block levels in code. This is not the same as
@@ -173,18 +173,11 @@ The fish parser. Contains functions for parsing code.
*/
#define UNEXPECTED_TOKEN_ERR_MSG _( L"Unexpected token of type '%ls'")
-/**
- Unexpected error in parser_get_filename()
-*/
-#define MISSING_COMMAND_ERR_MSG _( L"Error while searching for command '%ls'" )
-
-
/**
While block description
-*/
+*/
#define WHILE_BLOCK N_( L"'while' block" )
-
/**
For block description
*/
@@ -652,87 +645,6 @@ static const wchar_t *parser_find_end( const wchar_t * buff )
}
-wchar_t *parser_cdpath_get( void *context, wchar_t *dir )
-{
- wchar_t *res = 0;
-
- if( !dir )
- return 0;
-
-
- if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
- {
- struct stat buf;
- if( wstat( dir, &buf ) == 0 )
- {
- if( S_ISDIR(buf.st_mode) )
- {
- res = halloc_wcsdup( context, dir );
- }
- }
- }
- else
- {
- wchar_t *path;
- wchar_t *path_cpy;
- wchar_t *nxt_path;
- wchar_t *state;
- wchar_t *whole_path;
-
- path = env_get(L"CDPATH");
-
- if( !path || !wcslen(path) )
- {
- path = L".";
- }
-
- nxt_path = path;
- path_cpy = wcsdup( path );
-
- if( !path_cpy )
- {
- DIE_MEM();
- }
-
- for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
- nxt_path != 0;
- nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
- {
- wchar_t *expanded_path = expand_tilde( wcsdup(nxt_path) );
-
-// debug( 2, L"woot %ls\n", expanded_path );
-
- int path_len = wcslen( expanded_path );
- if( path_len == 0 )
- {
- free(expanded_path );
- continue;
- }
-
- whole_path =
- wcsdupcat2( expanded_path,
- ( expanded_path[path_len-1] != L'/' )?L"/":L"",
- dir, (void *)0 );
-
- free(expanded_path );
-
- struct stat buf;
- if( wstat( whole_path, &buf ) == 0 )
- {
- if( S_ISDIR(buf.st_mode) )
- {
- res = whole_path;
- halloc_register( context, whole_path );
- break;
- }
- }
- free( whole_path );
- }
- free( path_cpy );
- }
- return res;
-}
-
void parser_forbid_function( wchar_t *function )
{
@@ -771,111 +683,6 @@ void error( int ec, int p, const wchar_t *str, ... )
}
-wchar_t *parser_get_filename( void *context, const wchar_t *cmd )
-{
- wchar_t *path;
-
- CHECK( cmd, 0 );
-
- debug( 3, L"parser_get_filename( '%ls' )", cmd );
-
- if(wcschr( cmd, L'/' ) != 0 )
- {
- if( waccess( cmd, X_OK )==0 )
- {
- struct stat buff;
- wstat( cmd, &buff );
- if( S_ISREG(buff.st_mode) )
- return halloc_wcsdup( context, cmd );
- else
- return 0;
- }
- }
- else
- {
- path = env_get(L"PATH");
- if( path == 0 )
- {
- if( contains_str( PREFIX L"/bin", L"/bin", L"/usr/bin", (void *)0 ) )
- {
- path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
- }
- else
- {
- path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
- }
- }
-
- /*
- Allocate string long enough to hold the whole command
- */
- wchar_t *new_cmd = halloc( context, 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 );
-
- }
- return 0;
-}
-
void parser_init()
{
if( profile )
@@ -2141,7 +1948,7 @@ static int parse_job( process_t *p,
}
else
{
- p->actual_cmd = parser_get_filename( j, (wchar_t *)al_get( args, 0 ) );
+ p->actual_cmd = path_get_path( j, (wchar_t *)al_get( args, 0 ) );
/*
Check if the specified command exists
@@ -2155,7 +1962,7 @@ static int parse_job( process_t *p,
implicit command.
*/
wchar_t *pp =
- parser_cdpath_get( j, (wchar_t *)al_get( args, 0 ) );
+ path_get_cdpath( j, (wchar_t *)al_get( args, 0 ) );
if( pp )
{
wchar_t *tmp;
diff --git a/parser.h b/parser.h
index 510bb6a5d..d873a1fbd 100644
--- a/parser.h
+++ b/parser.h
@@ -188,15 +188,6 @@ extern event_block_t *global_event_block;
*/
extern io_data_t *block_io;
-/**
- Finds the full path of an executable in a newly allocated string.
-
- \param cmd The name of the executable.
- \param context the halloc context to use for memory allocations
- \return 0 if the command can not be found, the path of the command otherwise.
-*/
-wchar_t *parser_get_filename( void *context, const wchar_t *cmd );
-
/**
Evaluate the expressions contained in cmd.
@@ -325,15 +316,6 @@ int parser_test( const wchar_t * buff, int *block_level, string_buffer_t *out, c
*/
int parser_test_args( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
-/**
- Returns the full path of the specified directory. If the \c in is a
- full path to an existing directory, a copy of the string is
- returned. If \c in is a directory relative to one of the
- directories i the CDPATH, the full path is returned. If no
- directory can be found, 0 is returned.
-*/
-wchar_t *parser_cdpath_get( void *context, wchar_t *in );
-
/**
Tell the parser that the specified function may not be run if not
inside of a conditional block. This is to remove some possibilities
diff --git a/path.c b/path.c
new file mode 100644
index 000000000..27f4718d0
--- /dev/null
+++ b/path.c
@@ -0,0 +1,267 @@
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "fallback.h"
+#include "util.h"
+
+#include "common.h"
+#include "env.h"
+#include "wutil.h"
+#include "halloc.h"
+#include "halloc_util.h"
+#include "path.h"
+#include "expand.h"
+
+/**
+ Unexpected error in path_get_path()
+*/
+#define MISSING_COMMAND_ERR_MSG _( L"Error while searching for command '%ls'" )
+
+
+
+wchar_t *path_get_path( void *context, const wchar_t *cmd )
+{
+ wchar_t *path;
+
+ CHECK( cmd, 0 );
+
+ debug( 3, L"path_get_path( '%ls' )", cmd );
+
+ if(wcschr( cmd, L'/' ) != 0 )
+ {
+ if( waccess( cmd, X_OK )==0 )
+ {
+ struct stat buff;
+ wstat( cmd, &buff );
+ if( S_ISREG(buff.st_mode) )
+ return halloc_wcsdup( context, cmd );
+ else
+ return 0;
+ }
+ }
+ else
+ {
+ path = env_get(L"PATH");
+ if( path == 0 )
+ {
+ if( contains_str( PREFIX L"/bin", L"/bin", L"/usr/bin", (void *)0 ) )
+ {
+ path = L"/bin" ARRAY_SEP_STR L"/usr/bin";
+ }
+ else
+ {
+ path = L"/bin" ARRAY_SEP_STR L"/usr/bin" ARRAY_SEP_STR PREFIX L"/bin";
+ }
+ }
+
+ /*
+ Allocate string long enough to hold the whole command
+ */
+ wchar_t *new_cmd = halloc( context, 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 );
+
+ }
+ return 0;
+}
+
+
+wchar_t *path_get_cdpath( void *context, wchar_t *dir )
+{
+ wchar_t *res = 0;
+
+ if( !dir )
+ return 0;
+
+
+ if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
+ {
+ struct stat buf;
+ if( wstat( dir, &buf ) == 0 )
+ {
+ if( S_ISDIR(buf.st_mode) )
+ {
+ res = halloc_wcsdup( context, dir );
+ }
+ }
+ }
+ else
+ {
+ wchar_t *path;
+ wchar_t *path_cpy;
+ wchar_t *nxt_path;
+ wchar_t *state;
+ wchar_t *whole_path;
+
+ path = env_get(L"CDPATH");
+
+ if( !path || !wcslen(path) )
+ {
+ path = L".";
+ }
+
+ nxt_path = path;
+ path_cpy = wcsdup( path );
+
+ if( !path_cpy )
+ {
+ DIE_MEM();
+ }
+
+ for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
+ nxt_path != 0;
+ nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
+ {
+ wchar_t *expanded_path = expand_tilde( wcsdup(nxt_path) );
+
+// debug( 2, L"woot %ls\n", expanded_path );
+
+ int path_len = wcslen( expanded_path );
+ if( path_len == 0 )
+ {
+ free(expanded_path );
+ continue;
+ }
+
+ whole_path =
+ wcsdupcat2( expanded_path,
+ ( expanded_path[path_len-1] != L'/' )?L"/":L"",
+ dir, (void *)0 );
+
+ free(expanded_path );
+
+ struct stat buf;
+ if( wstat( whole_path, &buf ) == 0 )
+ {
+ if( S_ISDIR(buf.st_mode) )
+ {
+ res = whole_path;
+ halloc_register( context, whole_path );
+ break;
+ }
+ }
+ free( whole_path );
+ }
+ free( path_cpy );
+ }
+ return res;
+}
+
+
+wchar_t *path_get_config( void *context)
+{
+ wchar_t *xdg_dir, *home;
+ int done = 0;
+ wchar_t *res = 0;
+
+ xdg_dir = env_get( L"XDG_CONFIG_HOME" );
+ if( xdg_dir )
+ {
+ res = wcsdupcat( xdg_dir, L"/fish" );
+ if( !create_directory( res ) )
+ {
+ done = 1;
+ }
+ else
+ {
+ free( res );
+ }
+
+ }
+ else
+ {
+ home = env_get( L"HOME" );
+ if( home )
+ {
+ res = wcsdupcat( home, L"/.config/fish" );
+ if( !create_directory( res ) )
+ {
+ done = 1;
+ }
+ else
+ {
+ free( res );
+ }
+ }
+ }
+
+ if( done )
+ {
+ halloc_register_function( context, &free, res );
+ return res;
+ }
+ else
+ {
+ debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
+ return 0;
+ }
+
+}
+
diff --git a/path.h b/path.h
new file mode 100644
index 000000000..c825160b6
--- /dev/null
+++ b/path.h
@@ -0,0 +1,43 @@
+/** \file path.h
+
+ Directory utilities. This library contains functions for locating
+ configuration directories, for testing if a command with a given
+ name can be found in the PATH, and various other path-related
+ issues.
+*/
+
+#ifndef FISH_PATH_H
+#define FISH_PATH_H
+
+/**
+ Returns the user configuration directory for fish. If the directory
+ or one of it's parents doesn't exist, they are first created.
+
+ \param context the halloc context to use for memory allocations
+ \return 0 if the no configuration directory can be located or created, the directory path otherwise.
+*/
+wchar_t *path_get_config( void *context);
+
+/**
+ Finds the full path of an executable in a newly allocated string.
+
+ \param cmd The name of the executable.
+ \param context the halloc context to use for memory allocations
+ \return 0 if the command can not be found, the path of the command otherwise.
+*/
+wchar_t *path_get_path( void *context, const wchar_t *cmd );
+
+/**
+ Returns the full path of the specified directory. If the \c in is a
+ full path to an existing directory, a copy of the string is
+ returned. If \c in is a directory relative to one of the
+ directories i the CDPATH, the full path is returned. If no
+ directory can be found, 0 is returned.
+
+ \param in The name of the directory.
+ \param context the halloc context to use for memory allocations
+ \return 0 if the command can not be found, the path of the command otherwise.
+*/
+wchar_t *path_get_cdpath( void *context, wchar_t *in );
+
+#endif
diff --git a/share/config.fish.in b/share/config.fish.in
new file mode 100644
index 000000000..bc4d21f2e
--- /dev/null
+++ b/share/config.fish.in
@@ -0,0 +1,86 @@
+#
+# Main file for fish command completions. This file contains various
+# common helper functions for the command completions. All actual
+# completions are located in the completions subdirectory.
+#
+# @configure_input@
+
+#
+# Set default search paths for completions and shellscript functions
+# unless they already exist
+#
+
+set -l configdir ~/.config
+if set -q XDG_CONFIG_HOME
+ set configdir $XDG_CONFIG_HOME
+end
+
+
+
+if not set -q fish_function_path
+ set -U fish_function_path $configdir/fish/functions @sysconfdir@/fish/functions @datadir@/fish/functions
+end
+
+if not set -q fish_complete_path
+ set -U fish_complete_path $configdir/fish/completions @sysconfdir@/fish/completions @datadir@/fish/completions
+end
+
+set __fish_help_dir @docdir@
+
+# This is a Solaris-specific test to modify the PATH so that
+# Posix-conformant tools are used by default.
+
+if test -d /usr/xpg4/bin
+ if not contains /usr/xpg4/bin $PATH
+ set PATH /usr/xpg4/bin $PATH
+ end
+end
+
+
+#
+# Make sure there are no invalid entries in the PATH
+#
+
+if status --is-interactive
+ 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
+end
+
+#
+# Add a few common directories to path, if they exists. Note that pure
+# console programs like makedep sometimes live in /usr/X11R6/bin, so we
+# want this even for text-only terminals.
+#
+
+set -l path_list /bin /usr/bin /usr/X11R6/bin @prefix@/bin @optbindirs@
+
+# Root should also have the sbin directories in the path
+if test "$USER" = root
+ set path_list $path_list /sbin /usr/sbin /usr/local/sbin
+end
+
+# Make a regular expression that matches any component in the PATH. A
+# trailing slash is ok. The sed call is to remove the last '|'.
+set -l tmp (printf "%s" \^$PATH'/?$|')
+set -l path_regexp \((echo $tmp | sed -e "s/.\$//")\)
+
+for i in (printf "%s\n" $path_list|grep -E -v $path_regexp)
+ if test -d $i
+ set PATH $PATH $i
+ end
+end
+
+
+if status --is-interactive
+ . config_interactive.fish
+end
diff --git a/share/config_interactive.fish.in b/share/config_interactive.fish.in
new file mode 100644
index 000000000..87564d99b
--- /dev/null
+++ b/share/config_interactive.fish.in
@@ -0,0 +1,213 @@
+#
+# Initializations that should only be performed when in interactive mode.
+#
+
+#
+# @configure_input@
+#
+
+
+set -l configdir ~/.config
+if set -q XDG_CONFIG_HOME
+ set configdir $XDG_CONFIG_HOME
+end
+
+if not set -q __fish_init_1_22_0
+
+ if test -f ~/.fish_history -o -f ~/.fish -o -d ~/.fish.d -a ! -d $configdir/fish
+
+ # Perform upgrade of configuration file hierarchy
+
+ if not test -d $configdir
+ builtin mkdir $configdir >/dev/null
+ end
+
+ if test -d $configdir
+ if builtin mkdir $configdir/fish
+
+ # These files are sometimes overwritten to by fish, so
+ # we want backups of them in case something goes wrong
+
+ cp ~/.fishd.(hostname) $configdir/fish/fishh.(hostname).backup
+ cp ~/.fish_history $configdir/fish/fish_history.backup
+
+ # Move the files
+
+ mv ~/.fish_history $configdir/fish/fish_history
+ mv ~/.fish $configdir/fish/config.fish
+ mv ~/.fish_inputrc $configdir/fish/fish_inputrc
+ mv ~/.fish.d/functions $configdir/fish/functions
+ mv ~/.fish.d/completions $configdir/fish/completions
+
+ #
+ # Move the fishd stuff from another shell to avoid concurrency problems
+ #
+
+ /bin/sh -c mv\ \~/.fishd.(hostname)\ $configdir/fish/fishd.(hostname)\;kill\ -9\ (echo %fishd)
+
+ # Update paths to point to new configuration locations
+
+ set fish_function_path (printf "%s\n" $fish_function_path|sed -e "s|@sysconfdir@/fish.d/|@sysconfdir@/fish/|")
+ set fish_complete_path (printf "%s\n" $fish_complete_path|sed -e "s|@sysconfdir@/fish.d/|@sysconfdir@/fish/|")
+
+ set fish_function_path (printf "%s\n" $fish_function_path|sed -e "s|$HOME/.fish.d/|$configdir/fish/|")
+ set fish_complete_path (printf "%s\n" $fish_complete_path|sed -e "s|$HOME/.fish.d/|$configdir/fish/|")
+
+ printf (_ "\nWARNING\n\nThe location for fish configuration files has changed to %s.\nYour old files have been moved to this location.\n You can change to a different location by changing the value of the variable \$XDG_CONFIG_HOME.\n\n") $configdir
+
+ end ^/dev/null
+ end
+ end
+
+ # Make sure this is only done once
+ set -U __fish_init_1_22_0
+
+end
+
+
+#
+# Print a greeting
+#
+
+if not set -q fish_greeting
+ set -l line1 (printf (_ 'Welcome to fish, the friendly interactive shell') )
+ set -l line2 (printf (_ 'Type %shelp%s for instructions on how to use fish') (set_color green) (set_color normal))
+ set -U fish_greeting $line1\n$line2
+end
+
+echo $fish_greeting
+
+
+#
+# Set exit message
+#
+
+function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
+ printf (_ "Good bye\n")
+end
+
+#
+# Set INPUTRC to something nice
+#
+# We override INPUTRC if already set, since it may be set by a shell
+# other than fish, which may use a different file. The new value should
+# be exported, since the fish inputrc file plays nice with other files
+# by including them when found.
+#
+
+for i in ~/$config_dir/fish/fish_inputrc @sysconfdir@/fish/fish_inputrc ~/.inputrc /etc/inputrc
+ if test -f $i
+ set -xg INPUTRC $i
+ break
+ end
+end
+
+
+#
+# Set various defaults using these throwaway functions
+#
+
+function set_default -d "Set an universal variable, unless it has already been set"
+ if not set -q $argv[1]
+ set -U -- $argv
+ end
+ if not set -q $argv[1]
+ set -g -- $argv
+ end
+end
+
+# Regular syntax highlighting colors
+set_default fish_color_normal normal
+set_default fish_color_command green
+set_default fish_color_redirection normal
+set_default fish_color_comment red
+set_default fish_color_error red --bold
+set_default fish_color_escape cyan
+set_default fish_color_operator cyan
+set_default fish_color_quote brown
+set_default fish_color_valid_path --underline
+
+set_default fish_color_cwd green
+
+# Background color for matching quotes and parenthesis
+set_default fish_color_match cyan
+
+# Background color for search matches
+set_default fish_color_search_match purple
+
+# Pager colors
+set_default fish_pager_color_prefix cyan
+set_default fish_pager_color_completion normal
+set_default fish_pager_color_description normal
+set_default fish_pager_color_progress cyan
+
+#
+# Directory history colors
+#
+
+set_default fish_color_history_current cyan
+
+
+#
+# Setup the CDPATH variable
+#
+
+set_default CDPATH . ~
+
+#
+# Remove temporary functions for setting default variable values
+#
+
+functions -e set_default
+
+#
+# A few minor convenience functions
+#
+# The naming heuristic is that __fish_complete_* prints completions
+# 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"
+ cat /etc/passwd | sed -e "s/^\([^:]*\):[^:]*:[^:]*:[^:]*:\([^:]*\):.*/\1\t\2/"
+end
+
+function __fish_complete_groups -d "Print a list of local groups, with group members as the description"
+ cat /etc/group | sed -e "s/^\([^:]*\):[^:]*:[^:]*:\(.*\)/\1\tMembers: \2/"
+end
+
+function __fish_complete_command -d "Complete using all available commands"
+ printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
+end
+
+function __fish_print_interfaces -d "Print a list of known network interfaces"
+ netstat -i -n -a | awk 'NR>2'|awk '{print $1}'
+end
+
+function __fish_print_addresses -d "Print a list of known network addresses"
+ /sbin/ifconfig |grep 'inet addr'|cut -d : -f 2|cut -d ' ' -f 1
+end
+
+function __fish_print_users -d "Print a list of local users"
+ cat /etc/passwd | cut -d : -f 1
+end
+
+#
+# Completions for the shell and it's builtin commands and functions
+#
+
+for i in (builtin -n|grep -E -v '(while|for|if|function|switch)' )
+ complete -c $i -s h -l help -d "Display help and exit"
+end
+
+
+#
+# Completions for SysV startup scripts
+#
+
+complete -x -p "/etc/init.d/*" -a start\t(_ 'Start service')
+complete -x -p "/etc/init.d/*" -a stop\t(_ 'Stop service')
+complete -x -p "/etc/init.d/*" -a status\t(_ 'Print service status')
+complete -x -p "/etc/init.d/*" -a restart\t(_ 'Stop and then start service')
+complete -x -p "/etc/init.d/*" -a reload\t(_ 'Reload service configuration')
+
diff --git a/share/fish.in b/share/fish.in
deleted file mode 100644
index 79546c623..000000000
--- a/share/fish.in
+++ /dev/null
@@ -1,148 +0,0 @@
-#
-# Main file for fish command completions. This file contains various
-# common helper functions for the command completions. All actual
-# completions are located in the completions subdirectory.
-#
-# @configure_input@
-
-#
-# Set default search paths for completions and shellscript functions
-# unless they already exist
-#
-
-if not set -q fish_function_path
- set -U fish_function_path ~/.fish.d/functions @sysconfdir@/fish.d/functions @datadir@/fish/functions
-end
-
-if not set -q fish_complete_path
- set -U fish_complete_path ~/.fish.d/completions @sysconfdir@/fish.d/completions @datadir@/fish/completions
-end
-
-set __fish_help_dir @docdir@
-
-# This is a Solaris-specific test to modify the PATH so that
-# Posix-conformant tools are used by default.
-
-if test -d /usr/xpg4/bin
- if not contains /usr/xpg4/bin $PATH
- set PATH /usr/xpg4/bin $PATH
- end
-end
-
-
-#
-# Make sure there are no invalid entries in the PATH
-#
-
-if status --is-interactive
- 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
-end
-
-#
-# Add a few common directories to path, if they exists. Note that pure
-# console programs like makedep sometimes live in /usr/X11R6/bin, so we
-# want this even for text-only terminals.
-#
-
-set -l path_list /bin /usr/bin /usr/X11R6/bin @prefix@/bin @optbindirs@
-
-# Root should also have the sbin directories in the path
-if test "$USER" = root
- set path_list $path_list /sbin /usr/sbin /usr/local/sbin
-end
-
-# Make a regular expression that matches any component in the PATH. A
-# trailing slash is ok. The sed call is to remove the last '|'.
-set -l tmp (printf "%s" \^$PATH'/?$|')
-set -l path_regexp \((echo $tmp | sed -e "s/.\$//")\)
-
-for i in (printf "%s\n" $path_list|grep -E -v $path_regexp)
- if test -d $i
- set PATH $PATH $i
- end
-end
-
-#
-# Print a greeting
-#
-
-if not set -q fish_greeting
- set -l line1 (printf (_ 'Welcome to fish, the friendly interactive shell') )
- set -l line2 (printf (_ 'Type %shelp%s for instructions on how to use fish') (set_color green) (set_color normal))
- set -U fish_greeting $line1\n$line2
-end
-
-if status --is-interactive
- echo $fish_greeting
-end
-
-#
-# Don't need completions in non-interactive mode
-#
-
-if not status --is-interactive
- exit
-end
-
-#
-# Convenience functions
-#
-# The naming heuristic is that __fish_complete_* prints completions
-# 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"
- cat /etc/passwd | sed -e "s/^\([^:]*\):[^:]*:[^:]*:[^:]*:\([^:]*\):.*/\1\t\2/"
-end
-
-function __fish_complete_groups -d "Print a list of local groups, with group members as the description"
- cat /etc/group | sed -e "s/^\([^:]*\):[^:]*:[^:]*:\(.*\)/\1\tMembers: \2/"
-end
-
-function __fish_complete_command -d "Complete using all available commands"
- printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
-end
-
-function __fish_print_interfaces -d "Print a list of known network interfaces"
- netstat -i -n -a | awk 'NR>2'|awk '{print $1}'
-end
-
-function __fish_print_addresses -d "Print a list of known network addresses"
- /sbin/ifconfig |grep 'inet addr'|cut -d : -f 2|cut -d ' ' -f 1
-end
-
-function __fish_print_users -d "Print a list of local users"
- cat /etc/passwd | cut -d : -f 1
-end
-
-#
-# Completions for the shell and it's builtin commands and functions
-#
-
-for i in (builtin -n|grep -E -v '(while|for|if|function|switch)' )
- complete -c $i -s h -l help -d "Display help and exit"
-end
-
-
-#
-# Completions for SysV startup scripts
-#
-
-complete -x -p "/etc/init.d/*" -a start\t(_ 'Start service')
-complete -x -p "/etc/init.d/*" -a stop\t(_ 'Stop service')
-complete -x -p "/etc/init.d/*" -a status\t(_ 'Print service status')
-complete -x -p "/etc/init.d/*" -a restart\t(_ 'Stop and then start service')
-complete -x -p "/etc/init.d/*" -a reload\t(_ 'Reload service configuration')
-
diff --git a/util.h b/util.h
index 8def4a209..9f9655085 100644
--- a/util.h
+++ b/util.h
@@ -307,7 +307,9 @@ int hash_str_cmp( void *a,
void *b );
/**
- Hash function suitable for wide character strings.
+ Hash function suitable for wide character strings. Uses a version
+ of the sha cryptographic function which is simplified in order to
+ returns a 32-bit number.
*/
int hash_wcs_func( void *data );