Shell 核心循環:提示 → 讀取 → 解析 → 執行 → 等待。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_LINE 1024
#define MAX_ARGS 64
int main() {
char line[MAX_LINE];
char *args[MAX_ARGS];
while (1) {
printf("|-> "); // 提示符
if (!fgets(line, MAX_LINE, stdin)) break;
line[strcspn(line, "\n")] = 0; // 去換行
// 簡易解析:按空格分割
int argc = 0;
char *tok = strtok(line, " ");
while (tok && argc < MAX_ARGS-1) {
args[argc++] = tok;
tok = strtok(NULL, " ");
}
args[argc] = NULL;
// 內建命令
if (argc == 0) continue;
if (strcmp(args[0], "exit") == 0) break;
if (strcmp(args[0], "cd") == 0) { chdir(args[1] ? args[1] : getenv("HOME")); continue; }
// 外部命令:fork + exec
pid_t pid = fork();
if (pid == 0) { execvp(args[0], args); perror("exec"); _exit(1); }
else if (pid > 0) waitpid(pid, NULL, 0);
else perror("fork");
}
return 0;
}
fgets 讀整行,支援含空格參數(需更完善的解析器處理引號/轉義)。fork() 複製進程,子進程 execvp() 替換映像執行命令,父進程 waitpid() 回收避免殭屍。cd、exit、pwd)必須在 Shell 進程內執行,不能 fork。|:pipe() + 多 fork 重定向 stdin/stdout。> <:dup2() 替換文件描述符。&:父進程不 wait,設置 SIGCHLD 處理器。readline 庫或自行維護歷史陣列。|-> ls
main.c shell.c test.txt
|-> cd ..
|-> pwd
/home/user
|-> exit