Небольшая учебная командная оболочка (shell) на C: читает команду из stdin, парсит её на слова и пайпы, поддерживает конвейеры (|), перенаправления (< и >), фоновый запуск (&) и встроенную команду cd.
Проект подходит как компактный пример: парсинг ввода + fork/exec + pipe + dup2 + wait.
- Запуск внешних программ через
execvp() - Конвейеры (pipes):
cmd1 | cmd2 | cmd3 - Перенаправление ввода/вывода:
cmd > file— stdout в файл (создаётся/перезаписывается)cmd < file— stdin из файла
- Фоновый режим:
cmd &(shell не ждёт завершения) - Поддержка кавычек
"для слов с пробелами:
echo "hello world" - Встроенная команда:
cd [path](если без аргумента или~— переход в$HOME)
- Выход:
exit/quit
gcc -Wall -Wextra -O2 -o minishell main.c./minishellShell работает в бесконечном цикле: читает одну строку → выполняет → ждёт следующую.
ls -la
ls -la | grep ".c" | wc -l
echo hello > out.txt
wc -l < out.txt
sleep 10 &
cd /tmp
cd ~
cd
ps aux | grep ssh
echo "some text" > file.txt
cat < file.txt
sleep 5 &
echo "я не жду завершения sleep"
Ввод разбирается на структуру вида:
-
char ***cmds— список команд в конвейереcmds[i]—char **argvдляexecvpcmds[i][j]— отдельное слово/аргумент
Ключевые функции:
get_word()— читает одно слово из stdin (учитывает"; отдельные токены<,>,|,&)get_list()— собирает список слов (argv) до\nили|get_cmds()— собирает массив команд до конца строки; возвращаетn— сколько команд в pipeline
-
do_cmds(cmds, n):-
если команда
cd— выполняется без fork (в текущем процессе), т.к.chdir()должен менять директорию shell’а -
если
n == 1— одинfork()иexecvp() -
если
n > 1— создаются пайпыpipefd, для каждой команды делаетсяfork(), затем:dup2()подменяет stdin/stdout нужными концами pipe- вызывается
execvp()
-
Функция redir(cmd) ищет токены < или >:
>→open(..., O_WRONLY|O_CREAT|O_TRUNC, 0644)иdup2(fd, 1)<→open(..., O_RDONLY)иdup2(fd, 0)
После этого токены перенаправления удаляются из argv (через del_w()), чтобы execvp() получил чистые аргументы.
-
В одной команде корректно обрабатывается по одному перенаправлению за вызов
redir(). В коде оно вызывается дважды, чтобы попытаться обработать и<, и>. -
Нет поддержки:
>>(append)2>(stderr redirection);,&&,||, скобок, переменных окружения, подстановок и т.п.
-
Промпта (
$) нет — ввод просто читается из stdin. -
Парсер довольно “низкоуровневый”: использует
read()посимвольно.
Динамически выделенные структуры освобождаются через:
free_3_arr(cmds)— освобождаетchar***(команды + аргументы + строки)