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

📄 if.c

📁 Unix 第 6 版的 sh 手册和源码
💻 C
字号:
/*
 * if exprression cmd [arg]....
 * if 是 test 命令的前身。在测试完表达式之后,如果为真则执行后面的命令。
 * 这里的 if 命令建立在 v7 test 命令基础上。
 */

#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>

#define EQ(a,b)	((tmp=a)==0?0:(strcmp(tmp,b)==0))

int 	ac;
char	**av;
int 	ap;
char	*tmp;

#define DIR 1
#define FIL 2
char *nxtarg(int mt);
int expr(void);
int e1(void);
int e2(void);
int e3(void);
int tio(char *a, int  f);
int ftype(char *f);
int fsizep(char *f);
void synbad(char *s1, char *s2);
int length(char *s);
int doex(char *earg);

int main(int argc, char**argv)
{
	ac = argc;
	av = argv;
	ap = 1;
	argv[ac] = 0;

	if (ac<=1)
		return 1;
	if (expr())
		return doex(0);
	else	
		return 1;
}
/*
 * 获得下一个参数。mt 指示在读到列表尾部的时候是否为语法错误,
 * 1 返回空指针,0 提示错误并退出。
 */
char *nxtarg(int mt)
{
	if (ap>=ac) {
		if(mt) {
			ap++;
			return(0);
		}
		synbad("argument exprected","");
	}
	return(av[ap++]);
}
/*
 * expr ::= * e1 -o expr | expr
 */
int expr(void)
{
	int p1;

	p1 = e1();
	if (EQ(nxtarg(1), "-o"))
		return(p1 | expr());
	ap--;
	return(p1);
}
/*
 * e1 ::= e2 -a e1 | e1
 */
int e1(void)
{
	int p1;

	p1 = e2();
	if (EQ(nxtarg(1), "-a"))
		return (p1 & e1());
	ap--;
	return(p1);
}
/*
 * e2 ::= e3 | ! e3
 */
int e2(void)
{
	if (EQ(nxtarg(0), "!"))
		return(!e3());
	ap--;
	return(e3());
}
/*
 * e3 ::= ( expr ) | { command ... } | -op file | string -op string
 */
int e3(void)
{
	int p1,r;
	register char *a;
	char *p2;
	int int1, int2;
	int ccode;

	a=nxtarg(0);
	if(EQ(a, "(")) {
		p1 = expr();
		if(!EQ(nxtarg(0), ")")) 
			synbad(") exprected","");
		return(p1);
	}
	if(EQ(a, "{")) { /* 执行一个命令并等待退出状态 */
		if(fork()) /* 父进程执行部分 */ 
			wait(&ccode);
		else { /* 子进程执行部分 */
			if ((r=doex("}")) != 0)
				if (r == 1)
					synbad("} exprected","");
				else
					exit(r);
			else
				exit(0);
		}
		while((a=nxtarg(0)) && (!EQ(a,"}")));
		return(ccode? 0 : 1);
	}
	if(EQ(a, "-r"))
		return(tio(nxtarg(0), 0));

	if(EQ(a, "-w"))
		return(tio(nxtarg(0), 1));

	if(EQ(a, "-d"))
		return(ftype(nxtarg(0))==DIR);

	if(EQ(a, "-f"))
		return(ftype(nxtarg(0))==FIL);

	if(EQ(a, "-s"))
		return(fsizep(nxtarg(0)));

	if(EQ(a, "-t")) {
		if(ap>=ac)
			return(isatty(1));
		else
			return(isatty(atoi(nxtarg(0))));
	}
	if(EQ(a, "-n"))
		return(!EQ(nxtarg(0), ""));
	if(EQ(a, "-z"))
		return(EQ(nxtarg(0), ""));

	p2 = nxtarg(1);
	if (p2==0)
		return(!EQ(a,""));
	if(EQ(p2, "="))
		return(EQ(nxtarg(0), a));

	if(EQ(p2, "!="))
		return(!EQ(nxtarg(0), a));

	if(EQ(a, "-l")) {
		int1=length(p2);
		p2=nxtarg(0);
	} else{	int1=atoi(a);
	}
	int2 = atoi(nxtarg(0));
	if(EQ(p2, "-eq"))
		return(int1==int2);
	if(EQ(p2, "-ne"))
		return(int1!=int2);
	if(EQ(p2, "-gt"))
		return(int1>int2);
	if(EQ(p2, "-lt"))
		return(int1<int2);
	if(EQ(p2, "-ge"))
		return(int1>=int2);
	if(EQ(p2, "-le"))
		return(int1<=int2);
	synbad("unknown operator ",p2);
	return 0;
}
/*
 * 文件访问测试
 */
int tio(char *a, int  f)
{

	f = open(a, f);
	if (f>=0) {
		close(f);
		return(1);
	}
	return(0);
}
/*
 * 文件类型测试
 */
int ftype(char *f)
{
	struct stat statb;

	if(stat(f,&statb)<0)
		return(0);
	if((statb.st_mode&S_IFMT)==S_IFDIR)
		return(DIR);
	return(FIL);
}
/*
 * 文件大小测试
 */
int fsizep(char *f)
{
	struct stat statb;
	if(stat(f,&statb)<0)
		return(0);
	return(statb.st_size>0);
}
/*
 * 打印错误信息并退出
 */
void synbad(char *s1, char *s2)
{
	write(2, "if: ", 6);
	write(2, s1, strlen(s1));
	write(2, s2, strlen(s2));
	write(2, "\n", 1);
	exit(1);
}
/*
 * 字符串长度测试
 */
int length(char *s)
{
	char *es=s;
	while(*es++);
	return((int)(es-s-1));
}
/*
 * 执行命令
 * earg 是终止参数
 */
int doex(char *earg)
{
	static char ncom[]="/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
	char *p=av[ap];
	char **v=av+ap;
	int i=0;
	char c;

	if (p == 0)
		return 0;

	if (earg != 0) {
		while (*v != 0 && !EQ(*v,earg))
			v++;
		if (*v == 0)
			return 1;
		else
			*v=0;
	}

	execv(p, av+ap);
	while((c=p[i])) {
		ncom[9+i++] = c;
	}
	ncom[9+i] = '\0';
	execv(ncom+4, av+ap);
	execv(ncom, av+ap);
	return 127;
}

⌨️ 快捷键说明

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