Внутренние команды Bash из программы на C (Ubuntu v / s MacOS) - PullRequest
0 голосов
/ 20 сентября 2018

Следующий код успешно перечисляет содержимое текущего каталога в Ubuntu Bash и MacOS Bash.

int main() {
    char* args[3];
    args[0] = "ls";
    args[1] = NULL;
    args[2] = NULL;
    execvp(args[0], args);
    return 0;
}

Следующий код ничего не печатает в Ubuntu Bash, но печатает ls is /bin/ls в MacOS Bash.

int main() {
    //pid_t pid = fork();
    char * args[3];
    args[0] = "type";
    args[1] = "ls";
    args[2] = NULL;
    //if (!pid) 
    execvp(args[0], args);
    return 0;
}

Когда я запускаю type непосредственно в Ubuntu bash, он печатает ls is hashed (/bin/ls).

Разница в том, что type является внутренней командой bash, а ls - нет.Но почему bash в Ubuntu ведет себя иначе, чем в MacOS?

Ubuntu bash version: GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

MacOS bash version: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)

Судя по номерам версий(что может быть неправильно), старая версия печатает вывод правильно, а новая - нет?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

В вашем вопросе нет bash.То есть, ничего при выполнении этой программы не имеет ничего общего с bash.

execvp, по сути, системный вызов, который имеет эффект (если он успешен, который не должен бытькак само собой разумеющееся) замены текущей среды выполнения новым образом процесса, загрузки исполняемого файла из файла, указанного в качестве первого аргумента.ОС не требуется или не требуется помощь от bash для запуска программы.

Если вы хотите использовать bash, вам нужно попросить ОС запустить bash.Это может быть полезно, если вы хотите запустить встроенную команду bash:

char* args[] = { "bash", "-c", "type ls", 0};
execvp(args[0], args);

Но так как вы не вызываете bash, вы полагаетесь на существование внешней утилиты команды с именем type.И это существование или нет той полезности, которая приводит к другому поведению.Это не имеет ничего общего с bash или любой другой оболочкой.

0 голосов
/ 20 сентября 2018

Вы забыли проверить на отказ execvp.Попробуйте хотя бы кодировать:

if (execvp(args[0], args)) {
   fprintf(stderr, "execvp %s failed: %s\n",
           args[0], strerror(errno));
   exit(EXIT_FAILURE);
} 

Возможно, на вашем Ubuntu execvp из type не удается.Возможно, у MacOSX есть /usr/bin/type или что-то еще найденное в вашем PATH.

Внимательно прочитайте документацию execvp (3) на обеих системах.Также рассмотрите возможность использования strace (1) в Linux, чтобы понять, что происходит (вы можете найти похожую вещь для MacOSX).

Обратите внимание, что execvp работаеттолько для исполняемых файлов (не для встроенных команд оболочки)

...