Linux.实现一个简单的shell
2017-03-25 13:26
821 查看
fork & execve
identify the command
cannot identify then print ‘bad command’ and go back to wait
if exit then exit() shell
else fork(), child execve() the Executable file, father wait() for the child
support absolue path and relative path
then chdir() should called by shell itself
int dispatch(char *input) to identify command and paraments, then store them(include cmd and paras) in char* cmd_paras[]
void get_input(char *cmd) to read up to 255 charactors from user input
Shell框架
shell start and wait for inputing command and paramentsidentify the command
cannot identify then print ‘bad command’ and go back to wait
if exit then exit() shell
else fork(), child execve() the Executable file, father wait() for the child
实现简单的命令
my_pwd
print current working directory/* * my_pwd.c */ #include <unistd.h> #include <stdio.h> char curp[255]; void main(int argc,char *argv[]) { getcwd(curp,255); printf("PWD: %s\n",curp); return; }
my_ls
list the directory and regular file contained by the given directorysupport absolue path and relative path
/* * my_ls.c * */ #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <string.h> #include <dirent.h> #include <stdlib.h> ... char **pths = NULL; //store the pathes to list int pth_n = 0; //the number of paths ... int res = 0; struct stat st_f; DIR* dir = NULL; struct dirent* dir_ent = NULL; for(int i = 0; i < pth_n; ++i){ char pth[255]; if(pths[i][0] == '/') sprintf(pth,"%s",pths[i]); else // char cwd[255] & getcwd(cwd,sizeof(cwd)) sprintf(pth,"%s/%s", cwd, pths[i]); res = stat(pth, &st_f); if(res < 0){ printf("cannot stat path %s\n", pth); continue; } if(!S_ISDIR(st_f.st_mode)){ printf("%s is not a directory\n", pth); continue; }else{ dir = opendir( pth ); if(dir == NULL) printf("cannot open ab_path %s\n", pth); dir_ent = readdir( dir ); while( dir_ent != NULL ){ //ignore ".." "." and ".*" which are hidden files if(dir_ent->d_name[0] == '.'){ dir_ent = readdir( dir ); continue; } if(dir_ent->d_type == DT_DIR) printf("d %s\n",dir_ent->d_name); else if(dir_ent->d_type == DT_REG) printf("r %s\n",dir_ent->d_name); dir_ent = readdir( dir ); } } }
my_cd
fork & execve cannnot change father process’s current working directorythen chdir() should called by shell itself
/* * test_cwd.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> void main(int argc,char**argv) { char cwd[255]; int cwd_size = sizeof(cwd); printf("cwd_size = %d\n", cwd_size); getcwd(cwd, cwd_size); printf("riginal father cwd = %s\n", cwd ); pid_t pid = fork(); if(pid == 0){ chdir("/home"); getcwd(cwd, 255); printf("child cwd = %s\n", cwd ); } else if(pid > 0){ wait(pid); getcwd(cwd, 255); printf("father cwd = %s\n", cwd ); } }
MyShell Process
void my_exec(char *filename) to fork & execve with the given filename, and father process should wait()int dispatch(char *input) to identify command and paraments, then store them(include cmd and paras) in char* cmd_paras[]
void get_input(char *cmd) to read up to 255 charactors from user input
/* * my_shell.c */ #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <pwd.h> #include <sys/types.h> char* cmd_set[] = {"exit","my_cd","my_ls","my_pwd"}; char* cmd_paras[MY_CMD_NUM]; int cmd_paras_n = 0; char cwd[ MY_CWD_SIZE ]; void my_exec(char *path) { int pid = fork(); if(pid == 0) execve(path, cmd_paras, env); else if(pid > 0){ int status = 0; pid_t pidd = 0; pidd = wait(&status); } else if(pid < 0) printf("fail to fork process.\n"); } int dispatch(char *input) { int ret = -1, res = 0; ... //cmd_paras[0] is the command //cmd_paras[1..n] are the paramenst //cmd_paras_n = n+1 if(!strcmp(cmd_paras[0], cmd_set[0])) ret = 0; //exit if(!strcmp(cmd_paras[0], cmd_set[1])){ //cd ret = 1; char dir[MY_CWD_SIZE]; if(cmd_paras_n == 1){ uid_t usrid = getuid(); struct passwd* pwd = getpwuid(usrid); sprintf(dir, "/home/%s", pwd->pw_name); } else{ char* new_cwd = cmd_paras[1]; if(new_cwd[0] == '/') sprintf(dir, "%s", new_cwd); else sprintf(dir, "%s/%s", cwd, new_cwd); } res = chdir(dir); if(res < 0)printf("failed to change cwd to %s\n",dir); } if(!strcmp(cmd_paras[0], cmd_set[2])) ret = 2; //ls if(!strcmp(cmd_paras[0], cmd_set[3])) ret = 3; //pwd return ret; } void get_input(char *cmd) { int i = 0; char c = getchar(); while( c != '\n' && i < 255 ){ cmd[ i++ ] = c; c = getchar(); } cmd[ i ] = '\0'; } void main(int argc,char **argv) { char cmd[ MY_CMD_SIZE ]; const char * cmd_path = "/home/niugen/LINUX_CLASS"; int cmd_n = 0, loop = 1; char cmd_file[ MY_CMD_SIZE ]; while(loop){ getcwd(cwd, MY_CWD_SIZE); printf("MyShell@%s > ", cwd); get_input( cmd ); cmd_n = dispatch( cmd ); if(cmd_n < 0)printf("Bad Command.\n"); //bad command else if(cmd_n == 0) loop = 0; //exit else if(cmd_n != 1){ //not 'cd' sprintf(cmd_file,"%s/%s", cmd_path, cmd_paras[0]); my_exec(cmd_file); } } }
相关文章推荐
- 利用linux下的c语言编程来简单的实现一个shell功能实现!
- Linux下实现一个简单进度条和shell脚本实现彩色进度条
- 【Linux】实现一个简单的shell
- 【Linux】实现一个简单的shell
- 用C语言实现一个简单的Linux壳层(Shell)
- UNIX-LINUX编程实践教程->第八章->实例代码注解->写一个简单的shell
- linux下的一个简单md5shell
- 【1】实现一个简单的linux系统引导程序
- C语言 实现一个简单的Shell (支持管道和"cd")
- Linux编程实现一个简单的Shell
- Linux下C语言实现简单Shell
- linux下如何自动检测并重新启动一个死掉的进程(shell脚本实现)
- Linux下两个远程登陆用户如何共享同一个登陆shell,以实现远程教育或远程协助
- 关于一个简单的shell的实现
- Clojure:在REPL上实现一个简单的shell(二)
- UNIX-LINUX编程实践教程->第八章->实例代码注解->写一个简单的shell->在shell中启动另一个程序
- 实现一个简单的shell
- Linux C++ 一个线程池的简单实现(附代码)
- 用Qt实现一个简单的shell (Qt5+V8)
- 操作系统上机——实现一个简单的shell