execve в linux, выполнить из аргументов

Мне нужно создать программу, которая позволяет пользователю выполнять команду, переданную в качестве аргумента, с помощью execve в Linux. Я не уверен в синтаксисе команды execve. Я написал программу, но она не работает с несколькими аргументами, и я не могу понять, почему.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
    ///Father process
    wait(&status);
    printf("Process terminated with status = %d\n",status);
}
else
{
    ///son process
    int i;
    char param[100];

    printf("I'm the son woth PID= %d\n",getpid());
    printf("%s\n",argv[0]);
    printf("%s\n",argv[1]);
    printf("%s\n",argv[2]);
    strcpy(param,"/bin/");
    strcat(param,argv[1]);  

    execve(param,argv,NULL);
    exit(-1);
}


return 0;
}

Команда, которая не работает с использованием этого кода,

cp file1.txt file2.txt

Кто-нибудь может мне помочь?


person Federico Zucchi    schedule 07.05.2017    source источник
comment
Что значит не работает? Почему бы вам не запустить свою программу на тестовой программе, которой вы полностью управляете, чтобы вы могли сначала проверить свои ожидания?   -  person Kerrek SB    schedule 08.05.2017
comment
Он не выполняет команду. Я передаю команду и параметры, и execv должен повторить команду, используя параметры, переданные в основной   -  person Federico Zucchi    schedule 08.05.2017
comment
Для чего argv[2]? Либо вы получите сообщение об ошибке от printf, либо вы не сможете передать аргумент вместе с командой argv[1].   -  person Weather Vane    schedule 08.05.2017
comment
Третий аргумент основных аргументов.   -  person Federico Zucchi    schedule 08.05.2017
comment
Какой результат вы получаете? Вы говорите, что это не работает, но не говорите нам, что происходит! Выводит ли что-нибудь?   -  person David Schwartz    schedule 08.05.2017
comment
Кажется, используется команда, например cp, в качестве первого аргумента самого cp   -  person Federico Zucchi    schedule 08.05.2017
comment
Ах, я не прочитал вопрос должным образом.   -  person Weather Vane    schedule 08.05.2017
comment
Обратите внимание, что execve() не выполняет поиск команды для выполнения на основе PATH. Если у вас нет двоичного файла ./cp в текущем каталоге, команда не будет работать, потому что она не может найти исполняемый файл. Непрохождение какой-либо среды является жестоким и необычным наказанием, хотя cp, вероятно, не пострадает. На многие другие команды никакая среда не повлияет. Лучше использовать execv() или execvp() — или даже execvpe(), если ваша платформа поддерживает это (Linux поддерживает, а macOS и многие другие системы — нет).   -  person Jonathan Leffler    schedule 08.05.2017


Ответы (1)


Эта версия исправлена:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
    ///Father process
    wait(&status);
    printf("Process terminated with status = %d\n",status);
}
else
{
    ///son process
    int i;
    char program[100];

    printf("I'm the son woth PID= %d\n",getpid());
    strcpy(program,argv[1]);

    printf("Program: %s\n", program);

    execve(program, argv+1, NULL);
    exit(0);
}


return 0;
}

Пример:

$ ./a.out /bin/cp a.txt b.txt
I'm the son woth PID= 1590
Program: /bin/cp
/bin/cp
a.txt
b.txt
Process terminated with status = 0

Пример 2:

./a.out /bin/ls
I'm the son woth PID= 3021
Program: /bin/ls
/bin/ls
a.c a.out
Process terminated with status = 0

Я добавил #include <unistd.h>, потому что мне это было нужно.

Я рекомендую вам сделать больше printf, чтобы понять и устранить неполадки.

Изменить Как сказал @jonathan-leffler, вы можете использовать execvp, чтобы иметь возможность запускать программы, используя PATH:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char **argv)
{
int status;
pid_t pid;
if((pid = fork())>0)
{
    ///Father process
    wait(&status);
    printf("Process terminated with status = %d\n",status);
}
else
{
    ///son process
    int i;
    char program[100];

    printf("I'm the son woth PID= %d\n",getpid());
    strcpy(program,argv[1]);

    printf("Program: %s\n", program);

    execvp(program, argv+1);
    exit(0);
}


return 0;
}

Пример:

▶ ./a.out ls
I'm the son woth PID= 5056
Program: ls
a.c a.out
Process terminated with status = 0
person Robert    schedule 07.05.2017