diff --git a/tests/usr.bin/mkdep/Makefile b/tests/usr.bin/mkdep/Makefile index 80c3f1eba0ce..bb8e2557925c 100644 --- a/tests/usr.bin/mkdep/Makefile +++ b/tests/usr.bin/mkdep/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2021/08/11 20:42:26 rillig Exp $ +# $NetBSD: Makefile,v 1.3 2021/08/20 06:36:10 rillig Exp $ .include @@ -13,5 +13,6 @@ PROG= h_findcc SRCS= h_findcc.c findcc.c CPPFLAGS+= -I${NETBSDSRCDIR}/usr.bin/mkdep MAN.h_findcc= # none +WARNS= 6 .include diff --git a/tests/usr.bin/mkdep/t_findcc.sh b/tests/usr.bin/mkdep/t_findcc.sh index 4ef2af973124..541a97e39e04 100644 --- a/tests/usr.bin/mkdep/t_findcc.sh +++ b/tests/usr.bin/mkdep/t_findcc.sh @@ -1,4 +1,4 @@ -# $NetBSD: t_findcc.sh,v 1.2 2021/08/20 05:45:19 rillig Exp $ +# $NetBSD: t_findcc.sh,v 1.3 2021/08/20 06:36:10 rillig Exp $ # # Copyright (c) 2021 The NetBSD Foundation, Inc. # All rights reserved. @@ -51,6 +51,31 @@ base_found_body() { "$(atf_get_srcdir)"/h_findcc 'echo' } +# A plain program name is searched in the PATH and, in this example, it is +# found in '/bin', which comes second in the PATH. +# +atf_test_case base_found_second +base_found_second_body() { + atf_check -o "inline:/bin/echo$n" \ + env -i PATH='/nonexistent:/bin' \ + "$(atf_get_srcdir)"/h_findcc 'echo' +} + +# A plain program name is searched in the PATH and, in this example, it is +# found in './bin', a relative path in the PATH, which is rather unusual in +# practice. +# +atf_test_case base_found_reldir +base_found_reldir_body() { + mkdir bin + echo '#! /bin/sh' > 'bin/reldir-echo' + chmod +x 'bin/reldir-echo' + + atf_check -o "inline:bin/reldir-echo$n" \ + env -i PATH='/nonexistent:bin' \ + "$(atf_get_srcdir)"/h_findcc 'reldir-echo' +} + # The C compiler can be specified as a program with one or more arguments. # If the program name is a plain name without any slash, the argument is # discarded. @@ -143,6 +168,8 @@ abs_arg_found_body() { atf_init_test_cases() { atf_add_test_case base_not_found atf_add_test_case base_found + atf_add_test_case base_found_second + atf_add_test_case base_found_reldir atf_add_test_case base_arg_found atf_add_test_case rel_not_found diff --git a/usr.bin/mkdep/findcc.c b/usr.bin/mkdep/findcc.c index a446fd1d9e3f..97f6065e77f1 100644 --- a/usr.bin/mkdep/findcc.c +++ b/usr.bin/mkdep/findcc.c @@ -1,4 +1,4 @@ -/* $NetBSD: findcc.c,v 1.9 2021/08/20 05:45:19 rillig Exp $ */ +/* $NetBSD: findcc.c,v 1.10 2021/08/20 06:36:10 rillig Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ #if !defined(lint) __COPYRIGHT("@(#) Copyright (c) 1999 The NetBSD Foundation, Inc.\ All rights reserved."); -__RCSID("$NetBSD: findcc.c,v 1.9 2021/08/20 05:45:19 rillig Exp $"); +__RCSID("$NetBSD: findcc.c,v 1.10 2021/08/20 06:36:10 rillig Exp $"); #endif /* not lint */ #include @@ -49,47 +49,40 @@ __RCSID("$NetBSD: findcc.c,v 1.9 2021/08/20 05:45:19 rillig Exp $"); #include "findcc.h" char * -findcc(const char *cc_command) +findcc(const char *progname) { - char *progname, *path, *dir, *next; - char buffer[MAXPATHLEN]; + char *cc; + const char *path, *dir; + char buffer[MAXPATHLEN]; + size_t progname_len, dir_len; - if ((progname = strdup(cc_command)) == NULL) - return NULL; + progname_len = strcspn(progname, " "); - if ((next = strchr(progname, ' ')) != NULL) - *next = '\0'; - - if (strchr(progname, '/') != NULL) { - if (access(progname, X_OK) == 0) - return progname; - free(progname); + if (memchr(progname, '/', progname_len) != NULL) { + if ((cc = strndup(progname, progname_len)) == NULL) + return NULL; + if (access(cc, X_OK) == 0) + return cc; + free(cc); return NULL; } - if (((path = getenv("PATH")) == NULL) || - ((path = strdup(path)) == NULL)) { - free(progname); + if ((path = getenv("PATH")) == NULL) return NULL; + + for (dir = path; *dir != '\0'; ) { + dir_len = strcspn(dir, ":"); + + if ((size_t)snprintf(buffer, sizeof(buffer), "%.*s/%.*s", + (int)dir_len, dir, (int)progname_len, progname) + < sizeof(buffer) + && access(buffer, X_OK) == 0) + return strdup(buffer); + + dir += dir_len; + if (*dir == ':') + dir++; } - dir = path; - while (dir != NULL) { - if ((next = strchr(dir, ':')) != NULL) - *next++ = '\0'; - - if (snprintf(buffer, sizeof(buffer), - "%s/%s", dir, progname) < (int)sizeof(buffer)) { - if (access(buffer, X_OK) == 0) { - free(path); - free(progname); - return strdup(buffer); - } - } - dir = next; - } - - free(path); - free(progname); return NULL; }