home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
tex
/
texsrc1
/
Src
/
lib
/
c
/
pathsrch
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-21
|
13KB
|
437 lines
/* pathsrch.c: look for files based on paths, i.e., colon-separated
lists of directories.
Perhaps we should allow % specifiers in the paths for the resolution, etc.
This is a RISC OS ONLY version!
Things not needed in RISC OS are cut out
Copyright (C) 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "c-pathch.h"
#include "c-namemx.h"
#include "c-pathmx.h"
#include "paths.h"
#include "c-ctype.h"
#include "riscos_ex.h"
#include "pathsrch.h"
#define dir_p(name) riscos_isdir(name)
static void add_directory P3H(string **, unsigned *, string);
static void expand_subdir P3H(string **, unsigned *, string);
static string readable P1H(string);
#if 0
static string *find_dir_list P1H(string);
static void save_dir_list P2H(string, string *);
#endif
boolean riscos_readaccess P1H(string);
/* If FILENAME is absolute or explicitly relative (i.e., starts with
`@.', or `^.' or there's a ':', '&', '\' or '$' in it), or if DIR_LIST is
null, we return whether
FILENAME is readable as-is. Otherwise, we test if FILENAME is in any of
the directories listed in DIR_LIST. (The last entry of DIR_LIST must
be null.) We return the complete path if found, NULL else.
In the interests of doing minimal work here, we assume that each
element of DIR_LIST already ends with a `.'.
DIR_LIST is most conveniently made by calling `initialize_path_list'.
This is a separate routine because we allow recursive searching, and
it may take some time to discover the list of directories.
We do not want to incur that overhead every time we want to look for
a file.
(Actually, `.' is not hardwired into this routine; we use PATH_SEP,
defined above.) */
string
find_path_filename P2C(string, filename, string *, dir_list)
{
string found_name = NULL;
/* If FILENAME is absolute or explicitly relative, or if DIR_LIST is
null, only check if FILENAME is readable. */
if (riscos_absolute (filename) || dir_list == NULL)
{
found_name = readable (filename);
}
else
{ /* Test if FILENAME is in any of the directories in DIR_LIST. */
string save_filename = filename;
boolean substituting; /* if true, we substituted @ */
while (*dir_list != NULL)
{
if (**dir_list == '@') {
substituting = true;
filename = concat3(current_path, *dir_list + 1, save_filename);
}
else {
filename = concat (*dir_list, save_filename);
substituting = false;
}
found_name = readable (filename);
if (found_name == NULL)
{
free (filename);
dir_list++;
}
else
{
if (found_name != filename)
free (filename);
if (substituting) found_name = concat(*dir_list, save_filename);
break;
}
}
}
return found_name;
}
/* If NAME is readable, return it. If the error is ENAMETOOLONG,
truncate any too-long path components and return the result (unless
there were no too-long components, i.e., a overall too-long name
caused the error, in which case return NULL). On any other error,
return NULL.
POSIX invented this brain-damage of not necessarily truncating
pathname components; the system's behavior is defined by the value of
the symbol _POSIX_NO_TRUNC, but you can't change it dynamically!
RISC OS does things a bit differently. We need some kernel routines
for testing read access, and we don't truncate filenames, as different
filing systems might allow different filename lengths. */
#include <kernel.h>
static string
readable (name)
string name;
{
string ret = NULL;
if (riscos_readaccess(name))
ret = name;
else
{
char *pos;
#ifdef RISCOS_DEBUG
fprintf(stderr, "readable(\"%s\") tries ", name);
#endif
/* Try .sty file without extension */
pos = strrchr(name, '.');
if (pos && strcmp(pos + 1, "sty") == 0) {
*pos = '\0';
#ifdef RISCOS_DEBUG
fprintf(stderr, "\"%s\"\n", name);
#endif
if (riscos_readaccess(name)) ret = name;
else *pos = '.';
}
#ifdef RISCOS_DEBUG
fprintf(stderr, "\n");
#endif
}
return ret;
}
/* OS_File 17: prm p.836 or c.riscos_ex */
boolean
riscos_readaccess(string name)
{
_kernel_osfile_block block;
return (_kernel_osfile(17, name, &block) == 1 && (block.end & 1));
}
/* Return a NULL-terminated array of directory names, each name ending
with PATH_SEP, created by parsing the PATH_DELIMITER-separated list
in the value of the environment variable ENV_NAME, or DEFAULT_PATH if
the envvar is not set.
A leading or trailing colon in the value of ENV_NAME is replaced by
DEFAULT_PATH.
Any element of the path that ends with double PATH_SEP characters
(e.g., `foo..') is replaced by all its subdirectories.
If ENV_NAME is null, only parse DEFAULT_PATH. If both are null, do
nothing and return NULL.
Under RISC OS all paths have "$Path" appended. */
string *
initialize_path_list P2C(string, env_name, string, default_path)
{
string dir, path;
string *dir_list = NULL;
unsigned dir_count = 0;
string env_value = NULL;
string orig_path;
if (env_name) {
string path_name;
path_name = concat (env_name, "$Path");
env_value = getenv (path_name);
}
orig_path = expand_default (env_value, default_path);
if (orig_path == NULL || *orig_path == 0)
return NULL;
/* If we've already seen this colon-separated list, then just get it
back instead of going back to the filesystem. */
#if 0
dir_list = find_dir_list (orig_path);
if (dir_list != NULL)
return dir_list;
#endif
if (*orig_path == PATH_DELIMITER)
add_directory(&dir_list, &dir_count, "@.");
path = concat (PATH_DELIMITER_STRING, orig_path);
#ifdef RISCOS_DEBUG
fprintf(stderr, "Parsing \"%s\"\n", path);
#endif
/* Find each element in the path in turn. */
for (dir = strtok (path, PATH_DELIMITER_STRING); dir != NULL;
dir = strtok (NULL, PATH_DELIMITER_STRING))
{
int len;
len = strlen (dir);
/* If `dir' is the empty string, skip it. */
if (len == 0)
continue;
/* If `dir' ends in double dots, do subdirectories (and remove
the second dot, so the final pathnames we return don't look
like foo..bar.). Because we obviously want to do subdirectories
of `dir', we don't check if it is a leaf. This means that if
`dir' is `foo..', and `foo' contains only symlinks (so our leaf
test below would be true), the symlinks are chased. */
if (len > 2 && dir[len - 1] == PATH_SEP && dir[len - 2] == PATH_SEP)
{
dir[len - 1] = 0;
if (riscos_isdir (dir))
{
add_directory (&dir_list, &dir_count, dir);
expand_subdir (&dir_list, &dir_count, dir);
}
}
else
{ /* Don't bother to add the directory if it doesn't exist. */
if (riscos_isdir (dir))
add_directory (&dir_list, &dir_count, dir);
}
}
/* Add the terminating null entry to `dir_list'. */
dir_count++;
XRETALLOC (dir_list, dir_count, string);
dir_list[dir_count - 1] = NULL;
#if 0
/* Save the directory list we just found. */
save_dir_list (orig_path, dir_list);
#endif
#ifdef RISCOS_DEBUG
{
int i = 0;
while (dir_list[i]) fprintf(stderr, " \"%s\"\