For some reason, execvp()
doesn't find the commands (like ls, pwd, etc.) in my PATH file, which includes /bin. Since I have a customized terminal alias with ls, I'm using pwd, etc. to test (as well as a fresh Linux machine), but I keep getting this for the output:
gcc main.c
./a.out
What would you like to do?
ls
arg[0]: ls
arg[1]: (null)
arg[2]: (null)
arg[3]: (null)
arg[4]: (null)
arg[5]: (null)
arg[6]: (null)
arg[7]: (null)
arg[8]: (null)
arg[9]: (null)
before exec
after exec
ERROR: No such file or directory
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
/*
Write a c program that runs a command line program with exactly one command line argument. It should work as follows:
Prompts the user for a program to run via the command line.
Reads in that line (using fgets) and parses it to be used by one of the exec functions.
Runs the command using exec
You do not need to fork off a separate process and wait, the purpose of this assignment is only to parse a single line of input and run a program once.
*/
int main() {
printf("\nWhat would you like to do?\n");
char* input = malloc( 100 ); //100 character string for input
fgets(input, 100, stdin); //reads from stdin (terminal input "file")
//parses command in input (max of 8 flags)
int number_of_args = 10;
char *args[number_of_args];
//puts cmd && flags in args
int i = 0;
for(; i < number_of_args; i++) {
args[i] = strsep( &input, " ");
printf("arg[%i]: %s\n", i, args[i]);
}
args[number_of_args - 1] = 0; //last element for execvp must be NULL;
// printf("nullify final index -> args[%i] = %s\n", number_of_args - 1, args[number_of_args -1]);
printf("before exec\n");
int e = execvp( args[0], args);
printf("after exec\n");
if(e < 0)
printf("ERROR: %s\n", strerror(errno));
return 0;
}
EDIT: Thought it'd be good to include my PATH as well:
echo $PATH
/usr/local/bin:/usr/local/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
fgets()
reads in the newline character if there's space available in the buffer. So when you input ls
, it's actually ls\n
. Obivously, execvp()
can't find such a command and it fails. So the solution is to remove the trailing newline, if any.
char *p = strchr(input, '\n');
if (p) *p = 0;
You should also use argc
for argument processing (if you read in the commands and arguments via main()'s argument) rather than assuming some fixed numbers. Or simply break the loop when strsep()
returns NULL the first time. Technically, your code invokes undefined behaviour when you print all those null strings.