Написание базовой оболочки - PullRequest
21 голосов
/ 25 января 2011

Для моего класса я должен создать базовую оболочку, похожую на bash, которая позволит пользователю вызывать такие команды, как ls, sleep и т. Д. Я ищу ресурсы о том, как это сделать: учебные пособия, текст справки, пример кода или даже просто общую информацию о том, как начать работу. У кого-нибудь есть ссылки или информация, чтобы помочь мне?

Ответы [ 7 ]

24 голосов
/ 25 января 2011

Руководство по glibc содержит полезную информацию о реализации управления заданиями в оболочке: http://www.gnu.org/software/libc/manual/html_node/Implementing-a-Shell.html#Implementing-a-Shell

10 голосов
/ 25 января 2011

Это действительно зависит от того, насколько простой должна быть ваша оболочка. Если вам не нужен контроль работы (т.е. фоновый режим) или конвейеры, тогда это очень просто. Вот пример:

#include <stdio.h>
#include <stdlib.h>

#define MAX_LENGTH 1024

int main(int argc, char *argv[]) {
  char line[MAX_LENGTH];

  while (1) {
    printf("$ ");
    if (!fgets(line, MAX_LENGTH, stdin)) break;
    system(line);
  }

  return 0;
}

Вы можете выйти из приведенного выше примера с помощью CTRL-D. Чтобы добавить встроенные команды, такие как exit или cd , вам необходимо токенизировать строку с помощью strtok () и посмотреть на первый токен. Вот более сложный пример с добавлением этих команд:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifdef _WIN32
#include <windows.h>
#define chdir _chdir

#else
#include <unistd.h>
#endif

#define MAX_LENGTH 1024
#define DELIMS " \t\r\n"

int main(int argc, char *argv[]) {
  char *cmd;
  char line[MAX_LENGTH];

  while (1) {
    printf("$ ");
    if (!fgets(line, MAX_LENGTH, stdin)) break;

    // Parse and execute command
    if ((cmd = strtok(line, DELIMS))) {
      // Clear errors
      errno = 0;

      if (strcmp(cmd, "cd") == 0) {
        char *arg = strtok(0, DELIMS);

        if (!arg) fprintf(stderr, "cd missing argument.\n");
        else chdir(arg);

      } else if (strcmp(cmd, "exit") == 0) {
        break;

      } else system(line);

      if (errno) perror("Command failed");
    }
  }

  return 0;
}

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

В качестве примечания, простой способ добавить историю команд и функции редактирования строк - использовать библиотеку GNU readline .

4 голосов
/ 25 января 2011

Я написал очень простую оболочку для проекта HelenOS .Он имеет следующие функции:

  • Редактирование строки / история
  • Buit в командах / загружаемых командах
  • Путь поиска для поиска внешних команд
  • ЧРЕЗВЫЧАЙНОбазовые сценарии
  • Приглушенные реализации большинства основных утилит ядра GNU (сделанные с нуля) в виде встроенных функций.

Большинство из них реализованы в очень простой многоразовой средепостроены вокруг функциональных указателей.Как минимум, вам понадобится встроенный 'exit' или 'quit', чтобы кто-то действительно мог выйти из оболочки, плюс 'cd' и 'pwd'.Встроенный 'export' / 'Declare' также имеет смысл.

Вы можете посмотреть лицензионный код (BSD) здесь .Или загрузите репозиторий, он находится в uspace / app / bdsh.Я, вероятно, могу выкопать последнюю рабочую версию Linux, до того момента, когда я ее портировал, если вам это нужно.Самым большим отличием является то, что версия HelenOS использует встроенный редактор строк, task_spawn () вместо execve () / posix_spawn () и т. Д. Остальное переносимо.Первоначально он был разработан, чтобы сделать тестирование функций простым и интерактивным.Я не реализовывал контроль работы, так как он не был нужен.Однако это может быть достигнуто тривиально.

Если вы хотите изучить «настоящую» оболочку, я настоятельно рекомендую взглянуть на dash, вам будет гораздо проще понять, чем погружаться прямо в кодbash.

Анекдотически, 'bdsh' означает ' мертвая оболочка мозга '.

2 голосов
/ 26 августа 2015

Если вы только начинаете, попробуйте http://stephen -brennan.com / 2015/01/16 / write-a-shell-in-c / и далее для подробных знаний http://www.gnu.org/software/libc/manual/html_node/Data-Structures.html#Data-Structures.

Кроме того, при обучении программированию оболочки с использованием C / C ++ возникает привычка обращаться к справочным страницам команд.

2 голосов
/ 25 января 2011

Вы можете посмотреть на BusyBox для некоторых очень маленьких реализаций оболочки.

0 голосов
/ 25 января 2011

Lowball ответ:

Если программа очень простая, то простые системные вызовы могут быть реализованы в виде сценария с помощью команды "system("putdesiredcommandhere");"

Когда вы устанавливаете "printf" в программе, вы делаете простой системный вызов с помощью stdio.h.

Ниже приведен небольшой пример кода.

#include <stdio.h>
#include <stdlib.h>
main ()
{
    system ("clear");
    system ("echo this is an example of a basic system call");
    printf ("just as you've always done.\n");

    return 0;
}

Используя этот метод, вы можете транскрибировать сценарии bash или csh в программу c. Это потребует использования системного вызова для каждой строки в скрипте.

0 голосов
/ 25 января 2011

Bash сам по себе предоставляет очень мало команд: cd, pushd, popd, процедуры обработки переменных (set и $x) и все элементы потока управления, такие как циклы и условные выражения.Почти все другие команды находятся в $PATH.

Если только состояния присваивания не заданы иначе, игнорируйте переменные и поток управления.Просто укажите REPL , который просматривает $PATH и выполняет все, что вводит пользователь (предположительно через posix_spawn()), и передает аргументы командной строки.

...