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

原创 2012年03月21日 22:28:01

原题见《操作系统—精髓与设计原理(第五版)》一书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 ~]$ 	

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

 

 


相关文章推荐

操作系统实验四之实现shell

操作系统实验之实现shell。实现简单的shell, 程序可以在后台运行,按下ctrl+c系统不会终止shell。实现历史记录功能,按下ctrl+c展示最近10条命令,使用“rx”执行其中的命令,x ...

gcc编译通过,运行却显示“段错误”的解决方法

​第一次在Liunx上(liunx mint 17)使用gcc编译c文件,竟然提示“找不到stdio.h",经过google后发现执行 sudo apt-get install build-essen...

"library not found for - "解决办法

在我们编译的时候有时候会报这个错误 "library not found for - " 由于是我们在项目中使用了一些第三方的库,就比如我再使用百度的静态库文件的时候,报出的这个错误...

操作系统开发之——一个简单的Bootsect(改进版)

我们在前一篇文章: 操作系统开发之——一个简单的Bootsect 当中写了一个最最最简单的Bootsect,但还有些漏洞和缺陷,比如说,没有打印显示文字,等等。 还是直接贴代码: ;-------...
  • imcjysy
  • imcjysy
  • 2015年11月07日 09:15
  • 238

LINUX实现一个简单的SHELL

  • 2011年12月20日 20:38
  • 2KB
  • 下载

机器人操作系统ROS Indigo 入门学习(12)——用C++语言写一个简单的发布者和订阅者

这个教程将会包含怎样用C++去写一个发布者和订阅者.   1.1写一个发布者Node “Node”是连接在ROS网络中一个可执行单元的术语.这里我们创建一个会不断广播messages...

机器人操作系统ROS Indigo 入门学习(12)——用C++语言写一个简单的发布者和订阅者

这个教程将会包含怎样用C++去写一个发布者和订阅者.   1.1写一个发布者Node “Node”是连接在ROS网络中一个可执行单元的术语.这里我们创建一个会不断广播messages的发布者(“...

操作系统上机:为MyLinux添加一个字符设备

这是操作系统第五次上机,主要是实现为MyLinux添加一个字符设备。    这次环境用的是自己制定的RedHat   2.6.18的内核   废话不多说,首先看基本知识: 系统调用是操作系统内核...

一个简单操作系统的实现

  • 2012年05月19日 15:56
  • 189KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:操作系统上机——实现一个简单的shell
举报原因:
原因补充:

(最多只允许输入30个字)