@need 3200

@node File-name Manipulation Functions
@chapter File-name Manipulation Functions

The functions in this chapter are for managing strings which are
file names.  Though the actual implementation is unix-specific, the
calling conventions for these functions (based on the design of GNU
Emacs) should support other operating systems as well.


@strong{WARNING: some of the functions in this chapter use `must_malloc' 
when it would be better to use some other allocation function.
This is likely to be fixed in a future release.}

@menu
* Home Directories::
* File-name Algebra::
* Paths::
@end menu

@need 3200

@node Home Directories
@section Home Directories
@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_home_directory}@fuindex file_name_home_directory
@*
@example
@group
char * file_name_home_directory (void);
@end group
@group
@end group
@end example

Return the user's home directory.


The path returned should not be freed by the caller and
may be returned more than once by @code{file_name_home_directory}.


The home directory is defined to be the value of the
environment variable HOME, unless that variable is unbound
or is bound to an empty string.  If HOME is undefined, then
the home directory is found using @code{getpwuid} and the 
real user id of the process.


If the home directory can not be computed, or storage can not
be allocated, @code{panic} is called to force the process to exit.


The directory name returned is formatted as if returned
by @code{file_name_as_directory} (it will end with a single @code{/}).

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_is_absolute}@fuindex file_name_is_absolute
@*
@example
@group
int file_name_is_absolute (t_uchar * f);
@end group
@group
@end group
@end example
@example
@group
     return f && f[0] && (f[0] == '/');
@end group
@group
@end group
@end example
@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_tilde_expand}@fuindex file_name_tilde_expand
@*
@example
@group
t_uchar * file_name_tilde_expand (alloc_limits limits, char * fname);
@end group
@group
@end group
@end example

Return a newly allocated copy of @code{fname} with a leading @code{~} or
@code{~user} expanded to the appropriate home directory.


If allocation fails (but does not call @code{panic}) this function returns @code{0}.


If asked to expand @code{~}, and unable to find a home directory for the
current process, this function panics and exits.


If asked to expand @code{~user}, and unable to find a home directory for
@code{user}, this function returns a newly allocated copy of @code{fname}.




@need 3200

@node File-name Algebra
@section File-name Algebra
@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_tail}@fuindex file_name_tail
@*
@example
@group
char * file_name_tail (alloc_limits limits, char * fname);
@end group
@group
@end group
@end example

Return a newly allocated string containing only the last element of
the file-name @code{fname}.  The last element is everything following
the last @code{"/"} or all of @code{fname} if it contains no @code{"/"}
characters.

@example
@group
     "/usr/bin/ls"   =>      "ls"
     "/usr/bin/"     =>      ""
     "ls"            =>      "ls"
@end group
@group
@end group
@end example

If allocation fails (but does not call @code{panic}) this function returns @code{0}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_head}@fuindex file_name_head
@*
@example
@group
t_uchar * file_name_head (alloc_limits limits, char * fname);
@end group
@group
@end group
@end example

@geindex /usr/bin/ls
@dfn{/usr/bin/ls}        =>      @geindex /
@dfn{/}
@geindex usr/bin/ls
@dfn{usr/bin/ls}         =>      @geindex usr
@dfn{usr}
@geindex ls
@dfn{ls}                 =>      @geindex ls
@dfn{ls}
@code{0}                    =>      @code{0}

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_sans_head}@fuindex file_name_sans_head
@*
@example
@group
t_uchar * file_name_sans_head (alloc_limits limits, char * fname);
@end group
@group
@end group
@end example

@geindex /
@dfn{/}                  =>      @code{0}
@geindex /usr/bin/ls
@dfn{/usr/bin/ls}        =>      @geindex usr/bin/ls
@dfn{usr/bin/ls}
@geindex usr/bin/ls
@dfn{usr/bin/ls}         =>      @geindex bin/ls
@dfn{bin/ls}
@geindex usr/
@dfn{usr/}               =>      @code{0}
@geindex ls
@dfn{ls}                 =>      @code{0}
0                    =>      @code{0}

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_as_directory}@fuindex file_name_as_directory
@*
@example
@group
t_uchar * file_name_as_directory (alloc_limits limits, t_uchar * f);
@end group
@group
@end group
@end example

Return a newly allocated copy of file-name @code{f}, ensuring that the
copy ends in a single @code{"/"}.

@example
@group
     "/usr/bin/ls"   =>      "/usr/bin/ls/"
     "/usr/bin/"     =>      "/usr/bin/"
     "/usr/bin///"   =>      "/usr/bin/"
     "ls"            =>      "ls/"
     "/"             =>      "/"
@end group
@group
@end group
@end example

If allocation fails (but does not call @code{panic}) this function returns @code{0}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_from_directory}@fuindex file_name_from_directory
@*
@example
@group
t_uchar * file_name_from_directory (alloc_limits limits, t_uchar * f);
@end group
@group
@end group
@end example

Return a newly allocated copy of file-name @code{f}, removing all 
trailing @code{"/"} characters.  The root directory is treated specially:

@example
@group
     "/usr/bin/ls"   =>      "/usr/bin/ls"
     "ls"            =>      "ls"
     "/usr/bin/"     =>      "/usr/bin"
     "/usr/bin///"   =>      "/usr/bin"
     "/"             =>      "/"
@end group
@group
@end group
@end example

If allocation fails (but does not call @code{panic}) this function returns @code{0}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_directory}@fuindex file_name_directory
@*
@example
@group
t_uchar * file_name_directory (alloc_limits limits, t_uchar * f);
@end group
@group
@end group
@end example

Return a newly allocated copy of the directory portion of file-name
@code{f}, ensuring that the copy ends with a single @code{"/"}.


The directory portion is everything except the last component of a
file-name.  If @code{f} already ends with a @code{"/"}, then this function is
the same as @code{file_name_as_directory}.  If @code{f} has no directory
component, this function returns @code{0}:

@example
@group
     "/usr/bin/ls"   =>      "/usr/bin/"
     "/usr/bin///ls" =>      "/usr/bin/"
     "/usr/bin/"     =>      "/usr/bin/"
     "/usr/bin"      =>      "/usr/"
     "ls"            =>      0
     "/"             =>      "/"
@end group
@group
@end group
@end example

If allocation fails (but does not call @code{panic}) this function returns @code{0}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_directory_file}@fuindex file_name_directory_file
@*
@example
@group
t_uchar * file_name_directory_file (alloc_limits limits, t_uchar * f);
@end group
@group
@end group
@end example

Return a newly allocated copy of the directory portion of file-name
@code{f}, ensuring that the copy does not end with a single @code{"/"} (with
one exception).


The directory portion is everything except the last component of a
file-name.  If @code{f} has no directory component, this function returns @code{0}:

@example
@group
     "/usr/bin/ls"   =>      "/usr/bin"
     "/usr/bin///ls" =>      "/usr/bin"
     "/usr/bin/"     =>      "/usr/bin"
     "/usr/bin"      =>      "/usr"
     "ls"            =>      0
     "/"             =>      "/"
@end group
@group
@end group
@end example

If allocation fails (but does not call @code{panic}) this function returns @code{0}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_is_path_prefix}@fuindex file_name_is_path_prefix
@*
@example
@group
int file_name_is_path_prefix (t_uchar * maybe_prefix, t_uchar * path);
@end group
@group
@end group
@end example

Return non-zero if @code{maybe_prefix} is equal to @code{path} or to some
path-prefix of @code{path}.


For example:

@example
@group
     "/usr/bin"      is a prefix of  "/usr/bin/ls"
     "/usr/bin"      is a prefix of  "/usr/bin"
     "/usr/bin"      is a prefix of  "/usr/bin/"
     "/usr/bin/"     is a prefix of  "/usr/bin/"
@end group
@group
@end group
@end example

@noindent
but:

@example
@group
     "/usr/bin"      is _not_ a prefix of    "/usr/bin-utils/ls"
     "/usr/bin/"     is _not_ a prefix of    "/usr/bin"
@end group
@group
@end group
@end example
@sp 1
@need 1750
@noindent
@b{* Function} @code{file_name_in_vicinity}@fuindex file_name_in_vicinity
@*
@example
@group
t_uchar * file_name_in_vicinity (alloc_limits limits,
                                 t_uchar * dir,
                                 t_uchar * file);
@end group
@group
@end group
@end example

Return a newly allocated string which is @code{dir}, followed by @code{"/"},
followed by @code{file}.  If @code{dir} is a directory name and @code{file} is a
relative file-name, then the result is a name for @code{file}, relative
to @code{dir}.  If @code{dir} already ends in @code{"/"}, no additional @code{"/"} is
added.


If @code{dir} is @code{0} or @code{""}, a newly allocated copy of @code{file} is returned.


If @code{file} is an absolute file name (begins with @code{"/"}) a newly allocated copy
of @code{file} is returned.

@example
@group
     "/usr/bin", "ls"        =>      "/usr/bin/ls"
     "/usr/bin/", "ls"       =>      "/usr/bin/ls"
     "/usr/bin///", "ls"     =>      "/usr/bin/ls"
     "/etc", "/usr/bin/ls"   =>      "/usr/bin/ls"
     0, "ls"                 =>      "ls"
@end group
@group
@end group
@end example

If allocation fails (but does not call @code{panic}) this function returns @code{0}.




@need 3200

@node Paths
@section Paths
@sp 1
@need 1750
@noindent
@b{* Function} @code{path_parse}@fuindex path_parse
@*
@example
@group
t_uchar ** path_parse (alloc_limits limits, char * path);
@end group
@group
@end group
@end example

Convert a path of file-names separated by ':' to form a 0-terminated
array of file-names.


An empty file-name is converted to @code{"."}.


The array is allocated by the variable sized array functions and
should be freed using @code{ar_free} (see @ref{Variable Size Arrays}).
Note that @code{ar_size} returns the size of the array, including the
final @code{0}.


The elements of the array are allocated by @code{must_malloc} and should be
freed using @code{must_free}.  @emph{THIS IS A BUG.}


The function @code{free_path} can be used to free a path allocated by
@code{path_parse}.


If allocation fails (but does not call @code{panic}) this function returns @code{0}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{free_path}@fuindex free_path
@*
@example
@group
void free_path (alloc_limits limits, t_uchar ** path)
@end group
@group
@end group
@end example

Free a path allocated by @code{path_parse}.

@sp 1
@need 1750
@noindent
@b{* Function} @code{path_find_executable}@fuindex path_find_executable
@*
@example
@group
t_uchar * path_find_executable (alloc_limits limits, 
                                t_uchar ** path,
                                t_uchar * tail);
@end group
@group
@end group
@end example

Search on @code{path} for a file named @code{tail} that is executable by 
this process.  Returns a newly allocated copy of the name of such a file 
or @code{0}.


The file-name returned is formed by @code{file_name_in_vicinity (limits, path[N], tail)} 
and should be freed by @code{must_free}.


The effective user and group ids are used to check whether or not the
file can be executed (which should be the same rule used by the kernel).


If allocation fails (but does not call @code{panic}) this function returns @code{0}.







