欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

minishell全过程

程序员文章站 2022-07-10 15:41:50
...
#include <stdio.h>
#include <unistd.h>

void show()//程序开始输出与shell一样的命令行
{
    char path[256]={0};/创建buf存储当前路径
    getcwd(path,sizeof(path));//调用getcwd获得当前路径
    printf("[email protected]:%s$ ",path);//存放在缓存区
    fflush(stdout);       //立即输出缓存区
}

开始界面的设置

minishell全过程

 总体的所有文件

难点在于对于输入命令的解析,判断。mmmm

#include <string.h>
#include <stdio.h>
#include "show.h"//前面所设置的显示界面头文件
#include "docmd.h"//后面执行命令的头文件

int proccmd()//命令解释函数
{
    char cmd[512]={0};//存储用户输入的命令
    char* arg[4]={0};//定义指针数组,先分析命令最长不超过四个,所以定义四个指针
    while(1)
    {
        show();
        fgets(cmd,sizeof(cmd),stdin);//输入命令比如ls  敲\n
        cmd[strlen(cmd)-1]='\0';//去掉\n

        arg[0]=strtok(cmd," ");//用strtok函数将输入的命令用空格断开
        if(NULL == arg[0])
        {
            continue;//这是判断如果用户输入的是空格那么跳过此次循环从新开始下一次,相当于又把命 
                     //令行输出一边
        }
        else
        {
            break;//如果命令不为空跳出while循环
        }

    }
    arg[1]=strtok(NULL," ");//分别让剩下的三个指针指向分割下来的命令
    arg[2]=strtok(NULL," ");
    arg[3]=strtok(NULL," ");

    int ret = docmd(arg);//调用执行命令函数并且接收一下执行命令函数的返回值,判断是否成功
    
	return ret;
}

命令分解(解释函数)

#include <string.h>
#include "mingling.h"
#include "ll.h"//写的ll命令的头文件
#include "cat.h"//cat头文件
#include "ln.h"
#include "touch.h"//各种命令的头文件
#include "rm.h"
#include "mv.h"

int  docmd(char* arg[4])//传入刚才的指针数组
{
    if(0 == strcmp("ls", arg[0]))//因为是字符串所以用strcmp比较
    {
        dols(arg);//ls ls/etc。ls有两种可能
    }
    else if(0 == strcmp("cp", arg[0]))//cp命令
    {
        docp(arg);//ls ls/etc
    }
    else if(0 == strcmp("cd", arg[0]))
    {
        docd(arg);//ls ls/etc
    }
    else if(0 == strcmp("quit",arg[0]))//退出程序命令
    {

        return 1;//返回1程序结束,其他成功返回0
    }
	else if(0 == strcmp("ll",arg[0]))
	{
		doll(arg);
	}
	else if(0 == strcmp("cat",arg[0]))
	{
		docat(arg);
	}
	else if(0 == strcmp("ln",arg[0]))
	{
		doln(arg);
	}
	else if(0 == strcmp("touch",arg[0]))
	{
		dotouch(arg);
	}
	else if(0 == strcmp("mv",arg[0]))
	{
		domv(arg);
	}
	else if(0 == strcmp("rm",arg[0]))
	{
		dorm(arg);
	}

    return 0;
}

 各种命令调用函数,这里我大概写了11个命令,ls,cp,ll,touch,mv等......

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>

int Mystat(char *filename)
{
	struct stat st;
	int ret = stat(filename,&st);
	if(-1 == ret)
	{
		printf("stat error\n");

		return -1;
	}

	if(S_ISREG(st.st_mode))
	{
		fputc('-',stdout);
	}
	else if(S_ISDIR(st.st_mode))
	{
		fputc('d',stdout);
	}
	else if(S_ISCHR(st.st_mode))
	{
		fputc('c',stdout);
	}
	else if(S_ISBLK(st.st_mode))
	{
		fputc('b',stdout);
	}
	else if(S_ISFIFO(st.st_mode))
	{
		fputc('p',stdout);
	}
	else if(S_ISLNK(st.st_mode))
	{
		fputc('l',stdout);
	}
	else if(S_ISSOCK(st.st_mode))
	{
		fputc('s',stdout);
	}
	if(st.st_mode &S_IRUSR )
    {
        fputc('r',stdout);
    }
    else 
    {
        fputc('-',stdout);
    }
    if(st.st_mode &S_IWUSR )
    {
        fputc('w',stdout);
    }
    else 
    {
        fputc('-',stdout);
    }
    if(st.st_mode &S_IXUSR )
    {
        fputc('x',stdout);
    }
    else 
    {
        fputc('-',stdout);
    }
	 if(st.st_mode &S_IRGRP )
    {
        fputc('r',stdout);
    }
    else 
    {
        fputc('-',stdout);
    }
    if(st.st_mode &S_IWGRP )
    {
        fputc('w',stdout);
    }
    else 
    {
        fputc('-',stdout);
    }
    if(st.st_mode &S_IXGRP )
    {
        fputc('x',stdout);
    }
    else 
    {
        fputc('-',stdout);
    }
	 if(st.st_mode &S_IROTH )
    {
        fputc('r',stdout);
    }
    else
    {
        fputc('-',stdout);
    }
    if(st.st_mode &S_IWOTH )
    {
        fputc('w',stdout);
    }
    else
    {
        fputc('-',stdout);
    }
    if(st.st_mode &S_IXOTH )
    {
        fputc('x',stdout);
    }
    else
    {
        fputc('-',stdout);
    }


	struct tm *tm_info = localtime(&st.st_mtime);//获取当地时间
	 uid_t uid =1000;
    struct passwd * pw = getpwuid(uid);
    if(NULL == pw)
    {
        printf("getpwuid error\n");
        return 1;
    }
	
	gid_t gid =1000;//获得linux用户名,不然只是id号1000,与系统不一致
    struct group * gr = getgrgid(gid);
    if(NULL == gr)
    {
        printf("getgrgid error\n");
        return 1;
    }
    //仿照linux的ll输出样板,进行输出
	printf(" %lu %s %s %lu %4d-%02d-%02d %02d:%02d:%02d %s\n",st.st_nlink,
			pw->pw_name,gr->gr_name,st.st_size,tm_info->tm_year+1900,tm_info->tm_mon+1,tm_info->tm_mday
           ,tm_info->tm_hour,tm_info->tm_min,tm_info->tm_sec,filename);

	return 0;
}

int doll(char *arg[])//命令名,命令的具体函数
{
	DIR *dir;
	if(NULL != arg[1])
	{
		dir = opendir(arg[1]);//判断是不是当前路径,不是就切换
		chdir(arg[1]);
	}
	else
	{
		dir = opendir("./");//如果后面不跟参数默认为当前路径
	}
	if(NULL == dir)
	{
		printf("opendir erreor\n");//空就为打开失败
		return -1;
	}

	while(1)
	{
		struct dirent *info = readdir(dir);//读取目录
		if(NULL == info)
		{
			break;
		}

		Mystat(info->d_name);
	}

	closedir(dir);//不能忘记关闭目录

	printf("目录详细信息,如上^\n");//这个是我自己加的一个输出显示

	return 0;
}

这是ll命令的.c函数

#ifndef __LL_H__//判断是否已经进行过声明,如果没有就声明,有就不声明了
#define __LL_H__

extern int doll(char *arg[]); //定义一个外部的函数
#endif

这是ll命令的.h文件

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include "mingling.h"

int dols(char* arg[])
{
    // ls  ls /etc
	int i = -1;
    DIR* dir =NULL;
    if(NULL == arg[1])
    {
        dir =opendir("./");
    }
    else
    {
        dir =opendir(arg[1]);
    }

    if(NULL == dir)
    {
        printf("打开目录失败\n");
        return 1;
    }
    while(1)
    {
        struct dirent  * info = readdir(dir);
        if(NULL == info)
        {
            break;
        }
		i++;
		if(0 == i%8)
		{
			printf("\n");
		}
        printf("%-12s   ",info->d_name);
    }

    closedir(dir);

	printf("\n");
	printf("目录展开成功,如上^\n");

    return 0;

}

int docp(char* arg[])
{
    // cp 1 2
    int srcfd = open(arg[1],O_RDONLY);
    int dstfd = open(arg[2],O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(-1 ==srcfd || -1 == dstfd)
    {
        printf("open error\n");
        return 1;
    }
    char buf[1024]={0};
    while(1)
    {
        int rd_ret = read(srcfd,buf,sizeof(buf));
        if(rd_ret<=0)
        {
            break;
        }
        write(dstfd,buf,rd_ret);
    }
    close(srcfd);
    close(dstfd);

	printf("文件复制成功\n");
	printf("%s-->%s\n",arg[1],arg[2]);

    return 0;

}


int docd(char* arg[])
{
    //cd   cd /etc
    if(NULL == arg[1])
    {
        chdir("/home/linux");
		printf("成功进入到家目录\n");
    }
    else
    {
        int ret = chdir(arg[1]);
        if(-1 == ret)
        {
            perror("chdir");
        }

		printf("成功进入到%s\n",arg[1]);
    }


    return 0;
}

这段代码实现了ls,cd,cp,这是.c文件

#ifndef __MINGLING_H__
#define __MINGLING_H__
extern int dols(char* arg[]);
extern int docp(char* arg[]);
extern int docd(char* arg[]);
#endif

这是ls,cd,cp的.h文件

#include <stdio.h>

int docat(char *arg[])
{

	FILE *fp = fopen(arg[1], "r");
	if (NULL == fp)
	{
		printf("fail to fopen\n");
		return -1;
	}

	while (1)
	{
		int ch = fgetc(fp);
		if (EOF == ch)
		{
			if (feof(fp))
			{
				break;
			}
			else if (ferror(fp))
			{
				printf("fgetc error\n");
				return -1;
			}
		}
		fputc(ch, stdout);
	}

		printf("文件详细信息如上^\n");
	fclose(fp);

	return 0;
}

这是cat.c

声明就和之前ll.h一样

其他的就比较简单不一一说明了,如有需要请留言