aboutsummaryrefslogtreecommitdiffstats
path: root/bcsh.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcsh.c')
-rw-r--r--bcsh.c156
1 files changed, 137 insertions, 19 deletions
diff --git a/bcsh.c b/bcsh.c
index 6830671..08f7ac7 100644
--- a/bcsh.c
+++ b/bcsh.c
@@ -1,40 +1,161 @@
1#include "cmd.h" 1#include "cmd.h"
2 2
3extern int yyparse(); 3extern int yyparse();
4char hostname[100];
5char *username;
6char pwd[100];
4 7
5int main(int argc, char **argv) { 8int 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
20void 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
12Command *newcmd() { 27Command *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
22int runcmd(Command *cmd) { 42int 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
40void freecmd(Command *cmd) { 161void 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]);
58void 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