专栏博客链接
《操作系统真象还原》从零开始自制操作系统 全章节博客链接
shell相关文件
编写完的buildin_cmd.c
#include "buildin_cmd.h"
#include "../fs/file.h"
#include "../fs/fs.h"
#include "debug.h"
#include "string.h"
#include "syscall.h"
#include "stdio-kernel.h"
#include "../fs/dir.h"
#include "../fs/fs.h"
#include "stdio.h"
#include "shell.h"
extern char final_path[160];
void wash_path(char* old_abs_path,char* new_abs_path)
{
ASSERT(old_abs_path[0] == '/');
char name[MAX_FILE_NAME_LEN] = {0};
char* sub_path = old_abs_path;
sub_path = path_parse(sub_path,name);
if(name[0] == 0)
{
new_abs_path[0] = '/';
new_abs_path[1] = 0;
return;
}
new_abs_path[0] = 0;
strcat(new_abs_path,"/");
while(name[0])
{
if(!strcmp("..",name))
{
char* slash_ptr = strrchr(new_abs_path,'/');
if(slash_ptr != new_abs_path)
*slash_ptr = 0;
else
*(slash_ptr+1) = 0;
}
else if(strcmp(".",name))
{
if(strcmp(new_abs_path,"/"))
strcat(new_abs_path,"/");
strcat(new_abs_path,name);
}
memset(name,0,MAX_FILE_NAME_LEN);
if(sub_path)
sub_path = path_parse(sub_path,name);
}
}
void make_clear_abs_path(char* path,char* final_path)
{
char abs_path[MAX_PATH_LEN] = {0};
if(path[0] != '/')
{
memset(abs_path,0,MAX_PATH_LEN);
if(getcwd(abs_path,MAX_PATH_LEN) != NULL)
{
if(!((abs_path[0] == '/') && abs_path[1] == 0))
strcat(abs_path,"/");
}
}
strcat(abs_path,path);
wash_path(abs_path,final_path);
}
void buildin_pwd(uint32_t argc,char** argv)
{
if(argc != 1)
printf("pwd: no argument support!\n");
else
{
if(getcwd(final_path,MAX_PATH_LEN) != NULL)
printf("%s\n",final_path);
else
printf("pwd: get current work directory failed\n");
}
}
char* buildin_cd(uint32_t argc,char** argv)
{
if(argc > 2)
{
printf("cd: only support 1 argument!\n");
return NULL;
}
if(argc == 1)
{
final_path[0] = '/';
final_path[1] = 0;
}
else make_clear_abs_path(argv[1],final_path);
if(chdir(final_path) == -1)
{
printf("cd: no such directory %s\n",final_path);
return NULL;
}
return final_path;
}
void buildin_ls(uint32_t argc,char** argv)
{
char* pathname = NULL;
struct stat file_stat;
memset(&file_stat,0,sizeof(struct stat));
bool long_info = false;
uint32_t arg_path_nr = 0;
uint32_t arg_idx = 1;
while(arg_idx < argc)
{
if(argv[arg_idx][0] == '-')
{
if(!strcmp("-l",argv[arg_idx]))
long_info = true;
else if(!strcmp("-h",argv[arg_idx]))
{
printf("usage: -l list all all information about the file.\nnot support -h now sry - -\n");
return;
}
else
{
printf("ls: invaild option %s\nTry 'ls -l' u can get what u want\n",argv[arg_idx]);
return;
}
}
else
{
if(arg_path_nr == 0)
{
pathname = argv[arg_idx];
arg_path_nr = 1;
}
else
{
printf("ls: only support one path\n");
return;
}
}
++arg_idx;
}
if(pathname == NULL)
{
if(getcwd(final_path,MAX_PATH_LEN) != NULL)
pathname = final_path;
else
{
printf("ls: getcwd for default path failed\n");
return;
}
}
else
{
make_clear_abs_path(pathname,final_path);
pathname = final_path;
}
if(stat(pathname,&file_stat) == -1)
{
printf("ls: cannot access %s: No such file or directory\n",pathname);
return;
}
if(file_stat.st_filetype == FT_DIRECTORY)
{
struct dir* dir = opendir(pathname);
struct dir_entry* dir_e = NULL;
char sub_pathname[MAX_PATH_LEN] = {0};
uint32_t pathname_len = strlen(pathname);
uint32_t last_char_idx = pathname_len - 1;
memcpy(sub_pathname,pathname,pathname_len);
if(sub_pathname[last_char_idx] != '/')
{
sub_pathname[pathname_len] = '/';
++pathname_len;
}
rewinddir(dir);
if(long_info)
{
char ftype;
printf("total: %d\n",file_stat.st_size);
while((dir_e = readdir(dir)))
{
ftype = 'd';
if(dir_e->f_type == FT_REGULAR)
ftype = '-';
sub_pathname[pathname_len] = 0;
strcat(sub_pathname,dir_e->filename);
memset(&file_stat,0,sizeof(struct stat));
if(stat(sub_pathname,&file_stat) == -1)
{
printf("ls: cannot access %s:No such file or directory\n",dir_e->filename);
return;
}
printf("%c %d %d %s\n",ftype,dir_e->i_no,file_stat.st_size,dir_e->filename);
}
}
else
{
while((dir_e = readdir(dir)))
printf("%s ",dir_e->filename);
printf("\n");
}
closedir(dir);
}
else
{
if(long_info)
printf("- %d %d %s\n",file_stat.st_ino,file_stat.st_size,pathname);
else
printf("%s\n",pathname);
}
}
void buildin_ps(uint32_t argc,char** argv)
{
if(argc != 1)
{
printf("ps: no argument support!\n");
return;
}
ps();
}
void buildin_clear(uint32_t argc,char** argv)
{
if(argc != 1)
{
printf("clear: no argument support!\n");
return;
}
clear();
}
int32_t buildin_mkdir(uint32_t argc,char** argv)
{
int32_t ret = -1;
if(argc != 2)
printf("mkdir: only support 1 argument!\n");
else
{
make_clear_abs_path(argv[1],final_path);
if(strcmp("/",final_path))
{
if(mkdir(final_path) == 0)
ret = 0;
else
printf("mkdir: create directory %s failed.\n",argv[1]);
}
}
return ret;
}
int32_t buildin_rmdir(uint32_t argc,char** argv)
{
int32_t ret = -1;
if(argc != 2)
printf("rmdir: only support 1 argument!\n");
else
{
make_clear_abs_path(argv[1],final_path);
if(strcmp("/",final_path))
{
if(rmdir(final_path) == 0)
ret = 0;
else printf("rmdir: remove %s failed\n");
}
}
return ret;
}
int32_t buildin_rm(uint32_t argc,char** argv)
{
int32_t ret = -1;
if(argc != 2)
printf("rm: only support 1 argument!\n");
else
{
make_clear_abs_path(argv[1],final_path);
if(strcmp("/",final_path))
{
if(unlink(final_path) == 0)
ret = 0;
else printf("rm: delete %s failed\n",argv[1]);
}
}
return ret;
}
编写完的buildin_cmd.h
#ifndef __SHELL_BUILDIN_CMD_H
#define __SHELL_BUILDIN_CMD_H
#include "stdint.h"
void wash_path(char* old_abs_path,char* new_abs_path);
void make_clear_abs_path(char* path,char* final_path);
void buildin_pwd(uint32_t argc,char** argv);
char* buildin_cd(uint32_t argc,char** argv);
void buildin_ls(uint32_t argc,char** argv);
void buildin_ps(uint32_t argc,char** argv);
void buildin_clear(uint32_t argc,char** argv);
int32_t buildin_mkdir(uint32_t argc,char** argv);
int32_t buildin_rmdir(uint32_t argc,char** argv);
int32_t buildin_rm(uint32_t argc,char** argv);
#endif
编写完的shell.c
#include "shell.h"
#include "global.h"
#include "stdint.h"
#include "string.h"
#include "syscall.h"
#include "stdio.h"
#include "../fs/file.h"
#include "../kernel/debug.h"
#include "buildin_cmd.h"
#include "../fs/fs.h"
#include "../userprog/exec.h"
#define cmd_len 128
#define MAX_ARG_NR 16
char cmd_line[cmd_len] = {0};
char cwd_cache[64] = {0};
char final_path[MAX_PATH_LEN];
char* argv[MAX_ARG_NR];
void print_prompt(void)
{
printf("[Love 6@localhost %s]$ ",cwd_cache);
}
void readline(char* buf,int32_t count)
{
ASSERT(buf != NULL && count > 0);
char* pos = buf;
while(read(stdin_no,pos,1) != -1 && (pos - buf) < count)
{
switch(*pos)
{
case 'l'-'a':
*pos = 0;
clear();
print_prompt();
printf("%s",buf);
break;
case 'u'-'a':
while(buf != pos)
{
putchar('\b');
*(pos--) = 0;
}
break;
case '\n':
case '\r':
*pos = 0;
putchar('\n');
return;
case '\b':
if(buf[0] != '\b')
{
--pos;
putchar('\b');
}
break;
default:
putchar(*pos);
++pos;
}
}
printf("readline: cant fine entry_key in the cmd_line,max num of char is 128\n");
}
int32_t cmd_parse(char* cmd_str,char** argv,char token)
{
ASSERT(cmd_str != NULL);
int32_t arg_idx = 0;
while(arg_idx < MAX_ARG_NR)
{
argv[arg_idx] = NULL;
arg_idx++;
}
char* next = cmd_str;
int32_t argc = 0;
while(*next)
{
while(*next == token) ++next;
if(*next == 0) break;
argv[argc] = next;
while(*next && *next != token)
++next;
if(*next)
*(next++) = 0;
if(argc > MAX_ARG_NR)
return -1;
++argc;
}
return argc;
}
void my_shell(void)
{
cwd_cache[0] = '/';
cwd_cache[1] = 0;
int argc = -1;
while(1)
{
print_prompt();
memset(cmd_line,0,cmd_len);
memset(final_path,0,MAX_PATH_LEN);
memset(argv,0,sizeof(char*) * MAX_ARG_NR);
readline(cmd_line,cmd_len);
if(cmd_line[0] == 0)
continue;
argc = -1;
argc = cmd_parse(cmd_line,argv,' ');
if(argc == -1)
{
printf("num of arguments exceed %d\n",MAX_ARG_NR);
continue;
}
if(!strcmp("ls",argv[0]))
buildin_ls(argc,argv);
else if(!strcmp("pwd",argv[0]))
buildin_pwd(argc,argv);
else if(!strcmp("ps",argv[0]))
buildin_ps(argc,argv);
else if(!strcmp("cd",argv[0]))
{
if(buildin_cd(argc,argv) != NULL)
{
memset(cwd_cache,0,MAX_PATH_LEN);
strcpy(cwd_cache,final_path);
}
}
else if(!strcmp("clear",argv[0]))
buildin_clear(argc,argv);
else if(!strcmp("mkdir",argv[0]))
buildin_mkdir(argc,argv);
else if(!strcmp("rmdir",argv[0]))
buildin_rmdir(argc,argv);
else if(!strcmp("rm",argv[0]))
buildin_rm(argc,argv);
else
{
printf("external command\n");
}
}
PANIC("my_shell: should not be here");
}
编写完的shell.h
#ifndef __SHELL_SHELL_H
#define __SHELL_SHELL_H
#include "stdint.h"
#include "../fs/fs.h"
void print_prompt(void);
void readline(char* buf,int32_t count);
void my_shell(void);
int32_t cmd_parse(char* cmd_str,char** argv,char token);
#endif