• linux c语言编写一个shell壳


    目的:我们要用c语言编写一个shell可以运行在linux机器上的。

    介绍:shell所在的层次

    我们要做的是操作系统,用于用户与操作系统进行交互的myhsell

    思路:用户输入  一行字符串,我们先将其进行切割为一段段的字符串,然后一一匹配判断是内置命令还是 外置命令。内置命令是写在shell程序里面的,而外置命令是单独写的程序,用exec族系统调用。

    好,那么下面我们看代码:

      1 #include<stdio.h>
      2 #include<unistd.h>
      3 #include<sys/wait.h>
      4 #include<stdlib.h>
      5 #include<pwd.h>
      6 #include<string.h>
      7 #define MAX_CMD 255
      8 #define MAX_DIR_NAME 255
      9 
     10 //help帮助文档
     11 int helps(char *inputs[],int i){
     12         if(i==1){
     13 printf("These shell commands are defined internally.  Type 'help' to see this list.
    ");
     14 printf("Type 'help name' to find out more about the function 'name'
    ");
     15        return 1;
     16         }
     17         else if (strcmp(inputs[1],"pwd")==0){
     18                 printf("pwd:打印当前绝对路径
    ");
     19        return 1; 
     20         }else if(strcmp(inputs[1],"cd")==0){
     21         printf("cd:可以切换当前目录
    "); 
     22         return 1;
     23         } else if(strcmp(inputs[1],"exit")==0){
     24         printf("exit:退出shell
    "); 
     25         return 1;
     26         } else if(strcmp(inputs[1],"echo")==0){
     27         printf("echo:显示并换行
    "); 
     28         return 1;
     29         } 
     30                  return 0;
     31 }                
     32 
     33 
     34 
     35 //编写一个外置命令函数专门写内置指令 
     36 //返回值为1时为成功执行外置指令 
     37 //返回0时为执行失败不是外置命令
     38 int build_out_command(char *inputs[],int i){
     39 char path[]="/root/Desktop/codec/myshell/";
     40 char buffer[10];
     41 bzero(buffer,10);
     42 int fd[2];
     43 if(pipe(fd)==-1){
     44 return 0;
     45 }
     46 int rc=fork();
     47 if(rc<0){
     48 return 0;
     49 }
     50 else if(rc==0){
     51 //关掉读 
     52 close(fd[0]);
     53 if(execv(strcat(path,inputs[0]),inputs)<0){
     54 write(fd[1],"false",10);
     55 }else{
     56 write(fd[1],"true",10);
     57 }
     58 close(fd[1]);
     59 exit(0);
     60 //结束子进程 
     61 }else if(rc>0){
     62 close(fd[1]);
     63 wait(NULL);
     64 read(fd[0],buffer,10);
     65 if(strcmp(buffer,"false")==0){
     66 return 0;
     67 }else{
     68 return 1;
     69 }
     70 }
     71 }
     72 
     73 
     74 
     75 
     76 //编写一个内置命令函数专门写内置指令
     77 //返回值为1时为成功执行内置指令 
     78 //返回0时为不是内置命令 
     79 int build_in_command(char cmdstring[],char *inputs[],int i){
     80 //1.实现exit退出
     81 //printf("inputs[0]=%s",inputs[0]);
     82 if(strcmp(inputs[0],"exit")==0){
     83 printf("Bye.
    ");
     84 exit(0);
     85 }
     86 //2.实现pwd返回目录
     87 else if(strcmp(inputs[0],"pwd")==0){
     88 char path[MAX_DIR_NAME];
     89 memset(path,0,MAX_DIR_NAME);
     90 printf("%s
    ",getcwd(path,MAX_DIR_NAME));
     91 return 1;
     92 }
     93 //3.实现cd改变目录 
     94 else if(strcmp(inputs[0],"cd")==0){
     95         if(chdir(inputs[1])==0){
     96                 return 1;
     97         }
     98 
     99 }
    100 //4.echo显示并换行
    101 else if(strcmp(inputs[0],"echo")==0){
    102         char *buf1=cmdstring;
    103         while(*buf1==' '){
    104                 buf1++;
    105         }
    106         while(*buf1!=' '){
    107                 buf1++;
    108         }
    109         while(*buf1==' '){
    110                 buf1++;
    111         }
    112 
    113         printf("%s
    ",buf1);
    114         return 1;
    115 
    116 }
    117 //help帮助文档 
    118 else if(strcmp(inputs[0],"help")==0){
    119 int i1= helps(inputs,i);
    120 return i1;
    121 }
    122 
    123 
    124 
    125 return 0;
    126 }
    127 
    128 
    129 struct passwd *pwd1;
    130 pwd1=getpwuid(getuid());
    131 char path[MAX_DIR_NAME];
    132 memset(path,0,MAX_DIR_NAME);
    133 getcwd(path,MAX_DIR_NAME);
    134 int i=0;
    135 int len=strlen(path);
    136 char *p=path;
    137 
    138 int i1=len;
    139 for(i1;i1>=0;i1--){
    140 if(path[i1]=='/'){
    141 path[i1]='';
    142 break;
    143 }
    144 }
    145 for(i;i<=i1;i++){
    146 p++;
    147 }
    148 printf("<%s@localhost :%s#> ",pwd1->pw_name,p);
    149 } 
    150 
    151 
    152 
    153 
    154 
    155 //解析指令 例如ls -l  ,将该指令分为ls和-l两个字符串分别存储在inputs字符串数数组
    156 //返回值是存储的个数最后一位为NULL一共i+1个
    157 int parsecommand(char buf[],char *inputs[]){
    158 bzero(inputs,MAX_CMD);
    159 int in=0;
    160 char *p=buf;
    161 int i=0;
    162 while(*p==' '){
    163     p++;
    164     i++;
    165 }
    166 inputs[in]=p;
    167 in++;
    168 int i1=i;
    169 int len=strlen(buf);
    170 for(i;i<=len;i++){
    171 if(buf[i]==' '){
    172     buf[i]='';
    173 
    174 }
    175 }
    176 i1++;
    177 p++;
    178 for(i1;i1<=len;i1++,p++){
    179 if(buf[i1]!=''){
    180     if(buf[i1-1]==''){
    181         inputs[in]=p;
    182         in++;
    183     }
    184 
    185 }
    186 }
    187 inputs[in]=NULL;
    188 
    189 return in;
    190 
    191 //一共有in+1个字符串,最后一位NULL
    192 
    193 }
    194 
    195 
    196 //整体执行函数分为内部命令和外部命令
    197 //内部命令直接调用函数执行就好
    198 //外部命令自己编写在另一个文件,通过gcc编译
    199 //在该函数里通过exec家族函数调用执行
    200 int  eval(char cmdstring[]){
    201 char *inputs[MAX_CMD];
    202 char buf[MAX_CMD];
    203 strcpy(buf,cmdstring);
    204 int i=parsecommand(buf,inputs);
    205 //下面实现一些功能
    206 //调用内置外置函数 
    207 
    208 int returnin=build_in_command(cmdstring,inputs,i);
    209 if(returnin==0){
    210 int rtout=build_out_command(inputs,i);
    211 if(rtout==0){
    212 printf("%s: not find command
    ",cmdstring);
    213 return 0;
    214 }
    215 }
    216 return 1;
    217 }
    218 
    219 
    220 
    221 
    222 //main函数通过循环不断接受用户数据
    223 //调用eval功能函数实现
    224 int main(int argc,char *argv[]){
    225 system("stty erase ^H");
    226 char cmdstring[MAX_CMD];
    227 bzero(cmdstring,MAX_CMD);
    228 while(1){
    229 attention();
    230 fflush(stdout);
    231 //读取输入流
    232 fgets(cmdstring,MAX_CMD,stdin);
    233 //如果没有输入从新开始
    234 if(cmdstring[0]=='
    '){
    235 continue;
    236 }
    237 int i=0;
    238 for(i;cmdstring[i]!='
    ';i++){
    239     ;
    240 }
    241 cmdstring[i]='';
    242 
    243 int p=eval(cmdstring);
    244 }
    245 return 0;
    246 
    247 }
    248   

    外置命令单独写文件

    对myshell运行使用几个命令如下:

    代码从main函数开始看,如果有不明白的欢迎给我留言哦!!!

     

  • 相关阅读:
    FCKeditor的问题
    每天学习一点点(2010年二月)
    Excel使用小技巧
    JavaScript 取页面属性
    附加 数据库错误 5120
    CSS中元素水平居中显示的方法
    css中height:100%不起作用的解决方法
    SQL SERVER数据库开发之存储过程应用(转载)
    双路由器双小型交换机组建公司网络,2个公网IP上网案例(转载)
    如何解决VS2005没有代码智能提示(联想)的问题(转载)
  • 原文地址:https://www.cnblogs.com/lhyzdd/p/13997373.html
Copyright © 2020-2023  润新知