Reputation: 33
My program should use fork and exec system calls. The exec should change the child process such that it takes another command as an argument and executes that command. For example, to display the message of the day:
./myexec cat /etc/motd
This is my current code
extern char **environ; /* environment info */
main(int argc, char **argv) {
/* argc -- number of arguments */
/* argv -- an array of strings */
char *argvNew[argc + 1];
int pid;
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc + 1] = NULL;
printf("After For: %s\n",argvNew[0]);
printf("After For: %s\n",argvNew[1]);
printf("After For: %s\n",argvNew[2]);
printf("After For: %s\n",argvNew[3]);
if ((pid = fork()) < 0) {
fprintf(stderr, "Fork error%sstrerror\n", strerror(errno));
exit(1);
}
else if (pid == 0) {
/* child process */
if (execve(argvNew[0], argvNew, environ) < 0) {
fprintf(stderr, "Execve error%d %s\n",errno,strerror(errno));
exit(1);
}
}
else {
/* parent */
wait(0); /* wait for the child to finish */
}
}
After running ./myexecv cat etc/motd
nothing happens; just the print statements. Any advice going forward?
Upvotes: 3
Views: 3657
Reputation: 73376
The calling parameters of execve()
require the first parameter to be the filename to execute. Unfortunately you pass it argvNew[0]
which is the same value as argv[0]
. This means that you call and call again your own program and never the script. You need to shift the parameters by one:
...
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
...
Upvotes: 1
Reputation: 118340
There are multiple bugs in the shown code.
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc+1] = NULL;
On it's face value, the NULL assignment is wrong, and will result in undefined behavior because argvNew
is declared as
char *argvNew[argc + 1];
So the array contains values argvNew[0]
through argvNew[argc]
, and argvNew[argc+1]=NULL;
runs off past the end of the array, that results in undefined behavior. This should obviously be
argvNew[argc] = NULL;
But even that would also be wrong, because:
execve(argvNew[0], argvNew, environ);
argvNew[0]
is copied from argv[0]
, which is the name of this program being executed. This is going to fork and run the same program, in the child process.
You will end up forkbombing yourself. If this is a shared server, you will make the system administrator very very mad.
You need to remove argv[0]
from the equation, and copy over only argv[1]
, and on. The correct loop, and copy, is:
int pid;
char *argvNew[argc];
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
Upvotes: 2