操作系统上机——实现一个简单的shell

原题见《操作系统—精髓与设计原理(第五版)》一书110页。

 

这里是实现代码。实现了基本的功能,主要通过系统调用,实验环境为Fedora 16 linux 。

//myshell.h

 

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


#define MAX_BUFFER 1024      //字符串长度最大值
#define MAX_ARGS 64          //参数最大数量
#define SWEPARATOR " \n\t"       



//myshell.c

 

/**********************************************************
myshell-basic shell replacement
>my shell
从键盘输入一行字符串,分割字符串并解析为cmd命令
clr 清屏
ls <directory> 列出<directory>目录下面的文件,默认为当前目录
environ 环境变量 
quit 退出
**********************************************************/

#include<myshell.h>

extern char **environ;       

/**********************************************************/

int main(int argc,char** argv)
{
	//system("title MyShell");
	char linebuf[MAX_BUFFER];
	char cmndbuf[MAX_BUFFER];
	char *args[MAX_ARGS];
	char **arg;
	char* prompt="==>";
	while(!feof(stdin))
	{
		system("pwd");
		fputs(prompt,stdout);
		fflush(stdout);
		//输入参数
		if(fgets(linebuf,MAX_BUFFER,stdin))
		{
			arg=args;
			*arg++=strtok(linebuf,SWEPARATOR);//按空格,换行符,制表符等分割字符串		
			while((*arg++=strtok(NULL,SWEPARATOR)));
			if(args[0])//第一个参数存在
			{
				//printf("args[0]:%s\n",args[0]);
				cmndbuf[0]=0;
				//printf("cmndbuf[0]:%c\n%s\n",cmndbuf[0],args[0]);
				//检查是否为系统已经存在的命令
				if(!strcmp(args[0],"clr"))
				{
					strcpy(cmndbuf,"clear");
				}
				else if(!strcmp(args[0],"dir"))
				{					
					strcpy(cmndbuf,"ls ");
					if(!args[1])
					{
						args[1]=".";//没输入参数默认为当前目录
					}
					strcat(cmndbuf,args[1]);
					//printf("%s",cmndbuf);
				}
				else if(!strcmp(args[0],"help"))
                                {
                                        strcpy(cmndbuf,"more ./readme");//显示当前目录下的readme
                                }
				else if(!strcmp(args[0],"pause"))
                                {
					//printf("Press enter to continue...\n");//提示暂停,直到按下回车键
					strcpy(cmndbuf,"read -n 1 -p \"Press any key to continue...\"");
				//	char temp=malloc(sizeof(char));
				//	scanf("%c",&temp);
				//	while(strcmp(temp,'\n'))
				//	{
				//		scanf("%c",&temp);
				//	}
										
                                }

				else if(!strcmp(args[0],"cd"))
                                {
                                        if(!args[1])
                                        {
                                                args[1]=".";//没输入参数默认为当前目录
                                        }
					int result=chdir(args[1]);
					if(result<0)
					{printf("Error:directory not exist!\n");}
 				}                                        
				else if(!strcmp(args[0],"environ"))
				{
                  			char** envstr=environ;
		                    while(*envstr)
                		    {
		                          printf("%s\n",*envstr);
                		          envstr++;
		                    }
					
				}
				else if(!strcmp(args[0],"quit"))
				{
					break;//return 0,退出循环
				}
				else      //其他命令
				{	
					int i=1;
					strcpy(cmndbuf,args[0]);
					while(args[i])
					{
						strcat(cmndbuf," ");
						strcat(cmndbuf,args[i++]);
					}
				}
				//调用系统命令
				if(cmndbuf[0])
				{
					system(cmndbuf);
				}
	
			}
		}
	}
return 0;
	
} 

其中的cd命令通过chdir函数实现。通过查资料和实验得知,在shell里面直接用cd命令实现工作目录切换不可以,因为system(command)是通过创建子进程实现系统命令调用,原则上是子进程执行cd命令,shell并未改变目录,因此必须通过其他方式比如调用chdir函数实现。

 

以下是makefile

#makefile
myshell:myshell.c myshell.h
gcc -I. myshell.c -o myshell

 

以下是readme

//readme

 

myshell - 一个简单的shell

概要
	myshell

版权
	myshell is Copyright (C) 2012 by Duan Cong.

介绍
	myshell 是一个简单的shell程序,通过它你可以用来实现简单的命令行操作,比如列出目录下面的文件,清屏等等。

用法
	在终端下输入myshell,即可打开程序。
	
	后台运行:在终端下输入myshell时,紧接着输入一个&,即输入myshell&。
	
功能
	当进入myshell后,你可以通过输入相应命令实现以下功能:		

	cd [directory] —— 把当前默认目录改变为[directory]。不输入参数默认为当前目录。
	dir [directory] —— 列出目录[directory]的内容。不输入参数默认为当前目录。
	clr —— 清屏。
	environ —— 列出所有的环境变量。
	echo [comment] —— 在屏幕上显示[comment]并换行。
	help —— 显示本用户手册。
	quit —— 退出myshell。

	还调用其他程序和系统命令。

说明
	输入输出重定向功能:
	在myshell中使用命令行如programname arg1 arg2 > outputfile 时,programname的输出将输出到outputfile里而不是显示屏幕上。如果outputfile已存在则覆盖已有文件,如果不存在则创建输出文件。
	在myshell中使用命令行如programname arg1 arg2 >> outputfile 时,programname的输出将追加到outputfile里而不是显示屏幕上。如果outputfile已存在则将输出添加到已有文件尾部,如果不存在则创建输出文件。

示例
	当前目录为/home/dc,在终端下输入myshell,显示如下:

	[dc@localhost ~]$ myshell
	/home/dc
	==>

	说明已经进入程序。
	继续输入dir,显示如下:
	
	/home/dc
	==>dir
	A	    Desktop    index.php      note.xml	Public	   Untitled 1.docx
	Audiobooks  Documents  index.php.bak  Pictures	Templates  Videos
	blog.docx   Downloads  Music	      Podcasts	test.txt
	/home/dc
	==>		

	输入clr,显示如下:
	
	/home/dc
	==>
	
	屏幕被清空。
	输入environ,显示如下(中间省略部分环境变量,用省略号代替):
	
	/home/dc
	==>environ
	XDG_VTNR=1
	XDG_SESSION_ID=2
	HOSTNAME=localhost.localdomain
	IMSETTINGS_INTEGRATE_DESKTOP=yes
	GPG_AGENT_INFO=/tmp/keyring-sFt4mm/gpg:0:1
	TERM=xterm
	SHELL=/bin/bash
	...
	XAUTHORITY=/var/run/gdm/auth-for-dc-mesabL/database
	_=/home/dc/Desktop/operating_system/project/myshell
	OLDPWD=/home/dc/Desktop/operating_system/project
	/home/dc
	==>

	输入dir /,显示如下:
	
	/home/dc
	==>dir /       
	bin   dev  home  lost+found  mnt  proc	run   srv  tmp	var
	boot  etc  lib	 media	     opt  root	sbin  sys  usr
	/home/dc
	==>

	另外,myshell可以调用其他程序,例如输入gedit,将调用GUI的文本编辑器gedit,在终端中按下ctrl+C可以结束gedit进程。
	
	在myshell中输入quit,退出myshell,返回终端,显示如下:
	
	/home/dc
	==>quit
	[dc@localhost ~]$ 	

	以上仅为部分示例,更多详细请参考“功能”。

 

 


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值