在Linux环境下模拟实现简单命令解释器

在Linux环境下模拟实现简单命令解释器,第1张

你是要这几个命令的实现吗?

我以前写过一个pwd的。。。你可以看看

其实这都是一些系统调用。。。。。你要搞清楚。。。。好好去看看高编那块内容

以下是pwd命令的实现代码:

伪代码:

pwd

得到.的i-node

得到..的i-node

如果.和..的i-node不同

转到父节点(chdir)

显示父目录的pwd

显示/,加上.对应的目录名(链接名)

(opendir,readdir,closedir)

否则

结束,父目录是/

*/

#include <stdio.h>

#include <dirent.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc, const char *argv[])

{

struct dirent *s,*i1,*i2,*i3

DIR *p

while(1){

p=opendir(".")

while( (s=readdir(p))!=NULL){

if((strcmp(".",s->d_name)==0))

i1=s

if((strcmp("..",s->d_name)==0))

i2=s

}

if(i1->d_ino!=i2->d_ino)

{

chdir("..")

p=opendir(".")

while(i3=readdir(p))

{

if(i3->d_ino==i1->d_ino)

printf("/%s",i3->d_name)

}

}

else

{

printf("/")

break

}

}

closedir(p)

printf("\n")

return 0

}

姓名:罗学元       学号:21181214375     学院:广州研究院

【嵌牛导读】shell命令解释器该包含哪些部分

【嵌牛鼻子】shell命令解释器该包含哪些部分

【嵌牛提问】shell命令解释器该包含哪些部分

我们所做的这个简单的shell命令解释器可以实现简单的常用的基本命令,如ls、pwd、cd、cd - 、cd ~ 等

根据简单命令的定义,它的第一个参数是要执行的命令,后面的参数作为该命令的参数。

要执行的命令有两种情况:

一种是外部命令: 也就是对应着磁盘上的某个程序,例如 pwd、ls等等。对于这种外部命令,我们首先要到指定的路径下找到它,然后再执行它。

另一种是内部命令:内部命令并不对应磁盘上的程序,例如cd等等,它需要shell自己来决定该如何执行。例如对 cd 命令,shell就应该根据它后面的参数改变当前路径。

对于外部命令,需要创建一个子进程来执行它,本质就是fork+exec

#include <stdio.h>

#include <stdlib.h>

#include <assert.h>

#include <string.h>

#include <pwd.h>

#include <sys/utsname.h>

#include <sys/types.h>

#include <unistd.h>

#define MAX 10

#define STRLEN 128

#define PATH "/bin/" //系统bin路径位置

char OLDPWD[STRLEN]={0}//记录上一次的命令,为了cd -这条命令

//================================================================================

//每次敲回车输出当前所在用户信息

//普通用户和root用户的提示符区别

void Printf_Info()

{

char flag='$'

struct passwd *pw=getpwuid(getuid())

assert(pw!=NULL)

//uid为0则为root用户

if(pw->pw_uid==0)

{

flag='#'

}

struct utsname hostname//主机名

uname(&hostname)

char node[STRLEN]={0}

strcpy(node,hostname.nodename)//获取网络上的名称

char* name=strtok(node,".")

//获取绝对路径

char path[STRLEN]={0}

getcwd(path,STRLEN-1)

char*p=path+strlen(path)//p指向绝对路径的末尾

while(*p!='/')

{

p--

}

//p指向路径末尾往前的第一个‘/’位置处

if(strlen(path)!=1)

{

p++//++前,p->'/'

}

if(strcmp(path,pw->pw_dir)==0)

{

p="~"

}

printf("\033[32mMyBash[%s@%s %s]%c\033[0m",pw->pw_name,name,p,flag)

//  \033[4731mThis is a color test\033[0m  设置打印结果的颜色

    fflush(stdout)

}

//================================================================================

void Mycd(char*path)

{

//第一个字符串为cd而第二为空 如:cd 则结束本轮循环

if(path==NULL)

{

exit(0)

}

//cd ~ 回到用户根目录

if(strcmp(path,"~")==0)

    {

        struct passwd*pw=getpwuid(getuid())

        path=pw->pw_dir

    }

    //cd - 回到上一次的位置

    if(strcmp(path,"-")==0) 

    {

      //若是第一次输入命令,则cd -命令不存在!

        if(strlen(OLDPWD)==0)

        {

            printf("\033[31mMyBash:cd:OLDPWD not set\n\033[0m")

            return

        }

        //否则把上一次的命令给path

        path=OLDPWD

    }

    //getpwd记录当前工作目录的绝对路径

    char oldpwd[STRLEN]={0}

    getcwd(oldpwd,STRLEN-1)

if(-1==chdir(path))//反之则不是空,则通过chdir系统调用进入到该目录中

    {

        char err[128]="\033[31mMybash: cd \033[0m"

        strcat(err,path)

        perror(err)

    }

    //每次执行完cd命令后,把工作路径赋给OLDPWD

    strcpy(OLDPWD,oldpwd)

}

//================================================================================

//命令分割函数

void Strtok_cmd(char*buff,char*myargv[])

{

char *s=strtok(buff," ")//分割输入的字符串

if(s==NULL) //如果s为空,则进入下一轮循环

{

exit(0)

}

myargv[0]=s//把分割出来的第一个字符串放在myargv[0]中

int i=1

while((s=strtok(NULL,""))!=NULL) //把后续分割出来的字符串依次存放在数组中

{

myargv[i++]=s

}

}

//===============================================================

int main()

{

while(1)

{

char buff[128]={0}

Printf_Info()

//从终端获取命令存入buff中

fgets(buff,128,stdin)

buff[strlen(buff)-1]=0

char *myargv[MAX]={0}

//分割输入的命令

Strtok_cmd(buff,myargv)

//如果输入exit则退出循环

if(strcmp(myargv[0],"exit")==0)

{

exit(0)

}

//如果分割出来的第一个字符串为cd

else if(strcmp(myargv[0],"cd")==0)

{

Mycd(myargv[1])

continue

}

//若是系统调用,直接替换fork+exec

pid_t pid=fork()

assert(pid!=-1)

if(pid==0)

{

char path[256]={0}

if(strncmp(myargv[0],"./",2)!=0 &&strncmp(myargv[0],"/",1)!=0)

{

//先把路径放入path中

strcpy(path,PATH)

}

//进行命令拼接,路径+名称

strcat(path,myargv[0])

//替换进程 例如:/bin/ls

execv(path,myargv)

perror("\033[31mexecv error\033[0m")

}

//处理僵死进程

else

{

wait(NULL)

}

}

}

运行结果如下 :

异常处理如下:

若是第一次运行程序,则不能使用cd - 命令,因为此时还没有历史路径

若进入一个不存在的目录则会报错,没有这个文件或目录

若直接输入一个不存在的无法识别的命令,也会报错。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/9022236.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-24
下一篇 2023-04-24

发表评论

登录后才能评论

评论列表(0条)

保存