实验十*实现一个简单的shell命令行解释器

一、实验目的
本实验主要目的在于进一步学会如何在Linux系统下使用进程相关的系统调用,了解shell工作的基本原理,自己动手为Linux操作系统设计一个命令接口。
二、总体设计(含背景知识或基本原理与算法、或模块介绍、设计步骤等)
背景知识:
本实验要使用创建子进程的fork()函数,执行新的命令的exec()系列函数,通常shell是等待子进程结束后再接受用户新的输入,这可以使用waitpid()函数。以上相关的系统函数调用的说明请参见实验三的背景知识。
实验要求:
要设计的shell必须支持以下内部命令:cd<目录>更改当前的工作目录到另一个<目录>。如果<目录>未指定,输出当前工作目录。如果<目录>不存在,应当有适当的错误信息提示。这个命令应该也能改变PWD的环境变量。environ列出所有环境变量字符串的设置(类似于Linux系统下的env命令)。echo<内容>显示echo后的内容且换行。help简短概要的输出你的shell的使用方法和基本功能。jobs输出shell当前的一系列子进程,必须提供子进程的命名和PID号。quit,exit,bye退出shell。
题目分析:这个题目主要是分为六个模块,每个模块完成自己的任务,然后利用主函数把各个模块连接起来,根据输入调用函数就行。
设计步骤:(1)cd:录入,保存当前目录,然后从录入的字符串中摘取出输入的路径,如果没有则输出当前目录,如果有则跳转到指定目录,然后获取目录输出。
(2)environ:创建进程,根据返回值判断出子进程,子进程内调用exec函数,进入程序调用env命令列出环境变量。
(3)echo:键盘录入,然后输出去除前面五个字符和最后一个字符的内容。
(4)help:一连串输出,每一行输出一个功能的用法和功能。
(5)jobs:创建进程,根据返回值判断出子进程,子进程内调用exec函数,进入程序调用ps命令列出子进程。
(6)Main函数:根据输入用一个switch函数调用不同的函数。

#include 
#include 
#include 
#include 
#include 
#include 
int i;
void cd()
{
	printf("请输入目录,更改当前的工作目录到另一个目录\n");
	char st[200];
	memset(st,0,sizeof(st));
	scanf("%s",st);
	char mulu[200];
	memset(mulu,0,sizeof(mulu));//清空mulu数组
	getcwd(mulu,300);//调用函数保存当前目录
	printf("当前目录为: %s\n",mulu);
	if(strlen(st)==0)//没有输入,则输出当前目录
	         printf("没有输入路径,当前目录是:%s\n",mulu);
	else{
	      if(chdir(st)==0)//跳转至指定目录
	      {
	          memset(mulu,0,sizeof(mulu));//清空之前的存储内容
	          getcwd(mulu,200);//读取当前目录
	          printf("跳转目录至:%s\n",mulu);
	      }
	      else printf("跳转目录失败!请查看目录是否输入错误");
	}
}

void environ()
{
       pid_t pid=fork();//创建进程就是为了方便辨别当前进程为子进程还是父进程
       if(pid==0)//表示是子进程 
       {
	   execlp("env","",NULL);//execlp(constchar*file,constchar*arg,...); 
	}//env的作用是列出所以的环境变量的命令 
	else if(pid>0)//表示父进程 
	{
	    wait(NULL);//父进程先等待子进程运行结束 
	}
}

void echo()//输出echo<>中的内容后换行 
{
	printf("请输入您要打印的内容:");
	char st[200];
	fgets(st,200,stdin);//键盘录入echo<内容> 
	for(i=0;i:更改当前的目录环境到另一指定目录。\n"); 
	printf("    environ:列出所实验十有环境变量字符串的设置。\n"); 
	printf("    echo<内容>:显示echo后的内容且换行。\n"); 
        printf("    help:简短概要的输出你的shell的使用方法和基本功能。\n"); 
	printf("    jobs:输出shell当前的一系列子进程,必须提供子进程的命名和PID号。\n"); 
	printf("    quit,exit,bye:退出shell。\n"); 
 } 

void jobs()
{
	pid_t pid=fork();//创建进程就是为了方便辨别当前进程为子进程还是父进程 
        if(pid==0)//表示是子进程 
	{
		execlp("ps","",NULL);//execlp(constchar*file,constchar*arg,...); 
	}//tree显示进程树,也就输出了所以的子进程 
	else if(pid>0)//表示父进程 
	{
		wait(NULL);//父进程先等待子进程运行结束 
	}
}

int main()
{
	while(1)
	{
		printf("----------------------\n");
		printf(" shell 命令行解释器\n");
		printf("有以下功能选择:\n");
		printf("  cd      environ\n");
		printf("  echo    help\n");
		printf("  jobs    quit\n");
		printf("----------------------\n");
		char str[200];
		memset(str,0,sizeof(str));
		scanf("%s",str);
		if (strcmp(str,"cd")==0){
		                getchar();
		                cd();
		}
		else if(strcmp(str,"environ")==0){
		               getchar();
				environ();
		}
		else if(strcmp(str,"echo")==0){
		               getchar();
				echo();
		}
		else if(strcmp(str,"help")==0){
		               getchar();
				help();
		}
		else if(strcmp(str,"jobs")==0){
		               getchar();
				jobs();
		}
		else if(strcmp(str,"quit")==0||strcmp(str,"bye")==0||strcmp(str,"exit")==0){
		               break;
		}
		else  printf("输入错误,请查看提示信号后重新输入。\n");
	}
}

你可能感兴趣的:(linux,bash,运维,shell)