using a new path with execve to run ls command

做~自己de王妃 提交于 2019-11-30 18:36:01

问题


I am trying to use execve to run the ls command. Currently I'm running it with the following arguments:

execve(args[0], args, env_args)
//args looks like {"ls", "-l", "-a", NULL}
//env_args looks like {"PATH=/bin", "USER=me", NULL}

What I expected this to do was run the ls command using my new env_args meaning that it would look up ls in my PATH. However, this code actually doesn't do anything and when I run the code it just returns to my command prompt without output.

Using the same args[] I was using execvp and ls worked and searched my current path.

Can you tell me what I am doing wrong?

What I am trying to do is write my own shell program where I can create and export my own environment and have exec use the environment I have defined in a char**. Essentially I am writing my own functions to operate on env_args to add and remove vars and when I call exec i want to be able to call exec on {"ls", "-l", NULL} and have it look down my new environments path variable for a valid program called ls. I hope this explains what I am doing a little better. I don't think the extern environ var will work for me in this case.


回答1:


execve() does not look at PATH; for that, you need execvp(). Your program was failing to execute ls, and apparently you don't report failures to execute a program after the execve(). Note that members of the exec*() family of functions only return on error.

You'd get the result you expected (more or less) if you ran the program with /bin as your current directory (because ./ls - aka ls - would then exist).

You need to provide the pathname of the executable in the first argument to execve(), after finding it using an appropriate PATH setting.

Or continue to use execvp(), but set the variable environ to your new environment. Note that environ is now (POSIX 2008) declared in <unistd.h>, but previously was not declared anywhere.

extern char **environ;

environ = env_args;
execvp(args[0], &args[0]);

You don't need to save the old value and restore it; you're in the child process and switching its environment won't affect the main program (shell).


This seems to work as I'd expect - and demonstrates that the original code behaves as I'd expect.

#include <stdio.h>
#include <unistd.h>

extern char **environ;

int main(void)
{
    char *args[]     = { "ls", "-l", "-a", NULL };
    char *env_args[] = { "PATH=/bin", "USER=me", NULL };

    execve(args[0], args, env_args);
    fprintf(stderr, "Oops!\n");

    environ = env_args;
    execvp(args[0], &args[0]);
    fprintf(stderr, "Oops again!\n");

    return -1;
}

I get an 'Oops!' followed by the listing of my directory. When I create an executable ls in my current directory:

#!/bin/sh
echo "Haha!"

then I don't get the 'Oops!' and do get the 'Haha!'.



来源:https://stackoverflow.com/questions/7630551/using-a-new-path-with-execve-to-run-ls-command

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!