简体   繁体   中英

using a new path with execve to run ls command

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.

The execve() function 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 unique among POSIX global variables in that is it not declared in any header.

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!'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM