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

📄 sh.c

📁 用于motorala 68K系列处理器的小实时多任务操作系统 The OMU Kernel was written to provide a cut-down Unix-like O/S for a
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** *	Sh.c	Primitive shell-type routine. *		S.Hosgood, 23.feb.84, Modded T.Barnaby May 1985 for Codata ****************************************************************************** * *	When the shell is used internal to the kernal certain system calls *	have to be made in a special way ie through the system wrapper, *	Not direct. *	The routines that are relevent to this are at the end of this file. * *		xeq()		called via syscall() *		kwait()		called via syscall() *		putchar()	All console io done via write() system call *				because of interupt driven TTY. */# include	<sys/types.h># include	<errno.h>#if	defined(MSDOS)#define	STANDALONE	1#define	WILDCARDS	1#include	<sys/dirbsd.h>#include	<process.h>#else# include	<sys/dir.h>#endif#if	defined(STANDALONE)# include	<sys/stat.h># include	"inbin.h"# define	printk	printf#else# include	"../include/stat.h"# include	"../include/inbin.h"# include	"../include/state.h"#endif/*	WILDCARDS	If required define wild cards for internal shell *			Is an option because it will make the kernal big *			Approx + 2K */# define	WILDCARDS	1	/* Wild card mode on *//*	DATESET		If a call to dateset is required on power up *			Then define DATESET here *//* # define	DATESET		1 */# define	NARGS		10	/* Max number of argv's */# define	NENVS		10	/* Max number of env's */# define	ARGLEN		40	/* Line length enviroment varibles */# define	ENVLEN		40	/* Line length enviroment varibles */# define	LINELEN		100	/* Line length shell files */# define	NOTFOUND	-1	/* File not found to execute *//*	Execute mode bits 	*/# define	EBACKGRD	1	/* Background flag */# define	ENOERROR	2	/* No error check on shell files */extern	int errno;extern	struct Comm kercom[];/* Internal shell commands */int	cd(), setenv(), echo(), pmem(), smem(), shexit(), setid(), kstate();struct	Comm	shcom[] = {	"cd", 0, cd,	"exit", 0, shexit,	"shutdown", 0, shexit,	"setid", 0, setid,	"setenv", 0, setenv,	"echo", 0, echo,	"pmem", 0, pmem,	"smem", 0, smem,	"kstate", 0, kstate,	0, 0, 0,};int	fin, fout, ferr, chfiles;	/* Files opened */char	shenv[NENVS][ENVLEN];		/* Shell enviroment varibles */#ifdef	WILDCARDS# define	MAXNARGS 	50	/* Max number of args */# define	MAXAAREA	200	/* Max arg area */# define	MAXPATH		50	/* Max path length */struct	Args {	int	nargs;			/* Number of args */	char	*argp[MAXNARGS];	/* Argument pointers */	char	*endarg;		/* Last entry in arg area */	char	area[MAXAAREA];		/* Area where args is stored */};struct	Args wargv;#endif	WILDCARDS/* *	Sh()	Internal shell program itself */sh(){	char input[100], *argv[NARGS], *env[NENVS];	int nbytes, argc, c, in, error, backgnd, wargc;#if	defined(STANDALONE)	printk("Unix look-alike shell (testing)\n");#else	if(-1==chdir("/")) panic("change dir error\n"); 	/* Opens all files for shell */	openfiles();	printk("68000 One-Man-Unix System.	Version 4.0\n");	printk("Steve Hosgood, 1984 + Terry Barnaby 1985 + 1986\n");#endif	/* Setup enviroment pointers to enviroment area */	for(c = 0; c < NENVS; c++) env[c] = shenv[c];	/* Sets up dummy enviroment */	strcpy(shenv[0],"PATH=:/bin:/usr/bin:/INBIN");	strcpy(shenv[1],"HOME=/usr");	strcpy(shenv[2],"TERM=terries1");	strcpy(shenv[3],"TERMCAP=/etc/termcap");	strcpy(shenv[4],"EXINIT=map #0 i|map #1 x|set sm");	strcpy(shenv[5],"SHELL=/bin/csh");	env[5] = 0;# ifdef DATESET	/* set time */	argv[0] = "date";	printk("Enter date yymmddhhmm ? ");	if(getin(input)){		argv[1] = input;		argv[2] = 0;		if(execute("/bin/date", 2, argv, env, 0))			printk("Internal sh: Unable to execute /bin/date\n");	}# endif	/* Execute /etc/rc if present */	argv[0] = "rc";	argv[1] = 0;	execute("/etc/rc", 1, argv, env, ENOERROR);	/* Main shell internal loop */	while (1){		/* Prints prompt depending if root or not */		if(getuid()) write(1, "$> ", 3);		else write(1, "INSH# ", 6);		/* Gets input line */		nbytes = getin(input);		/* If no command continue to start of loop */		if (nbytes <= 1)			continue;		/* Parse the input command line into arguments */		argc = parse(input, argv);		/* Checks if process is to run background */		if(argv[argc-1][0] == '&'){			backgnd = 1;			argv[--argc] = 0;		}		else backgnd = 0;		/* Check if any file redirections required 		 * Sets file numbers as apropriate and sets chfiles		 * To indicate files have changed		 */		if((argc = chredir(argc, argv)) == -1) continue;#ifdef	WILDCARDS		/* Clear all previous args */		clearargs(&wargv);		wargc = 0;		for(c = 0; c < argc; c++){			/* Check if argument has wild cards if so do wild			 * card expansion			 */			if(wiswild(argv[c])){				if((in = wildexp(argv[c], "", &wargv)) == -1){					printk("Two many args\n");					break;				}			}			/* Else just add argument to args */			else{				if(!(in = addarg(argv[c], &wargv))){					printk("Two many args\n");					break;				}			}			wargc += in;		}		/* Try and execute program */		error = execute(wargv.argp[0], wargv.nargs, wargv.argp, env, backgnd);		/* If any redirections set to origanal files */		if(chfiles){			close(0);			close(1);			close(2);			openfiles();		}#else		/* Try and execute program */		error = execute(argv[0], argc, argv, env, backgnd);		/* If any redirections set to origanal files */		if(chfiles){			close(0);			close(1);			close(2);			openfiles();		}#endif	WILDCARDS		/* Print error messages */		switch(error){		case 0:			break;		case NOTFOUND:			/* Failed all attempts */			printk("%s: not found\n", argv[0]);			break;		default:			printk("%s: terminated %x\n",argv[0], error);			break;		}	}}/* *	Getin()		Get user input */getin(str)char	*str;{	int	num;	num = 0;	while(1){		read(fin, str, 1);		num++;		if((*str == '\n') || (*str == ';')) break;		str++;	}	*str = 0;	return num;}/* *	Opens all files for shell */openfiles(){	if ((fin = open("/dev/console", 2)) == -1){		if ((fin = open(":console", 2)) == -1)			panic("No console");	}	if (fin) panic("Std input non-zero");	fout = dup(fin);		/* Stdout and stderr */	ferr = dup(fout);	chfiles = 0;}/* *	Parse()		Parse command line into arguments return number. */parse(cptr, argv)char *cptr;char *argv[];{	int argc;	char	fquote;	/* scan line, breaking into args */	fquote = argc = 0;	while (1){		/* miss leading spaces */		while (*cptr && *cptr == ' ')			cptr++;		if (*cptr){			/* Check if quotes start of argument */			if(*cptr == '"'){				fquote = 1;				cptr++;			}			/* arg there */			argv[argc++] = cptr;			/* scan to end of word */			while (*cptr && ((*cptr != ' ') || fquote) &&				(*cptr != '"')) cptr++;			/* null terminate arg */			if ((*cptr == ' ') || (*cptr == '"')){				*cptr++ = '\0';				fquote = 0;			}		}		else			break;		if(argc >= (NARGS - 1)) break;	}	argv[argc] = 0;	return argc;}/* *	Execute()	Execute program, first checks internal shell *			commands then looks in places as defined in the *			enviroment varible PATH. *			If not found will exectute internal kernal command if *			found. *			Will execute shell files if found. *			Returns NOTFOUND if not found, or exit status *			of process if found. */execute(name, argc, argv, env, eflag)char *name;int argc, eflag;char *argv[], *env[];{	struct Comm *coms;	char	path[ENVLEN], *ps, *pe;	char	execname[ARGLEN];	int error;	/* Creates new proccess useing xeq (does fork and execl in one) */	error = 0;	/* Failed - try in PATH varible places */	/* Get path string */	retenv(env, "PATH", path);	ps = path;	/* Check internal shell commands */	coms = shcom;	while (coms->c_name && strcmp(coms->c_name, name) != 0) coms++;	/* Execute if found */	if(coms->c_name){		return (*coms->c_routine)(argc, argv, env);	}	/* Else check the paths as defined in the PATH enviroment */	while(1){		/* If end of path string break */		if(!(*ps)) break;		/* Find the end of the path entry */		pe = ps;		while(*pe && (*pe != ':')) pe++;		if(*pe) *pe++ = 0;		/* Copy this entry into the execname place and execute normally 		 */		strcpy(execname, ps);		/* If ps has a path in it add a slash */		if(execname[0]) strcat(execname, "/");		strcat(execname, name);		if((error = shexec(execname, argv, env, eflag)) != NOTFOUND)			return error;		/* Check if could be shell file */		if((error = shellfile(execname, argc, argv, env, eflag)) != NOTFOUND)			return error;		/* Next entry */		ps = pe;	}	/* failed there too - try built-in kernal commands */	coms = kercom;	while (coms->c_name && strcmp(coms->c_name, name) != 0) coms++;	/* try and execute */	if (coms->c_name){		return (*coms->c_routine)(argc, argv, env);	}	return NOTFOUND;}/* *	Shellfile()	Try and run shell file. *			Returns -1 if not found or not executable, *			Exit status of terminated program invoked. */shellfile(name, argc, argv, env, eflag)char *name;int argc, eflag;char *argv[], *env[];{	char *sargv[NARGS];	int file, sargc, err, error, backgnd;	char str[LINELEN];	/* Check if file executable */	if(access(name, 1)) return NOTFOUND;	/* Open file and execute */	if((file = open(name, 0)) != -1){		while(1){			if((err = getline(file, str)) == 1){				sargc = parse(str, sargv);				/* Checks if process is to run background */				backgnd = eflag & ENOERROR;				if(sargv[argc-1][0] == '&'){					backgnd |= EBACKGRD;					sargv[--argc] = 0;				}				/* Try and execute program */				error = execute(sargv[0],sargc,sargv,env,backgnd);				/* If errors are to be checked do check */				if(!(eflag & ENOERROR)){					switch(error){					case 0:						/* No error */						break;					case NOTFOUND:						/* Failed to execute */						printk("%s: not found\n", sargv[0]);						return error;					default:						/* Process returned with error */						printk("%s: terminated %x\n", sargv[0],						error);						return error;					}				}			}			else{				if(err == -1) return NOTFOUND;				else break;			}		}		close(file);	}	else return NOTFOUND;	return 0;}/* *	Getline()	Getline from a file terminated with newline. *			Returns 1 if found, 0 if end of file -1 if error. *			Ignores zero length lines and line begining with *			a #. */getline(file, line)int file;char *line;{	int count, n;	char *str;	/* Scans file for input line */	count = 0;	while(!count){		str = line;		*str = 0;		while(n = read(file, str, 1)){			if((*str == '\n') || (*str == ';')){				*str = 0;				break;			}			if((*str < ' ') || (*str > 'z')) return -1;			if(!count && (*str == '#')){				while((n = read(file, str, 1)) && *str != '\n');				break;			}			str++;			if(++count >= LINELEN) return -1;		}		if(!n) return 0;		}	return 1;}/* *	Chredir()	Check if any file redirections if found opens *			relevent files, and flags filech to indicate *			I/O files have been changed, removes *			the args from argv and returns the new value of argc;

⌨️ 快捷键说明

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