Beispiellösung

Content

Zur Frage

Die Funktionen strtok und strtok_r verändern das erste Argument, indem sie Nullbytes einsetzen. Daher dürfen diese nicht auf eine Zeichenkette angewandt werden, auf die getenv zurückliefert. Stattdessen wird diese mit strdup dupliziert. Dann kann diese problem verändert werden. Später sollte das mit free wieder freigegeben werden.

Programmtext

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <afblib/strlist.h>

int execvpe(const char* file, char* const argv[], char* const envp[]) {
   const char* path = getenv("PATH");
   if (strchr(argv[0], '/') || !path) {
      return execve(file, argv, envp);
   } else {
      char* mypath = strdup(path);
      if (!mypath) {
	 return -1;
      }
      char* lasts;
      char* dir = strtok_r(mypath, ":", &lasts);
      int fd = -1;
      while (fd < 0 && dir) {
	 int dirfd = open(dir, O_DIRECTORY|O_SEARCH);
	 if (dirfd < 0) continue;
	 fd = openat(dirfd, file, O_EXEC);
	 dir = strtok_r(0, ":", &lasts);
      }
      free(mypath);
      if (fd < 0) {
	 return -1;
      }
      return fexecve(fd, argv, envp);
   }
}

int main(int argc, char** argv) {
   strlist env = {0};
   const char* cmdname = *argv++; --argc;
   while (argc > 0 && strchr(*argv, '=')) {
      if (!strlist_push(&env, *argv)) {
	 perror(""); exit(1);
      }
      --argc; ++argv;
   }
   if (argc == 0) {
      fprintf(stderr, "Usage: %s param=value ... command\n", cmdname);
      exit(1);
   }
   if (!strlist_push0(&env)) {
      perror(""); exit(1);
   }
   execvpe(argv[0], argv, env.list);
   perror(argv[0]);
   exit(1);
}

Übersetzung und Ausführung

theon$ gcc -Wall -o environ2 environ2.c -lafb
environ2.c:6:10: fatal error: afblib/strlist.h: No such file or directory
    6 | #include <afblib/strlist.h>
      |          ^~~~~~~~~~~~~~~~~~
compilation terminated.
theon$ ./environ2 date
Tue Nov 15 23:15:31 CET 2022
theon$ ./environ2 LANG=de TZ=EST date
Dienstag, 15. November 2022 um 17:15:31 Uhr EST
theon$