-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrcsh.c
86 lines (69 loc) · 1.81 KB
/
rcsh.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include "inner_cmds.c"
#include "read_cmd.c"
pid_t execute(char *, char **);
void sigchld_wait(int);
void sigint_ignore(int sig) { return; }
int main(void) {
// bg実行終了後のリソース回収処理
if (signal(SIGCHLD, sigchld_wait) == SIG_ERR) {
fprintf(stderr, "rcsh: signal(SIGCHLD) failed\n");
exit(1);
}
int argc = 0, status;
bool exec_bg = false;
char **argv;
pid_t pid;
// 組み込みコマンドの取得
int inner_cmds_cnt;
char **inner_cmds = get_inner_cmd(&inner_cmds_cnt);
while (1) {
// ^Cを無視
if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
fprintf(stderr, "rcsh: signal(SIGINT) failed\n");
exit(1);
}
// read
if ((argv = read_cmd(&argc, &exec_bg)) == NULL) {
break;
}
// no input
if (argc < 1) {
free_argv(argv);
continue;
}
// exit
if (strcmp(argv[0], "exit") == 0) {
free_argv(argv);
break;
}
// update cmdpath if internal command
char *cmd = check_inner_cmd(inner_cmds_cnt, inner_cmds, argv);
// execute
pid = execute(cmd, argv);
// wait
if (!exec_bg) {
wait(&status);
}
free_argv(argv);
}
free_inner_cmds(inner_cmds_cnt, inner_cmds);
return 0;
}
pid_t execute(char *cmd, char *argv[]) {
pid_t pid = fork();
if (pid != 0) return pid;
signal(SIGINT, SIG_DFL);
execvp(cmd, argv);
perror(argv[0]);
exit(1);
}
void sigchld_wait(int sig) {
int status;
waitpid(-1, &status, WNOHANG);
printf("process exited with status %d\n", WEXITSTATUS(status));
}