Execvp (argv [1], argv), не возвращая такой файл или каталог - PullRequest
0 голосов
/ 23 сентября 2019

Я пишу программу на C, которая принимает аргументы, char *argv[], чтобы решить, какую exec() запустить.У меня есть execlp(argv[1], argv[1], NULL), чтобы работать нормально.По какой-то причине execvp(argv[1], argv) не может найти команду 'ls' для запуска.Все, что мне действительно нужно, - это если у меня более одного аргумента, не считая вызова ./filexec, я могу запустить exec(), который примет char* argv[] БЕЗ ВКЛЮЧЕНИЯ ПУТИ ФАЙЛА.Я понимал, что у execvp() есть возможности сделать это.

Я запускаю это на сервере ssh linux.

int main(int argc, char *argv[])
{
pid_t pid;

        /* fork a child process */
        pid = fork();

        if (pid < 0) {/* error occured */
                fprintf(stderr, "Fork Failed");
                return 1;
        }
        else if (pid == 0) {/* child process */
                //pass the right thing to the right exec?

                if (argc == 1)
                {
                        printf("CHILD started. No arguments provided. Terminating child.\n");
                }

                if (argc == 2)
                {
                        printf("CHILD started. One argument provided.      Calling execlp().\n");
                        execlp(argv[1],argv[1],NULL);
                }

                if (argc  >= 3)
                {
                        printf("CHILD started. More than one argument provided. Calling execvp().\n");
                        argv[argc++] = NULL;
                        execvp(argv[1],argv);
                }



        }
        else {/* parent process */
                /* parent will wait for the child to complete */
                printf("PARENT started, now waiting for processID#%u\n", getpid());
                wait(NULL);
                printf("PARENT resumed. Child exit code of 0. Now terminating parent.\n");
        }

        return 0;
}

Я ожидаю, что ./a.out ls -l вызову execvp(), что:

total XXX
info ---------filename
info ---------filename

и т. Д.

1 Ответ

0 голосов
/ 23 сентября 2019

Помните, что argv[0] - это «имя программы», поэтому при вызове вашей программы это будет что-то вроде ./a.out.Тогда argv[1] - это первый аргумент вашей программы, то есть имя программы, которую вы хотите exec, а остальная часть argv - это остальные аргументы для передачи этой программе.

Таким образом, массив argv, который вы хотите передать программе, которую вы собираетесь выполнить, начинается с argv[1].Или, если быть более точным, указатель argv, который вы хотите указать для программы, которую вы собираетесь exec, равен argv + 1.

Вы, очевидно, поняли это для вызова execlp, поскольку выуказан argv[1] дважды, один раз в качестве имени программы для exec и один раз в качестве первого (и единственного) элемента в массиве argv для передачи этой программе.Вам просто нужно сделать то же самое для звонка на execvp;вместо execvp(argv[1], argv) вам понадобится execvp(argv[1], argv + 1).

Сообщение об ошибке, которое вы получаете от самой утилиты ls.Вы вызвали ls с execvp, передав ему весь массив argv.Другими словами, вы сказали ему, что его имя ./a.out (что, вероятно, немного сбивает с толку, так как большинство утилит используют имя программы, которое они дают для создания сообщений об ошибках), и вы предоставили его ls -lв качестве аргументов командной строки.По сути, это то же самое, что командная строка:

ls ls -l

, которая, если вы попробуете это, с большой вероятностью скажет вам, что файл ls не существует.(Если в текущем каталоге нет файла с именем ls.)

Кстати:

argv[argc++] = NULL;

совершенно не нужен.argv[argc] гарантированно будет равным NULL, и вам не нужна переменная argc (и если она у вас есть, вам, вероятно, понадобится, чтобы она была на один меньше, а не на один больше).

...