《Unix/Linux编程实践教程》之Shell编程二
《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:
|
评论暂时关闭