Ваша программа верна; попробуйте это с "ls" вместо "bash",
$ ./a.out ls -al /tmp
Причина, по которой он не работает с bash
, заключается в том, что bash ожидает, что процесс будет лидером группы из группы процессов переднего плана терминала , которой это не является.
Тем не менее, несмотря на то, что программа корректна, ее серьезное отсутствие обработки ошибок обидно: - ). Например, при вызове программы, которая не существует, execvp()
возвращается с ошибкой (а не с возвратом вообще), которая игнорируется. С эффектом, который ... ну ... вы можете только догадываться, сработало ли это.
$ ./a.out frobozzzzz
$ # (hm)
Вот мое воплощение этого. Longer. Обработка ошибок. Видя, как все прошло после прекращения ребенка.
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
int main(int argc, char** argv)
{
int status;
pid_t pid, terminated;
pid = fork();
if (pid == -1 /*unlikely*/) {
perror("fork()");
exit(EXIT_FAILURE);
}
if (pid == 0 /*child*/) {
if (execvp(argv[1], &argv[1]) != 0) { // when argv[1] is no
// progrm in path
perror("execvp()");
exit(EXIT_FAILURE);
}
else
assert(!"not getting here because successful exec() never returns");
}
// optional: wait for child to terminate, and print diagnostics
terminated = waitpid(pid, &status, 0);
if (terminated == -1) {
perror("waitpid()");
exit(EXIT_FAILURE);
}
if (terminated == pid) { // how come those not be equal?
if (WIFEXITED(status))
fprintf(stderr, "child terminated with exit status %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
fprintf(stderr, "child terminated by %d\n", WTERMSIG(status));
else
fprintf(stderr, "see \"man waidpid\" for what that could be\n");
}
return 0;
}