HDU网安操作系统课程设计 实验三 模拟shell

本文介绍了作者编写的Myshell程序,它模拟了Linux shell的流程,包括cat、cp、ls、ls-l、pwd等命令,利用宏定义和switch语句选择外部命令,并通过opendir、readdir、closedir等API实现目录遍历和文件信息展示。同时,cal、ls-l和ls的具体实现也被详细阐述。

图1:模拟shell的流程图

实现了cat、cp、ls、ls -l、pwd等命令的功能,通过宏定义以及switch语句实现了对外部命令文件的选择,主函数中while(1)实现模拟多次输入命令,使用opendir、readdir、closedir、数个储存了文件详细信息的结构体,如dirent、stat、tm、passwd、group完成ls和ls -l的功能。

Myshell.c 

#include<stdio.h> 
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<ctype.h>
#include<sys/wait.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/types.h>

#define cal 1
#define cat 2
#define cp 3

void Myfork(int flag, char* const argv[], char* const envp[])
{
	if(fork() == 0)
	{
		switch(flag)
		{
			case cal:
				if(execve("cal", argv, envp) == -1)
					printf("Exec Failed");
				break;
			case cat:
				if(execve("cat", argv, envp) == -1)
					printf("Exec Failed");
				break;
			case cp:
				if(execve("cp", argv, envp) == -1)
					printf("Exec Failed");
				break;
				
			default:
				break;
		}
	}
	wait(NULL);
}

void Myls(void)
{
	DIR* dir = opendir(".");
    struct dirent* info = NULL;
    while((info = readdir(dir)) != NULL)
    {
    	if(strcmp(info->d_name,".") == 0)
            continue;
        if(strcmp(info->d_name,"..") == 0)
            continue;
    	printf("%s ",info->d_name);
	}
    closedir(dir);
    printf("\n");
}
//DIR *opendir(const char name);
//struct dirent readdir(DIR dir);
//int closedir(DIR *dir);

void Myls_l(void)
{
	DIR* dir = opendir(".");
    struct dirent* info = NULL;
    struct tm* time = NULL;
    struct passwd* pw = NULL;
    struct group* gp = NULL;
    struct stat st;
    
    while((info = readdir(dir)) != NULL)
    {
    	if(strcmp(info->d_name,".") == 0)
            continue;
        if(strcmp(info->d_name,"..") == 0)
            continue;
		    
        stat(info->d_name, &st);
		pw = getpwuid(st.st_uid);                        
        gp = getgrgid(st.st_gid);
        time = localtime(&st.st_mtime);
		    
        switch (st.st_mode & S_IFMT)               //判断文件类型
        {
            case S_IFBLK:  printf("b");    break;  //块设备类型	               
            case S_IFCHR:  printf("c");    break;  //字符类型		               
            case S_IFDIR:  printf("d");    break;  //目录类型       	               
            case S_IFIFO:  printf("p");    break;  //管道类型       	               
            case S_IFLNK:  printf("l");    break;  //链接类型         	               
            case S_IFREG:  printf("-");    break;  //文件类型    		               
            case S_IFSOCK: printf("s");    break;  //套接字类型           			              
            default:       printf("?");   break;  //无法识别类型 			               
        }
        
        for(int i=8; i>=0; i--)
        {
        	if(st.st_mode & (1 << i))
        	{
        		switch(i % 3)
        		{
        			case 2:    printf("r");    break;//文件该处具有读权限			               
                    case 1:    printf("w");    break;//文件该处具有写权限				          
                    case 0:    printf("x");    break;//文件该处具有执行权限
				}
			}
			else
				printf("-");
		}
		
		printf(" %d ", st.st_nlink);
		
		printf("%s ", pw->pw_name);
        printf("%s ", gp->gr_name);
        
        printf("%6d ", st.st_size);
        
		printf("%2d月 %2d日 %2d:%2d ", time->tm_mon + 1, 
		time->tm_mday, time->tm_hour, time->tm_min);

    	printf("%s\n",info->d_name);
	}
    closedir(dir);
}

void Mypwd(void)
{
	char buffer[1024];
	getcwd(buffer, 1024);
	printf("%s\n", buffer);
}

int main(int argc, char* const argv[], char* const envp[])
{
	char cmd[20] = {0};
    while(1)
    {
        printf("[Myshell]# ");
        scanf("%s",cmd);
        if(strcmp(cmd,"exit") == 0)
            exit(0);
        else if(strcmp(cmd,"ls-l") == 0)
        	Myls_l();
		else if(strcmp(cmd,"ls") == 0)
        	Myls();
		else if(strcmp(cmd,"pwd") == 0)
        	Mypwd();
		else if(strcmp(cmd,"cal") == 0)
        	Myfork(cal, argv, envp);
		else if(strcmp(cmd,"cat") == 0)
        	Myfork(cat, argv, envp);
		else if(strcmp(cmd,"cp") == 0)
        	Myfork(cp, argv, envp);
        else
        	printf("invalid cmd");
    }
    return 0;
}

 cal.c 其实就是一个简单的加减乘除的计算器

#include<stdio.h>

int main()
{
	int flag = 1,sum,i;
	char f;
	scanf("%d",&sum);
	while(1)
	{
		scanf("%c",&f); 
		if(f == '=') break;
		scanf("%d",&i);
		if(f == '+') sum += i;
		else if(f == '-') sum -= i;
		else if(f == '*') sum *= i;
		else if(f == '/') 
		{
			if(i == 0 ) flag = 0;
			else sum /= i;
		}
		else flag = 0;
	}
	if(flag == 0) printf("ERROR");
	else printf("%d",sum);
	return 0;
}

cat.c 实现linux中查看文件内容的功能

#include<stdio.h>
#include<string.h>

int main()
{
	FILE *fp;
	char ch;
	char filename[20] = {0};
	scanf("%s",filename);
	fp = fopen(filename, "r");
	if(fp==NULL)
		printf("can not open!\n");
	else
	{
		fscanf(fp,"%c",&ch);
		while(!feof(fp))
		{
			putchar(ch);
			fscanf(fp,"%c",&ch);
		}
		fclose(fp);
	}
	printf("\n");
	return 0; 
}

cp.c 实现linux中复制文件的功能 可以是相对路径也可以是绝对路径

#include <stdio.h>
#include <stdlib.h>

long FileCopy(FILE* filesource, FILE* filetarget)
{
	int BufferLen = 1024;
	char* mbuffer = (char*)malloc(BufferLen);
	long sumbytes=0;
	
	while(fread(mbuffer, 1, 1, filesource) > 0)
	{
	    sumbytes += 1;
	    fwrite(mbuffer,1,1,filetarget);
	}
	fflush(filetarget);
	free(mbuffer);
	
	return  sumbytes;
}

int main()
{
    char source[60]; 
    char target[60]; 
    long filesize = 0;
    
    scanf("%s", source);
    scanf("%s", target);
    FILE* filesource = fopen(source,"r+");
    FILE* filetarget = fopen(target,"w+");
	filesize = FileCopy(filesource, filetarget); 
    if(filesize == 0)
    	printf("FileCopy Failed\n");

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值