《Unix/Linux编程实践教程》之Shell编程二


《Unix/Linux编程实践教程》第九章将第八章所编的shell做进一步的完善,包括:

1)加入命令行解析,方便用户在一行里输完命令和所有参数

2)加入if..else..控制语句

3)加入局部变量和环境变量

对于上章后面的练习题(解决SIGINT信号杀死shell的BUG),本章也给出了解决方案,简单流程如下:

在shell中忽略SIGINT和SIGQUIT,在子进程中对恢复信号的默认操作。

《Unix/Linux编程实践教程》之Shell编程一

《Unix/Linux编程实践教程》之Shell编程二

《Unix/Linux编程实践教程》之管道

Unix/Linux编程实践教程【高清PDF中文版+附录光盘+代码】:

代码如下,一共4个文件:

smsh.h:

  1: #define	YES	1
  2: #define	NO	0
  3: 
  4: char	*next_cmd();
  5: char	**splitline(char *);
  6: void	freelist(char **);
  7: void	*emalloc(size_t);
  8: void	*erealloc(void *, size_t);
  9: int	execute(char **);
 10: void	fatal(char *, char *, int );
 11: 
 12: int	process();

smsh1.c:

  1: /**  smsh1.c  small-shell version 1
  2:  **		first really useful version after prompting shell
  3:  **		this one parses the command line into strings
  4:  **		uses fork, exec, wait, and ignores signals
  5:  **/
  6: 
  7: #include	<stdio.h>
  8: #include	<stdlib.h>
  9: #include	<unistd.h>
 10: #include	<signal.h>
 11: #include	"smsh.h"
 12: 
 13: #define	DFL_PROMPT	"> "
 14: 
 15: int main()
 16: {
 17: 	char	*cmdline, *prompt, **arglist;
 18: 	int	result;
 19: 	void	setup();
 20: 
 21: 	prompt = DFL_PROMPT ;
 22: 	setup();
 23: 
 24: 	while ( (cmdline = next_cmd(prompt, stdin)) != NULL ){
 25: 		if ( (arglist = splitline(cmdline)) != NULL  ){
 26: 			result = execute(arglist);
 27: 			freelist(arglist);
 28: 		}
 29: 		free(cmdline);
 30: 	}
 31: 	return 0;
 32: }
 33: 
 34: void setup()
 35: /*
 36:  * purpose: initialize shell
 37:  * returns: nothing. calls fatal() if trouble
 38:  */
 39: {
 40: 	signal(SIGINT,  SIG_IGN);
 41: 	signal(SIGQUIT, SIG_IGN);
 42: }
 43: 
 44: void fatal(char *s1, char *s2, int n)
 45: {
 46: 	fprintf(stderr,"Error: %s,%s/n", s1, s2);
 47: 	exit(n);
 48: }
 49: 
 50: 

splitline.c:

  1: /* splitline.c - commmand reading and parsing functions for smsh
  2:  *    
  3:  *    char *next_cmd(char *prompt, FILE *fp) - get next command
  4:  *    char **splitline(char *str);           - parse a string
  5: 
  6:  */
  7: 
  8: #include	<stdio.h>
  9: #include	<stdlib.h>
 10: #include	<string.h>
 11: #include	"smsh.h"
 12: 
 13: char * next_cmd(char *prompt, FILE *fp)
 14: /*
 15:  * purpose: read next command line from fp
 16:  * returns: dynamically allocated string holding command line
 17:  *  errors: NULL at EOF (not really an error)
 18:  *          calls fatal from emalloc()
 19:  *   notes: allocates space in BUFSIZ chunks.  
 20:  */
 21: {
 22: 	char	*buf ; 				/* the buffer		*/
 23: 	int	bufspace = 0;			/* total size		*/
 24: 	int	pos = 0;			/* current position	*/
 25: 	int	c;				/* input char		*/
 26: 
 27: 	printf("%s", prompt);				/* prompt user	*/
 28: 	while( ( c = getc(fp)) != EOF ) {
 29: 
 30: 		/* need space? */
 31: 		if( pos+1 >= bufspace ){		/* 1 for /0	*/
 32: 			if ( bufspace == 0 )		/* y: 1st time	*/
 33: 				buf = emalloc(BUFSIZ);
 34: 			else				/* or expand	*/
 35: 				buf = erealloc(buf,bufspace+BUFSIZ);
 36: 			bufspace += BUFSIZ;		/* update size	*/
 37: 		}
 38: 
 39: 		/* end of command? */
 40: 		if ( c == '/n' )
 41: 			break;
 42: 
 43: 		/* no, add to buffer */
 44: 		buf[pos++] = c;
 45: 	}
 46: 	if ( c == EOF && pos == 0 )		/* EOF and no input	*/
 47: 		return NULL;			/* say so		*/
 48: 	buf[pos] = '/0';
 49: 	return buf;
 50: }
 51: 
 52: /**
 53:  **	splitline ( parse a line into an array of strings )
 54:  **/
 55: #define	is_delim(x) ((x)==' '||(x)=='/t')
 56: 
 57: char ** splitline(char *line)
 58: /*
 59:  * purpose: split a line into array of white-space separated tokens
 60:  * returns: a NULL-terminated array of pointers to copies of the tokens
 61:  *          or NULL if line if no tokens on the line
 62:  *  action: traverse the array, locate strings, make copies
 63:  *    note: strtok() could work, but we may want to add quotes later
 64:  */
 65: {
 66: 	char	*newstr();
 67: 	char	**args ;
 68: 	int	spots = 0;			/* spots in table	*/
 69: 	int	bufspace = 0;			/* bytes in table	*/
 70: 	int	argnum = 0;			/* slots used		*/
 71: 	char	*cp = line;			/* pos in string	*/
 72: 	char	*start;
 73: 	int	len;
 74: 
 75: 	if ( line == NULL )			/* handle special case	*/
 76: 		return NULL;
 77: 
 78: 	args     = emalloc(BUFSIZ);		/* initialize array	*/
 79: 	bufspace = BUFSIZ;
 80: 	spots    = BUFSIZ/sizeof(char *);
 81: 
 82: 	while( *cp != '/0' )
 83: 	{
 84: 		while ( is_delim(*cp) )		/* skip leading spaces	*/
 85: 			cp++;
 86: 		if ( *cp == '/0' )		/* quit at end-o-string	*/
 87: 			break;
 88: 
 89: 		/* make sure the array has room (+1 for NULL) */
 90: 		if ( argnum+1 >= spots ){
 91: 			args = erealloc(args,bufspace+BUFSIZ);
 92: 			bufspace += BUFSIZ;
 93: 			spots += (BUFSIZ/sizeof(char *));
 94: 		}
 95: 
 96: 		/* mark start, then find end of word */
 97: 		start = cp;
 98: 		len   = 1;
 99: 		while (*++cp != '/0' && !(is_delim(*cp)) )
100: 			len++;
101: 		args[argnum++] = newstr(start, len);
102: 	}
103: 	args[argnum] = NULL;
104: 	return args;
105: }
106: 
107: /*
108:  * purpose: constructor for strings
109:  * returns: a string, never NULL
110:  */
111: char *newstr(char *s, int l)
112: {
113: 	char *rv = emalloc(l+1);
114: 
115: 	rv[l] = '/0';
116: 	strncpy(rv, s, l);
117: 	return rv;
118: }
119: 
120: void 
121: freelist(char **list)
122: /*
123:  * purpose: free the list returned by splitline
124:  * returns: nothing
125:  *  action: free all strings in list and then free the list
126:  */
127: {
128: 	char	**cp = list;
129: 	while( *cp )
130: 		free(*cp++);
131: 	free(list);
132: }
133: 
134: void * emalloc(size_t n)
135: {
136: 	void *rv ;
137: 	if ( (rv = malloc(n)) == NULL )
138: 		fatal("out of memory","",1);
139: 	return rv;
140: }
141: void * erealloc(void *p, size_t n)
142: {
143: 	void *rv;
144: 	if ( (rv = realloc(p,n)) == NULL )
145: 		fatal("realloc() failed","",1);
146: 	return rv;
147: }
148: 
149: 

execute.c:

  1: /* execute.c - code used by small shell to execute commands */
  2: 
  3: #include	<stdio.h>
  4: #include	<stdlib.h>
  5: #include	<unistd.h>
  6: #include	<signal.h>
  7: #include	
  8: 
  9: int execute(char *argv[])
 10: /*
 11:  * purpose: run a program passing it arguments
 12:  * returns: status returned via wait, or -1 on error
 13:  *  errors: -1 on fork() or wait() errors
 14: 
 15:  */
 16: {
 17: 	int	pid ;
 18: 	int	child_info = -1;
 19: 
 20: 	if ( argv[0] == NULL )		/* nothing succeeds	*/
 21: 		return 0;
 22: 
 23: 	if ( (pid = fork())  == -1 )
 24: 		perror("fork");
 25: 	else if ( pid == 0 ){
 26: 		signal(SIGINT, SIG_DFL);
 27: 		signal(SIGQUIT, SIG_DFL);
 28: 		execvp(argv[0], argv);
 29: 		perror("cannot execute command");
 30: 		exit(1);
 31: 	}
 32: 	else {
 33: 		if ( wait(&child_info) == -1 )
 34: 			perror("wait");
 35: 	}
 36: 	return child_info;
 37: }
 38: 

 

  • 1
  • 2
  • 下一页

相关内容