aboutsummaryrefslogtreecommitdiffstats
path: root/bcsh.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcsh.c')
-rw-r--r--bcsh.c209
1 files changed, 20 insertions, 189 deletions
diff --git a/bcsh.c b/bcsh.c
index 656d608..f1f6b42 100644
--- a/bcsh.c
+++ b/bcsh.c
@@ -19,199 +19,30 @@ int main(int argc, char **argv) {
19} 19}
20 20
21void showPrompt() { 21void showPrompt() {
22 printf("\033[01;32m%s" 22 if (getuid() == 0) {
23 "\033[35m@%s\033[00m:" 23 printf("%s@%s:%s# ", username, hostname, pwd);
24 "\033[33m%s\033[00m$ ",
25 username, hostname, pwd);
26 fflush(stdout);
27}
28
29Command *newCmd() {
30 Command *cmd = (Command *)malloc(sizeof(Command));
31 cmd->argc = 0;
32 cmd->args = NULL;
33 cmd->type = CMD_NORMAL;
34 cmd->left = NULL;
35 cmd->right = NULL;
36 for (int i = 0; i < 3; i++) {
37 cmd->redirectFile[i] = NULL;
38 cmd->redirectFD[i] = i;
39 }
40 cmd->background = false;
41 return cmd;
42}
43
44int runCmd(Command *cmd) {
45 int status;
46 if (cmd == NULL) {
47 fprintf(stderr, "cmd is NULL\n");
48 return -1;
49 }
50 switch (cmd->type) {
51 case CMD_NORMAL:
52 status = runNormalCmd(cmd);
53 break;
54 case CMD_PIPE:
55 status = runPipeCmd(cmd);
56 break;
57 case CMD_AND:
58 case CMD_OR:
59 status = runAndOrCmd(cmd);
60 break;
61 }
62
63 freeCmd(cmd);
64 return status;
65}
66
67int runNormalCmd(Command *cmd) {
68 pid_t pid;
69 int status;
70 if (!strcmp(cmd->args[0], "exit")) {
71 printf("Good Bye, %s!\n", username);
72 exit(0);
73 } else if (!strcmp(cmd->args[0], "cd")) {
74 if (cmd->argc == 1) {
75 chdir(getenv("HOME"));
76 } else {
77 chdir(cmd->args[1]);
78 }
79 printf("\r");
80 getcwd(pwd, sizeof(pwd));
81 } else { 24 } else {
82 if ((pid = fork()) == 0) { 25 printf("\033[01;32m%s"
83 // consider the redirection now 26 "\033[35m@%s\033[00m:"
84 // it's just a part of normal command 27 "\033[33m%s\033[00m$ ",
85 // but not in other types 28 username, hostname, pwd);
86 redirect(cmd);
87 exit(execvp(cmd->args[0], cmd->args));
88 } else {
89 if (!cmd->background) {
90 waitpid(pid, &status, 0);
91 if (!WIFEXITED(status)) {
92 // when here, the child process exited abnormally
93 fprintf(stderr, "Process %d exited with status %d\n", pid,
94 WEXITSTATUS(status));
95 }
96 }
97 }
98 // return the exit status of the child process
99 return WEXITSTATUS(status);
100 }
101}
102
103int runPipeCmd(Command *cmd) {
104 int status;
105 // create a pipe file and gets two file descriptors
106 // fd[0] is the read end, while fd[1] the write end
107 int fd[2];
108 pid_t left, right;
109 pipe(fd);
110 if ((left = fork()) == 0) {
111 /*
112 * close the read end of the pipe, so that the child process
113 * can only write to it; then redirect the standard output
114 * to the write end of the pipe, and close the write end
115 * itself as a file descriptor.
116 */
117 close(fd[0]);
118 dup2(fd[1], 1);
119 close(fd[1]);
120 exit(runCmd(cmd->left));
121 }
122 if ((right = fork()) == 0) {
123 close(fd[1]);
124 dup2(fd[0], 0);
125 close(fd[0]);
126 exit(runCmd(cmd->right));
127 }
128 // close the pipe, because the parent process doesn't need it
129 // and wait for the two child processes to exit
130 close(fd[0]);
131 close(fd[1]);
132 waitpid(left, NULL, 0);
133 waitpid(right, NULL, 0);
134}
135
136int runAndOrCmd(Command *cmd) {
137 int status;
138 if (cmd->type == CMD_AND) {
139 if (fork() == 0) {
140 exit(runCmd(cmd->left));
141 } else {
142 waitpid(-1, &status, 0);
143 if (WIFEXITED(status) && WEXITSTATUS(status) == 0 && fork() == 0) {
144 status = runCmd(cmd->right);
145 }
146 wait(NULL);
147 }
148 } else if (cmd->type == CMD_OR) {
149 if (fork() == 0) {
150 exit(runCmd(cmd->left));
151 } else {
152 waitpid(-1, &status, 0);
153 if (WIFEXITED(status) && WEXITSTATUS(status) != 0 && fork() == 0) {
154 status = runCmd(cmd->right);
155 }
156 wait(NULL);
157 }
158 }
159}
160
161void redirect(Command *cur) {
162 int fd;
163 char *rfile;
164 for (int i = 0; i < 3; i++) {
165 fd = cur->redirectFD[i];
166 rfile = cur->redirectFile[i];
167 if (fd < -1 || fd > 2) {
168 fprintf(stderr, "file descriptor %d is invalid\n", fd);
169 exit(1);
170 }
171 if (fd == i && rfile == NULL) {
172 continue;
173 }
174 if (fd == -1) {
175 // append
176 fd = open(rfile, O_WRONLY | O_CREAT | O_APPEND, 0666);
177 } else if (rfile != NULL) {
178 // normal redirection
179 fd = open(rfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
180 } else {
181 // file descriptor redirection
182 // when here, fd is surely in 0, 1, 2
183 ;
184 }
185
186 if (fd < 0) {
187 fprintf(stderr, "open file %s failed\n", rfile);
188 exit(1);
189 }
190 close(i);
191 dup2(fd, i);
192 close(fd);
193 } 29 }
30 fflush(stdout);
194} 31}
195 32
196void freeCmd(Command *cmd) { 33void argInsert(struct Command *cmd, char *s, bool isStr) {
197 if (cmd == NULL) { 34 if (cmd->argc == 0) {
198 return; 35 cmd->args = malloc(2 * sizeof(char *));
199 } 36 } else {
200 if (cmd->left != NULL) { 37 cmd->args = realloc(cmd->args, (cmd->argc + 2) * sizeof(char *));
201 freeCmd(cmd->left);
202 }
203 if (cmd->right != NULL) {
204 freeCmd(cmd->right);
205 }
206 int i;
207 for (i = 0; i < cmd->argc; i++) {
208 free(cmd->args[i]);
209 } 38 }
210 free(cmd->args); 39 if (isStr) {
211 for (i = 0; i < 3; i++) { 40 cmd->args[cmd->argc] = strdup(s + 1);
212 if (cmd->redirectFile[i] != NULL) { 41 cmd->args[cmd->argc][strlen(cmd->args[cmd->argc]) - 1] = '\0';
213 free(cmd->redirectFile[i]); 42 free(s);
214 } 43 } else {
44 cmd->args[cmd->argc] = s;
215 } 45 }
216 free(cmd); 46 cmd->args[cmd->argc + 1] = NULL;
47 cmd->argc++;
217} \ No newline at end of file 48} \ No newline at end of file