summaryrefslogtreecommitdiff
path: root/Content/posts/2023-11-28-shell-lab.md
blob: ab735b842a370ec034ad8840b6f844ae3742b8d0 (plain)
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
---
date: 2023-11-28
description: Walkthrough of Shell Lab for CSCI 2400 Computer Systems
tags: C, CSCI2400, UNIX
draft: true 
---

# Shell Lab

## Introduction


...


We will be solving this lab trace by trace.

## trace01

We don't have to do anything here. The pre-existing code skeleton already passes this.

## trace 02

```
#
# trace02.txt - Process builtin quit command.
#
quit
WAIT
```

From the lab handout, we know that we need to implement this in the `builtin_cmd` 

```
// builtin_cmd: Recognizes and interprets the built-in commands: quit, fg, bg, and jobs. [25 lines]

/////////////////////////////////////////////////////////////////////////////
//
// builtin_cmd - If the user has typed a built-in command then execute
// it immediately. The command name would be in argv[0] and
// is a C string. We've cast this to a C++ string type to simplify
// string comparisons; however, the do_bgfg routine will need 
// to use the argv array as well to look for a job number.
//
int builtin_cmd(char **argv) 
{
  string cmd(argv[0]);
  return 0;     /* not a builtin command */
}
```

We can simply add an if statement and check if the passes string is equal to `quit`

```
int builtin_cmd(char **argv) 
{
  string cmd(argv[0]);
  if (cmd == "quit") {
    exit(0);
  }
  return 0;     /* not a builtin command */
}
```

Now, we also need to make sure we are checking if the passes command is a builtin command. So, looking at `eval`

```
/////////////////////////////////////////////////////////////////////////////
//
// eval - Evaluate the command line that the user has just typed in
// 
// If the user has requested a built-in command (quit, jobs, bg or fg)
// then execute it immediately. Otherwise, fork a child process and
// run the job in the context of the child. If the job is running in
// the foreground, wait for it to terminate and then return.  Note:
// each child process must have a unique process group ID so that our
// background children don't receive SIGINT (SIGTSTP) from the kernel
// when we type ctrl-c (ctrl-z) at the keyboard.
//
void eval(char *cmdline) 
{
  /* Parse command line */
  //
  // The 'argv' vector is filled in by the parseline
  // routine below. It provides the arguments needed
  // for the execve() routine, which you'll need to
  // use below to launch a process.
  //
  char *argv[MAXARGS];

  //
  // The 'bg' variable is TRUE if the job should run
  // in background mode or FALSE if it should run in FG
  //
  int bg = parseline(cmdline, argv); 
  if (argv[0] == NULL)  
    return;   /* ignore empty lines */

  return;
}
```

We simply add a check for `builtin_cmd`

```
void eval(char *cmdline) 
{
  /* Parse command line */
  //
  // The 'argv' vector is filled in by the parseline
  // routine below. It provides the arguments needed
  // for the execve() routine, which you'll need to
  // use below to launch a process.
  //
  char *argv[MAXARGS];

  //
  // The 'bg' variable is TRUE if the job should run
  // in background mode or FALSE if it should run in FG
  //
  int bg = parseline(cmdline, argv); 

  if (argv[0] == NULL)  
    return;   /* ignore empty lines */

  // First check if it is a builtin command
  if (!builtin_cmd(argv)) {
    return;
  }

  return;
}
```

## Trace 03

```
#
# trace03.txt - Run a foreground job.
#
/bin/echo tsh> quit
quit
```