From cb6bdab388e6317562048751ea7b838549052996 Mon Sep 17 00:00:00 2001 From: 10195501441 <10195501441@stu.ecnu.edu.com> Date: Wed, 10 Mar 2021 17:40:03 +0800 Subject: [PATCH] initial commit --- yeeshell | Bin 0 -> 22976 bytes yeeshell.c | 415 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yeeshell.h | 59 +++++++++ 3 files changed, 474 insertions(+) create mode 100755 yeeshell create mode 100644 yeeshell.c create mode 100644 yeeshell.h diff --git a/yeeshell b/yeeshell new file mode 100755 index 0000000000000000000000000000000000000000..cbf51a210b9843cdf0364351dabf8232912b213e GIT binary patch literal 22976 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 literal 0 HcmV?d00001 diff --git a/yeeshell.c b/yeeshell.c new file mode 100644 index 0000000..4338544 --- /dev/null +++ b/yeeshell.c @@ -0,0 +1,415 @@ +#include +#include +#include +#include +#include +#include +#include +#include "yeeshell.h" + +/* record cmdline history */ +char **history = NULL; +int cmdline_amount = 0; + +/* next job ID to allocate */ +int nextjid = 1; + +/* environment variable */ +extern char **environ; + +/* The job list */ +struct job_t jobs[JOBS_MAX_QUANTITY]; + +int main() +{ + char *cmdline = NULL, *pwd = NULL; + char *args[ARGS_MAX_QUANTITY]; + int status = 1; + pwd = (char *)calloc(PATH_MAX, sizeof(char)); + if (!(history = (char **)calloc(CMDLINE_HISTORY_MAX_QUANTITY, CMDLINE_MAX_SIZE * sizeof(char *)))) + { + printf("yeeshell: allocation error!\n"); + exit(EXIT_FAILURE); + } + + /* execute the shell's read, parse and execution loop */ + do + { + if (!getcwd(pwd, PATH_MAX)) + { + printf("yeeshell: The current path cannot be obtained!\n"); + exit(0); + } + printf("[yeeshell %s]# ", pwd); + cmdline = readline(); + history[cmdline_amount++] = cmdline; + status = execute(cmdline, args); + free(cmdline); + } while (status); + free(history); + exit(EXIT_SUCCESS); +} + +char *readline() +{ + char *cmdline = NULL; + ssize_t bufsize = 0; + getline(&cmdline, &bufsize, stdin); + return cmdline; +} + +int parseline(char *cmdline, char **args) +{ + static char array[CMDLINE_MAX_SIZE]; /* holds local copy of command line */ + char *buf = array; /* ptr that traverses command line */ + char *delim; /* points to first space delimiter */ + int argc; /* number of args */ + int bg; /* background job? */ + + strcpy(buf, cmdline); + buf[strlen(buf) - 1] = ' '; /* replace trailing '\n' with space */ + while (*buf && (*buf == ' ')) /* ignore leading spaces */ + { + buf++; + } + + /* Build the argv list */ + argc = 0; + if (*buf == '\'') + { + buf++; + delim = strchr(buf, '\''); + } + else + { + delim = strchr(buf, ' '); + } + + while (delim) + { + args[argc++] = buf; + *delim = '\0'; + buf = delim + 1; + while (*buf && (*buf == ' ')) /* ignore spaces */ + { + buf++; + } + + if (*buf == '\'') + { + buf++; + delim = strchr(buf, '\''); + } + else + { + delim = strchr(buf, ' '); + } + } + args[argc] = NULL; + + if (argc == 0) /* ignore blank line */ + { + return 1; + } + + /* should the job run in the background? */ + if ((bg = (*args[argc - 1] == '&')) != 0) + { + args[--argc] = NULL; + } + return bg; +} + +int execute(char *cmdline, char **args) +{ + int bg = 0, i = 0; + pid_t pid; + sigset_t mask_all, mask_prev; + sigprocmask(SIG_BLOCK, NULL, &mask_all); + sigaddset(&mask_all, SIGCHLD); + bg = parseline(cmdline, args); + + if (args[0] == NULL) + { + return 1; + } + if (!built_in(args)) + { + /* Prevent child processes from ending between parent processes, that is, between addJob and deleteJob. */ + sigprocmask(SIG_BLOCK, &mask_all, &mask_prev); /* Shield SIGCHLD */ + + if ((pid = fork()) == 0) /* Child process */ + { + /* The child process inherits the parent's signal mask and will inherit it after exec, + so it needs to restore the signal mask before executing. */ + sigprocmask(SIG_SETMASK, &mask_prev, NULL); /* Child process, unblock SIGCHLD */ + + /* Set the pid of the current process to the group number of the process group it belongs to. */ + /* avoid being grouped with tsh */ + setpgid(0, 0); + if (execve(args[0], args, environ) <= 0) + { + printf("%s: Command not found\n", args[0]); + exit(0); + } + } + else + { + do + { + } while (!args[i++]); + + if (bg) /* bg task */ + { + addjob(jobs, pid, BG, cmdline); + } + else /* fg task */ + { + addjob(jobs, pid, FG, cmdline); + } + + sigprocmask(SIG_SETMASK, &mask_prev, NULL); + + if (bg) /* Don't wait for background tasks to finish */ + { + printf("[%d](%d)%s", pid2jid(pid), pid, cmdline); + } + else /* Wait for foreground tasks to finish */ + { + waitfg(pid); + } + } + } + return 1; +} + +int built_in(char **args) +{ + if (!strcmp(args[0], "exit")) + { + exit(0); + } + else if (!strcmp(args[0], "cd")) + { + return builtin_cd(args); + } + else if (!strcmp(args[0], "history")) + { + return builtin_history(args); + } + else if (!strcmp(args[0], "mytop")) + { + return builtin_mytop(args); + } + else if (!strcmp(args[0], "ls")) + { + return builtin_ls(args); + } + else if (!strcmp(args[0], "jobs")) + { + return builtin_jobs(args); + } + else + { + return -1; + } +} + +int builtin_cd(char **args) +{ + if (args[1] == NULL) + { + return 1; + } + else + { + if (chdir(args[1]) != 0) + { + perror("yeeshell"); + } + return 1; + } +} + +int builtin_ls(char **args) +{ + DIR *dp; + struct dirent *dirp; + char *path = NULL; + + if (args[1] == NULL) + { + path = (char *)calloc(PATH_MAX, sizeof(char)); + getcwd(path, PATH_MAX) + } + else if (args[1]) + + if ((dp = opendir(args[1])) == NULL) + { + perror("yeeshell"); + } + while ((dirp = readdir(dp)) != NULL) + { + printf("%s\n", dirp->d_name); + } + + closedir(dp); + return 0; +} + +int builtin_history(char **args) +{ + int n = atoi(args[1]); + printf("ID\tCommandline\n"); + for (int i = 0; i < ((n < cmdline_amount) ? n : cmdline_amount); i++) + { + printf("%d\t%s\n", i, history[i]); + } + return 1; +} + +int builtin_jobs(char **args) +{ + /* To prevent interruptions, block all signals. */ + sigset_t mask_all, mask_prev; + sigfillset(&mask_all); + sigprocmask(SIG_SETMASK, &mask_all, &mask_prev); + + for (int i = 0; i < JOBS_MAX_QUANTITY; i++) + { + if (jobs[i].pid != 0) + { + printf("[%d] (%d) ", jobs[i].jid, jobs[i].pid); + switch (jobs[i].state) + { + case BG: + printf("Running "); + break; + case FG: + printf("Foreground "); + break; + case ST: + printf("Stopped "); + break; + default: + printf("listjobs: Internal error: job[%d].state=%d ", + i, jobs[i].state); + } + printf("%s", jobs[i].cmdline); + } + } + + sigprocmask(SIG_SETMASK, &mask_prev, NULL); /* unclock */ + return 1; +} + +int builtin_mytop(char **args) +{ +} + +int do_bgfg(char **args) +{ +} + +/************************ + * manipulate job list + ************************/ +int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline) +{ + int i; + + if (pid < 1) + return 0; + + for (i = 0; i < JOBS_MAX_QUANTITY; i++) + { + if (jobs[i].pid == 0) + { + jobs[i].pid = pid; + jobs[i].state = state; + jobs[i].jid = nextjid++; + if (nextjid > JOBS_MAX_QUANTITY) + nextjid = 1; + strcpy(jobs[i].cmdline, cmdline); + + printf("Added job [%d] %d %s\n", jobs[i].jid, jobs[i].pid, jobs[i].cmdline); + + return 1; + } + } + printf("Tried to create too many jobs\n"); + return 0; +} + +int pid2jid(pid_t pid) +{ + int i; + + if (pid < 1) + return 0; + for (i = 0; i < JOBS_MAX_QUANTITY; i++) + if (jobs[i].pid == pid) + { + return jobs[i].jid; + } + return 0; +} + +void listjobs(struct job_t *jobs) +{ + for (int i = 0; i < JOBS_MAX_QUANTITY; i++) + { + if (jobs[i].pid != 0) + { + printf("[%d] (%d) ", jobs[i].jid, jobs[i].pid); + switch (jobs[i].state) + { + case BG: + printf("Running "); + break; + case FG: + printf("Foreground "); + break; + case ST: + printf("Stopped "); + break; + default: + printf("listjobs: Internal error: job[%d].state=%d ", i, jobs[i].state); + } + printf("%s", jobs[i].cmdline); + } + } +} + +void waitfg(pid_t pid) +{ + sigset_t m; + sigemptyset(&m); + while (pid == fgpid(jobs)) + { + /* Wake up when there is a signal to check whether the foreground process PID change, */ + /* change means that the foreground process is over. */ + sigsuspend(&m); + } + return; +} + +pid_t fgpid(struct job_t *jobs) +{ + for (int i = 0; i < JOBS_MAX_QUANTITY; i++) + if (jobs[i].state == FG) + return jobs[i].pid; + return 0; +} + +int hide(const char *path) +{ + if (*path == '.') + { + return 1; + } + else + { + return 0; + } +} \ No newline at end of file diff --git a/yeeshell.h b/yeeshell.h new file mode 100644 index 0000000..a3ef706 --- /dev/null +++ b/yeeshell.h @@ -0,0 +1,59 @@ +#pragma once + +#define CMDLINE_MAX_SIZE 1024 /* max length of a single command line */ +#define ARGS_MAX_QUANTITY 128 /* max args on a command line */ +#define BUFFER_MAX_SIZE 64 /* max size of a buffer which contains parsed arguments */ +#define CMDLINE_DIV ' \t\r\n\a' +#define CMDLINE_HISTORY_MAX_QUANTITY 256 +#define JOBS_MAX_QUANTITY 16 +#define PATH_MAX_SIZE 256 + +#define FG 1 /* running in foreground */ +#define BG 2 /* running in background */ +#define ST 3 /* stopped */ + +/* job_t - The job struct */ +struct job_t +{ + pid_t pid; /* job PID */ + int jid; /* job ID [1, 2, ...] */ + int state; /* UNDEF, BG, FG, or ST */ + char cmdline[CMDLINE_MAX_SIZE]; /* command line */ +}; + +/* readline - Get the command line */ +char *readline(); + +/* parseline - Evaluate the command line that the user has just typed in */ +int parseline(char *cmdline, char **args); + +/* execute - Execute the command line */ +int execute(char *cmdline, char **args); + +/* builtin functions - Handle built-in command */ +int built_in(char **args); +int builtin_cd(char **args); +int builtin_ls(char **args); +int builtin_history(char **args); +int builtin_jobs(char **args); +int builtin_mytop(char **args); + +/* do_bgfg - Execute background/foregroung tasks */ +int do_bgfg(char **args); + +/* addjob - Add jobs to joblist */ +int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline); + +/* pide2jid - Map process ID to job ID*/ +int pid2jid(pid_t pid); + +/* waitfg - Wait foreground jobs to finish */ +void waitfg(pid_t pid); + +/* fgpid - Return PID of current foreground job, 0 if no such job */ +pid_t fgpid(struct job_t *jobs); + +/* determine if a file is hidden */ +int hide(const char *path); + +/* */ \ No newline at end of file