--- 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 ```