Делая вид, что необходимо продублировать аргументы и использовать fork()
, и наблюдая, что если вы запустите:
./exec ls
, то вы захотите использовать только аргументы из индекса 1 при вызове execvp()
, тогда вы получите код, подобный следующему:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
char *args[argc];
for (int i = 0; i < argc - 1; ++i)
{
if ((args[i] = strdup(argv[i+1])) == NULL)
{
fprintf(stderr, "%s: failed to allocate memory for '%s'\n",
argv[0], argv[i+1]);
exit(EXIT_FAILURE);
}
}
args[argc-1] = NULL;
int rc = fork();
if (rc == 0)
{
execvp(args[0], args);
fprintf(stderr, "%s: failed to execute '%s'\n", argv[0], args[0]);
exit(EXIT_FAILURE);
}
else if (rc < 0)
{
fprintf(stderr, "%s: failed to fork\n", argv[0]);
exit(EXIT_FAILURE);
}
return 0;
}
Родительский процесс должен действительно wait()
для ребенка, прежде чем выйти из него. Код, вероятно, должен включать функцию для вывода содержимого списка аргументов. Вот пересмотренная версия кода, которая не использует strdup()
, хотя она все еще работает. Он использует некоторый код, который доступен в моем репозитории SOQ (Вопросы о переполнении стека) на GitHub в виде файлов stderr.c
и stderr.h
в подкаталоге src / libsoq . Это упрощает обработку ошибок - отчеты об ошибках используют один вызов функции вместо нескольких строк кода, как раньше.
#include <unistd.h>
#include <sys/wait.h>
#include "stderr.h"
int main (int argc, char *argv[])
{
err_setarg0(argv[0]);
if (argc <= 1)
err_usage("cmd [arg ...]");
int rc = fork();
if (rc == 0)
{
execvp(argv[1], &argv[1]);
err_syserr("failed to execute '%s': ", argv[1]);
}
else if (rc < 0)
err_syserr("failed to fork: ");
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
if (corpse != rc)
err_remark("unexpected child PID %d status 0x%.4X\n", corpse, status);
}
if (WIFEXITED(status))
rc = WEXITSTATUS(status);
else if (WIFSIGNALED(status))
rc = 128 + WTERMSIG(status);
else
rc = 255; /* Something weird happened! */
return rc;
}
Конечно, если вы не используете fork()
, вам не нужно wait()
либо. Это радикально уменьшает код:
#include <unistd.h>
#include "stderr.h"
int main (int argc, char *argv[])
{
err_setarg0(argv[0]);
if (argc <= 1)
err_usage("cmd [arg ...]");
execvp(argv[1], &argv[1]);
err_syserr("failed to execute '%s': ", argv[1]);
}