From 51daf0de9fd6f4a1ce22ff060fd248e0f6d92b32 Mon Sep 17 00:00:00 2001
From: Andrew To <andrewto.307@gmail.com>
Date: Sat, 15 Feb 2025 23:53:54 -0500
Subject: [PATCH] HW3 Code
---
hw3/dsh | Bin 0 -> 21688 bytes
hw3/dsh.dSYM/Contents/Info.plist | 20 ++
hw3/dsh.dSYM/Contents/Resources/DWARF/dsh | Bin 0 -> 10156 bytes
hw3/dsh_cli.c | 96 ++++++++++
hw3/dshlib.c | 101 +++++++++++
hw3/dshlib.h | 50 +++++
hw3/input.txt | 1 +
hw3/makefile | 27 +++
hw3/questions.md | 30 +++
hw3/test.sh | 212 ++++++++++++++++++++++
hw3/test2.txt | 1 +
11 files changed, 538 insertions(+)
create mode 100755 hw3/dsh
create mode 100644 hw3/dsh.dSYM/Contents/Info.plist
create mode 100644 hw3/dsh.dSYM/Contents/Resources/DWARF/dsh
create mode 100644 hw3/dsh_cli.c
create mode 100644 hw3/dshlib.c
create mode 100644 hw3/dshlib.h
create mode 100644 hw3/input.txt
create mode 100644 hw3/makefile
create mode 100644 hw3/questions.md
create mode 100755 hw3/test.sh
create mode 100644 hw3/test2.txt
diff --git a/hw3/dsh b/hw3/dsh
new file mode 100755
index 0000000000000000000000000000000000000000..34e87e91f6ac8bcbcb4531b93588307288026695
GIT binary patch
literal 21688
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
I0~(hB0OXA(i2wiq
literal 0
HcmV?d00001
diff --git a/hw3/dsh.dSYM/Contents/Info.plist b/hw3/dsh.dSYM/Contents/Info.plist
new file mode 100644
index 0000000..ec2ee63
--- /dev/null
+++ b/hw3/dsh.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.xcode.dsym.dsh</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>dSYM</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ </dict>
+</plist>
diff --git a/hw3/dsh.dSYM/Contents/Resources/DWARF/dsh b/hw3/dsh.dSYM/Contents/Resources/DWARF/dsh
new file mode 100644
index 0000000000000000000000000000000000000000..c278650260f6a7682cead370b059d53bc92dd3f2
GIT binary patch
literal 10156
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
literal 0
HcmV?d00001
diff --git a/hw3/dsh_cli.c b/hw3/dsh_cli.c
new file mode 100644
index 0000000..e690947
--- /dev/null
+++ b/hw3/dsh_cli.c
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dshlib.h"
+
+/*
+ * Implement your main function by building a loop that prompts the
+ * user for input. Use the SH_PROMPT constant from dshlib.h and then
+ * use fgets to accept user input. Since we want fgets to also handle
+ * end of file so we can run this headless for testing we need to check
+ * the return code of fgets. I have provided an example below of how
+ * to do this assuming you are storing user input inside of the cmd_buff
+ * variable.
+ *
+ * while(1){
+ * printf("%s", SH_PROMPT);
+ * if (fgets(cmd_buff, ARG_MAX, stdin) == NULL){
+ * printf("\n");
+ * break;
+ * }
+ * //remove the trailing \n from cmd_buff
+ * cmd_buff[strcspn(cmd_buff,"\n")] = '\0';
+ *
+ * //IMPLEMENT THE REST OF THE REQUIREMENTS
+ * }
+ *
+ * Also, use the constants in the dshlib.h in this code.
+ * SH_CMD_MAX maximum buffer size for user input
+ * EXIT_CMD constant that terminates the dsh program
+ * SH_PROMPT the shell prompt
+ * OK the command was parsed properly
+ * WARN_NO_CMDS the user command was empty
+ * ERR_TOO_MANY_COMMANDS too many pipes used
+ *
+ * Expected output:
+ *
+ * CMD_OK_HEADER if the command parses properly. You will
+ * follow this by the command details
+ *
+ * CMD_WARN_NO_CMD if the user entered a blank command
+ * CMD_ERR_PIPE_LIMIT if the user entered too many commands using
+ * the pipe feature, e.g., cmd1 | cmd2 | ... |
+ *
+ * See the provided test cases for output expectations.
+ */
+int main()
+{
+ char *cmd_buff = malloc(SH_CMD_MAX);
+ command_list_t clist;
+
+ while(1){
+ printf("%s", SH_PROMPT);
+ if (fgets(cmd_buff, ARG_MAX, stdin) == NULL){
+ exit(OK);
+ }
+ //remove the trailing \n from cmd_buff
+ cmd_buff[strcspn(cmd_buff,"\n")] = '\0';
+
+ if (cmd_buff[0] == '\0'){
+ printf(CMD_WARN_NO_CMD);
+ continue;
+ }
+
+ if (strcmp(cmd_buff, EXIT_CMD) == 0){
+ break;
+ }
+
+ build_cmd_list(cmd_buff, &clist);
+
+ if (clist.num > CMD_MAX){
+ printf(CMD_ERR_PIPE_LIMIT, CMD_MAX);
+ printf("%s", SH_PROMPT);
+ break;
+ }
+
+ printf(CMD_OK_HEADER, clist.num);
+ int count = 1;
+ while (clist.num != 0){
+ command_t command = clist.commands[count-1];
+ printf("<%d> ", count);
+ count++;
+ printf("%s ", command.exe);
+ if (command.args[0]!='\0'){
+ printf("[%s]\n", command.args);
+ }
+ clist.num--;
+ }
+
+
+//IMPLEMENT THE REST OF THE REQUIREMENTS
+ }
+ free(cmd_buff);
+
+ exit(OK);
+}
\ No newline at end of file
diff --git a/hw3/dshlib.c b/hw3/dshlib.c
new file mode 100644
index 0000000..d207cc8
--- /dev/null
+++ b/hw3/dshlib.c
@@ -0,0 +1,101 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "dshlib.h"
+
+/*
+ * build_cmd_list
+ * cmd_line: the command line from the user
+ * clist *: pointer to clist structure to be populated
+ *
+ * This function builds the command_list_t structure passed by the caller
+ * It does this by first splitting the cmd_line into commands by spltting
+ * the string based on any pipe characters '|'. It then traverses each
+ * command. For each command (a substring of cmd_line), it then parses
+ * that command by taking the first token as the executable name, and
+ * then the remaining tokens as the arguments.
+ *
+ * NOTE your implementation should be able to handle properly removing
+ * leading and trailing spaces!
+ *
+ * errors returned:
+ *
+ * OK: No Error
+ * ERR_TOO_MANY_COMMANDS: There is a limit of CMD_MAX (see dshlib.h)
+ * commands.
+ * ERR_CMD_OR_ARGS_TOO_BIG: One of the commands provided by the user
+ * was larger than allowed, either the
+ * executable name, or the arg string.
+ *
+ * Standard Library Functions You Might Want To Consider Using
+ * memset(), strcmp(), strcpy(), strtok(), strlen(), strchr()
+ */
+int build_cmd_list(char *cmd_line, command_list_t *clist)
+{
+ char *pointer = cmd_line;
+ char* pipe = strchr(pointer, PIPE_CHAR);
+
+ clist->num = 0;
+
+ command_t new_command;
+
+ void make_command(command_t new_command, char *pointer, command_list_t *clist, size_t sub_length){
+ while (*pointer == ' '){
+ pointer++;
+ }
+ char *space = strchr(pointer, SPACE_CHAR);
+
+ if (space==NULL){
+ memset(new_command.exe, 0, sizeof(new_command.exe));
+ size_t exe_length = strlen(pointer);
+ strncpy(new_command.exe, pointer, exe_length);
+
+ memset(new_command.args, 0, sizeof(new_command.args));
+ new_command.args[0] = '\0';
+
+ clist->commands[clist->num] = new_command;
+ clist->num = clist->num+1;
+ } else{
+ while (*space==' '){
+ space++;
+ }
+ size_t exe_length = space - pointer;
+ memset(new_command.exe, 0, sizeof(new_command.exe));
+ strncpy(new_command.exe, pointer, exe_length);
+ new_command.exe[exe_length] = '\0';
+
+ size_t arg_length = pointer + sub_length - space;
+ memset(new_command.args, 0, sizeof(new_command.args));
+ strncpy(new_command.args, space, arg_length);
+ new_command.args[arg_length] = '\0';
+ clist->commands[clist->num] = new_command;
+ clist-> num = clist->num + 1;
+ }
+ }
+
+ while(pointer != NULL){
+
+ pipe = strchr(pointer, PIPE_CHAR);
+
+ if (pipe==NULL){
+ size_t command_length = strlen(pointer);
+ make_command(new_command, pointer, clist, command_length);
+ pointer = pipe;
+ } else{
+ size_t sub_length = pipe - pointer;
+
+ char sub_string[sub_length + 1];
+ strncpy(sub_string, pointer, sub_length);
+ sub_string[sub_length] = '\0';
+
+ make_command(new_command, sub_string, clist, sub_length);
+ pointer = pipe + 1;
+
+ }
+
+ }
+
+ return OK;
+}
\ No newline at end of file
diff --git a/hw3/dshlib.h b/hw3/dshlib.h
new file mode 100644
index 0000000..1353bbd
--- /dev/null
+++ b/hw3/dshlib.h
@@ -0,0 +1,50 @@
+#ifndef __DSHLIB_H__
+#define __DSHLIB_H__
+
+// Constants for command structure sizes
+#define EXE_MAX 64
+#define ARG_MAX 256
+#define CMD_MAX 8
+// Longest command that can be read from the shell
+#define SH_CMD_MAX EXE_MAX + ARG_MAX
+
+typedef struct command
+{
+ char exe[EXE_MAX];
+ char args[ARG_MAX];
+} command_t;
+
+typedef struct command_list
+{
+ int num;
+ command_t commands[CMD_MAX];
+} command_list_t;
+
+// Special character #defines
+#define SPACE_CHAR ' '
+#define PIPE_CHAR '|'
+#define PIPE_STRING "|"
+
+#define SH_PROMPT "dsh> "
+#define EXIT_CMD "exit"
+
+// Standard Return Codes
+#define OK 0
+#define WARN_NO_CMDS -1
+#define ERR_TOO_MANY_COMMANDS -2
+#define ERR_CMD_OR_ARGS_TOO_BIG -3
+
+// starter code
+#define M_NOT_IMPL "The requested operation is not implemented yet!\n"
+#define EXIT_NOT_IMPL 3
+#define NOT_IMPLEMENTED_YET 0
+
+// prototypes
+int build_cmd_list(char *cmd_line, command_list_t *clist);
+
+// output constants
+#define CMD_OK_HEADER "PARSED COMMAND LINE - TOTAL COMMANDS %d\n"
+#define CMD_WARN_NO_CMD "warning: no commands provided\n"
+#define CMD_ERR_PIPE_LIMIT "error: piping limited to %d commands\n"
+
+#endif
\ No newline at end of file
diff --git a/hw3/input.txt b/hw3/input.txt
new file mode 100644
index 0000000..e89c87f
--- /dev/null
+++ b/hw3/input.txt
@@ -0,0 +1 @@
+command1 arg1 | command2 arg2
diff --git a/hw3/makefile b/hw3/makefile
new file mode 100644
index 0000000..9d20e5b
--- /dev/null
+++ b/hw3/makefile
@@ -0,0 +1,27 @@
+# Compiler settings
+CC = gcc
+CFLAGS = -Wall -Wextra -g
+
+# Target executable name
+TARGET = dsh
+
+# Find all source and header files
+SRCS = $(wildcard *.c)
+HDRS = $(wildcard *.h)
+
+# Default target
+all: $(TARGET)
+
+# Compile source to executable
+$(TARGET): $(SRCS) $(HDRS)
+ $(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
+
+# Clean up build files
+clean:
+ rm -f $(TARGET)
+
+test:
+ ./test.sh
+
+# Phony targets
+.PHONY: all clean
\ No newline at end of file
diff --git a/hw3/questions.md b/hw3/questions.md
new file mode 100644
index 0000000..d1c7801
--- /dev/null
+++ b/hw3/questions.md
@@ -0,0 +1,30 @@
+1. In this assignment I suggested you use `fgets()` to get user input in the main while loop. Why is `fgets()` a good choice for this application?
+
+ > **Answer**: _start here_
+
+2. You needed to use `malloc()` to allocte memory for `cmd_buff` in `dsh_cli.c`. Can you explain why you needed to do that, instead of allocating a fixed-size array?
+
+ > **Answer**: _start here_
+
+
+3. In `dshlib.c`, the function `build_cmd_list(`)` must trim leading and trailing spaces from each command before storing it. Why is this necessary? If we didn't trim spaces, what kind of issues might arise when executing commands in our shell?
+
+ > **Answer**: _start here_
+
+4. For this question you need to do some research on STDIN, STDOUT, and STDERR in Linux. We've learned this week that shells are "robust brokers of input and output". Google _"linux shell stdin stdout stderr explained"_ to get started.
+
+- One topic you should have found information on is "redirection". Please provide at least 3 redirection examples that we should implement in our custom shell, and explain what challenges we might have implementing them.
+
+ > **Answer**: _start here_
+
+- You should have also learned about "pipes". Redirection and piping both involve controlling input and output in the shell, but they serve different purposes. Explain the key differences between redirection and piping.
+
+ > **Answer**: _start here_
+
+- STDERR is often used for error messages, while STDOUT is for regular output. Why is it important to keep these separate in a shell?
+
+ > **Answer**: _start here_
+
+- How should our custom shell handle errors from commands that fail? Consider cases where a command outputs both STDOUT and STDERR. Should we provide a way to merge them, and if so, how?
+
+ > **Answer**: _start here_
\ No newline at end of file
diff --git a/hw3/test.sh b/hw3/test.sh
new file mode 100755
index 0000000..6d586db
--- /dev/null
+++ b/hw3/test.sh
@@ -0,0 +1,212 @@
+#!/usr/bin/env bats
+
+@test "Simple Command" {
+ run ./dsh <<EOF
+test_command
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>test_commanddsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+@test "Simple Command with Args" {
+ run ./dsh <<EOF
+cmd -a1 -a2
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output
+ expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>cmd[-a1-a2]dsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+
+@test "No command provided" {
+ run ./dsh <<EOF
+
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>warning:nocommandsprovideddsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+@test "Two commands" {
+ run ./dsh <<EOF
+command_one | command_two
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS2<1>command_one<2>command_twodsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+@test "three commands with args" {
+ run ./dsh <<EOF
+cmd1 a1 a2 a3 | cmd2 a4 a5 a6 | cmd3 a7 a8 a9
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS3<1>cmd1[a1a2a3]<2>cmd2[a4a5a6]<3>cmd3[a7a8a9]dsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+@test "try max (8) commands" {
+ run ./dsh <<EOF
+cmd1 | cmd2 | cmd3 | cmd4 | cmd5 | cmd6 | cmd7 | cmd8
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS8<1>cmd1<2>cmd2<3>cmd3<4>cmd4<5>cmd5<6>cmd6<7>cmd7<8>cmd8dsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+@test "try too many commands" {
+ run ./dsh <<EOF
+cmd1 | cmd2 | cmd3 | cmd4 | cmd5 | cmd6 | cmd7 | cmd8 | cmd9
+exit
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>error:pipinglimitedto8commandsdsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
+
+@test "kitchen sink - multiple commands" {
+ run ./dsh <<EOF
+cmd1
+cmd2 arg arg2
+p1 | p2
+p3 p3a1 p3a2 | p4 p4a1 p4a2
+EOF
+
+ # Strip all whitespace (spaces, tabs, newlines) from the output
+ stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+ # Expected output with all whitespace removed for easier matching
+ expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>cmd1dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>cmd2[argarg2]dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS2<1>p1<2>p2dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS2<1>p3[p3a1p3a2]<2>p4[p4a1p4a2]dsh>"
+
+ # These echo commands will help with debugging and will only print
+ #if the test fails
+ echo "Captured stdout:"
+ echo "Output: $output"
+ echo "Exit Status: $status"
+
+ # Check exact match
+ [ "$stripped_output" = "$expected_output" ]
+
+ # Assertions
+ [ "$status" -eq 0 ]
+
+}
\ No newline at end of file
diff --git a/hw3/test2.txt b/hw3/test2.txt
new file mode 100644
index 0000000..e42252a
--- /dev/null
+++ b/hw3/test2.txt
@@ -0,0 +1 @@
+command
\ No newline at end of file
--
GitLab