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:
M | cmd/which.c | 55 | ++++++++++++++++++++++++++++++++++++++++++------------- |
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;