Репутація українського ІТ. Пройти опитування Асоціації IT Ukraine
×Закрыть

Хочу написать простую командную строку на С

Здравствуйте, хочу написать простую командную строку на С.
Но не знаю с чего начать.
Может кто знает литературу или статьи.

Команды или функционал который бы хотел реализовать:
-cd
-exit
-help
-path
-pwd
-cp
-mkdir
-cat
-echo
-ls
-флаги(-v и т.д)
-изменения цвета
-история команд
-логин пользователя
-ошибки ввода

LinkedIn

Лучшие комментарии пропустить

Маєш на увазі шелл по типу баша?
Я сподіваюсь hello world ти вже можеш написати.
Парсити аргументи на C по православному — це getopt: man7.org/...​-pages/man3/getopt.3.html (на stack overflow пошукай приклади використання)

Парсити user input треба через readline: tiswww.case.edu/...​/chet/readline/rltop.html (заодно там тобі і tab-completion)

cd — linux.die.net/man/2/chdir
exit — повертаєш EXIT_CODE з main() або exit(EXIT_CODE) (linux.die.net/man/2/exit)
help — пишеш вручну
path — я хз що це
pwd — man 2 pwd
cp — можна вручну — відкрити обидва файли, читати з одного писати в інший, або швидший варіант для linux — це sendfile
і т.д.

колір — просто пишеш ansi-послідовність байт в stdout/stderr і все що після цієї послідовності буде кольоровим
про логін я не дуже зрозумів куди він має логінитись
історія ніби є в libreadline вже (разом з навігацією стрілками вгору-вниз)
обробка помилок теж в libreadline

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Я джва года жду такую командную строку.

int main(int args, char *argv[]) { /* do big switch */ return 0; }

Начни с гугла:) letmegooglethat.com/...​q=write my own shell in c
А по поводу примеров реализаций, вот: github.com/...​wn-x#build-your-own-shell

Є багато прикладів початкових скелетів.
Наприклад, ось такий: www.shsu.edu/...​2000/cs431/shell-lab.html

А там вже м’ясо напишете.

при чем здесь это? подумал юзер, но кама-сутру все таки купил

Якщо я вірно пам’ятаю, то в даній монографії автори приводили приклад командного процесора.
muff.kiev.ua/...​ix-programmnoe-okruzhenie

Та й без неї гугляться мільйони статей на цю тему.

Ну берешь args[] из main и погнал свитчкейсами и ифами парсить)

Зачем тебе это надо? От этого надо плясать

Но не знаю с чего начать.

www.amazon.com/...​n-Kernighan/dp/0131103628

хочу написать простую командную строку на С.

Непогано було б розібратися з лексером та парсером.
В «Драконі» класно описано
www.amazon.com/...​s-Tools-2nd/dp/0321486811

...да-а-а, ребята, вы сделали мой день))

предложи свой вариант посмеяться

Маєш на увазі шелл по типу баша?
Я сподіваюсь hello world ти вже можеш написати.
Парсити аргументи на C по православному — це getopt: man7.org/...​-pages/man3/getopt.3.html (на stack overflow пошукай приклади використання)

Парсити user input треба через readline: tiswww.case.edu/...​/chet/readline/rltop.html (заодно там тобі і tab-completion)

cd — linux.die.net/man/2/chdir
exit — повертаєш EXIT_CODE з main() або exit(EXIT_CODE) (linux.die.net/man/2/exit)
help — пишеш вручну
path — я хз що це
pwd — man 2 pwd
cp — можна вручну — відкрити обидва файли, читати з одного писати в інший, або швидший варіант для linux — це sendfile
і т.д.

колір — просто пишеш ansi-послідовність байт в stdout/stderr і все що після цієї послідовності буде кольоровим
про логін я не дуже зрозумів куди він має логінитись
історія ніби є в libreadline вже (разом з навігацією стрілками вгору-вниз)
обробка помилок теж в libreadline

Щось мені здається, що readline занадто складний, щоб потренуватись код писати. Велосипед може буть цікавіше.

Зачем ты хочешь ее написать?

тебе надо парсить строковую команду.
1) разбиваешь на слова через strtok
2) делаешь таблицу (массив структур) {команда, указатель на обработчик}, где «команда» — одно из перечисленных тобою ключевых слов; обработчик — функция, принимающая массив строковых параметров (остальные слова из распаршенной команды)
3) собственно, пишешь обработчики, используя API операционной системы
4) отлаживаешь это все
5) сомнительный профит
Если что — пиши в личку или скайп denys.poltorak

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

Так тут же не командную строку с аргументами парсить, а сидеть в цикле, ловить команду через stdin, и ее уже разбивать. Там если не через strtok, то надо что-то сложное подключать.

Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.

Можно посмотреть исходники Busybox

Зачем? Достаточно посмотреть man.

Как пример упрощённой реализации того, что хочет топикстартер

Не было у них такой задумки. Их задумка: предоставить набор линуховых стандартных команд, чтобы они на любом говне могли работать и не тормозить. А это не про простоту кода и его написания.

Не «линуховых», а юниксовых, не на говне, а системах с ограниченными ресурсами, насчёт не торможения такого нигде не заявлялось, функциональность бузибокса сильно урезанная по сравнению с полновесными утилитами, а значит и объём кода меньше, соответственно его проще воспринимать.

Да хоть говно шоколадной конфетой назови, говном оно таки останется.

а значит и объём кода меньше, соответственно его проще воспринимать.

Нет, это одна из массово ретраслируемых сказок.

Мне неинтересно дискутировать с копрофилами

не на говне, а системах с ограниченными ресурсами

В зеркало посмотри.

Виктор, я отслеживаю твое состояние последние несколько лет. Происходит заметная регрессия, а сегодня у тебя какой-то срыв просто. Поспокойнее, оно того не стоит. Не порть нервы. Ты еще молодой. Поживи нормально с удовольствием.

а значит и объём кода меньше, соответственно его проще воспринимать.

Тут как повезет)
en.wikipedia.org/...​d_C_Code_Contest#Examples

И вот тебе классиика

void send (int *to, const int *from, int count)
{
  int n = (count + 7) / 8;
  switch (count % 8)
  {
    case 0: do { *to++ = *from++;
    case 7:      *to++ = *from++;
    case 6:      *to++ = *from++;
    case 5:      *to++ = *from++;
    case 4:      *to++ = *from++;
    case 3:      *to++ = *from++;
    case 2:      *to++ = *from++;
    case 1:      *to++ = *from++;
            } while (--n > 0);
  }
}

Это реально юзаемый почти всеми, кто юзает линух код. Уже не помню точно откуда он.
Код быстрый, правильный, лаконичный, но хер так ты его сходу поймешь.

Это Duff’s device en.wikipedia.org/wiki/Duff’s_device
* надо бы мне обновлять страницу прежде чем отвечать)

When numerous instances of Duff’s device were removed from the XFree86 Server in version 4.0, there was an improvement in performance and a noticeable reduction in size of the executable.[7] lkml.indiana.edu/...​x/kernel/0008.2/0171.html

но согласен, кого волнует практичность, ведь художник творит!

Всему свое время. Время оптимизировать руками и время доверить компилятору.

все выглядит очень просто

Эм... Это не из тех задач, которым посвящена литература. Просто садись и делай.

Но не знаю с чего начать.

Скорее всего он и С нее знает и даже питона с жабаскриптом и бэйсиком.

Ну тогда совет — не начинать с С)

ну С проще Питона, только писать не так удобно

Проще, но писать больше надо. Но у ТС, судя по тому, что он написал, вообще 0 в языках программирования.

Тогда другой совет — начать с Хелоу Ворлда. Потом Фузз-Бизз и т.д. и тп. Так и до командной строки дойдёт.

Вот это правильный совет ТС, присоединяюсь и поддерживаю.

ну С проще Питона, только писать не так удобно

П****а проще х**, только писать не так удобно

Cи знаю на уровне первого семестра программирования, задания на Операционные системы.

Некоторая часть готова кода, но не всё, да и хочется написать нормальное что-то. А не говно которое у меня.

Нормальное — это соответствующее ТЗ. У тебе его нет, так что не напишешь, всё будет нормально.

Проблема в том что нам даже не сказали что и как делать. Мы учили одно(как работает Линукс и Виндоус), как компилируются программы, гит, семафоры и мютекс в baci.
А тут сказали что нужно сделать свой микрошел.
Как и ТЗ, к сожалению не дали.

Какой микрошел? Какие мьютексы? Тут консольное приложение на 2 часа работы и строк на 200 максимум.

В Main метод строковый массив args заходит — это и есть твои параметры. Тебе просто нужно их распарсить и прикрутить к каждому соответствующий кусочек кода.

Какой массив args?
шелл висит в вечном цикле и интерактивно обрабатывает команды от пользователя

Так ему в каком виде командную строку надо, консольки или шела? Сомневаюсь, что вот так сходу задали второе.

А какая между ними разница?
Нужно что-то, во что можно ввести cd и поменять текущую директорию, потом ввести cp и скопировать файл.

Разница есть, но если достаточно консольки — то есму всего лишь нужно распарсить argv из int main(int argc, char **argv);

Ты получаешь высшее образования и теоретически выйдешь хотя бы инженером. Так вот тебе разумно научиться самому формулировать ТЗ.
Ты тут до сих пор не попытался его сформулировать что ты таки хочешь сделать.

Нормальным было бы решение через паттерн «Команда». Но у тебя ничего не выйдет, потому что С)

Зачем оно здесь?
Undo не нужен
Несколько команд одновременно ввести нельзя

Можно сделать красивый котекстуальный биндинг по названию команды. Ну и всякие штуки типа истории команд, которую хотел автор.

историю можно сделать односвязным списком строк
KISS

Да можно вообще всё это одним свитчем написать. Но автор же учится.

Ему для начала начать учиться формулировать свои мысли.

Если включить телепалку, то и ежу понятно, что ему нужно, но нам всем будет полезно, если он таки закончит ВУЗ инженером, а не Васей Июнем.

С ТЗ сложно так как сказали написать микрошел и дали только список что должен делать. Всё.

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

Толком не сказали как это сделать. А сказали сделать много. Например сейчас я не знаю как сделать адрес каталога в которым я сейчас нахожусь и как принимать команды к программам которые есть в каталоге и запускать их(из помощи к заданию — " fork() + exec*()")

принимаешь все строкой из stdin (fread) и парсишь на слова (strtok)
адрес каталога хранишь в строке (const char*) или строчном буфере (char[257])
запускать, да, (fork + exec). По ним гугл знает 100500 обучалок.

Подписаться на комментарии