I had the opportunity to try making myshell, and I will summarize what I wrote at that time.
Put the location of the command in the environment variable passed to the executable file in an array of type char *
.
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 :
.
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
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 to
get_path_from_buf`, but since the contents are rewritten, I copied the value and passed it as an argument.
for (i = 0; i <5; i ++) buf ++; // rm" PATH = "
is not so good, so there should be a better way. .. ..
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