232 lines
5.9 KiB
C
232 lines
5.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/ioctl.h>
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "para.h"
|
|
#include "builtin.h"
|
|
|
|
|
|
static bool verbose = false;
|
|
|
|
int parse_cmd(char *cmd, char *argv[]) {
|
|
int argc = 0;
|
|
char *ptr = cmd;
|
|
char *token_start;
|
|
char quote_char = 0;
|
|
|
|
while (*ptr) {
|
|
while (*ptr == ' ' && quote_char == 0) ptr++;
|
|
if (*ptr == '\0') break;
|
|
|
|
token_start = ptr;
|
|
char *write_ptr = ptr;
|
|
|
|
while (*ptr) {
|
|
if (quote_char == 0 && *ptr == ' ') {
|
|
ptr++;
|
|
break;
|
|
}
|
|
|
|
if (*ptr == '"' || *ptr == '\'') {
|
|
if (quote_char == *ptr) quote_char = 0;
|
|
else if (quote_char == 0) quote_char = *ptr;
|
|
else *write_ptr++ = *ptr;
|
|
}
|
|
else {
|
|
*write_ptr++ = *ptr;
|
|
}
|
|
|
|
ptr++;
|
|
}
|
|
|
|
*write_ptr = '\0';
|
|
argv[argc++] = token_start;
|
|
|
|
if (argc >= MAX_ARGS - 1) break;
|
|
}
|
|
|
|
argv[argc] = NULL;
|
|
return argc;
|
|
}
|
|
|
|
// 반환값: 1(처리함), 0(파이프 없음)
|
|
int handle_pipe(char *argv[]) {
|
|
int pipe_idx = -1;
|
|
|
|
for (int i = 0; argv[i] != NULL; i++) {
|
|
if (strcmp(argv[i], "|") == 0) {
|
|
pipe_idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pipe_idx == -1) return 0;
|
|
|
|
argv[pipe_idx] = NULL;
|
|
char **left_cmd = &argv[0];
|
|
char **right_cmd = &argv[pipe_idx + 1];
|
|
|
|
if (right_cmd[0] == NULL) {
|
|
printf("gmsh: syntax error near unexpected token `|'\n");
|
|
return 1;
|
|
}
|
|
|
|
int fds[2];
|
|
if (pipe(fds) == -1) {
|
|
perror("pipe");
|
|
return 1;
|
|
}
|
|
|
|
pid_t pid1 = fork();
|
|
if (pid1 == 0) {
|
|
close(fds[0]);
|
|
dup2(fds[1], STDOUT_FILENO);
|
|
close(fds[1]);
|
|
|
|
handle_redirection((const char**) left_cmd);
|
|
execvp(left_cmd[0], left_cmd);
|
|
perror("execvp left");
|
|
exit(1);
|
|
}
|
|
|
|
pid_t pid2 = fork();
|
|
if (pid2 == 0) {
|
|
close(fds[1]);
|
|
dup2(fds[0], STDIN_FILENO);
|
|
close(fds[0]);
|
|
|
|
if (handle_pipe(right_cmd) == 1) {
|
|
exit(0);
|
|
}
|
|
else {
|
|
handle_redirection((const char**) right_cmd);
|
|
execvp(right_cmd[0], right_cmd);
|
|
perror("execvp right");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
close(fds[0]);
|
|
close(fds[1]);
|
|
|
|
waitpid(pid1, NULL, 0);
|
|
waitpid(pid2, NULL, 0);
|
|
|
|
return 1; // 처리 완료
|
|
}
|
|
|
|
void run_shell() {
|
|
char cmd_buf[MAX_CMD_LEN];
|
|
char *args[MAX_ARGS];
|
|
char cwd[1024];
|
|
|
|
while (1) {
|
|
if (getcwd(cwd, sizeof(cwd))) printf("\033[1;32mgmsh\033[0m:%s$ ", cwd);
|
|
else printf("gmsh:$ ");
|
|
fflush(stdout);
|
|
|
|
if (!fgets(cmd_buf, sizeof(cmd_buf), stdin)) break;
|
|
cmd_buf[strcspn(cmd_buf, "\n")] = 0;
|
|
if (strlen(cmd_buf) == 0) continue;
|
|
|
|
// int argc = 0;
|
|
// args[argc] = strtok(cmd_buf, " ");
|
|
// while (args[argc] != NULL && argc < MAX_ARGS - 1) args[++argc] = strtok(NULL, " ");
|
|
|
|
int argc = parse_cmd(cmd_buf, args);
|
|
|
|
if (argc == 0) continue;
|
|
|
|
if (handle_pipe(args)) {
|
|
continue;
|
|
}
|
|
|
|
if (verbose) {
|
|
printf("[debug] argc: %d\n", argc);
|
|
for(int i=0; i<argc; i++) printf("[debug] argv[%d]: '%s'\n", i, args[i]);
|
|
}
|
|
|
|
if (strcmp(args[0], "exit") == 0) exit(0);
|
|
else if (strcmp(args[0], "ls") == 0) cmd_ls(args[1]);
|
|
else if (strcmp(args[0], "cd") == 0) cmd_cd(args[1]);
|
|
else if (strcmp(args[0], "pwd") == 0) cmd_pwd();
|
|
// else if (strcmp(args[0], "cat") == 0) cmd_cat(argc, (const char**) args);
|
|
// else if (strcmp(args[0], "proc") == 0) cmd_proc();
|
|
// else if (strcmp(args[0], "echo") == 0) cmd_echo(argc, (const char**) args);
|
|
|
|
else if (strcmp(args[0], "size") == 0) cmd_size();
|
|
else if (strcmp(args[0], "resize") == 0){
|
|
if(argc != 3){
|
|
printf("Usage: resize <rows> <cols>\n");
|
|
}
|
|
else cmd_resize(args[1], args[2]);
|
|
}
|
|
|
|
else if (strcmp(args[0], "poweroff") == 0) cmd_poweroff();
|
|
else if (strcmp(args[0], "reboot") == 0) cmd_reboot();
|
|
else if (strcmp(args[0], "help") == 0) cmd_help();
|
|
else {
|
|
pid_t pid = fork();
|
|
|
|
// if (pid == 0) {
|
|
// execvp(args[0], args);
|
|
// printf("%s: command not found\n", args[0]);
|
|
// exit(1);
|
|
// } else wait(NULL);
|
|
|
|
if (pid == 0) {
|
|
handle_redirection((const char**) args);
|
|
execvp(args[0], args);
|
|
|
|
fprintf(stderr, "%s: command not found\n", args[0]);
|
|
exit(127);
|
|
} else if (pid > 0) {
|
|
int status;
|
|
|
|
if (verbose) {
|
|
printf("[debug] Spawned child PID: %d\n", pid);
|
|
}
|
|
|
|
waitpid(pid, &status, 0);
|
|
|
|
if (verbose) {
|
|
if (WIFEXITED(status)) {
|
|
printf("[debug] Process %d exited with code %d\n", pid, WEXITSTATUS(status));
|
|
} else if (WIFSIGNALED(status)) {
|
|
printf("[debug] Process %d killed by signal %d\n", pid, WTERMSIG(status));
|
|
}
|
|
}
|
|
} else {
|
|
perror("fork");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
printf("GMSH (GMS Minimal SHell) v1.0 initialized.\n");
|
|
|
|
int opt;
|
|
while ((opt = getopt(argc, argv, "v")) != -1) {
|
|
switch (opt) {
|
|
case 'v':
|
|
verbose = 1;
|
|
printf("[gmsh] Verbose mode enabled.\n");
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Usage: %s [-v]\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
run_shell();
|
|
return 0;
|
|
}
|