diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-09-25 09:23:02 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-09-25 09:23:02 -0700 |
commit | 5f944b144b5bae019e578213d76e9bd81237c6dd (patch) | |
tree | ad4838706d8d48d08a74b2b549346670e9a37566 /stream.c | |
parent | 7e36a3f2a6501a0bc6d24836610746f59427b496 (diff) | |
download | txr-5f944b144b5bae019e578213d76e9bd81237c6dd.tar.gz txr-5f944b144b5bae019e578213d76e9bd81237c6dd.tar.bz2 txr-5f944b144b5bae019e578213d76e9bd81237c6dd.zip |
path-search: rewrite in C with saner semantics.
The new function:
- just returns the name if it contains path name components.
- returns nil if the name is "." or "..".
- tests for existence only, not permission to execute.
* lisplib.c (path_test_set_entries): Do not auto-load path-test
module on the path-search symbol, since it is no longer implemented
there.
* stdlib/path-test.tl (path-search): Function removed.
* stream.c (path_var_sep_char): New global variable.
(path_search): New function.
(detect_path_separators): Also set path_var_sep_char to semicolon
on Cygnal.
(stream-init): Register path-search intrinsic here now.
* stream.h (path_var_sep_char, path_search): Declared.
* tests/018/path-test.tl: New tests.
* txr.1: Documentation revised for path-search.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 32 |
1 files changed, 30 insertions, 2 deletions
@@ -103,6 +103,7 @@ val socket_error_s; struct cobj_class *stream_cls, *stdio_stream_cls; const wchli_t *path_sep_chars = wli("/"); +wchar_t path_var_sep_char = ':'; val top_stderr; @@ -4383,6 +4384,31 @@ static void fds_clobber(struct save_fds *fds, int flags) fds_subst_nosave(fds->suberr, STDERR_FILENO); } +val path_search(val name, val path_in) +{ + val self = lit("path-search"); + val ps = static_str(path_sep_chars); + + if (empty(name) || equal(name, lit(".")) || equal(name, lit(".."))) { + return nil; + } else if (break_str(name, ps)) { + return name; + } else { + val path = default_arg_strict(path_in, getenv_wrap(lit("PATH"))); + val spath = if3(listp(path), path, split_str(path, chr(path_var_sep_char))); + for (; spath; spath = cdr(spath)) { + val dir = car(spath); + val full = path_cat(dir, name); + char *full8 = utf8_dup_to(c_str(full, self)); + int res = access(full8, F_OK); + free(full8); + if (res == 0) + return full; + } + return nil; + } +} + #if HAVE_FORK_STUFF static val open_subprocess(val name, val mode_str, val args, val fun) { @@ -4998,9 +5024,10 @@ static void detect_path_separators(void) struct utsname un; if (uname(&un) >= 0) { - if (strncmp(un.sysname, "CYGNAL", 6) == 0) + if (strncmp(un.sysname, "CYGNAL", 6) == 0) { path_sep_chars = wli("\\/"); - return; + path_var_sep_char = ';'; + } } #endif } @@ -5528,6 +5555,7 @@ void stream_init(void) reg_fun(intern(lit("open-file"), user_package), func_n2o(open_file, 1)); reg_fun(intern(lit("open-fileno"), user_package), func_n2o(open_fileno, 1)); reg_fun(intern(lit("open-tail"), user_package), func_n3o(open_tail, 1)); + reg_fun(intern(lit("path-search"), user_package), func_n2o(path_search, 1)); reg_fun(intern(lit("open-command"), user_package), func_n2o(open_command, 1)); reg_fun(intern(lit("open-pipe"), user_package), func_n2(open_command)); reg_fun(intern(lit("open-process"), user_package), func_n3o(open_process, 2)); |