Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / 《Unix/Linux编程实践教程》之Shell编程二

《Unix/Linux编程实践教程》第九章将第八章所编的shell做进一步的完善,包括:1)加入命令行解析,方便用户在一行里输完命令和所有参数2)加入if..else..控制语句3)加入局部变量和环境变量对于上章后面的练习题(解决SIGINT信号杀死shell的BUG),本章也给出了解决方案,简单流程如下:在shell中忽略SIGINT和SIGQUIT,在子进程中对恢复信号的默认操作。相关阅读:《Unix/Linux编程实践教程》之Shell编程一 http://www.linuxidc.com/Linux/2012-12/75690.htm《Unix/Linux编程实践教程》之Shell编程二 http://www.linuxidc.com/Linux/2012-12/75691.htm《Unix/Linux编程实践教程》之管道 http://www.linuxidc.com/Linux/2012-12/75692.htmUnix/Linux编程实践教程【高清PDF中文版+附录光盘+代码】:http://www.linuxidc.com/Linux/2011-08/41374.htm代码如下,一共4个文件:smsh.h:1: #defineYES12: #defineNO03: 4: char*next_cmd();5: char**splitline(char *);6: voidfreelist(char **);7: void*emalloc(size_t);8: void*erealloc(void *, size_t);9: intexecute(char **); 10: voidfatal(char *, char *, int ); 11:12: intprocess();smsh1.c:1: /**smsh1.csmall-shell version 12:**first really useful version after prompting shell3:**this one parses the command line into strings4:**uses fork, exec, wait, and ignores signals5:**/6: 7: #include<stdio.h>8: #include<stdlib.h>9: #include<unistd.h> 10: #include<signal.h> 11: #include"smsh.h" 12:13: #defineDFL_PROMPT"> " 14:15: int main() 16: { 17: char*cmdline, *prompt, **arglist; 18: intresult; 19: voidsetup(); 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 smsh2:*3:*char *next_cmd(char *prompt, FILE *fp) - get next command4:*char **splitline(char *str); - parse a string5: 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: intbufspace = 0;/* total size*/ 24: intpos = 0;/* current position*/ 25: intc;/* 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: #defineis_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: intspots = 0;/* spots in table*/ 69: intbufspace = 0;/* bytes in table*/ 70: intargnum = 0;/* slots used*/ 71: char*cp = line;/* pos in string*/ 72: char*start; 73: intlen; 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 strings109:* returns: a string, never NULL110:*/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 splitline124:* returns: nothing125:*action: free all strings in list and then free the list126:*/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: #include8: 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: intpid ; 18: intchild_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: