SlideShare a Scribd company logo
// This is the shell.c
Test: ./shell -test sub
#include <ctype.h> /* Character types */
#include <stdio.h> /* Standard buffered input/output */
#include <stdlib.h> /* Standard library functions */
#include <string.h> /* String operations */
#include <sys/types.h> /* Data types */
#include <sys/wait.h> /* Declarations for waiting */
#include <unistd.h> /* Standard symbolic constants and types */
#include "smp1_tests.h" /* Built-in test system */
/* DEFINE SECTION */
#define SHELL_BUFFER_SIZE 256 /* Size of the Shell input buffer */
#define SHELL_MAX_ARGS 8 /* Maximum number of arguments parsed */
#define SHELL_HISTORY_SIZE 10
/* VARIABLE SECTION */
enum { STATE_SPACE, STATE_NON_SPACE }; /* Parser states */
char shell_history[SHELL_HISTORY_SIZE][SHELL_BUFFER_SIZE];
int shell_history_next_index = 0;
int imthechild(const char *path_to_exec, char *const args[])
{
// TO-DO P5.1
return execvp(path_to_exec, args) ? -1 : 0;
}
void imtheparent(pid_t child_pid, int run_in_background)
{
int child_return_val, child_error_code;
/* fork returned a positive pid so we are the parent */
fprintf(stderr,
" Parent says 'child process has been forked with pid=%d'n",
child_pid);
if (run_in_background) {
fprintf(stderr,
" Parent says 'run_in_background=1 ... so we're not waiting for the child'n");
return;
}
// TO-DO P5.4
wait(&child_return_val);
/* Use the WEXITSTATUS to extract the status code from the return value */
child_error_code = WEXITSTATUS(child_return_val);
fprintf(stderr,
" Parent says 'wait() returned so the child with pid=%d is finished.'n",
child_pid);
if (child_error_code != 0) {
fprintf(stderr,
" Parent says 'Child process %d failed with code %d'n",
child_pid, child_error_code);
}
}
int get_shell_command(char *buffer, int size)
{
int i = 0;
char c;
while (i < size - 1 && (c = getchar()) != EOF && c != 'n') {
buffer[i++] = c;
}
buffer[i] = '0';
return i;
}
void parse_command(char *command, char **exec_args, int *exec_bg)
{
int argc = 0;
*exec_bg = 0;
while (*command != '0') {
/* Strip whitespace. */
while (isspace(*command)) {
++command;
}
if (*command == '0') {
break;
}
/* Save the argument. */
if (argc < SHELL_MAX_ARGS) {
exec_args[argc++] = command;
}
while (*command != '0' && !isspace(*command)) {
++command;
}
if (*command != '0') {
*command++ = '0';
}
}
exec_args[argc] = NULL;
/* Check for background execution request. */
if (argc > 0 && !strcmp(exec_args[argc - 1], "&")) {
*exec_bg = 1;
exec_args[--argc] = NULL;
}
}
void run_shell_command;
int main(int argc, char **argv)
{
pid_t shell_pid, pid_from_fork;
int n_read, i, exec_argc, parser_state, run_in_background;
char buffer[SHELL_BUFFER_SIZE];
char *exec_argv[SHELL_MAX_ARGS + 1];
// TO-DO new variables for P5.2, P5.3, P5.6
if (argc > 1 && !strcmp(argv[1], "-test"))
{
return run_smp1_tests(argc - 1, argv + 1);
}
shell_pid = getpid();
int command_counter = 1;
while (1)
{
/* The Shell runs in an infinite loop, processing input. */
if (exec_argc > 0)
{
command_counter++;
}
// TO-DO P5.2
fprintf(stdout, "Shell(pid=%d)%d> ", shell_pid, command_counter);
fflush(stdout);
if (fgets(buffer, SHELL_BUFFER_SIZE, stdin) == NULL)
return EXIT_SUCCESS;
n_read = strlen(buffer);
run_in_background = n_read > 2 && buffer[n_read - 2] == '&';
buffer[n_read - run_in_background - 1] = 'n';
// TO-DO P5.3
/* Parse the arguments: the first argument is the file or command *
* we want to run. */
parser_state = STATE_SPACE;
for (exec_argc = 0, i = 0;
(buffer[i] != 'n') && (exec_argc < SHELL_MAX_ARGS); i++)
{
if (!isspace(buffer[i]))
{
if (parser_state == STATE_SPACE)
exec_argv[exec_argc++] = &buffer[i];
parser_state = STATE_NON_SPACE;
}
else
{
buffer[i] = '0';
parser_state = STATE_SPACE;
}
}
buffer[i] = '0'; /* Terminate input, overwriting the '&' if it exists */
if (!exec_argc)
continue;
exec_argv[exec_argc] = NULL;
if (!strcmp(exec_argv[0], "exit"))
{
printf("Exiting process %dn", shell_pid);
return EXIT_SUCCESS; /* End Shell program */
} else if (!strcmp(exec_argv[0], "cd") && exec_argc > 1)
{
if (chdir(exec_argv[1]))
fprintf(stderr, "cd: failed to chdir %sn", exec_argv[1]);
}
else
{
pid_from_fork = fork();
if (pid_from_fork < 0)
{
fprintf(stderr, "fork failedn");
continue;
}
if (pid_from_fork == 0)
{
// TO-DO P5.6
return imthechild(exec_argv[0], &exec_argv[0]);
/* Exit from main. */
}
else
{
imtheparent(pid_from_fork, run_in_background);
}
}
}
return EXIT_SUCCESS;
}
/* end main() */
//This is the smp1._tests.c
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "testrunner.h"
#include "smp1_tests.h"
#define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);} while(0)
/* Prepare input, reroute file descriptors, and run the program. */
void run_test(const char *input, int argc, char **argv)
{
FILE *in = fopen("smp1.in", "w");
fprintf(in, input);
fclose(in);
freopen("smp1.in", "r", stdin );
freopen("smp1.out", "w", stdout);
freopen("smp1.err", "w", stderr);
/* Run the program */
quit_if(main(argc, argv) != EXIT_SUCCESS);
fclose(stdout);
fclose(stderr);
}
/* P5.1: Test of executing commands in the path */
int test_path(int argc, char **argv)
{
char *args[] = { "./shell", NULL };
FILE *out, *err;
int pid_tmp;
/* Run the test */
run_test("lsn/bin/lsnexitn", 1, args);
/* Check output */
err = fopen("smp1.err", "r");
quit_if(fscanf(err, " Parent says 'child process has been forked with pid=%d'n"
" Parent says 'wait() returned so the child with pid=%d is finished.'n"
" Parent says 'child process has been forked with pid=%d'n"
" Parent says 'wait() returned so the child with pid=%d is finished.'n",
&pid_tmp, &pid_tmp, &pid_tmp, &pid_tmp) != 4);
quit_if(!feof(err));
fclose(err);
return EXIT_SUCCESS;
}
/* P5.2: Test of command line counter */
int test_counter(int argc, char **argv)
{
char *args[] = { "./shell", NULL };
FILE *out, *err;
int pid_tmp;
/* Run the test */
run_test("n/bin/truenexitn", 1, args);
/* Check output */
out = fopen("smp1.out", "r");
quit_if(fscanf(out, "Shell(pid=%d)1> Shell(pid=%d)1> Shell(pid=%d)2> Exiting process %dn",
&pid_tmp, &pid_tmp, &pid_tmp, &pid_tmp) != 4);
quit_if(!feof(out));
fclose(out);
return EXIT_SUCCESS;
}
/* P5.3: Test of re-executing earlier commands */
int test_rerun(int argc, char **argv)
{
char *args[] = { "./shell", NULL };
FILE *out, *err;
int pid_tmp;
/* Run the test */
run_test("/bin/echo testn!1nexitn", 1, args);
/* Check output */
out = fopen("smp1.out", "r");
quit_if(fscanf(out, "Shell(pid=%d)1> testnShell(pid=%d)2> testnShell(pid=%d)3> Exiting
process %dn", &pid_tmp, &pid_tmp, &pid_tmp, &pid_tmp) != 4);
quit_if(!feof(out));
fclose(out);
return EXIT_SUCCESS;
}
/* P5.5: Test of depth-limited sub */
int test_sub(int argc, char **argv)
{
char *args[] = { "./shell", NULL };
FILE *out, *err;
int pids[4], warned_too_deep;
/* Run the test */
run_test("newsubnnewsubnnewsubnexitnexitnexitn", 1, args);
/* Check output */
out = fopen("smp1.out", "r");
err = fopen("smp1.err", "r");
/* First, check that the subshells were invoked. */
fscanf(out, "Shell(pid=%d)1> Shell(pid=%d)1> Shell(pid=%d)1> Shell(pid=%d)2> ", &pids[0],
&pids[1], &pids[2], &pids[3]);
quit_if(!((pids[0] != pids[1]) && (pids[1] != pids[2]) && (pids[0] != pids[2]) && (pids[2] ==
pids[3])));
/* Next, check for the "Too deep!" message: */
warned_too_deep = 0;
/* Use a while loop because multiple processes write to stderr concurrently. */
while (!warned_too_deep && !feof(err)) {
char too_deep[11];
fgets(too_deep, 11, err);
if (!strncmp(too_deep, "Too deep!n", 10))
warned_too_deep = 1;
}
quit_if(!warned_too_deep);
fclose(out);
fclose(err);
return EXIT_SUCCESS;
}
/*
* Main entry point for SMP1 test harness
*/
int run_smp1_tests(int argc, char **argv)
{
/* Tests can be invoked by matching their name or their suite name
or 'all' */
testentry_t tests[] = {
{ "newsub", "smp1", test_sub },
{ "rerun", "smp1", test_rerun },
{ "counter", "smp1", test_counter },
{ "path", "smp1", test_path } };
int result = run_testrunner(argc, argv, tests, sizeof(tests) / sizeof (testentry_t));
unlink("smp1.in");
unlink("smp1.out");
unlink("smp1.err");
return result;
}
1. Modify this project so that you can use 'ls' instead of '/bin/ls'

More Related Content

PDF
Tested on ubuntu,Linux#include stdio.h #include string.h.pdf
DOCX
cmdfile.txtsleep 5ls -latrsleep 3pwdsleep 1wc .docx
DOCX
Write a C program called pross-c to implement the UNIX-Linux equivalen.docx
DOCX
httplinux.die.netman3execfork() creates a new process by.docx
PDF
Shell to be modified#include stdlib.h #include unistd.h .pdf
PDF
Help Needed!UNIX Shell and History Feature This project consists.pdf
DOCX
Program Assignment Process ManagementObjective This program a.docx
PDF
Os lab final
Tested on ubuntu,Linux#include stdio.h #include string.h.pdf
cmdfile.txtsleep 5ls -latrsleep 3pwdsleep 1wc .docx
Write a C program called pross-c to implement the UNIX-Linux equivalen.docx
httplinux.die.netman3execfork() creates a new process by.docx
Shell to be modified#include stdlib.h #include unistd.h .pdf
Help Needed!UNIX Shell and History Feature This project consists.pdf
Program Assignment Process ManagementObjective This program a.docx
Os lab final

Similar to -- This is the shell-c Test- --shell -test sub #include -ctype-h- -- C.pdf (20)

PPTX
OS presentation (1).pptx
PDF
DOCX
#include string.h#include stdlib.h#include systypes.h.docx
PPTX
Linux Systems Programming: Process CommunCh11 Processes and Signals
DOCX
OverviewIn this assignment you will write your own shell i.docx
PDF
#define LOGFILE signal_log.txt Signal handlers void sigusr1.pdf
DOCX
assign4assign4_part1bonnie.c This is a file system ben.docx
PDF
Unix Programs
PPT
Unit 6
DOC
computer notes - Inter process communication
PDF
Mychurch File Upload
PDF
Systems Programming Assignment Help - Processes
PPT
process creation OS
PPTX
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
PPT
Unit 5
PPT
11_UNIX_Processes_Including_Select.ppt
PDF
IO redirection in C shellPlease implement input output redirect.pdf
PPT
1. Von Neumann + Booting Sequence + System Calls.ppt
OS presentation (1).pptx
#include string.h#include stdlib.h#include systypes.h.docx
Linux Systems Programming: Process CommunCh11 Processes and Signals
OverviewIn this assignment you will write your own shell i.docx
#define LOGFILE signal_log.txt Signal handlers void sigusr1.pdf
assign4assign4_part1bonnie.c This is a file system ben.docx
Unix Programs
Unit 6
computer notes - Inter process communication
Mychurch File Upload
Systems Programming Assignment Help - Processes
process creation OS
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
Unit 5
11_UNIX_Processes_Including_Select.ppt
IO redirection in C shellPlease implement input output redirect.pdf
1. Von Neumann + Booting Sequence + System Calls.ppt
Ad

More from AdrianEBJKingr (20)

PDF
1- Answer the following characteristics for Chytridiomycota Fungi- A-.pdf
PDF
1- A TIPS has a coupon of 7-- paid semiannually- The current rate of i.pdf
PDF
1- A General Right to Privacy was written explicitly into the US Const.pdf
PDF
1- A business has the following information for the year- Determine th.pdf
PDF
1- -8 points- Write a MIPS code to compute the factorial of a positive.pdf
PDF
1- (Aggregates) Consider an economy that is in below full employment e.pdf
PDF
1- (3 polats) O Suppose that A add B are ladepedbet ewnts- Furthemore-.pdf
PDF
-The following information applies to the questions displayed below- O.pdf
PDF
-NYP-- New York Paper Co-- is using its financial results for August 2.pdf
PDF
-Java lang- Q3 (10)- A program creates a queue- The program takes arra.pdf
PDF
-2-Cyanide is a highly fast-acting poison- In fact- it was developed a.pdf
PDF
-23-.pdf
PDF
-begin{tabular}{l-l} cHALlenge -- ACriviry -end{tabular} 4-3-1- Confid.pdf
PDF
---BUS-- public class Bus { String busIdentifier- String driverName- d.pdf
PDF
-10 points- For each of the Regular Expression- draw FA recognizing th.pdf
PDF
--What is wrong with this C++ program- -- # include iostream using nam.pdf
PDF
-10 points- Construct minimized DFA accepting language represented by.pdf
PDF
--INSTRUCTION- --It helps to first create if-then-else structure to fi.pdf
PDF
--kindly help---Explain what happens when the PUSHA instruction execut.pdf
PDF
1)What is the most important benefit you believe students get from the.pdf
1- Answer the following characteristics for Chytridiomycota Fungi- A-.pdf
1- A TIPS has a coupon of 7-- paid semiannually- The current rate of i.pdf
1- A General Right to Privacy was written explicitly into the US Const.pdf
1- A business has the following information for the year- Determine th.pdf
1- -8 points- Write a MIPS code to compute the factorial of a positive.pdf
1- (Aggregates) Consider an economy that is in below full employment e.pdf
1- (3 polats) O Suppose that A add B are ladepedbet ewnts- Furthemore-.pdf
-The following information applies to the questions displayed below- O.pdf
-NYP-- New York Paper Co-- is using its financial results for August 2.pdf
-Java lang- Q3 (10)- A program creates a queue- The program takes arra.pdf
-2-Cyanide is a highly fast-acting poison- In fact- it was developed a.pdf
-23-.pdf
-begin{tabular}{l-l} cHALlenge -- ACriviry -end{tabular} 4-3-1- Confid.pdf
---BUS-- public class Bus { String busIdentifier- String driverName- d.pdf
-10 points- For each of the Regular Expression- draw FA recognizing th.pdf
--What is wrong with this C++ program- -- # include iostream using nam.pdf
-10 points- Construct minimized DFA accepting language represented by.pdf
--INSTRUCTION- --It helps to first create if-then-else structure to fi.pdf
--kindly help---Explain what happens when the PUSHA instruction execut.pdf
1)What is the most important benefit you believe students get from the.pdf
Ad

Recently uploaded (20)

PPTX
PPH.pptx obstetrics and gynecology in nursing
PPTX
Institutional Correction lecture only . . .
PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
PDF
O5-L3 Freight Transport Ops (International) V1.pdf
PDF
2.FourierTransform-ShortQuestionswithAnswers.pdf
PDF
102 student loan defaulters named and shamed – Is someone you know on the list?
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PPTX
Microbial diseases, their pathogenesis and prophylaxis
PDF
TR - Agricultural Crops Production NC III.pdf
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
PPTX
Renaissance Architecture: A Journey from Faith to Humanism
PDF
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PPTX
Cell Types and Its function , kingdom of life
PDF
Anesthesia in Laparoscopic Surgery in India
PDF
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
PPTX
Lesson notes of climatology university.
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
PDF
Microbial disease of the cardiovascular and lymphatic systems
PDF
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
PPTX
master seminar digital applications in india
PPH.pptx obstetrics and gynecology in nursing
Institutional Correction lecture only . . .
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
O5-L3 Freight Transport Ops (International) V1.pdf
2.FourierTransform-ShortQuestionswithAnswers.pdf
102 student loan defaulters named and shamed – Is someone you know on the list?
human mycosis Human fungal infections are called human mycosis..pptx
Microbial diseases, their pathogenesis and prophylaxis
TR - Agricultural Crops Production NC III.pdf
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Renaissance Architecture: A Journey from Faith to Humanism
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
Cell Types and Its function , kingdom of life
Anesthesia in Laparoscopic Surgery in India
Physiotherapy_for_Respiratory_and_Cardiac_Problems WEBBER.pdf
Lesson notes of climatology university.
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
Microbial disease of the cardiovascular and lymphatic systems
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
master seminar digital applications in india

-- This is the shell-c Test- --shell -test sub #include -ctype-h- -- C.pdf

  • 1. // This is the shell.c Test: ./shell -test sub #include <ctype.h> /* Character types */ #include <stdio.h> /* Standard buffered input/output */ #include <stdlib.h> /* Standard library functions */ #include <string.h> /* String operations */ #include <sys/types.h> /* Data types */ #include <sys/wait.h> /* Declarations for waiting */ #include <unistd.h> /* Standard symbolic constants and types */ #include "smp1_tests.h" /* Built-in test system */ /* DEFINE SECTION */ #define SHELL_BUFFER_SIZE 256 /* Size of the Shell input buffer */ #define SHELL_MAX_ARGS 8 /* Maximum number of arguments parsed */ #define SHELL_HISTORY_SIZE 10 /* VARIABLE SECTION */ enum { STATE_SPACE, STATE_NON_SPACE }; /* Parser states */ char shell_history[SHELL_HISTORY_SIZE][SHELL_BUFFER_SIZE]; int shell_history_next_index = 0; int imthechild(const char *path_to_exec, char *const args[]) { // TO-DO P5.1 return execvp(path_to_exec, args) ? -1 : 0; }
  • 2. void imtheparent(pid_t child_pid, int run_in_background) { int child_return_val, child_error_code; /* fork returned a positive pid so we are the parent */ fprintf(stderr, " Parent says 'child process has been forked with pid=%d'n", child_pid); if (run_in_background) { fprintf(stderr, " Parent says 'run_in_background=1 ... so we're not waiting for the child'n"); return; } // TO-DO P5.4 wait(&child_return_val); /* Use the WEXITSTATUS to extract the status code from the return value */ child_error_code = WEXITSTATUS(child_return_val); fprintf(stderr, " Parent says 'wait() returned so the child with pid=%d is finished.'n", child_pid); if (child_error_code != 0) { fprintf(stderr, " Parent says 'Child process %d failed with code %d'n", child_pid, child_error_code);
  • 3. } } int get_shell_command(char *buffer, int size) { int i = 0; char c; while (i < size - 1 && (c = getchar()) != EOF && c != 'n') { buffer[i++] = c; } buffer[i] = '0'; return i; } void parse_command(char *command, char **exec_args, int *exec_bg) { int argc = 0; *exec_bg = 0; while (*command != '0') { /* Strip whitespace. */ while (isspace(*command)) { ++command; } if (*command == '0') { break;
  • 4. } /* Save the argument. */ if (argc < SHELL_MAX_ARGS) { exec_args[argc++] = command; } while (*command != '0' && !isspace(*command)) { ++command; } if (*command != '0') { *command++ = '0'; } } exec_args[argc] = NULL; /* Check for background execution request. */ if (argc > 0 && !strcmp(exec_args[argc - 1], "&")) { *exec_bg = 1; exec_args[--argc] = NULL; } } void run_shell_command; int main(int argc, char **argv) { pid_t shell_pid, pid_from_fork;
  • 5. int n_read, i, exec_argc, parser_state, run_in_background; char buffer[SHELL_BUFFER_SIZE]; char *exec_argv[SHELL_MAX_ARGS + 1]; // TO-DO new variables for P5.2, P5.3, P5.6 if (argc > 1 && !strcmp(argv[1], "-test")) { return run_smp1_tests(argc - 1, argv + 1); } shell_pid = getpid(); int command_counter = 1; while (1) { /* The Shell runs in an infinite loop, processing input. */ if (exec_argc > 0) { command_counter++; } // TO-DO P5.2 fprintf(stdout, "Shell(pid=%d)%d> ", shell_pid, command_counter); fflush(stdout); if (fgets(buffer, SHELL_BUFFER_SIZE, stdin) == NULL) return EXIT_SUCCESS; n_read = strlen(buffer);
  • 6. run_in_background = n_read > 2 && buffer[n_read - 2] == '&'; buffer[n_read - run_in_background - 1] = 'n'; // TO-DO P5.3 /* Parse the arguments: the first argument is the file or command * * we want to run. */ parser_state = STATE_SPACE; for (exec_argc = 0, i = 0; (buffer[i] != 'n') && (exec_argc < SHELL_MAX_ARGS); i++) { if (!isspace(buffer[i])) { if (parser_state == STATE_SPACE) exec_argv[exec_argc++] = &buffer[i]; parser_state = STATE_NON_SPACE; } else { buffer[i] = '0'; parser_state = STATE_SPACE; } } buffer[i] = '0'; /* Terminate input, overwriting the '&' if it exists */ if (!exec_argc)
  • 7. continue; exec_argv[exec_argc] = NULL; if (!strcmp(exec_argv[0], "exit")) { printf("Exiting process %dn", shell_pid); return EXIT_SUCCESS; /* End Shell program */ } else if (!strcmp(exec_argv[0], "cd") && exec_argc > 1) { if (chdir(exec_argv[1])) fprintf(stderr, "cd: failed to chdir %sn", exec_argv[1]); } else { pid_from_fork = fork(); if (pid_from_fork < 0) { fprintf(stderr, "fork failedn"); continue; } if (pid_from_fork == 0) { // TO-DO P5.6 return imthechild(exec_argv[0], &exec_argv[0]);
  • 8. /* Exit from main. */ } else { imtheparent(pid_from_fork, run_in_background); } } } return EXIT_SUCCESS; } /* end main() */ //This is the smp1._tests.c #define _GNU_SOURCE #include <stdio.h> #undef _GNU_SOURCE #include <stdlib.h> #include <string.h> #include <unistd.h> #include "testrunner.h" #include "smp1_tests.h" #define quit_if(cond) do {if (cond) exit(EXIT_FAILURE);} while(0) /* Prepare input, reroute file descriptors, and run the program. */ void run_test(const char *input, int argc, char **argv)
  • 9. { FILE *in = fopen("smp1.in", "w"); fprintf(in, input); fclose(in); freopen("smp1.in", "r", stdin ); freopen("smp1.out", "w", stdout); freopen("smp1.err", "w", stderr); /* Run the program */ quit_if(main(argc, argv) != EXIT_SUCCESS); fclose(stdout); fclose(stderr); } /* P5.1: Test of executing commands in the path */ int test_path(int argc, char **argv) { char *args[] = { "./shell", NULL }; FILE *out, *err; int pid_tmp; /* Run the test */ run_test("lsn/bin/lsnexitn", 1, args); /* Check output */ err = fopen("smp1.err", "r"); quit_if(fscanf(err, " Parent says 'child process has been forked with pid=%d'n"
  • 10. " Parent says 'wait() returned so the child with pid=%d is finished.'n" " Parent says 'child process has been forked with pid=%d'n" " Parent says 'wait() returned so the child with pid=%d is finished.'n", &pid_tmp, &pid_tmp, &pid_tmp, &pid_tmp) != 4); quit_if(!feof(err)); fclose(err); return EXIT_SUCCESS; } /* P5.2: Test of command line counter */ int test_counter(int argc, char **argv) { char *args[] = { "./shell", NULL }; FILE *out, *err; int pid_tmp; /* Run the test */ run_test("n/bin/truenexitn", 1, args); /* Check output */ out = fopen("smp1.out", "r"); quit_if(fscanf(out, "Shell(pid=%d)1> Shell(pid=%d)1> Shell(pid=%d)2> Exiting process %dn", &pid_tmp, &pid_tmp, &pid_tmp, &pid_tmp) != 4); quit_if(!feof(out)); fclose(out); return EXIT_SUCCESS; }
  • 11. /* P5.3: Test of re-executing earlier commands */ int test_rerun(int argc, char **argv) { char *args[] = { "./shell", NULL }; FILE *out, *err; int pid_tmp; /* Run the test */ run_test("/bin/echo testn!1nexitn", 1, args); /* Check output */ out = fopen("smp1.out", "r"); quit_if(fscanf(out, "Shell(pid=%d)1> testnShell(pid=%d)2> testnShell(pid=%d)3> Exiting process %dn", &pid_tmp, &pid_tmp, &pid_tmp, &pid_tmp) != 4); quit_if(!feof(out)); fclose(out); return EXIT_SUCCESS; } /* P5.5: Test of depth-limited sub */ int test_sub(int argc, char **argv) { char *args[] = { "./shell", NULL }; FILE *out, *err; int pids[4], warned_too_deep; /* Run the test */ run_test("newsubnnewsubnnewsubnexitnexitnexitn", 1, args);
  • 12. /* Check output */ out = fopen("smp1.out", "r"); err = fopen("smp1.err", "r"); /* First, check that the subshells were invoked. */ fscanf(out, "Shell(pid=%d)1> Shell(pid=%d)1> Shell(pid=%d)1> Shell(pid=%d)2> ", &pids[0], &pids[1], &pids[2], &pids[3]); quit_if(!((pids[0] != pids[1]) && (pids[1] != pids[2]) && (pids[0] != pids[2]) && (pids[2] == pids[3]))); /* Next, check for the "Too deep!" message: */ warned_too_deep = 0; /* Use a while loop because multiple processes write to stderr concurrently. */ while (!warned_too_deep && !feof(err)) { char too_deep[11]; fgets(too_deep, 11, err); if (!strncmp(too_deep, "Too deep!n", 10)) warned_too_deep = 1; } quit_if(!warned_too_deep); fclose(out); fclose(err); return EXIT_SUCCESS; } /* * Main entry point for SMP1 test harness
  • 13. */ int run_smp1_tests(int argc, char **argv) { /* Tests can be invoked by matching their name or their suite name or 'all' */ testentry_t tests[] = { { "newsub", "smp1", test_sub }, { "rerun", "smp1", test_rerun }, { "counter", "smp1", test_counter }, { "path", "smp1", test_path } }; int result = run_testrunner(argc, argv, tests, sizeof(tests) / sizeof (testentry_t)); unlink("smp1.in"); unlink("smp1.out"); unlink("smp1.err"); return result; } 1. Modify this project so that you can use 'ls' instead of '/bin/ls'