diff options
Diffstat (limited to 'bcsh.c')
-rw-r--r-- | bcsh.c | 156 |
1 files changed, 137 insertions, 19 deletions
@@ -1,40 +1,161 @@ | |||
1 | #include "cmd.h" | 1 | #include "cmd.h" |
2 | 2 | ||
3 | extern int yyparse(); | 3 | extern int yyparse(); |
4 | char hostname[100]; | ||
5 | char *username; | ||
6 | char pwd[100]; | ||
4 | 7 | ||
5 | int main(int argc, char **argv) { | 8 | int main(int argc, char **argv) { |
9 | // 获取当前登陆的用户名、系统主机名、当前工作路径 | ||
10 | gethostname(hostname, sizeof(hostname)); | ||
11 | getcwd(pwd, sizeof(pwd)); | ||
12 | username = getpwuid(getuid())->pw_name; | ||
13 | showPrompt(); | ||
6 | while (true) { | 14 | while (true) { |
7 | yyparse(); | 15 | yyparse(); |
8 | } | 16 | } |
9 | return 0; | 17 | return 0; |
10 | } | 18 | } |
11 | 19 | ||
20 | void showPrompt() { | ||
21 | printf("\033[01;32m%s@%s\033[00m:\033[33m%s\033[00m$ ", username, hostname, | ||
22 | pwd); | ||
23 | // 强制刷新缓冲区 | ||
24 | fflush(stdout); | ||
25 | } | ||
26 | |||
12 | Command *newcmd() { | 27 | Command *newcmd() { |
13 | Command *cmd = (Command *)malloc(sizeof(Command)); | 28 | Command *cmd = (Command *)malloc(sizeof(Command)); |
14 | cmd->argc = 0; | 29 | cmd->argc = 0; |
15 | cmd->args = NULL; | 30 | cmd->args = NULL; |
16 | cmd->type = CMD_TYPE_NORMAL; | 31 | cmd->type = CMD_NORMAL; |
17 | cmd->left = NULL; | 32 | cmd->left = NULL; |
18 | cmd->right = NULL; | 33 | cmd->right = NULL; |
34 | for (int i = 0; i < 3; i++) { | ||
35 | cmd->redirectFile[i] = NULL; | ||
36 | cmd->redirectFD[i] = i; | ||
37 | } | ||
38 | cmd->background = false; | ||
19 | return cmd; | 39 | return cmd; |
20 | } | 40 | } |
21 | 41 | ||
22 | int runcmd(Command *cmd) { | 42 | int runcmd(Command *cmd) { |
23 | int i; | 43 | int status; |
24 | if (cmd == NULL) { | 44 | if (cmd == NULL) { |
25 | fprintf(stderr, "cmd is NULL\n"); | 45 | fprintf(stderr, "cmd is NULL\n"); |
26 | } else if (cmd->type != CMD_TYPE_NORMAL) { | 46 | return -1; |
27 | runcmd(cmd->left); | ||
28 | runcmd(cmd->right); | ||
29 | return 0; | ||
30 | } | 47 | } |
31 | printcmd(cmd); | 48 | |
32 | if (!strcmp(cmd->args[0], "exit")) { | 49 | if (cmd->type == CMD_NORMAL) { |
33 | freecmd(cmd); | 50 | pid_t pid; |
34 | exit(0); | 51 | if (!strcmp(cmd->args[0], "exit")) { |
52 | printf("Good Bye, %s!\n", username); | ||
53 | exit(0); | ||
54 | } else if (!strcmp(cmd->args[0], "cd")) { | ||
55 | if (cmd->argc == 1) { | ||
56 | chdir(getenv("HOME")); | ||
57 | } else { | ||
58 | chdir(cmd->args[1]); | ||
59 | } | ||
60 | printf("\r"); | ||
61 | getcwd(pwd, sizeof(pwd)); | ||
62 | } else { | ||
63 | if ((pid = fork()) == 0) { | ||
64 | // consider the redirection now | ||
65 | // it's just a part of normal command | ||
66 | // but not in other types | ||
67 | for (int i = 0; i < 3; i++) { | ||
68 | if (cmd->redirectFD[i] != i) { | ||
69 | close(i); | ||
70 | dup2(cmd->redirectFD[i], i); | ||
71 | } else if (cmd->redirectFile[i] != NULL) { | ||
72 | int fd = | ||
73 | open(cmd->redirectFile[i], O_RDWR | O_CREAT, 0666); | ||
74 | if (fd < 0) { | ||
75 | fprintf(stderr, "open file %s failed\n", | ||
76 | cmd->redirectFile[i]); | ||
77 | exit(-1); | ||
78 | } | ||
79 | close(i); | ||
80 | dup2(fd, i); | ||
81 | close(fd); | ||
82 | } | ||
83 | } | ||
84 | if (cmd->background) { | ||
85 | setpgid(0, 0); | ||
86 | // no output, redirect 1 and 2 to /dev/null | ||
87 | int fd = open("/dev/null", O_RDWR); | ||
88 | dup2(fd, 1); | ||
89 | dup2(fd, 2); | ||
90 | close(fd); | ||
91 | } | ||
92 | exit(execvp(cmd->args[0], cmd->args)); | ||
93 | } else { | ||
94 | if (!cmd->background) { | ||
95 | waitpid(pid, &status, 0); | ||
96 | if (!WIFEXITED(status)) { | ||
97 | // when here, the child process exited abnormally | ||
98 | fprintf(stderr, "Process %d exited with status %d\n", | ||
99 | pid, WEXITSTATUS(status)); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | // return the exit status of the child process | ||
104 | return WEXITSTATUS(status); | ||
105 | } | ||
106 | } else if (cmd->type == CMD_PIPE) { | ||
107 | // create a pipe file and gets two file descriptors | ||
108 | // fd[0] is the read end, while fd[1] the write end | ||
109 | int fd[2]; | ||
110 | pid_t left, right; | ||
111 | pipe(fd); | ||
112 | if ((left = fork()) == 0) { | ||
113 | /* | ||
114 | * close the read end of the pipe, so that the child process | ||
115 | * can only write to it; then redirect the standard output | ||
116 | * to the write end of the pipe, and close the write end | ||
117 | * itself as a file descriptor. | ||
118 | */ | ||
119 | close(fd[0]); | ||
120 | dup2(fd[1], 1); | ||
121 | close(fd[1]); | ||
122 | exit(runcmd(cmd->left)); | ||
123 | } | ||
124 | if ((right = fork()) == 0) { | ||
125 | close(fd[1]); | ||
126 | dup2(fd[0], 0); | ||
127 | close(fd[0]); | ||
128 | exit(runcmd(cmd->right)); | ||
129 | } | ||
130 | // close the pipe, because the parent process doesn't need it | ||
131 | // and wait for the two child processes to exit | ||
132 | close(fd[0]); | ||
133 | close(fd[1]); | ||
134 | waitpid(left, NULL, 0); | ||
135 | waitpid(right, NULL, 0); | ||
136 | } else if (cmd->type == CMD_AND) { | ||
137 | if (fork() == 0) { | ||
138 | exit(runcmd(cmd->left)); | ||
139 | } else { | ||
140 | waitpid(-1, &status, 0); | ||
141 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0 && fork() == 0) { | ||
142 | status = runcmd(cmd->right); | ||
143 | } | ||
144 | wait(NULL); | ||
145 | } | ||
146 | } else if (cmd->type == CMD_OR) { | ||
147 | if (fork() == 0) { | ||
148 | exit(runcmd(cmd->left)); | ||
149 | } else { | ||
150 | waitpid(-1, &status, 0); | ||
151 | if (WIFEXITED(status) && WEXITSTATUS(status) != 0 && fork() == 0) { | ||
152 | status = runcmd(cmd->right); | ||
153 | } | ||
154 | wait(NULL); | ||
155 | } | ||
35 | } | 156 | } |
36 | freecmd(cmd); | 157 | freecmd(cmd); |
37 | return 0; | 158 | return status; |
38 | } | 159 | } |
39 | 160 | ||
40 | void freecmd(Command *cmd) { | 161 | void freecmd(Command *cmd) { |
@@ -52,13 +173,10 @@ void freecmd(Command *cmd) { | |||
52 | free(cmd->args[i]); | 173 | free(cmd->args[i]); |
53 | } | 174 | } |
54 | free(cmd->args); | 175 | free(cmd->args); |
55 | free(cmd); | 176 | for (i = 0; i < 3; i++) { |
56 | } | 177 | if (cmd->redirectFile[i] != NULL) { |
57 | 178 | free(cmd->redirectFile[i]); | |
58 | void printcmd(Command *cmd) { | 179 | } |
59 | int i; | ||
60 | for (i = 0; i < cmd->argc; i++) { | ||
61 | printf("%s ", cmd->args[i]); | ||
62 | } | 180 | } |
63 | printf("\n"); | 181 | free(cmd); |
64 | } \ No newline at end of file | 182 | } \ No newline at end of file |