|
@ -168,93 +168,172 @@ int check_redirect(char **args, char *redirect_filename, char **redirect_args) |
|
|
return redirect_flag; |
|
|
return redirect_flag; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int check_pipe(char **args, char **pipe_arg_1, char **pipe_arg_2) |
|
|
|
|
|
{ |
|
|
|
|
|
int pipe_flag = 0, i = 0, j = 0; |
|
|
|
|
|
|
|
|
|
|
|
while (args[i] != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!strcmp(args[i], "|")) |
|
|
|
|
|
{ |
|
|
|
|
|
pipe_flag = 1; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
pipe_arg_1[j++] = args[i++]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
j = 0; |
|
|
|
|
|
i++; |
|
|
|
|
|
while (args[i] != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
pipe_arg_2[j++] = args[i++]; |
|
|
|
|
|
} |
|
|
|
|
|
return pipe_flag; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int execute(char *cmdline, char **args) |
|
|
int execute(char *cmdline, char **args) |
|
|
{ |
|
|
{ |
|
|
int bg = 0, i = 0, redirect_flag = 0, fd = 1; |
|
|
|
|
|
|
|
|
int bg = 0, i = 0, redirect_flag = 0, fd = 1, pipe_num = 0; |
|
|
pid_t pid; |
|
|
pid_t pid; |
|
|
char *redirect_filename = NULL; |
|
|
char *redirect_filename = NULL; |
|
|
redirect_filename = (char *)calloc(REDIRECT_FILENAME_MAX_SIZE, sizeof(char)); |
|
|
|
|
|
char *redirect_args[ARGS_MAX_QUANTITY]; |
|
|
char *redirect_args[ARGS_MAX_QUANTITY]; |
|
|
|
|
|
char *pipe_arg_1[ARGS_MAX_QUANTITY]; |
|
|
|
|
|
char *pipe_arg_2[ARGS_MAX_QUANTITY]; |
|
|
|
|
|
|
|
|
|
|
|
redirect_filename = (char *)calloc(REDIRECT_FILENAME_MAX_SIZE, sizeof(char)); |
|
|
memset(redirect_args, NULL, sizeof(redirect_args)); |
|
|
memset(redirect_args, NULL, sizeof(redirect_args)); |
|
|
|
|
|
|
|
|
sigset_t mask_all, mask_prev; |
|
|
sigset_t mask_all, mask_prev; |
|
|
sigprocmask(SIG_BLOCK, NULL, &mask_all); |
|
|
sigprocmask(SIG_BLOCK, NULL, &mask_all); |
|
|
sigaddset(&mask_all, SIGCHLD); |
|
|
sigaddset(&mask_all, SIGCHLD); |
|
|
|
|
|
|
|
|
bg = parseline(cmdline, args); |
|
|
bg = parseline(cmdline, args); |
|
|
redirect_flag = check_redirect(args, redirect_filename, redirect_args); |
|
|
redirect_flag = check_redirect(args, redirect_filename, redirect_args); |
|
|
|
|
|
pipe_num = check_pipe(args, pipe_arg_1, pipe_arg_2); |
|
|
|
|
|
|
|
|
if (args[0] == NULL) |
|
|
if (args[0] == NULL) |
|
|
{ |
|
|
{ |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
if (!built_in(args)) |
|
|
|
|
|
|
|
|
if (pipe_num == 0) |
|
|
{ |
|
|
{ |
|
|
/* Prevent child processes from ending between parent processes, that is, between addJob and deleteJob. */ |
|
|
|
|
|
sigprocmask(SIG_BLOCK, &mask_all, &mask_prev); /* Shield SIGCHLD */ |
|
|
|
|
|
|
|
|
|
|
|
if ((pid = fork()) == 0) /* Child process */ |
|
|
|
|
|
|
|
|
if (!built_in(args)) /* built-in cmd? */ |
|
|
{ |
|
|
{ |
|
|
if (redirect_flag == 1) |
|
|
|
|
|
{ |
|
|
|
|
|
fd = open(redirect_filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); |
|
|
|
|
|
close(1); |
|
|
|
|
|
dup(fd); |
|
|
|
|
|
} |
|
|
|
|
|
else if (redirect_flag == 2) |
|
|
|
|
|
|
|
|
/* Prevent child processes from ending between parent processes, that is, between addJob and deleteJob. */ |
|
|
|
|
|
sigprocmask(SIG_BLOCK, &mask_all, &mask_prev); /* Shield SIGCHLD */ |
|
|
|
|
|
|
|
|
|
|
|
if ((pid = fork()) == 0) /* Child process */ |
|
|
{ |
|
|
{ |
|
|
fd = open(redirect_filename, O_RDONLY, S_IRUSR); |
|
|
|
|
|
close(0); |
|
|
|
|
|
dup(fd); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (redirect_flag == 1) /* redirect? */ |
|
|
|
|
|
{ |
|
|
|
|
|
fd = open(redirect_filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); |
|
|
|
|
|
close(1); |
|
|
|
|
|
dup(fd); |
|
|
|
|
|
} |
|
|
|
|
|
else if (redirect_flag == 2) |
|
|
|
|
|
{ |
|
|
|
|
|
fd = open(redirect_filename, O_RDONLY, S_IRUSR); |
|
|
|
|
|
close(0); |
|
|
|
|
|
dup(fd); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* The child process inherits the parent's signal mask and will inherit it after exec,
|
|
|
|
|
|
so it needs to restore the signal mask before executing. */ |
|
|
|
|
|
sigprocmask(SIG_SETMASK, &mask_prev, NULL); /* Child process, unblock SIGCHLD */ |
|
|
|
|
|
|
|
|
/* The child process inherits the parent's signal mask and will inherit it after exec,
|
|
|
|
|
|
so it needs to restore the signal mask before executing. */ |
|
|
|
|
|
sigprocmask(SIG_SETMASK, &mask_prev, NULL); /* Child process, unblock SIGCHLD */ |
|
|
|
|
|
|
|
|
/* Set the pid of the current process to the group number of the process group it belongs to. */ |
|
|
|
|
|
/* avoid being grouped with tsh */ |
|
|
|
|
|
setpgid(0, 0); |
|
|
|
|
|
|
|
|
/* Set the pid of the current process to the group number of the process group it belongs to. */ |
|
|
|
|
|
/* avoid being grouped with tsh */ |
|
|
|
|
|
setpgid(0, 0); |
|
|
|
|
|
|
|
|
if ((redirect_flag == 1) || (redirect_flag == 2)) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
if ((redirect_flag == 1) || (redirect_flag == 2)) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
if (execvp(redirect_args[0], redirect_args) <= 0) |
|
|
|
|
|
|
|
|
if (execvp(redirect_args[0], redirect_args) <= 0) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s: Command not found\n", args[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
close(fd); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
{ |
|
|
{ |
|
|
printf("%s: Command not found\n", args[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
|
|
|
if (execvp(args[0], args) <= 0) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s: Command not found\n", args[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
close(fd); |
|
|
|
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
if (execvp(args[0], args) <= 0) |
|
|
|
|
|
|
|
|
if (bg) /* bg task */ |
|
|
|
|
|
{ |
|
|
|
|
|
addjob(jobs, pid, BG, cmdline); |
|
|
|
|
|
} |
|
|
|
|
|
else /* fg task */ |
|
|
|
|
|
{ |
|
|
|
|
|
addjob(jobs, pid, FG, cmdline); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sigprocmask(SIG_SETMASK, &mask_prev, NULL); |
|
|
|
|
|
|
|
|
|
|
|
if (bg) /* Don't wait for background tasks to finish */ |
|
|
{ |
|
|
{ |
|
|
printf("%s: Command not found\n", args[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
|
|
|
printf("[%d](%d)%s", pid2jid(pid), pid, cmdline); |
|
|
|
|
|
} |
|
|
|
|
|
else /* Wait for foreground tasks to finish */ |
|
|
|
|
|
{ |
|
|
|
|
|
waitfg(pid); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
int fds[2]; |
|
|
|
|
|
pid_t prog_1, prog_2; |
|
|
|
|
|
sigprocmask(SIG_BLOCK, &mask_all, &mask_prev); |
|
|
|
|
|
|
|
|
|
|
|
if ((prog_1 = fork()) == 0) /* Child process 1 */ |
|
|
{ |
|
|
{ |
|
|
if (bg) /* bg task */ |
|
|
|
|
|
{ |
|
|
|
|
|
addjob(jobs, pid, BG, cmdline); |
|
|
|
|
|
} |
|
|
|
|
|
else /* fg task */ |
|
|
|
|
|
{ |
|
|
|
|
|
addjob(jobs, pid, FG, cmdline); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
dup2(fds[1], 1); |
|
|
|
|
|
dup2(fds[1], 2); |
|
|
|
|
|
close(fds[0]); |
|
|
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
|
sigprocmask(SIG_SETMASK, &mask_prev, NULL); |
|
|
sigprocmask(SIG_SETMASK, &mask_prev, NULL); |
|
|
|
|
|
setpgid(0, 0); |
|
|
|
|
|
|
|
|
if (bg) /* Don't wait for background tasks to finish */ |
|
|
|
|
|
|
|
|
if (execvp(pipe_arg_1[0], pipe_arg_1) <= 0) |
|
|
{ |
|
|
{ |
|
|
printf("[%d](%d)%s", pid2jid(pid), pid, cmdline); |
|
|
|
|
|
|
|
|
printf("%s: Command not found\n", pipe_arg_1[0]); |
|
|
|
|
|
exit(0); |
|
|
} |
|
|
} |
|
|
else /* Wait for foreground tasks to finish */ |
|
|
|
|
|
|
|
|
_exit(127); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((prog_2 = fork()) == 0) /* Child process 1 */ |
|
|
|
|
|
{ |
|
|
|
|
|
dup2(fds[0], 0); |
|
|
|
|
|
close(fds[0]); |
|
|
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
|
|
|
|
sigprocmask(SIG_SETMASK, &mask_prev, NULL); |
|
|
|
|
|
setpgid(0, 0); |
|
|
|
|
|
|
|
|
|
|
|
if (execvp(pipe_arg_2[0], pipe_arg_2) <= 0) |
|
|
{ |
|
|
{ |
|
|
waitfg(pid); |
|
|
|
|
|
|
|
|
printf("%s: Command not found\n", pipe_arg_2[0]); |
|
|
|
|
|
exit(0); |
|
|
} |
|
|
} |
|
|
|
|
|
_exit(127); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
close(fds[0]); |
|
|
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
|
|
|
|
waitfg(prog_1); |
|
|
|
|
|
waitfg(prog_2); |
|
|
} |
|
|
} |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|