Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 简单linux shell中的环境变量_C_Linux_Shell_Environment Variables_Getenv - Fatal编程技术网

C 简单linux shell中的环境变量

C 简单linux shell中的环境变量,c,linux,shell,environment-variables,getenv,C,Linux,Shell,Environment Variables,Getenv,我将用C语言为我的项目编写一个简单的shell,它可以实现环境变量。我查阅了如何使用getenv、setenv、putenv。到目前为止,我已经尝试使用getenv来显示shell变量…好吧。。。取得了一些成功。但我觉得我的推理有缺陷。我有一个char**argv,其中包含来自用户输入的解析输入。我现在检查argv是否以命令“echo”开头,然后检查以下输入是否以$符号开头。这是我的密码: int executeVariables(char** arguments){ int i = 0

我将用C语言为我的项目编写一个简单的shell,它可以实现环境变量。我查阅了如何使用getenv、setenv、putenv。到目前为止,我已经尝试使用getenv来显示shell变量…好吧。。。取得了一些成功。但我觉得我的推理有缺陷。我有一个
char**argv
,其中包含来自用户输入的解析输入。我现在检查
argv
是否以命令“echo”开头,然后检查以下输入是否以
$
符号开头。这是我的密码:

int executeVariables(char** arguments){
    int i = 0;
    if(strcmp(arguments[i], "echo") == 0){
        char *variable;
        for(i = 1; arguments[i] != NULL; i++){
            char *str = arguments[i];
            if( *(str + 0) == '$'){
                variable = getenv(str + 1);
            }else{
                variable = getenv(str);
            }
            if(!variable){
                //puts("not a variable");
                printf("%s ", arguments[i]);
            }else{
                //puts("a variable");
                printf("%s ", variable);
            }
        }
        printf("\n");
        exit(0);
    }

    return 1;

}
我认为普通的linux shell会找到
$
符号,它会在调用echo命令之前展开变量。我的shell没有遵循这个原则,它在echo命令本身内部扩展变量。你知道我该怎么做吗?谢谢

编辑:

我遇到的一个问题是:
echo$HOME
echo HOME
给了我相同的结果,但结果是错误的

编辑:


经过各种测试,一切正常。但要真正测试它,我需要创建一个局部变量,然后
echo
这个值。我使用
putenv
函数尝试了它,但它没有创建局部变量

i = 0;
char** temp = malloc(sizeof (*temp));
if(strstr(userInput, "=") != NULL){
    //puts("we got equals");
    puts(userInput);
    if(putenv(userInput) == 0){
       printf("doing putenv(%s)\n", userInput);
        exit(0);
    }
    else{
        puts("couldnt putenv");
       exit(1);
    }
}

userInput:
char*userInput
是使用
fgets()

从命令行获取的输入。是的,普通shell在解析命令行期间会展开变量。所以您需要在函数中替换变量,该函数生成“包含来自用户输入的解析输入”的数组。在这种情况下,
echo
(和其他命令)的代码将短得多。

您特别要求代码对字符串执行getenv(),即使找不到$。这就是为什么它将显示$HOME或HOME。只需删除找不到美元符号的else情况,并确保在声明时将变量初始化为NULL,然后将其放入循环中

大概是这样的:

// First, perform replacements
int executeVariables(char** arguments){
    int i = 0;

    for(i = 0; arguments[i] != NULL; i++){
        char *str = arguments[i];

        if(*str == '$'){
            // make sure the result isn't NULL, though I'm not sure a real shell does
            char *tmp = getenv(str + 1);
            if (tmp != NULL) {
                arguments[i] = getenv(str + 1); // save off the argument
            }
        }
    }

    // Then actually execute the function. This would be like bash's echo builtin
    if (strcmp(arguments[0], "echo") == 0) {
        int i;
        for (i = 1; arguments[i] != NULL; i++) {
            printf("%s ", arguments[i]);
        }
        printf("\n");
    }

    // Other functions could go here

    return 1;
}
编辑:就您的方法而言,为什么要专门检查echo?为什么不让它变得通用,并检查所有参数,包括第一个参数?实际上,您可能希望替换所有潜在的环境变量,因此,如果您在某个地方有MYECHO=echo,那么下面的方法就可以了。为了使它更通用,您需要有这个函数,它将根据扩展的变量执行这些内容。你可以把它做得很好,并且有单独的函数,但是为了适应这里的所有功能,我已经相应地更新了上面的代码,尽管我还没有测试过它。;)

Edit:话虽如此,werewindle之前关于执行此操作的评论确实适用——替换参数,如此处所示,然后使用更新的参数数组让单独的函数执行它需要执行的任何操作。:)

Edit:对于putenv()情况,您需要以下结构。这样,它将为shell以及在shell中运行的任何其他进程设置它

void do_args_env(char *args[])
{
    // do putenv, etc.
}

// inside main loop in shell process
while (1) { // just an example
    if (check_args_syntax(args) != 0) {
        // error
    }

    do_args_env(args);

    // fork and do other stuff
}
(希望是最终版)编辑:作为一种解释,流程通常不会(可能不会?)影响其层次结构中位于其之上的流程的环境;只有相反的方向。因此,如果在子级中放置env(),则该子级的同级(即从其父级派生的其他进程)将不会得到环境更改


很高兴我能帮上忙

你有什么问题?看起来你的代码会达到你想要的效果,不是吗?@DanFego不完全是:
echo$HOME
echo HOME
给了我相同的结果,但结果是错误的。putenv()失败了吗,还是返回0?作为记录,整个问题可能已经被拆分了,但既然我们还在这里,我将编辑我的答案等等,putenv()不应该接受userInput,而不是*userInput吗?很抱歉,我没有完全理解您的第二句话。当您解析用户输入(如“echo my home at$home”)时,必须用实际变量值替换$home。因此,在调用
executeVariables
期间,
参数中的
将是要处理的实际数据(即“echo”、“my”、“home”、“at”、“root”)。所有其他shell都是这样工作的。对不起,我想,您问过如何更好地替换环境变量。要修复代码,只需替换
variable=getenv(str)带有
变量=NULL
。好的,谢谢。解决了这个问题。如果我想更好地替换环境变量呢?:)那么您应该在前面替换它们:)。或者,您很快就会发现,在处理任何shell命令期间,您都有相同的代码来替换环境变量。另外,不要忘记,变量还有其他语法,比如${MYVAR}。我想创建一个特殊函数
subs_env(char*str)
,它将在解析用户输入的早期步骤中用
str
中的值替换所有可能的变量。谢谢您的帮助。它解决了这个问题。我不知道为什么我甚至保留了
else
条件。不管怎样,你认为我的推理正确吗?我的意思是我没有遵循正常的外壳行为。那是我的问题。我该怎么做呢?我想让它变得通用。删除第一个
if
条件,然后搜索每个参数是否包含一个美元符号,然后用正确的值替换
argv
,然后使用
execvp(*argv,argv)
do?更新了代码,但werewindle下面的注释为您指出了正确的方向。使用arguments数组,执行替换作为自己的操作,然后执行其余操作。谢谢。让我试试。我会用新的代码更新我的问题。经过各种测试,一切都很好。但要真正测试它,我需要创建一个局部变量。我使用
putenv
函数尝试了它,但它没有创建局部变量。请检查我编辑的问题。
void do_args_env(char *args[])
{
    // do putenv, etc.
}

// inside main loop in shell process
while (1) { // just an example
    if (check_args_syntax(args) != 0) {
        // error
    }

    do_args_env(args);

    // fork and do other stuff
}