“在路径中找到命令”是什么意思?

时间:2012-09-30 02:53:09

标签: linux shell path environment-variables

这是我的操作系统课程作业说明的摘录。粗体部分是我无法理解的部分,我现在也无法联系到教授,我真的很想今晚开始。我知道环境变量是什么,我想...只是在shell中声明的变量,对吧?但粗线特别是什么意思?

  

编写C程序以实现用户执行命令的交互式shell。

     

调用这个程序myshell(所以使用gcc -o myshell -Wall等来   编译)。

     

创建一个无限循环,重复提示用户输入   命令(参见下面的示例输出和输入)。

     

在执行用户输入的命令之前,必须执行命令   使用环境变量THEPATH指定的路径找到(不要   使用PATH!)。默认情况下,未设置THEPATH变量,因此   测试时,您需要手动设置(并取消设置)此变量(请参阅   详情如下)。如果找到THEPATH,您的程序必须执行   通过fork()和一个exec()系统在子进程中命令   调用

     

要获取并解析THEPATH,请考虑使用getenv()函数和   strtok()或strsep()函数。

3 个答案:

答案 0 :(得分:1)

对于运行程序的shell,它必须知道程序的位置。例如,您希望能够在提示符下键入ls,但可能会在ls找到/bin/ls的实际二进制文件。这就是PATH(或您的情况,THEPATH)的来源。当您键入ls时,shell会关闭并在每个PATH目录中查找匹配的程序名称。当它找到一个时,就会运行它。我们以ls为例,PATH设置为:

/usr/local/bin:/usr/bin:/bin

假设ls/bin/ls,那么shell首先在ls中查找/usr/local/bin,找不到它,然后查看/usr/bin,然后终于在/bin中找到并执行它。

实际上正在执行此操作是您的作业中有关getenvstrtokstrsep的提示的来源。

答案 1 :(得分:0)

您的变量THEPATH应包含目录列表,以冒号分隔,如

THEPATH=/usr/bin:/bin:some-other-dirs

您必须将其解析为目录列表。当用户输入命令时,您必须扫描所有目录,以便查找名称与用户输入的命令相匹配的可执行文件。

在这种复杂程度上编写shell并不是一项初学任务,如果你不理解系统的PATH处理是如何工作的(你只是在模仿shell的作用),那么你可能会在你的头脑中。 / p>

答案 2 :(得分:0)

我知道我已经迟到了,但你可以在这里耍弄狡猾的伎俩,这就是傅师傅的精神“通过不编码获得优点”。 execlp()execvp()execvpe() C库函数实际上为您搜索PATH变量。您所要做的就是用环境中的THEPATH替换PATH。它使您的shell更安全,因为您的所有子进程都将使用原始的THEPATH作为路径。

int i_path = -1;
int i_thepath = -1;
int i = 0;
while (envp[i] != NULL) {
    if (strstr(envp[i], "PATH=") == envp[i])
        i_path = i;
    if (strstr(envp[i], "THEPATH=") == envp[i])
        i_thepath = i;
    i++;
}
if (i_path >= 0 && i_thepath >= 0)
    envp[i_path] = envp[i_thepath] + 3; /* discard 'THE' */
else if (i_thepath >= 0)
    envp[i_thepath] = envp[i_thepath] + 3; /* discard 'THE' */
execvpe(command, argv, envp);

如果您要手动解析THEPATH,请不要创建目录列表。在像Perl这样的高级语言中很容易,但在C语言中涉及手动动态内存分配,因为您事先并不知道THEPATH中有多少个dir元素。要进行内存分配,首先需要遍历字符串。但是你可以在第一次迭代中完成真正的工作,使用strtok()":"作为分隔符。

char *thepath = envp[i_thepath];
char *dir;
strtok(thepath, "="); /* first discard 'THEPATH=' */
while (dir = strtok(NULL, ":") {
    /* now check if dir+command exists and is execuatble, exec */
}