c 实现的shell
来源:互联网 发布:西门大妈知乎 编辑:程序博客网 时间:2024/05/21 14:41
project需要,所以做了一个。参考了网站:http://stephen-brennan.com/2015/01/16/write-a-shell-in-c/
实现了:执行基本命令,从PROFILE文件读取初始working directory,进程持续5秒以后可以提示杀死进程,以及一个alias功能(时间不够只写了逻辑部分,如果读写没问题的话应该能够实现),以及一个if 的条件的解析(做的不太好,日后补上)
代码:
//// main.c// Shell_c//// Created by liuchang on 9/18/15.// Copyright (c) 2015 liuchang. All rights reserved.//#include <stdio.h>#include <time.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <signal.h>#include <sys/types.h>#include <string.h>void show_prompt();char * read_line();int exec_command(char**);char ** split_line(char *);int launch(char ** args);int is_fileexist(char * comm);//check if exists the commandchar buffer[80];//缓存用户输入的命令#define BUFFSIZE 500#define TRUE 1int command_length=0;//builtin functionint builtin_exit(char ** args);int builtin_cd(char ** args);int builtin_if(char ** args);int builtin_alias(char ** args);int builtin_help(char ** args);int num_builtin();int check_table(char * alias);// check if the alias exist in the tablechar * builtin_str[]={"exit","cd","if","alias","help"};int (*builtin_func[])(char **) = {&builtin_exit,&builtin_cd,&builtin_if,&builtin_alias,&builtin_help};int main(int argc, const char * argv[]) { //prepare time_t nowtime; struct tm *timeinfo; time( &nowtime ); timeinfo = localtime( &nowtime ); int year, month, day; year = timeinfo->tm_year + 1900; month = timeinfo->tm_mon + 1; day = timeinfo->tm_mday; printf("welcome to my shell\n"); printf("%d-%d-%d\n", year, month, day); //read file,switch workspace FILE * file;int i;char buf[BUFFSIZE]; memset(buf,0,sizeof(buf));if((file = fopen("PROFILE","r")) == NULL){printf(" cannot open file, terminate immediately\n");exit(1);}i=0;while(!feof(file)){buf[i++] = fgetc(file);//??? what the fuckif(i>50){printf("buffer is not enough\n");exit(1);}} buf[i-2]='\0';//-2?? i--; char * user=getlogin(); int count =0; while(count < sizeof(user)){ buf[i++] = user[count++]; } //change directory chdir(buf); //printf("the user is : %s\n",user);//printf("the directory is: %s ",buf); //main loop char * command; char ** args; int status=1; while (status) { command_length=0; //show propmpt show_prompt(); //read line command =read_line(); //printf("the input is : %s",command); //split command args=split_line(command); //execute in a child process status=exec_command(args); free(command); free(args); } }void show_prompt(){ //add user info char * path; char *user; path = get_current_dir_name(); user=getlogin(); printf("%s@%s$",user, path); }char * read_line(void){ //char *input=NULL;//用户输入命令 //int command_len=0;//输入字符个数 char *line = NULL; size_t bufsize = 0; // have getline allocate a buffer for us getline(&line, &bufsize, stdin); return line;}int exec_command(char ** args){ //printf("executing command..\n"); //check several conditions.. if(args[0]==NULL){ return 1;// 比如按下 enter } //if it is builtin command.. int i; //printf("the number of built in: %d",num_builtin()); for(i =0;i<num_builtin();i++){if(strcmp(args[0],builtin_str[i]) ==0){ //printf("call builtin function\n");return (*builtin_func[i])(args); } } //else //printf("using noral function\n"); return launch(args);}#define BUFFER_TOK_SIZE 64 // 节约空间的考虑?#define TOK_DELIM " \t\r\n\a" //了解下分隔符的意思char ** split_line(char * command){ //用函数截取 int buffsize = BUFFER_TOK_SIZE,position=0; char ** tokens = malloc(buffsize * sizeof(char*));//?? char * token; if (!tokens) { fprintf(stderr, "allocation failed\n"); exit(EXIT_FAILURE); } token = strtok(command,TOK_DELIM); command_length++; while (token!=NULL) { tokens[position]=token; position++; //如果超出缓冲区大小,增加缓冲区,使用realloc if(position>buffsize){ buffsize +=BUFFER_TOK_SIZE; tokens = realloc(tokens, buffsize * sizeof(char*)); if(!tokens){ fprintf(stderr, "allocate error\n"); exit(EXIT_FAILURE); } } token = strtok(NULL, TOK_DELIM); command_length++; } tokens[position]=NULL; //int i; // for ( i=0; i<sizeof(tokens);i++) { // printf("command: %d, %s \n",i,tokens[i]); // } return tokens; }int launch(char ** args){ if(is_fileexist(args[0])==-1){ printf("%s:command not found\n",args[0]); //exit(EXIT_FAILURE); return 1; } pid_t pid,wpid,pid_p; int status; pid_p = getpid(); //printf("parend pid %d \n",pid_p); pid = fork(); if(pid<0){ perror("fork failed"); }else if (pid ==0){ //child if (execvp(args[0], args) == -1) { printf("No such file or directory\n"); int error_code = errno; //printf("error code is %d: ",error_code); } exit(EXIT_FAILURE); }else{ // Parent process clock_t start,wait; start = clock(); pid_t pid_counter; pid_counter = fork(); if(pid_counter<0){ perror("fork failed"); }else if(pid_counter == 0){ //child while(1){ wait = clock();double duration = wait-start; if(duration/CLOCKS_PER_SEC>5){ //hint char * answer; while(1){ printf("do you want to kill the child process?(y/n)\n"); answer =read_line();if(answer[0]=='y'){kill(pid,SIGABRT);//type of signal printf("killed the chiled process because it last over five seconds\n");break; }else if(answer[0]=='n'){break;}else{printf("please enter y or n\n");} } //send signal pid_p//printf("duration: %f",duration/CLOCKS_PER_SEC); return(EXIT_SUCCESS); } }} wpid = waitpid(pid, &status, WUNTRACED); //wpid = waitpid(pid_counter, &status, WUNTRACED); //printf("retrieve the child process\n"); kill(pid_counter,SIGABRT); } return 1;}int is_fileexist(char * comm)//查找命令是否存在{ char * env_path, * p; int i=0; /* 使用getenv函数来获取系统环境变量,用参数PATH表示获取路径*/ env_path = getenv("PATH"); p = env_path; while(*p != '\0') { /* 路径列表使用":"来分隔路径*/ if(*p != ':') buffer[i ++] = *p; else { buffer[i ++] = '/'; buffer[i] = '\0'; /* 将指令和路径合成,形成pathname,并使用access函数来判断该文件是否存在*/ strcat(buffer, comm); if(access(buffer, F_OK) == 0) /* 文件被找到*/ return 0; else /* 继续寻找其他路径*/ i = 0; } p ++; } /* 搜索完所有路径,依然没有找到则返回 –1*/ return -1;}//built in funcion relatedint num_builtin(){ return sizeof(builtin_str)/ sizeof(char *);//very painful }int builtin_exit(char ** args){ printf("bye-bye~\n");return 0;}int builtin_cd(char ** args){ if (args[1] == NULL) { fprintf(stderr, "expected argument to \"cd\"\n"); } else { if (chdir(args[1]) != 0) { perror("chdir failed\n"); } } return 1;}int builtin_if(char ** args){ //parse if command1; then command2; else command3 fi int i; //printf("commands are:\n"); int arr[] = {0,0,0};// then, else,fi int pos_then = 0; int pos_else = 0; for(i = 0;i<command_length-1;i++){ //printf(" %s ",args[i]); if(strcmp("then",args[i])==0) {arr[0]=TRUE;pos_then=i;} if(strcmp("else",args[i])==0) { pos_else = i; arr[1]=TRUE;//just in case we need to run another process } if(i==command_length-2){ if(strcmp("fi",args[i])==0) arr[2]=TRUE; } } //printf("\n"); int j; //for(j=0;j<3;j++) printf("array %d, %d ",j,arr[j]); //printf("\n args before then:%s \n",args[pos_then-1]); if( (strcmp(args[pos_then-1],";")==0) && arr[0] && arr[2]){ //printf("valid if expression\n"); //split: command 1 , command 2 , command 3 //command1 int buffsize = BUFFER_TOK_SIZE,position=0; char ** tokens = malloc(buffsize * sizeof(char*)); int x; for(x =1;x<pos_then-1;x++){ tokens[position++] = args[x]; //printf("command 1 : %s\n ",args[x]); } //printf("token %s",tokens[1]); int res = launch_if(tokens); //printf("result for command 1:%d \n",res); //command 2 position=0; tokens = malloc(buffsize * sizeof(char*)); //printf("command length: %d , pos_then: %d \n",command_length,pos_then); if(!arr[1]){ for(x =pos_then+1;x<command_length-2;x++){ tokens[position++] = args[x]; //printf("command 2 : %s\n ",args[x]); } }else { for(x =pos_then+1;x<pos_else;x++){ tokens[position++] = args[x]; //printf("command 2 : %s\n ",args[x]); } } if(res){ // just command 2 //launch command 2 launch(tokens); }else{ //if exist, launch command3 if(arr[1]){ //split command3 position=0; tokens = malloc(buffsize * sizeof(char*)); int y; for(y =pos_else+1;y<command_length-2;y++){ tokens[position++] = args[y]; //printf("command 3 : %s\n ",args[y]); } //launch command 3 launch_if(tokens); } } }else{ printf("invalid expression, use like this:$ if command1 ; then command2 ; else command3 fi \n"); return 1; } }int launch_if(char ** args){ if(is_fileexist(args[0])==-1){ printf("%s:command not found\n",args[0]); //exit(EXIT_FAILURE); return 0; } pid_t pid,wpid,pid_p; int status; pid_p = getpid(); //printf("parend pid %d \n",pid_p); pid = fork(); if(pid<0){ perror("fork failed"); }else if (pid ==0){ //child if (execvp(args[0], args) == -1) { printf("No such file or directory\n"); int error_code = errno; //printf("error code is %d: ",error_code); return 0; } //exit(EXIT_FAILURE); return 1; }else{ // Parent process clock_t start,wait; start = clock(); pid_t pid_counter; wpid = waitpid(pid, &status, WUNTRACED); //wpid = waitpid(pid_counter, &status, WUNTRACED); //printf("retrieve the child process\n"); } return 1;}int builtin_alias(char ** args){ //printf("builtin func alias\n"); int j; //for(j=0;j<command_length-1;j++){ // printf("token: %s ",args[j]); // } //check if the alias is not exist in the alias table int res01; res01=check_table(args[2]); //printf("whether the alias exist no not: %d \n",res01); //check if the alias is a command int res02; res02 = is_fileexist(args[2]);// -1 not exist; 0 exist //printf("whether the alias is a command: %d \n",res02); //check if the command is a existed command int res03; res03 = is_fileexist(args[1]); //printf("whether the command is a existed command %d \n ",res03); if(res01) { printf("the alias:%s is already existed ...\n ",args[command_length-2]); return 1;} if(res02 == 0) { printf("the alias:%s itself is a command \n",args[command_length-2]); return 1;} if(res03 == -1){ printf("the command:%s not found\n",args[1]); return 1;} //save the command and alias to hardware char * command; command= (char*)malloc(BUFFSIZE); //copy int t; for(t=1;t<command_length-2;t++) strcat(command,args[t]); //printf("the command is :%s \n",command); printf("the alias has been saved\n"); return 1; }int check_table(char * alias){ //check if the alias exist return 0;//not existed}int builtin_help(char ** args){ printf("there are some helpful hints:\n the builtin functions are as follows\n"); int i; for (i = 0; i < num_builtin(); i++) { printf(" %s ", builtin_str[i]); } printf("\nfor other hints please check the document.\n");}
0 0
- c 实现的shell
- shell排序的c实现
- 实现求某天的前一天操作(C++,shell)
- shell排序算法的C/C++实现
- Linux Shell命令的C语言实现
- 用c实现的简单linux shell
- Linux C实现简单的shell
- C语言实现一个精简的shell
- shell排序C实现
- Linux下 Mini-shell的实现(C/C++)
- 用c语言的实现一个简单的交互式shell
- C 语言实现shell里的ls命令
- 在C语言中调用shell命令的实现方法
- C语言获取Shell返回结果的实现方法
- linux c实现简单shell
- Shell Sort C语言实现
- C语言实现shell框架
- C-shell的例子
- B树,B-树,B+树,B*树
- Esper之事件——篇2(esper Reference)
- Android 仿酷狗滑动控件实现 流畅运行
- 使用全局变量的四种方式:extern、AppDelegate、定义单例对象、NSUserDefaults 和单例工厂的使用方法
- Opengl Intro - glViewport
- c 实现的shell
- 反渗透设备:反渗透设备工艺先进
- IRQ与FIQ的区别
- Eclipse中注释部分的签名
- BZOJ 1483 [HNOI2009]梦幻布丁 链式前向星+启发式合并
- Java 字符的验证
- TelephonyManager类的方法详解
- java使用poi处理excel防止数字变成科学计数法的形式
- 反渗透设备:反渗透设备回收率高