OS2021_Project1.Shell
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

426 строки
7.6 KiB

#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()
{
}