#include #include #include #include #include #include #include #include #include #include"include/redirection.h" pid_t backgroundPids[1024]; int backgroundCount = 0; void handleSIGINT(int sig) { const char *msg = "\n"; write(STDOUT_FILENO, msg, 1); } void handleSIGCHLD(int sig) { int saved_errno = errno; pid_t pid; while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) { for(int i = 0; i < 1024; i++) { if(backgroundPids[i] == pid) { backgroundPids[i] = 0; } } } errno = saved_errno; } int detectBackground(char **args) { for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "&") == 0) { args[i] = NULL; return 1; } } return 0; } void executePipeline(char **args, int background) { int num_cmds = 1; for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "|") == 0) num_cmds++; } char ***cmds = malloc(num_cmds * sizeof(char **)); int cmd_idx = 0; cmds[cmd_idx++] = args; for (int i = 0; args[i] != NULL; i++) { if (strcmp(args[i], "|") == 0) { args[i] = NULL; cmds[cmd_idx++] = args + i + 1; } } int (*pipes)[2] = malloc((num_cmds - 1) * sizeof(int[2])); for (int i = 0; i < num_cmds - 1; i++) { if (pipe(pipes[i]) < 0) { perror("pipe"); free(cmds); free(pipes); return; } } pid_t *pids = malloc(num_cmds * sizeof(pid_t)); for (int i = 0; i < num_cmds; i++) { pids[i] = fork(); if (pids[i] == 0) { signal(SIGINT, SIG_DFL); if (i > 0) { dup2(pipes[i - 1][0], STDIN_FILENO); } if (i < num_cmds - 1) { dup2(pipes[i][1], STDOUT_FILENO); } for (int j = 0; j < num_cmds - 1; j++) { close(pipes[j][0]); close(pipes[j][1]); } Redirection in, out; detectRedirections(cmds[i], &in, &out); // Standard shell behavior: only first cmd gets <, only last gets > if (i != 0) in.type = REDIRECT_NONE; if (i != num_cmds - 1) out.type = REDIRECT_NONE; if (applyRedirections(in, out) < 0) exit(1); if (cmds[i][0] == NULL) exit(0); execvp(cmds[i][0], cmds[i]); perror("tinysh"); exit(1); } else if (pids[i] < 0) { perror("fork"); } } for (int i = 0; i < num_cmds - 1; i++) { close(pipes[i][0]); close(pipes[i][1]); } if (!background) { for (int i = 0; i < num_cmds; i++) { if (pids[i] > 0) waitpid(pids[i], NULL, 0); } } else { for (int i = 0; i < num_cmds; i++) { if (pids[i] > 0) { if (backgroundCount < 1024) { backgroundPids[backgroundCount++] = pids[i]; } } } printf("{background} pipeline started\n"); } free(cmds); free(pipes); free(pids); } 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(256 * sizeof(char *)); if (!args) { perror("malloc"); return NULL; } int i = 0; char *token = strtok(line, " \t\n"); while(token != NULL && i < 255) { 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); executePipeline(parsed, background); free(parsed); free(line); } }