The branch main has been updated by fernape: URL: https://cgit.FreeBSD.org/src/commit/?id=edadc3f9051595a9c2e693d8ab666a50b9e7a21a
commit edadc3f9051595a9c2e693d8ab666a50b9e7a21a Author: Fernando Apesteguía <[email protected]> AuthorDate: 2026-08-23 15:46:18 +0000 Commit: Fernando Apesteguía <[email protected]> CommitDate: 2026-08-29 15:15:43 +0000 whereis(1): Respect PORTSDIR variable PORTSDIR is a very common variable that points to the location of a ports directory. Make whereis(1) respect this variable too. Reviewed by: arrowd@, christos@ Approved by: christos@ Differential Revision: https://reviews.freebsd.org/D56845 --- usr.bin/whereis/whereis.1 | 4 ++ usr.bin/whereis/whereis.c | 118 +++++++++++++++++++++++++--------------------- 2 files changed, 69 insertions(+), 53 deletions(-) diff --git a/usr.bin/whereis/whereis.1 b/usr.bin/whereis/whereis.1 index 90922ce61db5..1b6adaeaf077 100644 --- a/usr.bin/whereis/whereis.1 +++ b/usr.bin/whereis/whereis.1 @@ -72,6 +72,10 @@ including all the subdirectories of .Pa /usr/src and .Pa /usr/ports . +If the environment variable +.Ev PORTSDIR +is defined and points to a directory then all its subdirectories +are included in the search of program sources. .Pp The following options are available: .Bl -tag -width indent diff --git a/usr.bin/whereis/whereis.c b/usr.bin/whereis/whereis.c index 8de56b9cf654..afc099276dfe 100644 --- a/usr.bin/whereis/whereis.c +++ b/usr.bin/whereis/whereis.c @@ -312,64 +312,76 @@ defaults(void) abort(); nele = 0; decolonify(b, &sourcedirs, &nele); - - if (stat(PATH_PORTS, &sb) == -1) { - if (errno == ENOENT) - /* no /usr/ports, we are done */ - return; - err(EX_OSERR, "stat(" PATH_PORTS ")"); + ccharp path_ports; + if ((cp = getenv("PORTSDIR")) != NULL) { + b = strdup(cp); + if (b == NULL) + abort(); } - if ((sb.st_mode & S_IFMT) != S_IFDIR) - /* /usr/ports is not a directory, ignore */ - return; - if (access(PATH_PORTS, R_OK | X_OK) != 0) - return; - if ((dir = opendir(PATH_PORTS)) == NULL) - err(EX_OSERR, "opendir" PATH_PORTS ")"); - while ((dirp = readdir(dir)) != NULL) { - /* - * Not everything below PATH_PORTS is of - * interest. First, all dot files and - * directories (e. g. .snap) can be ignored. - * Also, all subdirectories starting with a - * capital letter are not going to be - * examined, as they are used for internal - * purposes (Mk, Tools, ...). This also - * matches a possible CVS subdirectory. - * Finally, the distfiles subdirectory is also - * special, and should not be considered to - * avoid false matches. - */ - if (dirp->d_name[0] == '.' || - /* - * isupper() not used on purpose: the - * check is supposed to default to the C - * locale instead of the current user's - * locale. - */ - (dirp->d_name[0] >= 'A' && dirp->d_name[0] <= 'Z') || - strcmp(dirp->d_name, "distfiles") == 0) + ccharp ports_locations[2] = {PATH_PORTS, cp}; + int i; + for (i = 0; i < 2; i++) { + path_ports = ports_locations[i]; + if (!path_ports) continue; - if ((b = malloc(sizeof PATH_PORTS + 1 + dirp->d_namlen)) - == NULL) - abort(); - strcpy(b, PATH_PORTS); - strcat(b, "/"); - strcat(b, dirp->d_name); - if (stat(b, &sb) == -1 || - (sb.st_mode & S_IFMT) != S_IFDIR || - access(b, R_OK | X_OK) != 0) { - free(b); + if (stat(path_ports, &sb) == -1) { + if (errno == ENOENT) + /* no /usr/ports, we are done */ + continue; + err(EX_OSERR, "stat(%s)", path_ports); + } + if ((sb.st_mode & S_IFMT) != S_IFDIR) + /* This is not a directory, ignore */ + continue; + if (access(path_ports, R_OK | X_OK) != 0) continue; + if ((dir = opendir(path_ports)) == NULL) + err(EX_OSERR, "opendir %s)", path_ports); + while ((dirp = readdir(dir)) != NULL) { + /* + * Not everything below path_ports is of + * interest. First, all dot files and + * directories (e. g. .snap) can be ignored. + * Also, all subdirectories starting with a + * capital letter are not going to be + * examined, as they are used for internal + * purposes (Mk, Tools, ...). This also + * matches a possible CVS subdirectory. + * Finally, the distfiles subdirectory is also + * special, and should not be considered to + * avoid false matches. + */ + if (dirp->d_name[0] == '.' || + /* + * isupper() not used on purpose: the + * check is supposed to default to the C + * locale instead of the current user's + * locale. + */ + (dirp->d_name[0] >= 'A' && dirp->d_name[0] <= 'Z') || + strcmp(dirp->d_name, "distfiles") == 0) + continue; + if ((b = malloc(strlen(path_ports) + 1 + dirp->d_namlen)) + == NULL) + abort(); + strcpy(b, path_ports); + strcat(b, "/"); + strcat(b, dirp->d_name); + if (stat(b, &sb) == -1 || + (sb.st_mode & S_IFMT) != S_IFDIR || + access(b, R_OK | X_OK) != 0) { + free(b); + continue; + } + sourcedirs = realloc(sourcedirs, + (nele + 2) * sizeof(char *)); + if (sourcedirs == NULL) + abort(); + sourcedirs[nele++] = b; + sourcedirs[nele] = NULL; } - sourcedirs = realloc(sourcedirs, - (nele + 2) * sizeof(char *)); - if (sourcedirs == NULL) - abort(); - sourcedirs[nele++] = b; - sourcedirs[nele] = NULL; + closedir(dir); } - closedir(dir); } }
