操作系统实践 job5

结果展示

可以实现>,>>,<重定向,pwd,cd,exit操作

有一定的健壮性比如:可以识别">log"和"> log"

目录

结果展示

job5/sh2.c

main()

mysh2()

child()

redirect()

知识点

思路


job5/sh2.c

实现shell程序,要求在第1版的基础上,增加文件重定向功能

  • 重定向输入
  • 重定向输出
  • 重定向追加

指路job3:实现了基础的sh1.c

操作系统实践 job3_LarsGyonX的博客-CSDN博客

然后来康康job5吧!老师在课上给了一个伪代码:

首先分割出每一行命令,实现内置命令:exit,pwd,cd,然后创建子进程,实现systerm以及重定向功能。

 个人在老师的思路上进行了补充和完善。

main()

首先是主函数:分割每一行字符串,并将该行命令传给mysh2.

int main()
{
	while(1)
	{
		char command[100]={0};
		char c;
		printf(">");
		int i=0;
		do{
			c=getchar();
			command[i]=c;
			i++;
		}while(c!='\n');
		command[i-1]=0;
		mysh2(command);
	}
}

mysh2()

分别实现内置功能exit/pwd/cd,然后创建子进程,进入子函数实现systerm功能。这边不理解的看job3博客。

void mysh2(char command[])
{
	//printf("command is %s in mysh2\n",command);
	if(!strcmp(command,"exit"))exit(0);
	else if(!strcmp(command,"pwd"))
	{
		char *path=getcwd(NULL,0);
		printf("Current directory:%s\n",path);
		free(path);
	}
	else if(command[0]=='c'&&command[1]=='d')
	{
		char cd[100]={0};
		strcpy(cd,command+3);
		int error=chdir(cd);
		if(error<0)perror("cd");
		else{
			char *path=getcwd(NULL,0);
			printf("Current directory:%s\n",path);
			free(path);
		}
	}
	else 
	{
		pid_t pid;
		pid=fork();
		if(pid==0)
		{
			child(command);
		}
		wait(NULL);
	}
}

child()

略长,但是思路挺简单的,进一步分割command,检测到>,<,>>就将文件名开始的下标传给redirect重定向函数,(>是0,<是1,>>是2)处理完了以后,将文件名后的下标再传回child函数。

举个例子:cat <log >log1,检测到<是i=4,将其传给redirect提取log的文件名,返回i=7也就是'g'处的下标,进行下一轮检索。

为保证健壮性,讨论了很多可能性,代码较长,但是逻辑非常简单。

注意:先处理重定向,再调用execl,因为得先close(fd)重定向功能才会起作用。

void child(char command[]){
    //printf("command is %s in child\n",command);
    if(command==NULL){
	    printf("Error: wrong command!");
	    exit(0);
    }
    else{
	   // printf("can it been sent here %s\n",command);
	    for(int i =0;command[i]!='\0';i++)
	    {
		    //>log
		    if(command[i]=='>'&&command[i+1]!=' '&&command[i+1]!='>')
		    {
			    i=redirect(i+1,command,0);
		    }
	    	    //> log
		    else if(command[i]=='>'&&command[i+1]==' ')
		    {
			    i=redirect(i+2,command,0);
		    }
		    //<log
		    else if(command[i]=='<'&&command[i+1]!=' ')
		    {
			    i=redirect(i+1,command,1);
		    }
		    //< log
		    else if(command[i]=='<'&&command[i+1]==' ')
                    {
                            i=redirect(i+2,command,1);
                    }
		    //>>log
		    else if(command[i]=='>'&&command[i+1]=='>'&&command[i+1]!=' ')
                    {
                            i=redirect(i+2,command,2);
                    }
		    //>> log
		    else if(command[i]=='>'&&command[i+1]=='>'&&command[i+2]==' ')
                    {
                            i=redirect(i+3,command,2);
                    }
    	   }
	  int error=execl("/bin/sh","sh","-c",command,NULL);
    	  if(error<0)perror("execl");
    }
}

redirect()

重定向函数!

知识点

先回顾一下重点知识

#include <unistd.h>
int dup2(int oldfd, int newfd);

通过复制文件描述符oldfd,创建一个新的文件描述符newfd

newfd和oldfd指向相同的文件

dup2(fd,1);即为下图所示,将标准输出指向文件log,也就是说可以通过标准输出将内容输入或追加到log中。

 ->close(fd)->  

 同理dup2(fd,0)就是通过标准输入将log中的内容提取出来。

思路

  • 首先将文件路径/文件名提取出来
  • 创建/打开文件,注意打开参数的区别!
  • 如果是<就是重定向输入
  • 如果是>就是重定向输出
  • 如果是>>就是重定向添加

最后关闭文件

int redirect(int i,char command[],int flag)
{
	//printf("command is %s in redirect,i=%d\n",command,i);
	char file[100];
	int k=0,j,fd;
        for(j=i;command[j]!=' '&&command[j]!='\0';j++)
        {
               file[k++]=command[j];
        }
        file[k]=0;
	//printf("filename is %s\n",file);
	if(flag==0)
	{
		fd=open(file,O_CREAT|O_RDWR,0666);
        	dup2(fd,1);
        }
	else if(flag==1)
	{
		fd=open(file,O_CREAT|O_RDWR,0666);
		dup2(fd,0);
	}
	else if(flag==2)
	{
		fd=open(file,O_CREAT|O_APPEND,0666);
		dup2(fd,1);
	}
	close(fd);
	return j-1;
}

job1-job5的代码都传在gitee上了,欢迎交流指正~~~~

https://gitee.com/xyx1024/os

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值