发布于 

MIT 6.828 HW2 shell

Notes of MIT 6.828 HW2

In this HW, we implement several features in a small shell.

Executing simple commands

Fill the ‘’ case in runcmd.

1
2
3
4
5
6
7
8
9
case ' ':
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0)
_exit(0);

if ((execv(ecmd->argv[0], ecmd->argv) == -1))
fprintf(stderr, "execv failed\n");

break;

I/O redirection

Use the trick that open will choose the smallest free file descriptor.

1
2
3
4
5
6
7
8
9
10
11
case '>':
case '<':
rcmd = (struct redircmd*)cmd;
close(rcmd->fd);
if (open(rcmd->file, rcmd->flags, S_IRWXU) == -1) {
fprintf(stderr, "open failed\n");
break;
}

runcmd(rcmd->cmd);
break;

Implement Pipes

Use pipe and dup. Mind to close pipefds correctly and wait for child processes.

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
case '|':
pcmd = (struct pipecmd*)cmd;
int pipefds[2];
if ((pipe(pipefds)) == -1) {
fprintf(stderr, "create pipe failed\n");
}

int pid1, pid2;
if ((pid1 = fork1()) == 0) {
close(STDOUT_FILENO);
dup(pipefds[1]);
close(pipefds[0]);
close(pipefds[1]);
runcmd(pcmd->left);
}
else {
if ((pid2 = fork1()) == 0) {
close(STDIN_FILENO);
dup(pipefds[0]);
close(pipefds[0]);
close(pipefds[1]);
runcmd(pcmd->right);
}
else {
close(pipefds[0]);
close(pipefds[1]);
wait(&r);
wait(&r);
}
}
break;