Store the value of PATH from C language envp in an array

I had the opportunity to try making myshell, and I will summarize what I wrote at that time.

Thing you want to do

Put the location of the command in the environment variable passed to the executable file in an array of type char *.

Introduction

I investigated what the state of ʻenvp [] `, which contains environment variables, is.

show_all.c


int show_all(char *envp[])
{
  while(*envp)
      printf("%s\n",*envp++);

  return 0;
}

When I executed a function like this, ʻenvp [18]` contained the following value.

PATH=/Library/Frameworks/Python.framework/Versions/3.5/bin:/Users/rild/.pyenv/bin:/Users/rild/.rbenv/shims:/opt/local/bin:/opt/local/sbin:/opt/local/bin:/opt/local/sbin:/Users/rild/.nvm/versions/node/v5.5.0/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/TeX/texbin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Users/rild/.pyenv/bin:/Users/rild/.rbenv/shims:/opt/local/bin:/opt/local/sbin:/Users/rild/.sdkman/candidates/kotlin/current/bin:/Users/rild/.sdkman/candidates/gradle/current/bin:/Users/rild/Library/Android/sdk/platform-tools:/Users/rild/Documents/android/apktool.jar:/usr/local/share/python:/Users/rild/Library/Android/sdk/platform-tools:/Users/rild/Documents/android/apktool.jar:/usr/local/share/python

From here, I wanted to retrieve the path of the command, separated by :.

Target

I will make it like this.

path[0]=/Library/Frameworks/Python.framework/Versions/3.5/bin
path[1]=/Users/rild/.pyenv/bin
path[2]=/Users/rild/.rbenv/shims
path[3]=/opt/local/bin
path[4]=/opt/local/sbin
path[5]=/opt/local/bin
path[6]=/opt/local/sbin
path[7]=/Users/rild/.nvm/versions/node/v5.5.0/bin
path[8]=/usr/local/bin
path[9]=/usr/bin
path[10]=/bin
path[11]=/usr/sbin
path[12]=/sbin
path[13]=/opt/X11/bin
path[14]=/Library/TeX/texbin
path[15]=/Library/Frameworks/Python.framework/Versions/3.5/bin
path[16]=/Users/rild/.pyenv/bin
path[17]=/Users/rild/.rbenv/shims
path[18]=/opt/local/bin
path[19]=/opt/local/sbin
path[20]=/Users/rild/.sdkman/candidates/kotlin/current/bin
path[21]=/Users/rild/.sdkman/candidates/gradle/current/bin
path[22]=/Users/rild/Library/Android/sdk/platform-tools
path[23]=/Users/rild/Documents/android/apktool.jar
path[24]=/usr/local/share/python
path[25]=/Users/rild/Library/Android/sdk/platform-tools
path[26]=/Users/rild/Documents/android/apktool.jar
path[27]=/usr/local/share/python

code

envp.c


#include <string.h>
#include <stdio.h>

// split funtion with `:`---> start
int iscolon(char p)
{
  return p == ':';
}

void
split_wthcolon(int *path_c, char *path[], char *p)
{
    *path_c = 0;

    for(;;) {
      while (iscolon(*p))
          p++;
      if (*p == '\0') return;
      path[(*path_c)++] = p;

      while (*p && !iscolon(*p)) {
        p++;
      }
      if (*p == '\0')
        return;
      *p++ = '\0';
    }
}
// split funtion <--- end

// search "PATH=" index --->
int get_path_index(char *envp[])
{
  int envc = 0;

  // find char * pointing "PATH=..."
  while(*envp) {
    if (!strncmp(*envp, "PATH=", 5)) {
      return envc;
    }
    envc++;
    envp++;
  }
  return 0;
}
// search "PATH=" index <--- end

// split to path array
int get_path_from_buf(int * path_c, char *path[], char *buf)
{
  int i;
  for (i = 0; i < 5; i++) buf++; // rm "PATH="
  split_wthcolon(path_c, path, buf);

  return 0;
}

int main(int argc, char *argv[], char *envp[])
{
  char buf[1024]; // PATH contains '762 words'

  strcpy(buf, envp[get_path_index(envp)]);
  fprintf(stderr, "%d\n", get_path_index(envp)); // 18
  fprintf(stderr, "%s\n", buf); // envp[18]

  char *path[32]; // PATH contatins '27' colon ':'
  int path_c; // path count
  get_path_from_buf(&path_c, path, buf);

  int i;
  for (i = 0; i < path_c; i++) {
    fprintf(stderr, "%s\n", path[i]);
  }

  return 0;
}

At first, I passed ʻenvp [get_path_index (envp)]directly toget_path_from_buf`, but since the contents are rewritten, I copied the value and passed it as an argument.

Finally

for (i = 0; i <5; i ++) buf ++; // rm" PATH = " is not so good, so there should be a better way. .. ..

reference

Postscript

If you specify PATH in the getenv function, you don't need get_path_index. http://www.c-lang.net/general29/index.html

Recommended Posts