实现简单的shell

shell原理

shell就是运用程序替换的原理进行实现的。
何为程序替换?
假如操作系统正在执行某一个程序,然后我们利用程序替换函数指定一个新的程序,让操作系统去执行我们新指定的程序。也就是这样一种情形下,我们fork一个进程,如果fork成功,子进程会和父进程执行相同的代码,而我们创建子进程是希望子进程执行指定的操作,所以需要执行exec族函数。
这里写图片描述

实现简单的shell

实现步骤:
1)采用read函数读取标准输入写到显示器上的信息,并且返回读取到的字符个数,如果返回值大于0,说明有读取到字符,就将读到的字符串的最后加个字符串的结束符\0;否则,结束此次循环。
2)将读取到的字符串按照空格分成多个字符串,放进指针数组argv中,并在指针数组的最后加一个NULL。
3)创建一个子进程,父进程等待子进程执行完程序,子进程执行程序替换函数,关于程序替换函数的选择:我们选择的是execvp函数(因为我们已经知道要执行的程序的文件名,参数也已经全部存储在argv指针数组中)。
获得登录信息的关键函数:
这里写图片描述
这里写图片描述
shell的基本功能:
1)自动获取用户名,主机名,当前目录;
2)可以实现连续按回车的情况;
3)按错命令可以有删除的功能.

代码实现

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<wait.h>
#include<pwd.h>
#include<string.h>

void GetLoginName()       //获取登录名
{
     struct passwd *pwd;
     pwd=getpwuid(getuid());
     printf("[%s@",pwd->pw_name);
}

void GetHostName()      //获取主机名
{
     char name[100]={0};
     gethostname(name,sizeof(name)-1);
     printf("%s",name);
}

void GetDir()           //获取当前工作目录
{ 
     char pwd[100]={0};
     getcwd(pwd,sizeof(pwd)-1);              //pwd保存的是绝对路径
     int len=strlen(pwd);        
     char* p=pwd+len;
     while(*p!='/'&&len--)
     {
          p--;
     }
     p++;
     printf(" %s]#",p);
}


void myShell()
{
     while(1)
     {
          GetLoginName();
          GetHostName();
          GetDir();
          fflush(stdout);

          char line[1024];       //获取输入的命令,并解析
          ssize_t s=read(0,line,1024);
          char* myArgv[10];
          char* start=line;
          myArgv[0]=start;
          int i=1;
          if(s>0)
          {
               while(*start)        //以空格将输入的内容区分开
               {
                    if(isspace(*start))
                    {
                         while(isspace(*start))
                         {
                              *start='\0';
                              start++;
                         }
                         myArgv[i++]=start;
                    }
                    else
                    {
                         start++;
                      }

               }
          }
          else
          {
               continue;
          }
          myArgv[i-1]=NULL;


        pid_t id=vfork();      //fork子进程去执行输入的命令
          if(id==0)
          {

               execvp(myArgv[0],myArgv);
               perror("error ");
          }
          else
          {
               sleep(1);
               wait(NULL);
          }
          printf("\n");
     }
}

int main()
{
     myShell();
     return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值