#include #include #include #include #include #include #include #include #include"include/redirection.h" pid_t backgroundPids[64]; int backgroundCount = 0; void handleSIGINT(int sig) { printf("\n"); } void handleSIGCHLD(int sig) { int pid = waitpid(-1, NULL, WNOHANG); for(int i = 0; i < backgroundCount; i++) { if(backgroundPids[i] == pid) { printf("\n[done] %d\n", pid); backgroundPids[i] = 0; // clear it } } } int detectBackground(char **args) { for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "&") == 0) { args[i] = NULL; return 1; } } return 0; } int seperatePipe(char **args) { for(int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "|") == 0) return i; } return -1; } void executePipe(char **args, int pipeIndex) { args[pipeIndex] = NULL; char **cmd1 = args; char **cmd2 = args + pipeIndex + 1; int fd[2]; pipe(fd); pid_t pid1 = fork(); if (pid1 == 0) { dup2(fd[1], STDOUT_FILENO); close(fd[0]); close(fd[1]); signal(SIGINT, SIG_DFL); execvp(cmd1[0], cmd1); perror("tinysh"); exit(1); } pid_t pid2 = fork(); if (pid2 == 0) { dup2(fd[0], STDIN_FILENO); close(fd[0]); close(fd[1]); signal(SIGINT, SIG_DFL); execvp(cmd2[0], cmd2); perror("tinysh"); exit(1); } close(fd[0]); close(fd[1]); if (pid1 > 0) wait(NULL); if(pid2 > 0) wait(NULL); } int handleBuiltins(char **args) { if(strcmp(args[0], "cd") == 0) { chdir(args[1] == NULL ? getenv("HOME") : args[1]); return 1; } else if(strcmp(args[0], "exit") == 0) { exit(0); } else { return 0;} } char **parse(char *line) { char **args= malloc(64 * sizeof(char *)); int i = 0; char *token = strtok(line, " \t\n"); while(token !=NULL) { args[i] = token; i++; token = strtok(NULL, " \t\n"); } args[i] = NULL; return args; } int main() { signal(SIGINT, handleSIGINT); signal(SIGCHLD, handleSIGCHLD); while(1) { char *user = getenv("USER"); char dir[1024]; getcwd(dir, sizeof(dir)); char host[1024]; gethostname(host, sizeof(host)); char prompt[2051]; char *home = getenv("HOME"); if(strncmp(dir, home, strlen(home)) == 0) { snprintf(prompt, sizeof(prompt), "%s@%s ~%s$ ", user, host, dir + strlen(home)); } else { snprintf(prompt, sizeof(prompt), "%s@%s %s$ ", user, host, dir); } char *line = readline(prompt); if(line == NULL) return 0; if(line && *line) add_history(line); char **parsed = parse(line); if(parsed[0] == NULL) { free(parsed); free(line); continue; } if(handleBuiltins(parsed)) { free(line); free(parsed); continue; } int background = detectBackground(parsed); int pipeIndex = seperatePipe(parsed); if (pipeIndex != -1) { executePipe(parsed, pipeIndex); free(line); free(parsed); continue; } char *filename; int redirectionType = detectRedirect(parsed, &filename); if (redirectionType) { executeRedirect(parsed, redirectionType, filename); free(parsed); free(line); continue; } pid_t pid = fork(); if(pid == 0) { signal(SIGINT, SIG_DFL); if(execvp(parsed[0], parsed) == -1 ) { perror("tinysh"); exit(1); } } else if(pid > 0) { if(background) { printf("{background} %d \n", pid); backgroundPids[backgroundCount++] = pid; } else wait(NULL); } free(parsed); free(line); } }