libc

my libc
git clone git://git.evenfri.xyz/libc.git
Log | Files | Refs | README

execvp.c (1407B)


      1 /*
      2  * execvp.c - execute a file, searching PATH
      3  * Copyright (C) 2026. All rights reserved.
      4  */
      5 
      6 #include "libc.h"
      7 
      8 char **environ;
      9 
     10 int execvp(const char *file, char *const argv[]) {
     11   static char *empty_env[] = { NULL };
     12   char **env = (environ != NULL) ? environ : empty_env;
     13 
     14   if (strchr(file, '/') != 0) {
     15     return execve(file, argv, env);
     16   }
     17 
     18   const char *path_env = NULL;
     19   if (env != NULL) {
     20     for (char **ep = env; *ep != NULL; ++ep) {
     21       if (ep[0][0] == 'P' && ep[0][1] == 'A' && 
     22           ep[0][2] == 'T' && ep[0][3] == 'H' && ep[0][4] == '=') {
     23         path_env = *ep + 5;
     24         break;
     25       }
     26     }
     27   }
     28 
     29   if (path_env == NULL || *path_env == '\0') {
     30     path_env = "/bin";
     31   }
     32 
     33   char path_buf[1024];
     34   size_t file_len = strlen(file);
     35 
     36   const char *p = path_env;
     37   while (*p != '\0') {
     38     const char *start = p;
     39     while (*p != '\0' && *p != ':') {
     40       p++;
     41     }
     42 
     43     size_t dir_len = p - start;
     44 
     45     if (dir_len == 0) {
     46       if (file_len + 1 < sizeof(path_buf)) {
     47         memcpy(path_buf, file, file_len + 1);
     48         execve(path_buf, argv, env);
     49       }
     50     } else {
     51       if (dir_len + 1 + file_len + 1 < sizeof(path_buf)) {
     52         memcpy(path_buf, start, dir_len);
     53         path_buf[dir_len] = '/';
     54         memcpy(path_buf + dir_len + 1, file, file_len + 1);
     55         execve(path_buf, argv, env);
     56       }
     57     }
     58 
     59     if (*p == ':') {
     60       p++;
     61     }
     62   }
     63 
     64   return -1;
     65 }