Helpers - компьютеры, интернет, программирование

execvp() создает небольшую программу на основе оболочки unix

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

Вот мой код:

int main(int argc, char *argv[]){
    pid_t cpid;
    char *shell[5];
    shell[0]=argv[1];
    shell[1]=argv[2];
    shell[2]=argv[3];
    shell[4]=NULL;

    if(argc!=4){
        printf("Program expects 4 arguments");
    } else{
        cpid=fork();
        if(cpid==0){
            execvp("/bin/sh",shell);
        }//end child process
        if (cpid != wait(NULL)) {                          /* parent code */
            printf("Parent failed to wait");
            return 1;
        }
    }//end else

}//end main

Однако, когда я даю команду

$ ./shell simple sml_prog1 A

он говорит sml_prog1 not found примерно 15 или 20 раз.

Предполагается, что оболочка запускает simple, который принимает sml_prog1 A в качестве аргументов.

Программа работает сама по себе с теми же аргументами.

Я изменил разрешения sml_prog1 на read/write/executable. Более того, sml_prog1 — это .txt файл, содержащий данные, которые программа simple использует

08.10.2015

  • код проверяет argc слишком поздно. поэтому чтение argv[x] может обращаться к «неизвестному», это поведение undefined и может привести к событию сбоя сегмента. Предложите: 1) сначала проверьте количество argc. 2) сделать shell[] размером argc+1, чтобы было место для завершающей записи NULL. 3) используйте: execvp(shell[0], shell); 08.10.2015

Ответы:


1

Основная проблема заключается в том, как вы звоните execvp. Вы не хотите выполнять /bin/sh, вы хотите выполнять программу, которую передал пользователь, то есть argv[1].

Измените вызов на этот и добавьте следующую проверку ошибок:

execvp(shell[0],shell);
perror("exec failed");    // This line never gets called unless execvp fails
exit(1);                  // end the child process

Кроме того, вы никогда не устанавливаете shell[3] на что-либо. Вероятно, вы захотите установить это значение в NULL вместо shell[4]:

shell[0]=argv[1];
shell[1]=argv[2];
shell[2]=argv[3];
shell[3]=NULL;
08.10.2015
  • Это решило проблему «sml_prog1 not found», но теперь она не выполняется и ничего не делает. Он просто продолжает принимать команды после ввода ./shell simple sml_prog1 A 08.10.2015
  • Это дает мне информацию о пользователях и их разрешениях 08.10.2015
  • Должен ли я включить какой-либо конкретный заголовочный файл для exit(1); работать? Там написано incompatible implicit declaration of built-in function ‘exit’ В данный момент я включаю только stdio unistd.h и sys/types.h 08.10.2015
  • @AliRehman Для exit() вам нужно stdlib.h. Дает ли приведенная выше команда список каталогов? Как выглядит результат? 08.10.2015
  • что-то вроде этого total 40 drwxrwxrwt 2 lightdm lightdm 4096 Oct 8 04:36 at-spi2 drwx------ 2 ali ali 4096 Oct 8 04:36 keyring-nPZgUz drwx------ 2 ali ali 4096 Oct 8 04:36 pulse-1umMHHnYzsw3 drwx------ 2 lightdm lightdm 4096 Oct 8 04:37 pulse-2L9K88eMlGn7 drwx------ 2 root root 4096 Oct 8 04:35 pulse-PKdhtXMmr18n drwx------ 2 ali ali 4096 Oct 8 04:36 ssh-ZbTIeeCL2085 -rw-rw-r-- 1 lightdm lightdm 0 Oct 8 04:36 unity_support_test.0 drwx------ 2 ali ali 4096 Oct 8 04:36 vmware-ali drwxrwxrwt 2 root root 4096 Oct 8 04:35 VMwareDnD 08.10.2015
  • @AliRehman Это список каталогов, в частности вывод ls -l /tmp. Так что, похоже, это работает. Вызов вашей программы должен работать аналогичным образом. 08.10.2015
  • execvp() не работает, работает perror("exec failed"); 08.10.2015
  • @AliRehman Это все, что здесь сказано? Должно быть что-то вроде exec failed: (more descriptive message). 08.10.2015
  • Да, это все, что он говорит. Однако решение, опубликованное @old_mountain, работает. 08.10.2015

  • 2

    Самый простой пример использования execvp(), который я могу придумать, выглядит следующим образом:

    #include <stdio.h>
    #include <unistd.h>
    
    
    int main(int argc, char **argv)
    {
        ++argv;
        if (*argv)
            execvp(*argv, argv);
        return 0;
    }
    

    Скомпилируйте его с помощью:

    cc -Wextra -Wall какой-то.c -o какой-то

    И запустите его так:

    ./some ls -la
    

    Или чтобы более четко показать, что все аргументы передаются в execvp():

    ./some ls -la -R /etc
    

    Чтобы продемонстрировать его использование с вашим точным сценарием вызова оболочки, сравните вывод этих двух команд (имейте в виду, что использование /bin/sh напрямую, когда уже используется execvp()), довольно избыточно):

    ./some bash -c 'type history'
    
    ./some sh -c 'type history'
    
    08.10.2015

    3

    Если вам нужно выполнить вашу программу через /bin/sh, а не напрямую, вы должны сделать это по-другому.

    Вы должны передать программу как-то так:

    char * shell[4];
    shell[0] = "sh";
    shell[1] = "-c";
    shell[2] = "./simple sml_prog1 A";
    shell[3] = NULL;
    

    Видеть ? с опцией -c и полной программой

    Итак, что-то вроде этого должно сделать эту работу за вас:

    char * shell[4];
    shell[0] = "sh";
    shell[1] = "-c";
    char prog[100]; // be careful with this number
    snprintf (prog, 100, "./%s %s %s",argv[1], argv[2], argv[3]);
    shell[2] = prog;
    shell[3] = NULL;
    
    08.10.2015
    Новые материалы

    Интуитивное понимание тензоров в машинном обучении
    Тензор является важной концепцией во многих научных областях, таких как математика, физика, обработка сигналов и компьютерное зрение, и это лишь некоторые из них. В математике тензор — это..

    Использование машинного обучения для диагностики болезни Альцгеймера, часть 4
    Маркеры семантической согласованности для ранней диагностики болезни Альцгеймера (arXiv) Автор: Давиде Колла , Маттео Дельсанто , Марко Агосто , Бенедетто Витиелло , Даниэле Паоло Радичони..

    Почему объяснимость так важна прямо сейчас?
    По мере того, как системы искусственного интеллекта и инструменты на основе машинного обучения распространяются в нашей повседневной жизни, как практики, так и критики все чаще заявляют о..

    Анимированный математический анализ
    Использование Manim для создания математических анимированных визуализаций Визуализация данных помогает понять скрытые закономерности в данных, которые невозможно визуализировать..

    Создание простого слайдера изображений с помощью JavaScript
    Узнайте, как создать базовый слайдер изображений с помощью HTML, CSS и JavaScript. Введение В этом уроке мы создадим удобный слайдер изображений, используя JavaScript, HTML и CSS. Ползунок..

    Создание базы данных с помощью супергероя «Python»
    В этом посте мы узнаем, как создать «базу данных SQLite с помощью модуля python sqlite3, создав простую функцию входа и регистрации. Готовы ли вы к этому путешествию? Если да , давайте приступим..

    ИИ для чайников: руководство для начинающих по пониманию будущего технологий
    Вы чувствуете, что остались позади в мире ИИ? Не волнуйтесь, вы не одиноки! Со всей этой шумихой вокруг искусственного интеллекта может быть трудно понять, с чего начать. Но не позволяйте сленгу..