简单linux shell中的环境变量
我要为我的项目用 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()
从命令行获取的输入
I am to program a simple shell in C for my project that can implement environment variables. I looked up on how to use the getenv, setenv, putenv. So far so good i've tried to use the getenv to show the shell variables...well... with some succes . But I have a feeling that my reasoning is flawed. I have a char** argv
which contains parsed input from the user input. I now check if argv
starts with the command "echo" and then if any of the following inputs starts with a $
sign or not. Here's my code:
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) == '
I think that normal linux shell finds the $
sign, it expands the variable before invoking the echo command. My shell isn't following this principle, it's expanding variables inside the echo command itself. Any idea as to how I can implement this? Thanks.
EDIT:
A problem I have is: echo $HOME
and echo HOME
gives me the same result which is wrong.
EDIT:
After various tests everything works well. But to really test it i'll need to create a local variable then echo
this value. I tried it using putenv
function but it doesn't create the local variable.
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
is the input gotten from the command line using fgets()
){
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;
}
I think that normal linux shell finds the $
sign, it expands the variable before invoking the echo command. My shell isn't following this principle, it's expanding variables inside the echo command itself. Any idea as to how I can implement this? Thanks.
EDIT:
A problem I have is: echo $HOME
and echo HOME
gives me the same result which is wrong.
EDIT:
After various tests everything works well. But to really test it i'll need to create a local variable then echo
this value. I tried it using putenv
function but it doesn't create the local variable.
userInput: char *userInput
is the input gotten from the command line using fgets()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,普通 shell 在解析命令行期间会扩展变量。因此,您需要替换函数中的变量,该变量会生成“包含来自用户输入的解析输入”的数组。在这种情况下,
echo
(和其他命令)的代码将会短得多。Yes, normal shells expand variables during parsing command line. So you need substitute variables in function, that produces array that "contains parsed input from the user input". In this case code for
echo
(and other commands) will be much shorter.您专门要求代码对字符串执行 getenv() 操作,即使未找到 $ 也是如此。这就是为什么它会查找 $HOME 或 HOME。只需删除找不到美元符号的 else 情况,并确保在声明时将变量初始化为 NULL,并将其放入循环内。
像这样的事情:
编辑:就您的方法而言,为什么要专门检查回声?为什么不使其通用,并检查所有参数,包括第一个参数?您实际上可能想要替换所有潜在的环境变量,因此如果您在某处有 MYECHO=echo,则以下内容将起作用。为了使其更通用,您将拥有此函数,然后它将根据扩展的变量执行内容。您可以将其做得很好并具有单独的功能,但为了将其全部放在这里,我已经相应地更新了上面的代码,尽管我还没有测试它。 ;)
编辑:话虽这么说,werewindle 关于之前执行此操作的评论确实适用 - 替换参数,就像这里一样,然后使用更新后的参数数组让一个单独的函数执行它需要执行的任何操作。 :)
编辑: 对于 putenv() 情况,您需要如下结构。这样,它将为 shell 以及您在 shell 中运行的任何其他进程设置它。
(希望最终)编辑:作为解释,进程通常不会(也许不能?)影响其层次结构中位于其上方的进程的环境;恰恰相反。因此,如果您将 env() 放入子进程中,则该子进程的兄弟进程(即从其父进程派生的其他进程)将不会获得环境更改。
很高兴我能帮上忙!
You're specifically asking the code to do getenv() for the string, even if $ isn't found. That's why it will lookup $HOME or HOME. Just remove the else case for not finding the dollar-sign, and make sure to initialize variable to NULL at its declaration, and put it inside the loop.
Something like so:
Edit: As far as your methodology goes, why do you specifically check for echo? Why not make it generic, and check all the arguments, including the first one? You actually probably want to substitute all the potential environment variables, so if you had MYECHO=echo somewhere, the following would work. To make it more generic, you'd have this function, which would then execute the stuff based on the expanded variables. You could make it all nice and have separate functions, but to fit it all in here, I've updated the code above accordingly, though I haven't tested it. ;)
Edit: That being said, werewindle's comment about doing this earlier does apply -- replace the arguments, like here, and then use that updated arguments array to have a separate function do whatever it needs to do. :)
Edit: As for the putenv() situation, you'll want something structured like the following. This way, it will set it for the shell, and any other processes you run in the shell.
(Hopefully final) Edit: As an explanation, processes generally don't (perhaps can't?) affect the environment of processes above them in their hierarchy; only the other way around. So if you putenv() in a child, that child's siblings (i.e. other processes forked from its parent) won't get the environment change.
Glad I could be of help!