Question
Shell appears to be compiling correctly, but output from my code is not matching the example script output and I don't understand why. I've attached
Shell appears to be compiling correctly, but output from my code is not matching the example script output and I don't understand why. I've attached the example output, my code's output, my code, and the code for the script.
Example Output:
My Output:
My Code:
#define _POSIX_C_SOURCE 200809L
#include
#define _GNU_SOURCE #define MAX_ARGS 512 #define MAX_ARG_LEN 2048
// Declaring function prototypes: void str_replace(char *str, const char *old_str, const char *new_str); void expand_env(char *str);
// Signal handler for SIGINT and SIGTSTP void handle_signal(int signo) { printf(" "); fflush(stdout); }
// Function to replace a substring in a string with another string void str_replace(char *str, const char *old_str, const char *new_str) { size_t old_len = strlen(old_str); size_t new_len = strlen(new_str); char *pos = strstr(str, old_str); while (pos != NULL) { // Shift the characters after the old string to make room for the new string memmove(pos + new_len, pos + old_len, strlen(pos + old_len) + 1); // Copy the new string into the position of the old string memcpy(pos, new_str, new_len); // Look for the next occurrence of the old string pos = strstr(pos + new_len, old_str); } }
// Function to expand the environment variables in a string void expand_env(char *str) { int status; pid_t bg_pid = -1; // Declare the variable for background PID // Replace any occurrence of "$$" with the process ID char pid_str[16]; sprintf(pid_str, "%d", getpid()); str_replace(str, "$$", pid_str);
// Replace any occurrence of "$?" with the exit status char exit_str[16]; sprintf(exit_str, "%d", WEXITSTATUS(status)); str_replace(str, "$?", exit_str);
// Replace any occurrence of "$!" with the process ID of the most recent background process char bg_pid_str[16]; sprintf(bg_pid_str, "%d", bg_pid); str_replace(str, "$!", bg_pid_str);
// Replace any occurrence of "~/" at the beginning of a word with the value of HOME environment variable if (str[0] == '~' && (str[1] == '/' || str[1] == '\0')) { str_replace(str, "~/", getenv("HOME")); } }
int main() { // Set signal handlers for SIGINT and SIGTSTP struct sigaction sa; sa.sa_handler = handle_signal; sa.sa_flags = SA_RESTART; sigfillset(&sa.sa_mask); if (sigaction(SIGINT, &sa, NULL) == - 1) { perror("sigaction: SIGINT"); exit(1); } if (sigaction(SIGTSTP, &sa, NULL) == - 1) { perror("sigaction: SIGTSTP"); exit(1); } while (1) { // Check for any un-waited-for background processes pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { if (WIFEXITED(status)) { printf("background pid %jd is done: exit value %d ", (intmax_t) pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("background pid %jd is done: terminated by signal %d ", (intmax_t) pid, WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("background pid %jd is stopped: signal %d ", (intmax_t) pid, WSTOPSIG(status)); kill(pid, SIGCONT); printf("background pid %jd is continued ", (intmax_t) pid); } }
// Print the prompt printf(": "); fflush(stdout);
// Read the command line input char input[MAX_ARGS * MAX_ARG_LEN]; if (fgets(input, sizeof(input), stdin) == NULL) { break; } // Check if the input string is empty or contains only whitespace characters int i; for (i = 0; i 1) { if (chdir(args[1]) != 0) { perror(args[1]); } } else { if (chdir(getenv("HOME")) != 0) { perror("cd"); } } } else { // Execute the command pid_t pid = fork(); if (pid == -1) { perror("fork"); } else if (pid == 0) { // Child process execvp(args[0], args); perror(args[0]); exit(1); } else { // Parent process if (args[arg_count - 1][0] == '&') { // Background process printf("background pid %jd ", (intmax_t) pid); } else { // Foreground process waitpid(pid, &status, 0); if (WIFSIGNALED(status)) { printf("terminated by signal %d ", WTERMSIG(status)); } } } } } return 0; }
Testscript Code:
S. - smallsh/testscript.sh . /smallsh Beginning Test Script Variable expansions Reported expansion of \$\$: "274850" (Expecting "274850", 10 points) Reported expansion of \$?: " 0 " (Expecting " 0 ", 5 points) Reported expansion of $1:"4 (Expecting " ", 10 points) Reported expansion of /"/ tmp/tmp.6TVNPdjMzB /" (Expecting "/tmp/tmp.6TVNPdjMzB", 10 points) Testing: bash - c 'exit 166' Reported expansion of $ ?: "166" (Expecting "166", 5 points) Testing: echo PID=\$\$. Status=\$?. There's no place like N/Home! (10 points) PID =274850. Status =166. There's no place like /tmp/tmp. GTVNPdjMzB/Homel Parsing Comments Testing: echo Success! \#...not! This shouldn't be printed! 5 points) Successl Testing built-in cd command Testing: pwd / tmp/tmp. vwErHvbJEC Testing: cd Testing: pwd (Expecting "/tmp/tmp.6TVNPdjMzB", 15 points) /tmp/tmp.6TVNPdjMzB Testing: mkdir pid-\$\$-d1r Testing: 1s (Expecting "pid-274850-dir", 10 points) pid-274850-dir Testing: cd pid-274850-dir Testing: pwd (Expecting "/tmp/tmp.6TVNPdjMzB/pid-274850-diI", 10 points) /tmp/tmp.6TVNPdjMzB/pid-274850-dir Testing built-in exit command Testing: exit 166 exit Smallsh exited with value: 166 (expected 166,15 points) Checking for zombies: ( 5 points if detected) none detectedt starting next set of testsi Input / Output redirection operators Testing: head -c 1000/ dev/random > 1k-random-bytes Testing: wc - c 1k-random-bytes (Expecting "1000 1k-Iandom-bytes", 15 points) 1000 ik-random-bytes Testing: wc c10k-random-bytes Testing: wc -c 10k-random-bytes (Expecting "10000 10k-random-bytes", 15 points) 10000010k-Iandom-bytes Background Commands Testing: sleep 1 \& (Expecting "Child process 281733 done. Exit status 0.",15 points for pid, 5 points for status.) Child process 281733 done. Exit status . Sending SIGSTOP to a sleeping proccess (Expecting "Child process 292073 stopped. Continuing.", 5 points) Child process 292073 stopped. Continuing. Sending SIGINT to a background process (Expecting "Child process 297288 done. Signaled 2.", 10 points) Child process 297288 done. Signaled 2 . echo \$hr printf $ (tput bold setaf 4 ) Testing built-in exit command $ (tput sgr0) printf Testing: S(tput bold lexit \$randval\$(tput sgro) exit \$randval _EOF _OUTEREOF bgpid $ ! wait \$!! stat =$ ? echo \$hr printf "Smallsh exited with value: \$stat (expected Srandval, \$(tput setaf 4 bold) 15 points ( tput sgro) n steep 1 printf "Checking for zombies: (\$ (tput setaf 4 bold)-5 points $ (tput sgro) if detected) \ " pgrep -af 5$ ! II echo none detected! pkill 9-s $! timeout 10 env - PS1=" HOME=" "homedir" setsid bash <_outereof__ export ifs exec . __eof echo printf bold setaf input output redirection operatorss sgro testing: tput c1000 dev>1k-random-bytes $ (tput sgro) 1n head -c 1000/ dev/random >1k random-bytes printf Testing: S(tput bold)we - 1 1k-random-bytes\$(tput sgr0) (Expecting "1000 1k-random-bytes", \$(tput setaf 4 bold)15 pointss(tput sgr0) wc c 1k-random-bytes printf Testing: S(tput bold)wc c10k-random-bytes $( tput sgro) head c 18000 dev/random >10k random-bytes wC c 10k-random-bytes echo \$hr printf $( tput bold setaf 4)Background Commands\$(tput sgro) \ n sleep 1& status.) \ n sleep 2 5leep 100& printf \$(tput bold)Sending SIGSTOP to a sleeping proccess\$(tput sgr0) (Expecting "Child process IIIS! stopped. Continuing.", $( tput setaf 4 bold)5 points\$(tput sgre))1n kill -SIGSTOP. IIIS! sleep 1 steep 100& printf $( tput bold)Sending SIGINT to a background process\$(tput sgr0) (Expecting "Child process III\$! done. Signaled 2 .", $(tput setaf 4 bold)10 points\$(tput sgr0)) kill -SIGINT IIIs! sleep 1 _EOF _ OUTEREOF wait $ ! stat =$ ? echo \$hr sleep 1Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started