(二)嵌入式:通过MTD设备为只读文件系统修改登陆用户和密码

Lesson 6-通过MTD设备为只读文件系统修改登陆用户和密码

1.实现mtd驱动
1.1
首先进入目录linux-2.4.x/drivers/mtd/maps ,然后修改配置文件Config.in,在末尾添加语句,如图1-1所示:
在这里插入图片描述
图1-1 修改配置文件
然后添加驱动文件–myflash.c文件,如图1-2所示:
在这里插入图片描述
图1-2 添加驱动文件(见附录二)
接着还要修改Makefile,如图1-3所示:
在这里插入图片描述
图1-3 修改Makefile文件
分析:在做linux驱动时需要将自己写的驱动程序编译到内核总要修改Config.in文件,,其 中dep_tristate表示要依赖某些选项去定义一个选项。
这个语句表示定义了一个选项CFI Flash device mapped on myboard_flash ,只要 CONFIG_MTD_CFI被定义为y或m ,那么在mtd/maps分类下就会出现该选项,它对 应了CONFIG_MTD_MYFLASH 的定义。
然后修改makefile添加对应obj- ( C O N F I G M T D M Y F L A S H ) + = m y f l a s h . o , 对 应 m y f l a s h . c 文 件 。 (CONFIG_MTD_MYFLASH) += myflash.o ,对应 myflash.c文件。 (CONFIGMTDMYFLASH)+=myflash.omyflash.c(CONFIG_MTD_MYFLASH)的值对应CFI Flash device mapped on myboard_flash的值为y或者m,那么Makefile会根据obj-m和obj-y编译并连接对应的 源码。

1.2
然后退出到目录linux-2.4.x/include/linux/mtd/mtd.h ,
修改#define MTD_BLOCK_MAJOR 31 为 #define MTD_BLOCK_MAJOR 30
修改 #define MAX_MTD_DEVICES 16 为define MAX_MTD_DEVICES 3 。如图1-4所示:
在这里插入图片描述
图1-4 修改头文件mtd.h

还要修改文件Marvell/Firefox/Makefile ,添加如下的命令,如图1-5所示:
在这里插入图片描述
图1-5 修改Makefile文件
1.3
修改完成后,进行配置内核,输入make xconfig,开始配置MTD,如图1-6所示:
在这里插入图片描述
图1-6 配置内核
然后编译通过,连接开发板,通过TFTP下载内核和根文件系统到开发板。出现如图1-7所示的错误:
在这里插入图片描述
图1-7 下载内核和根文件系统到开发板出现错误
通过查找和对比,最终发现是内核映像溢出。对比前后两次的下载的内核大小,可以发现已经过大,如图1-8所示:
在这里插入图片描述
在这里插入图片描述
图1-8 前后两次对比内核的大小
所以,重新配置内核, make xconfig. 删除之前做的NFS,portmap等配置,然后重新下载内核,如图1-9所示:
在这里插入图片描述
图1-9 重新配置后内核的大小
这时候可以发现,启动成功。输入原始设置的账号和密码:123456(密码一样),进入shell。如图1-10所示:
在这里插入图片描述
图1-10 原始用户成功登陆
1.4
开始测试。查看启动时的打印信息,可以看见myflash驱动使能成功。如图1-11所示:
在这里插入图片描述
图1-11 打印信息

然后在开发板里面查看mtd分配的块设备信息,将mtd分的块设备挂载在/mnt里面,如图1-12所示:
在这里插入图片描述
图1-12 挂载并进行写操作
重新启动开发板,检查是否写入成功。如图1-13所示:
在这里插入图片描述
图1-13 检查写操作成功

2.实现修改用户和密码登陆
在user/scu目录下创建文件modify_user_passwd.c,打开编写测试C程序(参照正式程序自己看),编写完成后,先在Ubuntu下面进行编译测试,如图2-1所示:
在这里插入图片描述
图2-1 编译测试C程序
然后检查是否修改/etc/passwd1文件(我先指定登陆时检查的是passwd1文件的内容)
如图2-2所示:

图2-2 修改用户和密码成功
然后完善测试程序(见附录1),删除之编译的用户程序modify_user_passwd;使用命令rm。
接着按照hello的做法,首先修改uClinux-dist/config/config.in,如图2-3所示:
在这里插入图片描述
图2-3 修改config.in文件

然后修改uClinux-dist/config/Configure.help文件,如图2-4所示:
在这里插入图片描述
图2-4 修改Configure.help文件
然后检查user目录下的Makefile文件,是否有对scu目录的操作,并添加一行,如图2-5所示:
在这里插入图片描述
图2-5 修改user/Makefile文件
最后还要修改scu/Makefile文件,如图2-6所示:
在这里插入图片描述
图2-6 修改scu/Makefile文件
接下来,进入romfs文件夹下的bin目录,删除所有的指令,然后退出到uClinux-dist目录,执行make xconfig,make dep 和make 命令。如图2-7所示,选中刚刚制作好的命令:
在这里插入图片描述
图2-7 修改配置选项,使能刚刚做好的APP

然后,make dep ;make 。完成后,检查/romfs/bin文件夹,可以发现,出现了刚刚写的C程序编译出来的命令modift_user_passwd。如图2-8所示:
在这里插入图片描述
在这里插入图片描述
图2-8 前后对比/bin目录
由此可见编译成功,接下来分析,由于挂载/mtd/block0前后,文件并不会改变,所有考虑使用挂载到开发板上的/mnt目录下的文件来存放新创建的用户和密码。因此首先由原始密码登陆shell,然后运行刚刚编译的命令modift_usr_passwd,设置/mnt/passwd1下的内容为保存用户和密码(将用户和密码的保存文件复制到mnt/passwd1),并如图2-9所示:
在这里插入图片描述
图2-9 在开发板上面
修改完成后,要先卸载掉/mnt.然后退出去虚拟机山面的Ubuntu系统上面修改/uClinux-dist/vendors/Marvell/Firefox目录下的rc文件,使其在进入shell之前挂载mtdblock0,这样才能正确的读到password1如图2-10所示:
在这里插入图片描述
图2-10 修改rc文件
然后还要修改sash.c的代码,使其读出/mnt/passwd1里面的账户和密码与用户的输入作对比,如图2-11所示:
在这里插入图片描述
图2-11 修改sash.c的代码
接着才是,编译,下载和运行。如图2-12所示:
在这里插入图片描述
图2-12 使用新用户密码登陆
第一次修改用户和密码完成后,后面再次运行自己编译的modify_user_passwd命令,修改完新的用户和密码,只需要复制到/mnt/passwd1,然后重启开发板就行了,不再需要改动sash.c文件。

总结
第一次修改用户和密码完成后,后面再次运行自己编译的modify_user_passwd命令,修改完新的用户和密码,只需要重启开发板就行了,不再需要改动sash.c文件。这是因为第一次的/mnt/passwd1文件是空的,这时候如果sash.c文件里面读取的是/、mnt/passwd1,那么输入任何的用户和密码都必然是不对的,这样就永远进不了shell。所以需要第一次修改sash.c,成功进入shell后,第一次修改新的用户和密码后,保存在/mnt/passwd1里面,然后umount /mnt/,进入Ubuntu,修改sash.c使其读取/mnt/passwd1里面的数据,才能作对比。
思考
这样觉得有点麻烦,因此尝试做过不改动sash.c,而是修改rc文档,如下图所示:

使其仍然从/etc/passwd1下面读取数据,进入开发板,运行modify_user_passwd命令,修改完新的用户和密码,保存在/mnt/passwd1里面,然后重启开发板就行了。这样可以将该数据复制到/etc/passwd1,实现修改的目的。但是发现提示报错说,复制失败,因为该文件系统是只读文件系统,不支持修改。因此此次尝试失败。再考虑修改文件系统的属性,make xconfig,进入File systerm,未找到合适的文件系统属性,于是放弃此想法,退而求其次,选择上面描述的方法实现修改用户和密码。

附录一:


#if 1
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define  PATH  "/s1/uClinux/romfs/etc/passwd1"   //测试时用
int main()
{char usernamebuf[128],passwdbuf[128];char crypt_user[128], crypt_password[128];char buf[256]="user=0000000000000 passwd=0000000000000";char *cryptmode;int backdata,i;FILE *fp;printf("please input the user you want: ");fgets(usernamebuf,sizeof(usernamebuf),stdin); //保存新创建的用户到usernamebuf//passwdbuf = getpass("please enter the passwd to the user you created  : "); //(不回显)保存用户密码到passwdbufprintf("please input the passwd you want: ");fgets(passwdbuf,sizeof(passwdbuf),stdin); //保存新创建的用户到usernamebufcryptmode = "ab";strcpy(crypt_user, crypt(usernamebuf,cryptmode)); 	//加密用户名到crtyp_user//printf("crypt_user is %s\n",crypt_user);strcpy(crypt_password, crypt(passwdbuf,cryptmode)); //加密密码到crtyp_password//printf("crypt_password is %s\n",crypt_password);for(i=0 ; i<13; i++){buf[i+5] = crypt_user[i];}for(i=0 ; i<13 ; i++){buf[i+26] = crypt_password[i];}//printf("the buf is %s \n",buf);fflush(stdout);fflush(stdin);if((fp = fopen("/etc/passwd1" ,"w+r"))== NULL){printf("open failed \n");//return 1;}backdata = fputs(buf,fp);
//writedata = write(fd,buf,sizeof(buf));if(backdata == -1){printf("write failed \n");}fflush(stdout);fflush(stdin);fclose(fp);}#endif

附录二

/** Copyright (c) 1993 by David I. Bell* Permission is granted to use, distribute, or modify this source,* provided that this copyright notice remains intact.** Stand-alone shell for system maintainance for Linux.* This program should NOT be built using shared libraries.** 1.1.1, 	hacked to re-allow cmd line invocation of script file*		Pat Adamo, padamo@unix.asb.com*/
/*****************************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/**********************************/#include "sash.h"#ifndef CMD_HELP
#define	CMD_HELP
#endif
#undef INTERNAL_PATH_EXPANSION
#define FAVOUR_EXTERNAL_COMMANDS#include 
#include 
#include 
#include 
#include 
#include 
#include static char version[] = "1.1.1";extern int intflag;extern void do_test();typedef struct {char	name[10];char	usage[30];void	(*func)();int	minargs;int	maxargs;
} CMDTAB;CMDTAB	cmdtab[] = {
/*"alias",	"[name [command]]", 	do_alias,1,		MAXARGS,
*/"cd",		"[dirname]",		do_cd,1,		2,"sleep",		"seconds",		do_sleep,1,		2,"chgrp",	"gid filename ...",	do_chgrp,3,		MAXARGS,"chmod",	"mode filename ...",	do_chmod,3,		MAXARGS,"chown",	"uid filename ...",	do_chown,3,		MAXARGS,"cmp",		"filename1 filename2",	do_cmp,3,		3,"cp",		"srcname ... destname",	do_cp,3,		MAXARGS,/*"dd",		"if=name of=name [bs=n] [count=n] [skip=n] [seek=n]", do_dd,3,		MAXARGS,
*/"df",		"[file-system]",	do_df,1,		2,"echo",	"[args] ...",			do_echo,1,		MAXARGS,/*"ed",		"[filename]",		do_ed,1,		2,
*/"exec",		"filename [args]",	do_exec,2,		MAXARGS,"exit",		"",			do_exit,1,		1,"free",		"",			do_free,1,		1,/*"-grep",	"[-in] word filename ...",	do_grep,3,		MAXARGS,
*/#ifdef CMD_HELP"help",		"",			do_help,1,		MAXARGS,
#endif"hexdump",	"[-s] filename",	do_hexdump,1,		3,"hostname",	"[hostname]",		do_hostname,1,		2,"kill",		"[-sig] pid ...",	do_kill,2,		MAXARGS,"ln",		"[-s] srcname ... destname",	do_ln,3,		MAXARGS,"ls",		"[-lidC] filename ...",	do_ls,1,		MAXARGS,"mkdir",	"dirname ...",		do_mkdir,2,		MAXARGS,"mknod",	"filename type major minor",	do_mknod,5,		5,"more",	"filename ...",		do_more,2,		MAXARGS,"mount",	"[-t type] devname dirname",	do_mount,3,		MAXARGS,"mv",		"srcname ... destname",	do_mv,3,		MAXARGS,"printenv",	"[name]",		do_printenv,1,		2,"pwd",		"",			do_pwd,1,		1,"pid",		"",			do_pid,1,		1,"quit",		"",			do_exit,1,		1,"rm",		"filename ...",		do_rm,2,		MAXARGS,"rmdir",	"dirname ...",		do_rmdir,2,		MAXARGS,"setenv",	"name value",		do_setenv,3,		3,"source",	"filename",		do_source,2,		2,"sync",	"",			do_sync,1,		1,/*	"time",	"",			do_time,1,		1,
*/
/*"tar",		"[xtv]f devname filename ...",	do_tar,2,		MAXARGS,
*/"touch",	"filename ...",		do_touch,2,		MAXARGS,"umask",	"[mask]",		do_umask,1,		2,"umount",	"filename",		do_umount,2,		2,/*"unalias",	"name",			do_unalias,2,		2,
*/"ps",		"",			do_ps,1,		MAXARGS,/*	"reboot",	"",			do_reboot,1,		MAXARGS,
*/"cat",		"filename ...",		do_cat,2,		MAXARGS,"date",		"date [MMDDhhmm[YYYY]]",	do_date,1,		2,0,		0,			0,0,		0
};typedef struct {char	*name;char	*value;
} ALIAS;static	ALIAS	*aliastable;
static	int	aliascount;static	FILE	*sourcefiles[MAXSOURCE];
static	int	sourcecount;volatile static	BOOL	intcrlf = TRUE;static	void	catchint();
static	void	catchquit();
static	void	catchchild();
static	void	readfile();
static	void	command();
#ifdef COMMAND_HISTORY
#define do_command(c,h)	command(c,h)
#else
#define do_command(c,h)	command(c)
#endif
static	void	runcmd();
static	void	showprompt();
static	BOOL	trybuiltin();
static	BOOL	command_in_path();
static	ALIAS	*findalias();extern char ** environ;/* 
char text1[] = "Text";
char * text2 = text1;
char ** text3 = &text2;
*/char	buf[CMDLEN];
int exit_code = 0;main(argc, argv, env)char	**argv;char	*env[];
{struct sigaction act;char	*cp;
/*	char	buf[PATHLEN];*/int dofile = 0;if ((argc > 1) && !strcmp(argv[1], "-c")) {/* We are that fancy a shell */buf[0] = '\0';for (dofile = 2; dofile < argc; dofile++) {strncat(buf, argv[dofile], sizeof(buf));if (dofile + 1 < argc)strncat(buf, " ", sizeof(buf));}do_command(buf, FALSE);exit(exit_code);}/* ;'pa990523 + */if ((argc > 1) && strcmp(argv[1], "-t")){dofile++;printf("Shell invoked to run file: %s\n",argv[1]);}else{
#if 1char usernamebuf[128];char crtyppassword1[128], crtyppassword2[128];char *p,*passwd,*cryptmode,fpbuf[128],fpbuf1[13],fpbuf2[13];FILE *fp;int i,j=0,z=0;int x,y;printf("*********************\n");for(;;){fflush(stdout);fflush(stdin);printf("User: ");fgets(usernamebuf,sizeof(usernamebuf),stdin); //保存用户到usernamebufp = strchr(usernamebuf, '\n');if( p != 0 )*p=0;passwd = getpass("Enter the passwd :"); //(不回显)保存密码到passwdprintf("\n");cryptmode = "ab";strcpy(crtyppassword1, crypt(usernamebuf,cryptmode)); 	//加密用户名到1strcpy(crtyppassword2, crypt(passwd,cryptmode)); 		//加密密码到2//printf("crypt_user is %s\n",crtyppassword1);//printf("crypt_passwd is %s\n",crtyppassword2);fflush(stdout);fflush(stdin);if((fp = fopen("/etc/passwd1","r"))== NULL){printf("open failed \n");//return 1;}if(fgets(fpbuf,sizeof(fpbuf),fp)== NULL){printf("get data failed \n");//return 2;	}//printf(" the pervious data is :%s\n",fpbuf);/*for(i = 0; i<128 ; i++){if((fpbuf[i] == '=')&&(i<10)){j = 0;fpbuf1[j] = fpbuf[i+1];}else if(fpbuf[i] == '='){j = 0;fpbuf2[j] = fpbuf1[i+1];}else ;}*/for(i = 5 ; i<18; i++){fpbuf1[z] = fpbuf[i];z++;}for( i=26; i<39; i++){fpbuf2[j] = fpbuf[i];j++;}//printf("read user is %s\n",fpbuf1);//printf("read passwd is %s\n",fpbuf2);x = strncmp(crtyppassword1,fpbuf1,13);y = strncmp(crtyppassword2,fpbuf2,13);if(x!=0){printf("user  mistake \n");printf("\n");}else if(y!=0) {	printf("passwd  mistake \n");	printf("\n");}else	break;	}printf("user and passwd correct!!! \n");printf("\n");fclose(fp);
#endifprintf("\nSash command shell (version %s)\n", version);}fflush(stdout);signal(SIGINT, catchint);signal(SIGQUIT, catchquit);memset(&act, 0, sizeof(act));act.sa_handler = catchchild;act.sa_flags = SA_RESTART;sigaction(SIGCHLD, &act, NULL);if (getenv("PATH") == NULL)putenv("PATH=/bin:/usr/bin:/etc");/*	cp = getenv("HOME");if (cp) {strcpy(buf, cp);strcat(buf, "/");strcat(buf, ".aliasrc");if ((access(buf, 0) == 0) || (errno != ENOENT))readfile(buf);}
*/	/* ;'pa990523 -1/+ *//* readfile(NULL); */if (dofile){/* open the file for reading! */readfile(argv[1]);}else{readfile(NULL); /* no arguments! */} /* end if arguments supplied */exit(exit_code);
}/** Read commands from the specified file.* A null name pointer indicates to read from stdin.*/
static void
readfile(name)char	*name;
{FILE	*fp;int	cc;BOOL	ttyflag;char	*ptr;if (sourcecount >= MAXSOURCE) {fprintf(stderr, "Too many source files\n");return;}fp = stdin;if (name) {fp = fopen(name, "r");if (fp == NULL) {perror(name);return;}}sourcefiles[sourcecount++] = fp;ttyflag = isatty(fileno(fp));while (TRUE) {fflush(stdout);/* ;'pa990523 -1/+1 *//* if (1) */if (fp == stdin) /* using terminal, so show prompt */showprompt();if (intflag && !ttyflag && (fp != stdin)) {fclose(fp);sourcecount--;return;}if (fgets(buf, CMDLEN - 1, fp) == NULL) {if (ferror(fp) && (errno == EINTR)) {clearerr(fp);continue;}break;}cc = strlen(buf);while ((cc > 0) && isspace(buf[cc - 1]))cc--;buf[cc] = '\0';/* ;'pa990523 + */if (fp != stdin){/* taking commands from file - echo *//* printf("Command: %s\n",buf); */} /* end if (fp != stdin) *//* remove leading spaces and look for a '#' */ptr = &buf[0];while (*ptr == ' ') {ptr++;}if (*ptr != '#')do_command(buf, fp == stdin);}if (ferror(fp)) {perror("Reading command line");if (fp == stdin)exit(1);}clearerr(fp);if (fp != stdin){/* ;'pa990523 added braces and printf */fclose(fp);printf("Execution Finished, Exiting\n");} /* end if (fp != stdin) */sourcecount--;
}/** Parse and execute one null-terminated command line string.* This breaks the command line up into words, checks to see if the* command is an alias, and expands wildcards.*/
static void
#ifdef COMMAND_HISTORY
command(cmd, do_history)int do_history;
#else
command(cmd)
#endifchar	*cmd;
{ALIAS	*alias;char	**argv;int	argc;int 	bg;char   *c;intflag = FALSE;exit_code = 0;freechunks();while (isblank(*cmd))cmd++;#ifdef COMMAND_HISTORYif (do_history) {int i;static char *history[HISTORY_SIZE];if (*cmd == '!') {if (cmd[1] == '!')i = 0;else {i = atoi(cmd+1) - 1;if (i < 0 || i >= HISTORY_SIZE) {printf("%s: Out of range\n", cmd);return;}}if (history[i] == NULL) {printf("%s: Null entry\n", cmd);return;}strcpy(cmd, history[i]);} else if (*cmd == 'h' && cmd[1] == '\0') {for (i=0; i0; i--)history[i] = history[i-1];history[0] = strdup(cmd);}}
#endifif (c = strchr(cmd, '&')) {*c = '\0';bg = 1;} elsebg = 0;if ((cmd = expandenvvar(cmd)) == NULL)return;if ((*cmd == '\0') || !makeargs(cmd, &argc, &argv))return;/** Search for the command in the alias table.* If it is found, then replace the command name with* the alias, and append any other arguments to it.*/alias = findalias(argv[0]);if (alias) {cmd = buf;strcpy(cmd, alias->value);while (--argc > 0) {strcat(cmd, " ");strcat(cmd, *++argv);}if (!makeargs(cmd, &argc, &argv))return;}/** BASH-style variable setting*/if (argc == 1) {c = index(argv[0], '=');if (c > argv[0]) {*c++ = '\0';setenv(argv[0], c, 1);return;}}/** Now look for the command in the builtin table, and execute* the command if found.*/
#ifdef FAVOUR_EXTERNAL_COMMANDSif (!command_in_path(argv[0]))
#endifif (trybuiltin(argc, argv))return;/** Not found, run the program along the PATH list.*/runcmd(cmd, bg, argc, argv);
}#ifdef FAVOUR_EXTERNAL_COMMANDS
/** return true if we find this command in our* path.*/
static BOOL
command_in_path(char *cmd)
{struct stat	stat_buf;if (strchr(cmd, '/') == 0) {char	* path;static char	path_copy[PATHLEN];/* Search path for binary */for (path = getenv("PATH"); path && *path; ) {char * p2;strcpy(path_copy, path);if (p2 = strchr(path_copy, ':')) {*p2 = '\0';}if (strlen(path_copy))strcat(path_copy, "/");strcat(path_copy, cmd);if (!stat(path_copy, &stat_buf) && (stat_buf.st_mode & 0111))return(TRUE);p2 = strchr(path, ':');if (p2)path = p2 + 1;elsepath = 0;}} else if (!stat(cmd, &stat_buf) && (stat_buf.st_mode & 0111))return(TRUE);return(FALSE);
}
#endif /* FAVOUR_EXTERNAL_COMMANDS *//** Try to execute a built-in command.* Returns TRUE if the command is a built in, whether or not the* command succeeds.  Returns FALSE if this is not a built-in command.*/
static BOOL
trybuiltin(argc, argv)char	**argv;
{CMDTAB	*cmdptr;int	oac;int	newargc;int	matches;int	i;char	*newargv[MAXARGS];char	*nametable[MAXARGS];cmdptr = cmdtab - 1;do {cmdptr++;if (cmdptr->name[0] == 0)return FALSE;} while (strcmp(argv[0], cmdptr->name));/** Give a usage string if the number of arguments is too large* or too small.*/if ((argc < cmdptr->minargs) || (argc > cmdptr->maxargs)) {fprintf(stderr, "usage: %s %s\n",cmdptr->name, cmdptr->usage);fflush(stderr);return TRUE;}/** Check here for several special commands which do not* have wildcarding done for them.*//*        if (cmdptr->func == do_prompt) {(*cmdptr->func)(argc, argv);return TRUE;}
*//** Now for each command argument, see if it is a wildcard, and if* so, replace the argument with the list of matching filenames.*/newargv[0] = argv[0];newargc = 1;oac = 0;while (++oac < argc) {matches = expandwildcards(argv[oac], MAXARGS, nametable);if (matches < 0)return TRUE;if ((newargc + matches) >= MAXARGS) {fprintf(stderr, "Too many arguments\n");return TRUE;}if (matches == 0)newargv[newargc++] = argv[oac];for (i = 0; i < matches; i++)newargv[newargc++] = nametable[i];}(*cmdptr->func)(newargc, newargv);return TRUE;
}/** Execute the specified command.*/
static void
runcmd(cmd, bg, argc, argv)char	*cmd;int	bg;int	argc;char	**argv;
{register char *	cp;BOOL		magic;int		pid;int		status;int oac;int newargc;int matches;int i;char	*newargv[MAXARGS];char	*nametable[MAXARGS];struct sigaction act;newargv[0] = argv[0];#ifdef INTERNAL_PATH_EXPANSIONif (strchr(argv[0], '/') == 0) {char	* path;struct stat	stat_buf;static char	path_copy[PATHLEN];/* Search path for binary */for (path = getenv("PATH"); path && *path; ) {char * p2;strncpy(path_copy, path, sizeof(path_copy - 1));if (p2 = strchr(path_copy, ':')) {*p2 = '\0';}if (strlen(path_copy))strncat(path_copy, "/", sizeof(path_copy));strncat(path_copy, argv[0], sizeof(path_copy));if (!stat(path_copy, &stat_buf) && (stat_buf.st_mode & 0111)) {newargv[0] = path_copy;break;}p2 = strchr(path, ':');if (p2)path = p2 + 1;elsepath = 0;}}
#endif/** Now for each command argument, see if it is a wildcard, and if* so, replace the argument with the list of matching filenames.*/newargc = 1;oac = 0;while (++oac < argc) {matches = expandwildcards(argv[oac], MAXARGS, nametable);if (matches < 0)return;if ((newargc + matches) >= MAXARGS) {fprintf(stderr, "Too many arguments\n");return;}if (matches == 0)newargv[newargc++] = argv[oac];for (i = 0; i < matches; i++)newargv[newargc++] = nametable[i];}newargv[newargc] = 0;magic = FALSE;/*for (cp = cmd; *cp; cp++) {if ((*cp >= 'a') && (*cp <= 'z'))continue;if ((*cp >= 'A') && (*cp <= 'Z'))continue;	if (isdecimal(*cp))continue;if (isblank(*cp))continue;if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||(*cp == '+') || (*cp == '=') || (*cp == '_') ||(*cp == ':') || (*cp == ','))continue;magic = TRUE;}*/if (magic) {printf("%s: no such file or directory\n", cmd);system(cmd);return;}if (!bg)signal(SIGCHLD, SIG_DFL);/** No magic characters in the expanded command, so do the fork and* exec ourself.  If this fails with ENOEXEC, then run the* shell anyway since it might be a shell script.*/if (!(pid = vfork())) {int	ci;/** We are the child, so run the program.* First close any extra file descriptors we have opened.* be sure not to modify any globals after the vfork !*/	for (ci = 0; ci < sourcecount; ci++)if (sourcefiles[ci] != stdin)close(fileno(sourcefiles[ci]));signal(SIGINT, SIG_DFL);signal(SIGQUIT, SIG_DFL);signal(SIGCHLD, SIG_DFL);execvp(newargv[0], newargv);printf("%s: %s\n", newargv[0], (errno == ENOENT) ? "Bad command or file name" : strerror(errno));_exit(0);}if (pid < 0) {memset(&act, 0, sizeof(act));act.sa_handler = catchchild;act.sa_flags = SA_RESTART;sigaction(SIGCHLD, &act, NULL);perror("vfork failed");return;}if (bg) {/* printf("[%d]\n", pid); */return;}if (pid) {int cpid;status = 0;intcrlf = FALSE;for (;;) {cpid = wait4(pid, &status, 0, 0);if ((cpid < 0) && (errno == EINTR))continue;if (cpid < 0)break;if (cpid != pid) {fprintf(stderr, "sh %d: child %d died\n", getpid(), cpid);continue;}}act.sa_handler = catchchild;memset(&act.sa_mask, 0, sizeof(act.sa_mask));act.sa_flags = SA_RESTART;sigaction(SIGCHLD, &act, NULL);intcrlf = TRUE;if (WIFEXITED(status)) {if (WEXITSTATUS(status) == 0)return;exit_code = WEXITSTATUS(status);} elseexit_code = 1;
#if 0fprintf(stderr, "pid %d: %s (signal %d)\n", pid,(status & 0x80) ? "core dumped" : "killed",status & 0x7f);/* #else */fprintf(stderr, "pid %d: failed %d\n", pid, status);
#endiffflush(stderr);return;}perror(argv[0]);exit(1);
}#ifdef CMD_HELP
void
do_help(argc, argv)char	**argv;
{CMDTAB	*cmdptr;for (cmdptr = cmdtab; cmdptr->name && cmdptr->name[0]; cmdptr++)printf("%-10s %s\n", cmdptr->name, cmdptr->usage);
}
#endif /* CMD_HELP */#ifdef CMD_ALIAS
void
do_alias(argc, argv)char	**argv;
{char	*name;char	*value;ALIAS	*alias;int	count;char	buf[CMDLEN];if (argc < 2) {count = aliascount;for (alias = aliastable; count-- > 0; alias++)printf("%s\t%s\n", alias->name, alias->value);return;}name = argv[1];if (argc == 2) {alias = findalias(name);if (alias)printf("%s\n", alias->value);elsefprintf(stderr, "Alias \"%s\" is not defined\n", name);return;	}if (strcmp(name, "alias") == 0) {fprintf(stderr, "Cannot alias \"alias\"\n");return;}if (!makestring(argc - 2, argv + 2, buf, CMDLEN))return;value = malloc(strlen(buf) + 1);if (value == NULL) {fprintf(stderr, "No memory for alias value\n");return;}strcpy(value, buf);alias = findalias(name);if (alias) {free(alias->value);alias->value = value;return;}if ((aliascount % ALIASALLOC) == 0) {count = aliascount + ALIASALLOC;if (aliastable)alias = (ALIAS *) realloc(aliastable,sizeof(ALIAS *) * count);elsealias = (ALIAS *) malloc(sizeof(ALIAS *) * count);if (alias == NULL) {free(value);fprintf(stderr, "No memory for alias table\n");return;}aliastable = alias;}alias = &aliastable[aliascount];alias->name = malloc(strlen(name) + 1);if (alias->name == NULL) {free(value);fprintf(stderr, "No memory for alias name\n");return;}strcpy(alias->name, name);alias->value = value;aliascount++;
}
#endif /* CMD_ALIAS *//** Look up an alias name, and return a pointer to it.* Returns NULL if the name does not exist.*/
static ALIAS *
findalias(name)char	*name;
{ALIAS	*alias;int	count;count = aliascount;for (alias = aliastable; count-- > 0; alias++) {if (strcmp(name, alias->name) == 0)return alias;}return NULL;
}void
do_source(argc, argv)char	**argv;
{readfile(argv[1]);
}/*void
do_cd(argc, argv)char	**argv;
{char	*name;name = argv[1];if (chdir(name))perror("Unable to chdir to %s");}*/void
do_pid(argc, argv)
{printf("%d\n", getpid());
}void
do_exec(argc, argv)char	**argv;
{while (--sourcecount >= 0) {if (sourcefiles[sourcecount] != stdin)fclose(sourcefiles[sourcecount]);}argv[argc] = NULL;execvp(argv[1], &argv[1]);perror(argv[1]);exit(1);
}/*void
do_exit(argc, argv)char	**argv;
{if (argc>1)exit(atoi(argv[1]));elseexit(0);
}*/#ifdef CMD_ALIAS
void
do_unalias(argc, argv)char	**argv;
{ALIAS	*alias;while (--argc > 0) {alias = findalias(*++argv);if (alias == NULL)continue;free(alias->name);free(alias->value);aliascount--;alias->name = aliastable[aliascount].name;alias->value = aliastable[aliascount].value;	}
}
#endif /* CMD_ALIAS *//** Display the prompt string.*/
static void
showprompt()
{char	*cp;/* ;'pa990523 changed from 6... */char buf[60];*buf = '\0';getcwd(buf, sizeof(buf) - 1);printf("%s> ", buf);fflush(stdout);
}	static void
catchint()
{signal(SIGINT, catchint);intflag = TRUE;if (intcrlf)write(STDOUT, "\n", 1);
}static void
catchquit()
{signal(SIGQUIT, catchquit);intflag = TRUE;if (intcrlf)write(STDOUT, "\n", 1);
}static void
catchchild()
{char buf[40];pid_t pid;int status;/*signal(SIGCHLD, catchchild);*/ /* Unneeded */pid = wait4(-1, &status, WUNTRACED, 0);if (WIFSTOPPED(status))sprintf(buf, "sh %d: Child %d stopped\n", getpid(), pid);
#if 0elsesprintf(buf, "sh %d: Child %d died\n", getpid(), pid);
#endif /* 0 */if (intcrlf)write(STDOUT, "\n", 1);write(STDOUT, buf, strlen(buf));
}/* END CODE */


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部