POSIX requires that PATH searching be done only if the identifier (aka "file") has no '/' (if it has, it is a "path"). Allow searching qualified filenames, i.e. Resource Identifier, like dk/ctl, vect/in/dxf by setting an environment variable PATH_SEARCH_OPT with the setting 'Q' in the definition. It works in all the three shells (sh(1), ksh(1) and csh(1)) as well as with all the utilities using exec[lv]p or posit_spawnp (also then system(3)). A man page pathsearch(7) is added explaining this all.
The diff is attached and this can be also retrieved as: commit 502cb391d594a2722cca46e135f79c02516981d5 with https://github.com/tlaronde/BeSiDe diff --git a/include/pathsearch.h b/include/pathsearch.h new file mode 100644 index 000000000000..59df79021843 --- /dev/null +++ b/include/pathsearch.h @@ -0,0 +1,34 @@ +/* + * Written by Thierry Laronde <tlaro...@kergis.com> 2024-09 + * Public domain. + * See pathsearch(7). + */ + +#ifndef _PATHSEARCH_H_ +#define _PATHSEARCH_H_ + +#include <string.h> + +/* + * For the feature testing macros, the parameters are environment + * variable values of the same but upper case name. + */ +#define PATH_SEARCH_OPT_QFILENAME 'q' +#define PATH_SEARCH_OPT_QFILENAME_FORCED 'Q' +#define PATH_SEARCH_QFILENAME_ON(path_search_opt) \ +( (path_search_opt) != NULL \ + && strchr(path_search_opt, PATH_SEARCH_OPT_QFILENAME_FORCED) != NULL ) + +/* + * A qualified filename should be considered a Resource Identifier + * to be contrasted to a Locator (where a resource lies in the + * namespace). See pathsearch(7). + */ +#define PATH_SEARCH_IS_QFILENAME(name, name_len) \ + ( (name) != NULL && (name_len) != 0 \ + && (name)[0] != '/' && strstr(name, "./") == NULL \ + && (name)[(name_len)-1] != '/' \ + && (name)[(name_len)-1] != '.' ) + +#endif /* !_PATHSEARCH_H_ */ + diff --git a/share/man/man7/pathsearch.7 b/share/man/man7/pathsearch.7 new file mode 100644 index 000000000000..6ecc313e772b --- /dev/null +++ b/share/man/man7/pathsearch.7 @@ -0,0 +1,234 @@ +.\" +.\" Public Domain. +.\" +.Dd September 29, 2024 +.Dt PATHSEARCH 7 +.Os +.Sh NAME +.Nm pathsearch +.Nd when and how the search of a file to execute is handled. +.Sh DESCRIPTION +A program to execute is given to a shell, to one of the +.Xr exec 3 +or +.Xr posix_spawn 3 +family of functions in two forms: either as a +.Em locator +specifying exactly (even if implicitely) where the file is, or as an +.Em identifier +to be searched in order to be located. (POSIX generally use +.Em path +as a mean to imply a locator and +.Em file +to imply an identifier.) +.Pp +The shells +.Xr sh 1 , +.Xr ksh 1 , +.Xr csh 1 , +as well as the variants of the +.Xr execlp 3 +and +.Xr execvp 3 +functions, and the +.Xr posix_spawnp 3 +function (used by the implementation of +.Xr system 3 ) +handle both locators and identifiers. The other variants of +.Xr exec 3 +or +.Xr posix_spawn 3 +expect only locators and do no path searching. +.Pp +For the path searching, two environment variables drive the searching: +.Em PATH +and +.Em PATH_SEARCH_OPT . +.Pp +In order for the searching to be done, the command given as argument +has to be identified as an identifier, and not as a locator. +.Pp +The traditional POSIX rule for this is simple: when path searching is +to be attempted, if the command name given does not contain a +.Ql \&/ , +it is considered an identifier and is then searched. Otherwise, it is a +locator and no search is done. +.Pp +Hence, with the traditional behavior, given a command as +.Qq bar/foo , +no path searching would be done and this will be tried in the current +working directory. +.Pp +The rules concerning what is an identifier can be changed using the +.Em PATH_SEARCH_OPT +variable. See below +.Sx Extending identifiers to qualified filenames . +.Pp +When the argument is considered an identifier (according to whatever +rule), it is not searched everywhere but only in the directories +specified in the +.Em PATH +environment variable. +.Pp +The +.Em PATH +is a sequence of colon +.Ql \&: +separated directory pathnames to be tried, in turn, for locating the +identified resource. Initially, it is set to +.Pp +.Dl /usr/bin:/bin:/usr/pkg/bin:/usr/local/bin +by +.Xr login 1 . +It can be redefined later. +.Pp +An empty dir specification (that can be expressed in PATH by a leading +or a trailing colon, or by two consecutive colons) means the current +working directory. This is considered a security risk since, by the very +nature of the current working, what will be executed depends on the +context. It is thus highly recommended to verify that an empty dir +alternative has not slipped by mistake in the PATH definition. +.Pp +The +.Xr sh 1 +syntax allows for example to interpolate a dir specification via a +variable, but offers means to protect the PATH from having by mistake +a current working dir definition because the variable is not defined +or empty, in this way: +.Pp +.Dl PATH="/bin:/usr/bin:${MYSCRIPTS:+${MYSCRIPTS}:}/usr/pkg/bin" +.Pp +or +.Pp +.Dl PATH="/bin:/usr/bin${MYSCRIPTS:+:${MYSCRIPTS}}:/usr/pkg/bin" +.Pp +The trick here is that the variable is only expanded if it is +defined and not empty, and, in this case only, a +.Ql \&: +colon is added to its definition. The result being that if the +.Em MYSCRIPTS +variable were not defined or empty, this will not result in two +consecutive colons, adding by mistake the current working directory as +an alternative dir to search in. See +.Xr sh 1 +for an explanation of the syntax. +.Ss Extending identifiers to qualified filenames +The environment variable +.Em PATH_SEARCH_OPT +can be defined to change the path searching. +.Pp +The definition of the PATH_SEARCH_OPT is a string of ASCII letters +(the options are case sensitive). +.Pp +At the moment, only one option is defined: +.Bl -tag -width "Q" +.It Q +The rule identifying an identifier is changed to allow qualified +filenames like +.Qq bar/foo +to be searched for with the PATH. A +.Em qualified filename +is a Resource Identifier (not a locator) consisting of a sequence +of one or more components separated by +.Ql / , +the sequence not starting or ending by a +.Ql / +and any component not ending by a +.Ql \&. . +Thus +.Qq fs/create , +.Qq fs/ck , +.Qq fs/mount , +.Qq fs/ctl +are all qualified filenames, as well as +.Qq texlive/latex +or +.Qq kertex/latex , +as well as (G.R.A.S.S. example) +.Qq vect/in/dxf . +But +.Qq /vect/in/dxf +is not an identifier but a locator, as well as +.Qq ./vect/in/dxf +or +.Qq vect/in/dxf. +in this latter case because of the trailing dot of the last component. +.El +.Sh IMPLEMENTATION NOTES +Since the behavior can not be changed only at a shell level, there +has to be a mean to inform both the shell and the libc to change the +behavior. Hence the +.Em PATH_SEARCH_OPT +environment variable. And since it would be suboptimal to create +another variable when something has to be optionally changed in the way +the path is searched, the variable has to have a definition. +.Pp +The upper case was chosen because, initially, there was a lower case +variant meaning: do qualified filename searching if not +.Em POSIXLY_CORRECT . +But if this extended behavior is not, strictly speaking, POSIX +compliant, it is not a violation of the spirit: a qualified filename +is an identifier, not a locator that is a path wandering instruction; a +qualified filename can not escape the directory. In this sense, and +without judging the relevance of the notion of a +.Qq restricted shell , +as is expressed, for example, in +.Xr ksh 1 , +a qualified filename is neither absolute nor relative, so is +compatible with the notion. So the lower case variant was dropped, but +the principle of distinguishing between lower case (conditional) and +upper case (mandatory) is retained for possible further extensions. +.Pp +The new rule was designed so it can match the meaning (an identifier +not a locator), be compatible with a Unix filesystem hierarchy, and +easy to test. The restriction of no ending +.Ql \&. +was initially for the simplicity and thus efficiency of testing. But +it makes some sense. +.Ql \&. +and +.Qq \&.\&. +and not identifiers (they are not uniq and do not exist as names in +any filesystem) but are +.Qq pronoun +locators. They end with a dot. So any sequence ending with a dot can +be reserved for the group of pronoun locators allowing extensions +of the notion. +.Pp +The fact that, when extended filenames search is requested, a command +passed as +.Qq bar/foo +will be searched and not executed in the current directory, thus +imposing, if it was actually the intention to do so, to specify it as +.Qq ./bar/foo +is not considered a slight inconvenient but an improvement. +.Sh SEE ALSO +.Xr environ 7 , +.Xr exec 3 , +.Xr posix_spawn 3 , +.Xr sh 1 , +.Xr ksh 1 , +.Xr csh 1 . +.Sh SOURCES +.Pa include/pathsearch.h +.Pp lib/libc/gen/execvp.c +.Pp lib/libc/gen/posix_spawnp.c +.Pp bin/sh/exec.c +.Pp bin/ksh/exec.c +.Pp bin/csh/exec.c +.Sh HISTORY +Allowing qualified filenames for commands to be searched (not exactly +with the same rules) was first encountered by the author in the +.Em Plan9 +system. +.Sh AUTHOR +.An "Thierry Laronde" Aq Mt tlaro...@kergis.com . +.Pp +The +.Xr sh 1 +way of defining the +.Ev PATH +with interpolated variables, protecting from undefined ones, comes +from +.An "Robert Elz" Aq Mt k...@munnari.oz.au . + diff --git a/bin/csh/exec.c b/bin/csh/exec.c index bd06892a1c92..b45e1d3d5222 100644 --- a/bin/csh/exec.c +++ b/bin/csh/exec.c @@ -45,6 +45,7 @@ __RCSID("$NetBSD: exec.c,v 1.33 2019/01/05 16:54:00 christos Exp $"); #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <pathsearch.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -55,7 +56,8 @@ __RCSID("$NetBSD: exec.c,v 1.33 2019/01/05 16:54:00 christos Exp $"); /* * System level search and execute of a command. We look in each directory - * for the specified command name. If the name contains a '/' then we + * for the specified command name. If the name contains a '/' and + * qualified filenames is not on (see pathsearch.7) then we * execute only the full path name. If there is no search path then we * execute only full path names. */ @@ -194,13 +196,26 @@ doexec(Char **v, struct command *t) sigemptyset(&nsigset); (void)sigprocmask(SIG_SETMASK, &nsigset, NULL); /* - * If no path, no words in path, or a / in the filename then restrict the - * command search. + * If no path, no words in path, or a / in the filename but not + * doing qualified filename, then restrict the command search. */ - if (pathv == 0 || pathv->vec[0] == 0 || slash) + { + const char *path_search_opt; + size_t ln; + int do_qfilename; + + ln = strlen(short2str(*av)); + + path_search_opt = getenv("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(short2str(*av), ln); + + if (pathv == 0 || pathv->vec[0] == 0 + || (do_qfilename == 0 && slash) ) pv = justabs; else pv = pathv->vec; + } sav = Strspl(STRslash, *av); /* / command name for postpending */ Vsav = sav; if (havhash) @@ -510,12 +525,21 @@ iscommand(Char *name) Char **pv, *sav; int hashval, hashval1, i; int slash; + const char *path_search_opt; + size_t ln; + int do_qfilename; hashval = 0; slash = any(short2str(name), '/'); v = adrof(STRpath); - if (v == 0 || v->vec[0] == 0 || slash) + ln = strlen(short2str(name)); + + path_search_opt = getenv("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(short2str(name), ln); + + if (v == 0 || v->vec[0] == 0 || (do_qfilename == 0 && slash) ) pv = justabs; else pv = v->vec; @@ -700,10 +724,20 @@ tellmewhat(struct wordent *lexp, Char *str) if ((i = iscommand(sp->word)) != 0) { Char **pv; struct varent *v; + const char *path_search_opt; + size_t ln; + int do_qfilename; int slash = any(short2str(sp->word), '/'); + ln = strlen(short2str(sp->word)); + + path_search_opt = getenv("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(short2str(sp->word), ln); + + v = adrof(STRpath); - if (v == 0 || v->vec[0] == 0 || slash) + if (v == 0 || v->vec[0] == 0 || (do_qfilename == 0 && slash) ) pv = justabs; else pv = v->vec; diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c index 721f301f393f..0bf7d6e0cecd 100644 --- a/bin/ksh/exec.c +++ b/bin/ksh/exec.c @@ -11,6 +11,7 @@ __RCSID("$NetBSD: exec.c,v 1.28 2018/06/03 12:18:29 kamil Exp $"); #include <sys/stat.h> #include <ctype.h> +#include <pathsearch.h> #include <stdbool.h> #include "sh.h" @@ -575,7 +576,17 @@ comexec(t, tp, ap, flags) rv = subst_exstat; goto Leave; } else if (!tp) { - if (Flag(FRESTRICTED) && ksh_strchr_dirsep(cp)) { + const char *path_search_opt; + int ln; + int do_qfilename; + + ln = strlen(cp); + path_search_opt = str_val(global("PATH_SEARCH_OPT")); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(cp, ln); + + if (Flag(FRESTRICTED) && do_qfilename == 0 + && ksh_strchr_dirsep(cp)) { warningf(true, "%s: restricted", cp); rv = 1; goto Leave; @@ -899,8 +910,16 @@ findcom(name, flags) int insert = Flag(FTRACKALL); /* insert if not found */ char *fpath; /* for function autoloading */ char *npath; + const char *path_search_opt; + size_t ln; + int do_qfilename; + + ln = strlen(name); + path_search_opt = str_val(global("PATH_SEARCH_OPT")); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(name, ln); - if (ksh_strchr_dirsep(name) != NULL) { + if (do_qfilename == 0 && ksh_strchr_dirsep(name) != NULL) { insert = 0; /* prevent FPATH search below */ flags &= ~FC_FUNC; @@ -1050,18 +1069,26 @@ search(name, pathx, mode, errnop) const char *sp, *p; char *xp; XString xs; + const char *path_search_opt; int namelen; + int do_qfilename; if (errnop) *errnop = 0; - if (ksh_strchr_dirsep(name)) { + namelen = strlen(name); + + path_search_opt = str_val(global("PATH_SEARCH_OPT")); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(name, namelen); + + if (do_qfilename == 0 && ksh_strchr_dirsep(name)) { if (search_access(name, mode, errnop) == 0) return (char *)__UNCONST(name); return NULL; } - namelen = strlen(name) + 1; + ++namelen; /* to include terminal nul */ Xinit(xs, xp, 128, ATEMP); sp = pathx; diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 4b1c5885371c..09dc0cd09a66 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -47,6 +47,7 @@ __RCSID("$NetBSD: exec.c,v 1.59 2024/07/12 07:30:30 kre Exp $"); #include <unistd.h> #include <fcntl.h> #include <errno.h> +#include <pathsearch.h> /* PATH_SEARCH_OPT */ #include <stdio.h> #include <stdlib.h> @@ -125,12 +126,26 @@ void shellexec(char **argv, char **envp, const char *path, int idx, int vforked) { char *cmdname; +#ifndef SMALL + const char *path_search_opt; + size_t ln; + int do_qfilename; +#endif int e, action; struct stat statb; action = E_EXEC; +#ifndef SMALL + ln = strlen(argv[0]); + path_search_opt = lookupvar("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(argv[0], ln); + + if (do_qfilename == 0 && strchr(argv[0], '/') != NULL) { +#else if (strchr(argv[0], '/') != NULL) { +#endif tryexec(argv[0], argv, envp, vforked); e = errno; if (e == EACCES && stat(argv[0], &statb) == -1) @@ -574,9 +589,27 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) struct stat statb; int e; int (*bltin)(int,char **); +#ifndef SMALL + const char *path_search_opt; + size_t ln; + int do_qfilename; +#endif +#ifndef SMALL + ln = strlen(name); + path_search_opt = lookupvar("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(name, ln); + + /* + * If not searching for a qualified filename, then if the name + * contains a slash, don't use PATH or hash table. + */ + if (do_qfilename == 0 && strchr(name, '/') != NULL) { +#else /* If name contains a slash, don't use PATH or hash table */ if (strchr(name, '/') != NULL) { +#endif if (act & DO_ABS) { while (stat(name, &statb) < 0) { #ifdef SYSV diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi index a2274fb94a4b..021b9d2eea1f 100644 --- a/distrib/sets/lists/comp/mi +++ b/distrib/sets/lists/comp/mi @@ -3191,6 +3191,7 @@ ./usr/include/openssl/x509v3err.h comp-c-include ./usr/include/panel.h comp-c-include ./usr/include/paths.h comp-c-include +./usr/include/pathsearch.h comp-c-include ./usr/include/pcap-namedb.h comp-c-include ./usr/include/pcap.h comp-c-include ./usr/include/pcap/bpf.h comp-c-include diff --git a/distrib/sets/lists/man/mi b/distrib/sets/lists/man/mi index e1d4e9c3e2f1..3ddc26880564 100644 --- a/distrib/sets/lists/man/mi +++ b/distrib/sets/lists/man/mi @@ -6148,6 +6148,7 @@ ./usr/share/man/man7/openssl-threads.7 man-crypto-man .man,openssl=30 ./usr/share/man/man7/orders.7 man-reference-man .man ./usr/share/man/man7/packages.7 man-obsolete obsolete +./usr/share/man/man7/pathsearch.7 man-reference-man ./usr/share/man/man7/pcap-filter.7 man-netutil-man .man ./usr/share/man/man7/pcap-linktype.7 man-netutil-man .man ./usr/share/man/man7/pcap-tstamp.7 man-netutil-man .man diff --git a/distrib/sets/lists/manhtml/mi b/distrib/sets/lists/manhtml/mi index 0427facdeab2..9c1d76b19182 100644 --- a/distrib/sets/lists/manhtml/mi +++ b/distrib/sets/lists/manhtml/mi @@ -2370,6 +2370,7 @@ ./usr/share/man/html7/openssl-glossary.html man-crypto-htmlman html,openssl=30 ./usr/share/man/html7/openssl-threads.html man-crypto-htmlman html,openssl=30 ./usr/share/man/html7/orders.html man-reference-htmlman html +./usr/share/man/html7/pathsearch.html man-reference-htmlman html ./usr/share/man/html7/pcap-filter.html man-netutil-htmlman html ./usr/share/man/html7/pcap-linktype.html man-netutil-htmlman html ./usr/share/man/html7/pcap-tstamp.html man-netutil-htmlman html diff --git a/include/Makefile b/include/Makefile index f7e000fb2cb2..1ac92f38c095 100644 --- a/include/Makefile +++ b/include/Makefile @@ -16,7 +16,7 @@ INCS= a.out.h aio.h ar.h assert.h atomic.h \ login_cap.h lwp.h malloc.h math.h md2.h \ memory.h mntopts.h monetary.h mpool.h mqueue.h \ ndbm.h netconfig.h netdb.h netgroup.h nlist.h nl_types.h nsswitch.h \ - paths.h pwd.h quota.h randomid.h ranlib.h re_comp.h regex.h regexp.h \ + paths.h pathsearch.h pwd.h quota.h randomid.h ranlib.h re_comp.h regex.h regexp.h \ resolv.h res_update.h rmt.h sched.h search.h semaphore.h setjmp.h \ string.h sgtty.h signal.h spawn.h stab.h stddef.h stdio.h \ stdlib.h stdnoreturn.h strings.h stringlist.h struct.h sysexits.h \ diff --git a/lib/libc/gen/execvp.c b/lib/libc/gen/execvp.c index d29e2a0fc6d2..3219a99e7796 100644 --- a/lib/libc/gen/execvp.c +++ b/lib/libc/gen/execvp.c @@ -47,6 +47,7 @@ __RCSID("$NetBSD: execvp.c,v 1.32 2024/01/20 14:52:47 christos Exp $"); #include <limits.h> #include <unistd.h> #include <paths.h> +#include <pathsearch.h> #include "reentrant.h" #include "extern.h" @@ -62,9 +63,11 @@ execvpe(const char *name, char * const *argv, char * const * envp) int cnt; size_t lp, ln; int eacces = 0; + int do_qfilename; unsigned int etxtbsy = 0; char buf[PATH_MAX]; const char *bp, *path, *p; + const char *path_search_opt; _DIAGASSERT(name != NULL); @@ -74,8 +77,16 @@ execvpe(const char *name, char * const *argv, char * const * envp) goto done; } ln = strlen(name); - /* If it's an absolute or relative path name, it's easy. */ - if (strchr(name, '/')) { + + path_search_opt = getenv("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(name, ln); + + /* + * If it's an absolute or relative path name (and not a + * qualified filename and asked to search for it), it's easy. + */ + if (do_qfilename == 0 && strchr(name, '/')) { bp = name; path = ""; goto retry; diff --git a/lib/libc/gen/posix_spawnp.c b/lib/libc/gen/posix_spawnp.c index 2474bbe6970c..7e7e20e04313 100644 --- a/lib/libc/gen/posix_spawnp.c +++ b/lib/libc/gen/posix_spawnp.c @@ -39,6 +39,7 @@ __RCSID("$NetBSD: posix_spawnp.c,v 1.4 2020/05/11 14:54:34 kre Exp $"); #include <assert.h> #include <errno.h> #include <paths.h> +#include <pathsearch.h> #include <spawn.h> #include <stdio.h> #include <stdlib.h> @@ -53,15 +54,23 @@ int posix_spawnp(pid_t * __restrict pid, const char * __restrict file, { char fpath[FILENAME_MAX]; const char *path, *p; + const char *path_search_opt; size_t lp, ln; int err; + int do_qfilename; _DIAGASSERT(file != NULL); + ln = strlen(file); + path_search_opt = getenv("PATH_SEARCH_OPT"); + do_qfilename = PATH_SEARCH_QFILENAME_ON(path_search_opt) + && PATH_SEARCH_IS_QFILENAME(file, ln); + /* - * If there is a / in the name, fall straight through to posix_spawn(). + * If not treating a qualified filename, and there is a / in + * the name, fall straight through to posix_spawn(). */ - if (strchr(file, '/') != NULL) + if (do_qfilename == 0 && strchr(file, '/') != NULL) return posix_spawn(pid, file, fa, sa, cav, env); /* Get the path we're searching. */ @@ -72,7 +81,6 @@ int posix_spawnp(pid_t * __restrict pid, const char * __restrict file, * Find an executable image with the given name in the PATH */ - ln = strlen(file); err = 0; do { /* Find the end of this path element. */ diff --git a/share/man/man7/Makefile b/share/man/man7/Makefile index 9a8ab4202f52..d40457be1d81 100644 --- a/share/man/man7/Makefile +++ b/share/man/man7/Makefile @@ -20,6 +20,7 @@ MAN+= module.7 MAN+= nls.7 MAN+= operator.7 MAN+= orders.7 +MAN+= pathsearch.7 MAN+= pkgsrc.7 MAN+= release.7 MAN+= rfc6056.7 diff --git a/share/man/man7/environ.7 b/share/man/man7/environ.7 index b1c06f50ed4d..f88dbe818528 100644 --- a/share/man/man7/environ.7 +++ b/share/man/man7/environ.7 @@ -29,7 +29,7 @@ .\" .\" @(#)environ.7 8.3 (Berkeley) 4/19/94 .\" -.Dd January 21, 2011 +.Dd September 29, 2024 .Dt ENVIRON 7 .Os .Sh NAME @@ -174,6 +174,9 @@ is set to .Pp initially by .Xr login 1 . +.It Ev PATH_SEARCH_OPT +options to change the way path searching is done. Initially unset. See +.Xr pathsearch 7 . .It Ev PRINTER The name of the default printer to be used by .Xr lpr 1 , -- Thierry Laronde <tlaronde +AT+ kergis +dot+ com> http://www.kergis.com/ http://kertex.kergis.com/ Key fingerprint = 0FF7 E906 FBAF FE95 FD89 250D 52B1 AE95 6006 F40C