From d24f083e7cc9506189c4c35ab013a593f784d9c8 Mon Sep 17 00:00:00 2001 From: 10195501441 <10195501441@stu.ecnu.edu.com> Date: Wed, 10 Mar 2021 22:49:21 +0800 Subject: [PATCH] add some functions --- yeeshell | Bin 22976 -> 23488 bytes yeeshell.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++-------------- yeeshell.h | 68 +++++++++++-- 3 files changed, 304 insertions(+), 80 deletions(-) diff --git a/yeeshell b/yeeshell index cbf51a210b9843cdf0364351dabf8232912b213e..ba5008ebd197ad0d504ada7f333cf83206ac7c85 100755 GIT binary patch literal 23488 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 TjlqGFzDA9qTvVV?P-XuPrkq`v literal 22976 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 diff --git a/yeeshell.c b/yeeshell.c index 4338544..ae5ff24 100644 --- a/yeeshell.c +++ b/yeeshell.c @@ -2,15 +2,20 @@ #include #include #include +#include #include #include #include +#include #include "yeeshell.h" /* record cmdline history */ -char **history = NULL; +char *history[CMDLINE_HISTORY_MAX_QUANTITY]; int cmdline_amount = 0; +/* if true, print additional output */ +int verbose = 0; + /* next job ID to allocate */ int nextjid = 1; @@ -26,12 +31,21 @@ int main() 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 *)))) + for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++) { - printf("yeeshell: allocation error!\n"); - exit(EXIT_FAILURE); + history[i] = (char *)calloc(CMDLINE_MAX_SIZE, sizeof(char)); } + /* Install the signal handlers */ + + /* These are the ones you will need to implement */ + Signal(SIGINT, sigint_handler); /* ctrl-c */ + Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */ + Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */ + + /* This one provides a clean way to kill the shell */ + Signal(SIGQUIT, sigquit_handler); + initjobs(jobs); /* execute the shell's read, parse and execution loop */ do { @@ -40,13 +54,16 @@ int main() printf("yeeshell: The current path cannot be obtained!\n"); exit(0); } - printf("[yeeshell %s]# ", pwd); + printf("[root@yeeshell %s]# ", pwd); cmdline = readline(); - history[cmdline_amount++] = cmdline; + strcpy(history[cmdline_amount++], cmdline); status = execute(cmdline, args); free(cmdline); } while (status); - free(history); + for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++) + { + free(history[i]); + } exit(EXIT_SUCCESS); } @@ -147,7 +164,7 @@ int execute(char *cmdline, char **args) /* 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) + if (execvp(args[0], args) <= 0) { printf("%s: Command not found\n", args[0]); exit(0); @@ -201,17 +218,13 @@ int built_in(char **args) { 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; + return 0; } } @@ -231,39 +244,21 @@ int builtin_cd(char **args) } } -int builtin_ls(char **args) +int builtin_history(char **args) { - DIR *dp; - struct dirent *dirp; - char *path = NULL; - + int n = 0; if (args[1] == NULL) { - path = (char *)calloc(PATH_MAX, sizeof(char)); - getcwd(path, PATH_MAX) + n = cmdline_amount; } - else if (args[1]) - - if ((dp = opendir(args[1])) == NULL) - { - perror("yeeshell"); - } - while ((dirp = readdir(dp)) != NULL) + else { - printf("%s\n", dirp->d_name); + n = atoi(args[1]) < cmdline_amount ? atoi(args[1]) : cmdline_amount; } - - 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++) + for (int i = 0; i < n; i++) { - printf("%d\t%s\n", i, history[i]); + printf("%d\t%s\n", i + 1, history[i]); } return 1; } @@ -309,11 +304,98 @@ int builtin_mytop(char **args) int do_bgfg(char **args) { + /* initialize variables */ + struct job_t *currentJob; + int jid; + pid_t pid; + sigset_t mask_all, mask_prev; + sigfillset(&mask_all); + + sigprocmask(SIG_SETMASK, &mask_all, &mask_prev); + + /* bg or fg has the argument? */ + if (args[1] == NULL) + { + printf("%s command requires PID or %%jobid argument\n", args[0]); + return 1; + } + /* if process by jid, gets the corresponding Job structure*/ + else if (args[1][0] == '%') + { + jid = atoi(args[1][1]); + currentJob = getjobjid(jobs, jid); + if (currentJob == NULL) + { + printf("%%%d: No such job\n", jid); + return 1; + } + pid = currentJob->pid; + } + /* if process by pid, gets the corresponding Job structure */ + else + { + pid = atoi(args[1]); + currentJob = getjobpid(jobs, pid); + if (pid <= 0) + { + printf("%s: argument must be a PID or %%jobid\n", args[0]); + return 1; + } + currentJob = getjobpid(jobs, pid); + if (currentJob == NULL) + { + printf("(%d): No such process\n", pid); + return 1; + } + } + + /* bg or fg? */ + if (!strcmp(args[0], "bg")) /* if bg */ + { + currentJob->state = BG; + printf("[%d] (%d) %s", currentJob->jid, pid, currentJob->cmdline); + sigprocmask(SIG_SETMASK, &mask_prev, NULL); + kill(-pid, SIGCONT); /* send the SIGCONT to the pid */ + return 1; + } + else if (!strcmp(args[0], "fg")) /* if fg */ + { + currentJob->state = FG; + sigprocmask(SIG_SETMASK, &mask_prev, NULL); + kill(-pid, SIGCONT); /* send the SIGCONT to the pid */ + waitfg(currentJob->pid); /* Child process switched to FG, so wait for it to finish */ + return 1; + } + else if (!strcmp(args[0], "kill")) + { + sigprocmask(SIG_SETMASK, &mask_prev, NULL); + kill(-pid, SIGQUIT); + return 1; + } + return 1; +} + +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; +} + +void initjobs(struct job_t *jobs) +{ + int i; + + for (i = 0; i < JOBS_MAX_QUANTITY; i++) + clearjob(&jobs[i]); } -/************************ - * manipulate job list - ************************/ int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline) { int i; @@ -332,8 +414,10 @@ int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline) nextjid = 1; strcpy(jobs[i].cmdline, cmdline); - printf("Added job [%d] %d %s\n", jobs[i].jid, jobs[i].pid, jobs[i].cmdline); - + if (verbose) + { + printf("Added job [%d] %d %s\n", jobs[i].jid, jobs[i].pid, jobs[i].cmdline); + } return 1; } } @@ -341,20 +425,6 @@ int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline) 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++) @@ -381,17 +451,45 @@ void listjobs(struct job_t *jobs) } } -void waitfg(pid_t pid) +int deletejob(struct job_t *jobs, pid_t pid) { - sigset_t m; - sigemptyset(&m); - while (pid == fgpid(jobs)) + int i; + + if (pid < 1) + return 0; + + for (i = 0; i < JOBS_MAX_QUANTITY; i++) { - /* 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); + if (jobs[i].pid == pid) + { + clearjob(&jobs[i]); + nextjid = maxjid(jobs) + 1; + return 1; + } } - return; + return 0; +} + +void clearjob(struct job_t *job) +{ + job->pid = 0; + job->jid = 0; + job->state = UNDF; + job->cmdline[0] = '\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; } pid_t fgpid(struct job_t *jobs) @@ -402,14 +500,92 @@ pid_t fgpid(struct job_t *jobs) return 0; } -int hide(const char *path) +struct job_t *getjobpid(struct job_t *jobs, pid_t pid) { - if (*path == '.') + int i; + + if (pid < 1) + return NULL; + for (i = 0; i < JOBS_MAX_QUANTITY; i++) + if (jobs[i].pid == pid) + return &jobs[i]; + return NULL; +} + +struct job_t *getjobjid(struct job_t *jobs, int jid) +{ + int i; + + if (jid < 1) + return NULL; + for (i = 0; i < JOBS_MAX_QUANTITY; i++) + if (jobs[i].jid == jid) + return &jobs[i]; + return NULL; +} + +handler_t *Signal(int signum, handler_t *handler) +{ + struct sigaction action, old_action; + + action.sa_handler = handler; + sigemptyset(&action.sa_mask); /* block sigs of type being handled */ + action.sa_flags = SA_RESTART; /* restart syscalls if possible */ + + if (sigaction(signum, &action, &old_action) < 0) + fprintf(stdout, "%s: %s\n", 'Signal Error', strerror(errno)); + return (old_action.sa_handler); +} + +void sigchld_handler(int signal) +{ + pid_t pid; + int status; + while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { - return 1; + if (WIFEXITED(status)) /* Normal termination */ + { + deletejob(jobs, pid); + } + if (WIFSTOPPED(status)) /* Task suspension */ + { + struct job_t *job = getjobpid(jobs, pid); + int jid = pid2jid(pid); + printf("Job [%d] (%d) stopped by signal %d\n", jid, pid, WSTOPSIG(status)); + job->state = ST; + } + if (WIFSIGNALED(status)) /* Task terminated */ + { + int jid = pid2jid(pid); + printf("Job [%d] (%d) terminated by signal %d\n", jid, pid, WTERMSIG(status)); + deletejob(jobs, pid); + } } - else + return; +} + +void sigint_handler(int signal) +{ + pid_t pid = fgpid(jobs); + if (pid != 0) { - return 0; + kill(-pid, signal); } + return; +} + +void sigtstp_handler(int signal) +{ + pid_t pid = fgpid(jobs); + if (pid > 0) + { + kill(-pid, signal); + } + return; +} + +void sigquit_handler(int signal) +{ + printf("Terminating after receipt of SIGQUIT signal\n"); + exit(1); } \ No newline at end of file diff --git a/yeeshell.h b/yeeshell.h index a3ef706..b1c2152 100644 --- a/yeeshell.h +++ b/yeeshell.h @@ -7,10 +7,12 @@ #define CMDLINE_HISTORY_MAX_QUANTITY 256 #define JOBS_MAX_QUANTITY 16 #define PATH_MAX_SIZE 256 +#define LS_BUF_SIZE 1024 -#define FG 1 /* running in foreground */ -#define BG 2 /* running in background */ -#define ST 3 /* stopped */ +#define UNDF 0 /* undefined */ +#define FG 1 /* running in foreground */ +#define BG 2 /* running in background */ +#define ST 3 /* stopped */ /* job_t - The job struct */ struct job_t @@ -33,7 +35,6 @@ 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); @@ -41,19 +42,66 @@ int builtin_mytop(char **args); /* do_bgfg - Execute background/foregroung tasks */ int do_bgfg(char **args); +/* waitfg - Wait foreground jobs to finish */ +void waitfg(pid_t pid); + +/* initjobs - Initialize the job list */ +void initjobs(struct job_t *jobs); + /* addjob - Add jobs to joblist */ int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline); +/* listjobs - Print the job list */ +void listjobs(struct job_t *jobs); + +/* deletejob - Delete a job whose PID=pid from the job list */ +int deletejob(struct job_t *jobs, pid_t pid); + +/* clearjob - Clear the entries in a job struct */ +void clearjob(struct job_t *job); + /* 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); +/* getjobpid - Find a job (by PID) on the job list */ +struct job_t *getjobpid(struct job_t *jobs, pid_t pid); + +/* getjobjid - Find a job (by JID) on the job list */ +struct job_t *getjobjid(struct job_t *jobs, int jid); + +/* Signal - wrapper for the sigaction function */ +typedef void handler_t(int); +handler_t *Signal(int signum, handler_t *handler); + +/* + * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever + * a child job terminates (becomes a zombie), or stops because it + * received a SIGSTOP or SIGTSTP signal. The handler reaps all + * available zombie children, but doesn't wait for any other + * currently running children to terminate. + */ +void sigchld_handler(int signal); + +/* + * sigint_handler - The kernel sends a SIGINT to the shell whenver the + * user types ctrl-c at the keyboard. Catch it and send it along + * to the foreground job. + */ +void sigint_handler(int signal); + +/* + * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever + * the user types ctrl-z at the keyboard. Catch it and suspend the + * foreground job by sending it a SIGTSTP. + */ + +void sigtstp_handler(int signal); -/* */ \ No newline at end of file +/* + * sigquit_handler - The driver program can gracefully terminate the + * child shell by sending it a SIGQUIT signal. + */ +void sigquit_handler(int signal); \ No newline at end of file