|
|
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <string.h>
- #include <dirent.h>
- #include <signal.h>
- #include <errno.h>
- #include <fcntl.h>
- #include "yeeshell.h"
-
- /* record cmdline history */
- char *history[CMDLINE_HISTORY_MAX_QUANTITY];
- int cmdline_amount = 0;
-
- int main()
- {
- char *cmdline = NULL, *pwd = NULL;
- char *args[ARGS_MAX_QUANTITY];
- int status = 1;
- pwd = (char *)calloc(PATH_MAX_SIZE, sizeof(char));
- for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++)
- {
- history[i] = (char *)calloc(CMDLINE_MAX_SIZE, sizeof(char));
- }
-
- /* execute the shell's read, parse and execution loop */
- do
- {
- if (!getcwd(pwd, PATH_MAX_SIZE))
- {
- printf("yeeshell: The current path cannot be obtained!\n");
- exit(0);
- }
- printf("[root@yeeshell %s]# ", pwd);
- cmdline = readline();
- strcpy(history[cmdline_amount++], cmdline);
- status = execute(cmdline, args);
- free(cmdline);
- } while (status);
- for (int i = 0; i < CMDLINE_HISTORY_MAX_QUANTITY; i++)
- {
- free(history[i]);
- }
- 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 check_redirect(char **args, char *redirect_filename, char **redirect_args)
- {
- int i = 0, j = 0, redirect_flag = REDIRECT_NO;
- while (args[i] != NULL)
- {
- if (!strcmp(args[i], ">"))
- {
- redirect_flag = REDIRECT_OUT;
- break;
- }
- else if (!strcmp(args[i], "<"))
- {
- redirect_flag = REDIRECT_IN;
- break;
- }
- i++;
- }
-
- if ((redirect_flag == 1) || (redirect_flag == 2))
- {
- strcpy(redirect_filename, args[i + 1]);
- for (j = 0; j < i; j++)
- {
- redirect_args[j] = args[j];
- }
- }
-
- return redirect_flag;
- }
-
- int do_redirect(int redirect_flag, char *redirect_filename, char **redirect_args)
- {
- pid_t pid;
- int fd = 1;
- if ((pid = fork()) == 0) /* Child process */
- {
- if (redirect_flag == 1) /* in or out? */
- {
- fd = open(redirect_filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR);
- close(1);
- dup(fd);
- }
- else if (redirect_flag == 2)
- {
- fd = open(redirect_filename, O_RDONLY, S_IRUSR);
- close(0);
- dup(fd);
- }
- if (execvp(redirect_args[0], redirect_args) <= 0)
- {
- printf("%s: Command not found\n", redirect_args[0]);
- exit(0);
- }
- close(fd);
- }
- else /* parent process */
- {
- waitpid(pid, NULL, 0);
- }
- return 1;
- }
-
- int check_pipe(char **args, char **pipe_arg_1, char **pipe_arg_2)
- {
- int pipe_flag = 0, i = 0, j = 0;
-
- while (args[i] != NULL)
- {
- if (!strcmp(args[i], "|"))
- {
- pipe_flag = 1;
- break;
- }
- pipe_arg_1[j++] = args[i++];
- }
- pipe_arg_1[j] = NULL;
-
- j = 0;
- i++;
- while (args[i] != NULL)
- {
- pipe_arg_2[j++] = args[i++];
- }
- pipe_arg_2[j] = NULL;
- return pipe_flag;
- }
-
- int do_pipe(char **pipe_arg_1, char **pipe_arg_2)
- {
- int fds[2];
- pipe(fds);
- pid_t prog_1, prog_2;
-
- if ((prog_1 = fork()) == 0) /* Child process 1 */
- {
- close(1);
- dup(fds[1]);
- close(fds[0]);
- close(fds[1]);
-
- if (execvp(pipe_arg_1[0], pipe_arg_1) <= 0)
- {
- printf("%s: Command not found\n", pipe_arg_1[0]);
- exit(0);
- }
- }
-
- if ((prog_2 = fork()) == 0) /* Child process 1 */
- {
-
- dup2(fds[0], 0);
- close(fds[0]);
- close(fds[1]);
-
- if (execvp(pipe_arg_2[0], pipe_arg_2) <= 0)
- {
- printf("%s: Command not found\n", pipe_arg_2[0]);
- exit(0);
- }
- }
-
- close(fds[0]);
- close(fds[1]);
-
- waitpid(prog_1, NULL, 0);
- waitpid(prog_2, NULL, 0);
- return 1;
- }
-
- int do_bg_fg(char **args, int bg)
- {
- pid_t pid;
- if ((pid = fork()) == 0)
- {
- if (execvp(args[0], args) <= 0)
- {
- printf("%s: Command not found\n", args[0]);
- exit(0);
- }
- }
- else
- {
- if (bg)
- {
- signal(SIGCHLD, SIG_IGN);
- }
- else
- {
- waitpid(pid, NULL, 0);
- }
- }
- return 1;
- }
-
- int execute(char *cmdline, char **args)
- {
- int bg = 0, i = 0, redirect_flag = 0, pipe_num = 0;
- pid_t pid;
- char *redirect_filename = NULL;
- char *redirect_args[ARGS_MAX_QUANTITY];
- char *pipe_arg_1[ARGS_MAX_QUANTITY];
- char *pipe_arg_2[ARGS_MAX_QUANTITY];
-
- redirect_filename = (char *)calloc(REDIRECT_FILENAME_MAX_SIZE, sizeof(char));
- memset(redirect_args, NULL, sizeof(redirect_args));
-
- bg = parseline(cmdline, args);
- redirect_flag = check_redirect(args, redirect_filename, redirect_args);
- pipe_num = check_pipe(args, pipe_arg_1, pipe_arg_2);
-
- if (args[0] == NULL)
- {
- return 1;
- }
- if (pipe_num == 0) /* no pipe */
- {
- if (!built_in(args)) /* built-in cmd? */
- {
- if (redirect_flag != 0) /* redirection? */
- {
- return do_redirect(redirect_flag, redirect_filename, redirect_args);
- }
- else
- {
- return do_bg_fg(args, bg);
- }
- }
- else
- {
- return 1;
- }
- }
- else
- {
- return do_pipe(pipe_arg_1, pipe_arg_2);
- }
- }
-
- 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"))
- {
- int flag = builtin_mytop();
- if (flag == -1)
- {
- printf("yeeshell: unable to get memory info.\n");
- }
- else if (flag == -2)
- {
- printf("yeeshell: unable to get CPU info.\n");
- }
- return flag;
- }
- else
- {
- return 0;
- }
- }
-
- int builtin_cd(char **args)
- {
- if (args[1] == NULL)
- {
- return 1;
- }
- else
- {
- if (chdir(args[1]) != 0)
- {
- perror("yeeshell");
- }
- return 1;
- }
- }
-
- int builtin_history(char **args)
- {
- int n = 0;
- if (args[1] == NULL)
- {
- n = cmdline_amount;
- }
- else
- {
- n = atoi(args[1]) < cmdline_amount ? atoi(args[1]) : cmdline_amount;
- }
- printf("ID\tCommandline\n");
- for (int i = 0; i < n; i++)
- {
- printf("%d\t%s\n", i + 1, history[i]);
- }
- return 1;
- }
-
- int builtin_mytop()
- {
- int memory_flag = 0, CPU_flag = 0;
- memory_flag = mytop_memory();
- CPU_flag = mytop_CPU();
- if (!memory_flag)
- {
- return -1;
- }
- else if (!CPU_flag)
- {
- return -2;
- }
- else
- {
- return 1;
- }
- }
-
- int mytop_memory()
- {
- FILE *fp = NULL;
- int pagesize;
- long total = 0, free = 0, cached = 0;
-
- if ((fp = fopen("/proc/meminfo", "r")) == NULL)
- {
- return 0;
- }
-
- fscanf(fp, "%u %lu %lu %lu", &pagesize, &total, &free, &cached);
- fclose(fp);
-
- printf("memmory(KBytes):\t%ld total\t%ld free\t%ld cached\n", (pagesize * total) / 1024, (pagesize * free) / 1024, (pagesize * cached) / 1024);
-
- return 1;
- }
-
- int mytop_CPU()
- {
- }
|