⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test14_2.txt

📁 linux under the C programming which complementary with the book of <linux under the C programming
💻 TXT
字号:
/* 头文件head.h*/
#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <fcntl.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXINPUTLN 120
/*输出行的最大长度*/
#define MAXARG 15
/*一个简单命令的最大数目*/
#define PIPELINE 5
/*一个管道的最大简单命令数*/
#define MAXNAME 100
/*I/O重定向文件名字的最大长度*/

char inputln[MAXINPUTLN+1];
/*用户的输入 */
char *inputlnptr;
/* 指向当前inputln[ ]数组的当前位置*/
char avline[MAXINPUTLN+1];
/*从inputln[ ]数组中提取出来的参数字符串 */
char *avptr;
/*指向avline[]数组中的当前位置*/
char infile[MAXINPUTLN+1];
/* 输入重定向文件的名字*/
char outfile[MAXNAME+1];
/*输出重定向文件的名字*/
int background;
/*为TRUE时为后台命令(命令行以&结尾,否则为前台,*/
int lastpid;
/*管道中最后一条简单命令的进程标识*/
int append;
/*如果为TRUE表示命令结尾用>>来说明附加在某文件末尾*/

struct cmd
{
	char *av[MAXARG];
		/*存放命令和参数的一维数组*/
	int infd;
	int outfd;
}cmdlin[PIPELINE];
/*一个简单命令结构*/

/*主过程main.c*/
//#include "head.h"

main(void)
{
	int j;

	init_once( );
		/*对程序进行初始化*/
	for(;;)
	{
		init_command( );
			/*每执行一条命令都要进行一次初始化*/
		if(get_comln( ))
			/*得到命令行输入*/
			if(j=get_simcom())
				/*分析出简单命令的个数*/
				execute(j);
					/*执行这j个命令*/
	}
}

/*初始化文件init.c*/
init_once(void)
{
	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
}

init_command(void)
/*每次输入命令都要进行初始化*/
{
	int k;
	background=FALSE;
	inputlnptr=inputln;
	avptr=avline;
	infile[0]= '\0';
	outfile[0]= '\0';
	append=FALSE;

	for(k=0;k<OPEN_MAX;++k)
	{
		cmdlin[k].infd=0;
		cmdlin[k].outfd=1;
	}
	for(k=3;k<OPEN_MAX;++k)
		close(k);
	printf("tsh:");
	fflush(stdout);
}

/*语法分析文件get_simcom.c*/
get_simcom(void)
{
	int m;

	get_simarg(0);
	/*先分析第一条简单命令*/

	if(check( "<"))
	/*如果有输入文件,就记录输入文件名*/
		get_word(infile);
	/*下面是循环分析管道中的每一条简单命令*/
	for(m=1;m<PIPELINE;++m)
	{
		if(check("|"))
			get_simarg(m);
		else
			break;
	}
		
/*如果有输出文件,记录输出文件名*/
	if(check( ">"))
	{
		if(check( ">"))
		/*输出到某文件的末尾*/
			append=TRUE;
		get_word(outfile);
	}

		/*后台运行命令*/
	if(check( "&"))
		background=TRUE;
		/*下面代码分析完整个命令,返回简单命令个数*/
	if(check( "\n"))
		return(m);
	else
		/*如果没分析完毕,说明输入的命令行有语法错误*/
	{
		fprintf(stderr, "Command line syntax error\n");
		return(ERROR);
	}
}

/*得到下一个标识符get_word.c*/
get_word(char *name)
{
	int m;

	/*从inputln[]中得到一个单词,也就是一个标识符*/
	for(m=0;m<MAXNAME;++m)
	{
		switch(*inputlnptr)
		{
			case ' ':
			case '|':
			case '>':
			case '\n':
			case '<':
			case '&':
			case '\t':
				*name='\0';
				return;
			default:
				name=inputlnptr++;
				name++;
		}
	}
	*name= '\0';
}

/*得到当前命令行get_comin.c*/
get_comln(void)
{
	int m;

	for(m=0;(inputln[m]=getchar( ))!= '\n'&& m<MAXINPUTLN;++m);
	if(m==MAXINPUTLN)
		/*如果输入的命令超过了最大长度,就报错*/
	{
		fprintf(stderr, "Command line too long\n");
		return(ERROR);
	}
	inputln[m+1]='\0';
	return(OK);
}

/*执行简单命令run_com.c*/
run_com(struct cmd *ptr)
{
	int k,pid;

	if(pid=fork( ))
		/*父进程*/
	{
		if(background==TRUE)
			printf( "%d\n",pid);
			/*如果是后台命令,打印出进程标识*/
		lastpid=pid;
			/*记录最后一个简单命令的进程标志*/
	}
	else
	{
			/*如果是后台进程要关闭键盘输入*/
		if(ptr->infd==0&&background==TRUE)
			ptr->infd=open( "/dev/null",O_RDONLY);
			/*对输入进行重定向*/
		if(ptr->infd!=0)
		{
			close(0);
			dup(ptr->infd);
		}
			/*对输出进行重定向*/
		if(ptr->outfd!=1)
		{
			close(1);
			dup(ptr->outfd);
		}

			/*前台进程可以接受键盘输入的中断和退出信号*/
		if(background==FALSE)
		{
			signal(SIGINT,SIG_DFL);
			signal(SIGQUIT,SIG_DFL);
		}
			/*关闭其它文件描述符,使得除了标准输入、标准输出和错误输出2外设置的管道和I/O重定向*/
		for(k=3;k<OPEN_MAX;++k)
			close(k);
			/*下面代码执行一条简单命令*/
		execvp(ptr->av[0],ptr->av);
		exit(1);
	}
}

/*执行输入的命令的文件execute.c*/
execute(int j)
{
	int m,fd,fds[2];

	if(infile[0]!='\0')
	/*如果命令指定了输入文件则打开输入文件*/
		cmdlin[0].infd=open(infile,O_RDONLY);
	if(outfile[0]!= '\0')
		/*如果命令指定了输出文件则打开相应的输出文件*/
		if(append==FALSE)
			cmdlin[j-1].outfd=open(outfile,O_WRONLY|O_CREAT|O_TRUNC,0666);
		else
			cmdlin[j-1].outfd=open(outfile,O_WRONLY|O_CREAT|O_APPEND,0666);
		/*对前台进程和后台进程进行不同的处理*/
	if(background)
		signal(SIGCHLD,SIG_IGN);
	else
		signal(SIGCHLD,SIG_DFL);
		/*循环执行每个简单命令*/
	for(m=0;m<j;++m)
	{
			/*对管道进行操作*/
		if(m<j-1)
		{
			pipe(fds);
			cmdlin[m+1].infd=fds[0];
			cmdlin[m].outfd=fds[1];
		}
			/*执行一条简单命令*/
		run_com(&cmdlin[m]);
			/*关闭该命令的输入*/
		if(fd=cmdlin[m].infd)
			close(fd);
			/*关闭该命令的输出*/
		if((fd=cmdlin[m].outfd)!=1)
			close(fd);
	}
		/*如果不是后台命令,等待直到最后一条简单命令执行完毕*/
	if(background==FALSE)
		while(wait(NULL)!=lastpid);
}

	/*分析简单命令get_sirmarg.c*/
get_simarg(int j)
{
	int m,tag,inword;

	for(m=0;m<MAXARG-1;++m)
	{
		while(*inputlnptr== ' '||*inputlnptr== '\t')
			/*跳过空格符合Tab符*/
			++inputlnptr;

			/*在cmd数组中存放的j个量,如果j为0则为命令,否则为参数*/
		cmdlin[j].av[m]=avptr;
		cmdlin[j].av[m+1]=NULL;
		for(tag=0;tag==0;)
		{
			switch(*inputlnptr)
			{
				case ' ':
				case '\t':
					inword=FALSE;
						/*对于这两种情况指定下一个参数*/
					*avptr++= '\0';
					tag=1;
					break;
				case '>':
				case '\n':
				case '<':
				case '&':
				case '|':
					if(inword==FALSE)
						/*对于以上几种情况改命令结束*/
						cmdlin[j].av[m]=NULL;
					*avptr++= '\0';
					return;
				default:
					/*否则说明参数的名字还不全*/
					inword=TRUE;
					avptr=inputlnptr;
					avptr++;
					break;
			}
		}
	}
}

	/*字符串匹配check.c*/
check(char *ptr)
{
	char *tptr;
		
	while(*inputlnptr== ' ')
		/*跳过空格符*/
		inputlnptr++;
	tptr=inputlnptr;
	while(*ptr!= '\0'&&*ptr==*tptr)
		/*循环比较两个字符串是否相等*/
	{
		ptr++;
		tptr++;
	}
	if(*ptr= '\0')
		/*比较结果相等*/
	{
		inputlnptr=tptr;
	/*修改inputlnptr指针*/
		return(TRUE);
	}
	else
	/*比较结果不相等*/
		return(FALSE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -