logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/
commit: d533d3465fbb24d2574903d0ff674573abb71fb8
parent 1c81a03d121a969d0dfe9c52f480a66554efd00d
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri,  6 Jun 2025 06:00:47 +0200

cmd/which: get rid of strdup memory allocation

Diffstat:

Mcmd/which.c55++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 42 insertions(+), 13 deletions(-)

diff --git a/cmd/which.c b/cmd/which.c @@ -9,11 +9,23 @@ #include <stdbool.h> #include <stdio.h> // fprintf #include <stdlib.h> // getenv -#include <string.h> // strtok +#include <string.h> // strcpy, memcpy #include <unistd.h> // access, getopt const char *argv0 = "which"; +static const char * +which_strchrnul(const char *s, int c) +{ + if(!s) return s; + + const char *p = s; + while(*p != c && *p != '\0') + p++; + + return p; +} + int main(int argc, char *argv[]) { @@ -53,20 +65,35 @@ main(int argc, char *argv[]) for(int i = 0; i < argc; i++) { char *cmd = argv[i]; + size_t cmdlen = strlen(cmd); bool found = false; - char *state = NULL; + char *start = path; - char *hay = strdup(path); - if(hay == NULL) + const char *prev = start; + while(true) { - perror("which: error: Failed duplicating $PATH"); - return 1; - } + static char buf[PATH_MAX] = ""; + const char *stop = which_strchrnul(prev, ':'); - for(char *tok = strtok_r(hay, ":", &state); tok != NULL; tok = strtok_r(NULL, ":", &state)) - { - char buf[PATH_MAX] = ""; - snprintf(buf, PATH_MAX, "%s/%s", tok, cmd); + size_t buflen = stop - prev; + memcpy(buf, prev, buflen); + + if((PATH_MAX - buflen - 1) < cmdlen) + { + buf[buflen] = '\0'; + fprintf(stderr, + "which: warning: Concatenation of PATH element '%s' and command '%s' would be " + "greater than PATH_MAX\n", + buf, + cmd); + goto which_cont; + } + + buf[buflen++] = '/'; + + memcpy(buf + buflen, cmd, cmdlen); + buflen += cmdlen; + buf[buflen] = '\0'; if(access(buf, X_OK) == 0) { @@ -76,11 +103,13 @@ main(int argc, char *argv[]) if(!opt_a) break; } + + which_cont: + if(*stop == '\0') break; + prev = stop + 1; } if(!found) missing++; - - free(hay); } return missing;