|
10 | 10 | #include <dirent.h> |
11 | 11 |
|
12 | 12 | static char *trim(char *s) { |
13 | | - while (isspace(*s)) s++; |
14 | | - if (*s == 0) return s; |
15 | | - char *end = s + strlen(s) - 1; |
16 | | - while (end > s && isspace(*end)) end--; |
17 | | - end[1] = '\0'; |
18 | | - return s; |
| 13 | + while (isspace(*s)) |
| 14 | + s++; |
| 15 | + if (*s == 0) |
| 16 | + return s; |
| 17 | + char *end = s + strlen(s) - 1; |
| 18 | + while (end > s && isspace(*end)) |
| 19 | + end--; |
| 20 | + end[1] = '\0'; |
| 21 | + return s; |
19 | 22 | } |
20 | 23 |
|
21 | 24 | // split a string like "cmd arg1 arg2" into argv[] |
22 | 25 | static char **make_argv(char *cmd) { |
23 | | - int cap = 8, n = 0; |
24 | | - char **argv = malloc(sizeof(char*) * cap); |
25 | | - char *tok = strtok(cmd, " \t"); |
26 | | - while (tok) { |
27 | | - if (n + 1 >= cap) { |
28 | | - cap *= 2; |
29 | | - argv = realloc(argv, sizeof(char*) * cap); |
30 | | - } |
31 | | - argv[n++] = tok; |
32 | | - tok = strtok(NULL, " \t"); |
33 | | - } |
34 | | - argv[n] = NULL; |
35 | | - return argv; |
| 26 | + int cap = 8, n = 0; |
| 27 | + char **argv = malloc(sizeof(char *) * cap); |
| 28 | + char *tok = strtok(cmd, " \t"); |
| 29 | + while (tok) { |
| 30 | + if (n + 1 >= cap) { |
| 31 | + cap *= 2; |
| 32 | + argv = realloc(argv, sizeof(char *) * cap); |
| 33 | + } |
| 34 | + argv[n++] = tok; |
| 35 | + tok = strtok(NULL, " \t"); |
| 36 | + } |
| 37 | + argv[n] = NULL; |
| 38 | + return argv; |
36 | 39 | } |
37 | 40 |
|
38 | 41 | void list_dir(const char *path) { |
39 | | - DIR *d = opendir(path); |
40 | | - struct dirent *entry; |
41 | | - printf("Contents of %s:\n", path); |
42 | | - while ((entry = readdir(d)) != NULL) { |
43 | | - printf(" %s\n", entry->d_name); |
44 | | - } |
45 | | - closedir(d); |
46 | | - printf("\n"); |
| 42 | + DIR *d = opendir(path); |
| 43 | + struct dirent *entry; |
| 44 | + printf("Contents of %s:\n", path); |
| 45 | + while ((entry = readdir(d)) != NULL) { |
| 46 | + printf(" %s\n", entry->d_name); |
| 47 | + } |
| 48 | + closedir(d); |
| 49 | + printf("\n"); |
47 | 50 | } |
48 | 51 |
|
49 | 52 | int main(int argc, char **argv) { |
50 | | - if (argc < 3 || strcmp(argv[1], "-c") != 0) { |
51 | | - fprintf(stderr, "usage: %s -c \"command\"\n", argv[0]); |
52 | | - return 1; |
53 | | - } |
| 53 | + if (argc < 3 || strcmp(argv[1], "-c") != 0) { |
| 54 | + fprintf(stderr, "usage: %s -c \"command\"\n", argv[0]); |
| 55 | + return 1; |
| 56 | + } |
54 | 57 |
|
55 | | - int fd = open("etest.wasm", O_WRONLY, 0); |
56 | | - printf("FD etest: %d\n", fd); |
57 | | - close(fd); |
| 58 | + int fd = open("etest.wasm", O_WRONLY, 0); |
| 59 | + printf("FD etest: %d\n", fd); |
| 60 | + close(fd); |
58 | 61 |
|
59 | | - int nchildren=0; |
| 62 | + int nchildren = 0; |
60 | 63 |
|
61 | | - char *cmd = strdup(argv[2]); // full string |
62 | | - char *saveptr; |
63 | | - char *segment = strtok_r(cmd, "&", &saveptr); |
| 64 | + char *cmd = strdup(argv[2]); // full string |
| 65 | + char *saveptr; |
| 66 | + char *segment = strtok_r(cmd, "&", &saveptr); |
64 | 67 |
|
65 | | - while (segment) { |
66 | | - char *t = trim(segment); |
67 | | - if (*t) { |
68 | | - pid_t pid = fork(); |
69 | | - if (pid == 0) { |
70 | | - // child: exec command |
71 | | - char *copy = strdup(t); |
72 | | - char **cmd_argv = make_argv(copy); |
73 | | - |
74 | | - execv(cmd_argv[0], cmd_argv); |
75 | | - char errbuf[256]; |
76 | | - snprintf(errbuf, sizeof(errbuf), "execv(%s)", cmd_argv[0]); |
77 | | - perror(errbuf); |
78 | | - exit(1); |
79 | | - } else if (pid < 0) { |
80 | | - perror("fork"); |
81 | | - }else { |
82 | | - nchildren++; |
83 | | - } |
84 | | - // parent: do not wait (background) |
85 | | - } |
86 | | - segment = strtok_r(NULL, "&", &saveptr); |
87 | | - } |
| 68 | + while (segment) { |
| 69 | + char *t = trim(segment); |
| 70 | + if (*t) { |
| 71 | + pid_t pid = fork(); |
| 72 | + if (pid == 0) { |
| 73 | + // child: exec command |
| 74 | + char *copy = strdup(t); |
| 75 | + char **cmd_argv = make_argv(copy); |
88 | 76 |
|
89 | | - // behave like bash when all jobs are background: |
90 | | - // exit immediately, but reap zombies |
91 | | - for (int i = 0; i < nchildren; i++) { |
92 | | - int status; |
93 | | - pid_t w = wait(&status); |
94 | | - if (w > 0) { |
95 | | - printf("[mash] terminated pid %d, status %d\n", w, status); |
96 | | - } |
97 | | - } |
98 | | - |
99 | | - return 0; |
| 77 | + execv(cmd_argv[0], cmd_argv); |
| 78 | + char errbuf[256]; |
| 79 | + snprintf(errbuf, sizeof(errbuf), "execv(%s)", |
| 80 | + cmd_argv[0]); |
| 81 | + perror(errbuf); |
| 82 | + exit(1); |
| 83 | + } else if (pid < 0) { |
| 84 | + perror("fork"); |
| 85 | + } else { |
| 86 | + nchildren++; |
| 87 | + } |
| 88 | + // parent: do not wait (background) |
| 89 | + } |
| 90 | + segment = strtok_r(NULL, "&", &saveptr); |
| 91 | + } |
| 92 | + |
| 93 | + // behave like bash when all jobs are background: |
| 94 | + // exit immediately, but reap zombies |
| 95 | + for (int i = 0; i < nchildren; i++) { |
| 96 | + int status; |
| 97 | + pid_t w = wait(&status); |
| 98 | + if (w > 0) { |
| 99 | + printf("[mash] terminated pid %d, status %d\n", w, |
| 100 | + status); |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + return 0; |
100 | 105 | } |
0 commit comments