\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[a4paper, margin=0.75in]{geometry}

% set up hyperlink coloring
\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=blue,
    filecolor=magenta,
    urlcolor=cyan
}

\setlength{\parindent}{0pt} % no indentation

% checkbox list: https://tex.stackexchange.com/questions/247681/how-to-create-checkbox-todo-list
\usepackage{enumitem,amssymb}
\newlist{boxlist}{itemize}{2}
\setlist[boxlist]{label=$\square$}

% code support: listings and fancy verbatim
\usepackage{listings}
\lstset{basicstyle=\ttfamily\footnotesize}
\usepackage{fancyvrb}

\renewcommand{\familydefault}{\sfdefault} % default to sans serif

\usepackage{xcolor}
\newcommand{\code}[1]{\colorbox{lightgray}{\texttt{#1}}}
\newcommand{\sh}[1]{\code{\$ #1}}

%%%%%%%%%%%%%%%%
\begin{document}

\title{Advanced 3\\The Shell}
\author{EECS 201 Fall 2020}
\date{}
\maketitle

\section*{Submission Instructions}
This assignment will be submitted as a repository on the \href{https://gitlab.umich.edu}{UMich GitLab server}.
Create a Project on it with the name/path \code{eecs201-adv3} and add \code{brng} as a Reporter.
The repository should have the following directory structure, starting from the repository's root:
\begin{lstlisting}
/
|-- report.txt
|-- testing/
|    |-- runner.sh
|
|-- shell/
    |-- Makefile
    |-- (source files)
\end{lstlisting}


\section*{Preface}
This assignment can be done on both macOS and Linux.
\\\\
First, we'll need to acquire the starter files.
\begin{lstlisting}[language=bash]
$ wget https://www.eecs.umich.edu/courses/eecs201/files/assignments/adv3.tar.gz
\end{lstlisting}

Don't create your Git repo inside it: they don't have the right directory structure.
Create another directory and initialize a repository there and copy over whatever
files you need.

\section{Testing Made Easier (5)}

When working on a project in EECS, you should be writing test cases to make
sure your program is functioning properly. Checking your test cases can be
tedious, but fortunately for us, scripting can help make it easier to run your
test cases and report which ones are passing and which ones are failing. Here,
we will do just that.
\\\\
In the file archive you downloaded, you should see 3 files
under \code{testing/}: \code{test-pass.sh}, \code{test-fail.sh}, and
\code{test-timeout.sh}. These files will pass/fail according to their names.
You should not need to modify their contents.
\\\\
Write a shell script which takes all files in the current directory with
``test'' somewhere in the name, runs each of them, and reports whether the
program passed or failed the test case by printing ``SUCCESS'' or ``FAILURE''. Your
script should also stop programs from running for more than 3 seconds and
print ``TIMEOUT''.
\textbf{Note that these files are not necessarily Bash scripts: you should not assume
that they are to be run with Bash. You should be directly executing the file
instead of explicitly passing it to Bash. For example, you should be running \code{./test-pass.sh}}.
You will have to set the execute bit yourself for the provided test files.
This allows for flexibility: maybe we wanted to write a test in Python?
\textbf{The runner script is NOT responsible for setting execute bits. The runner script
can assume that the test files have their execute bits set. However, do note that
the test files you have been provided don't have them set; you'll have to do it yourself
outside of the script.}
\\\\
An example test runner file to use as a framework is below. A solution may follow the
structure very closely, but remember, there are almost always multiple ways of
solving the same problem, so feel free to deviate from the suggestions.
\\\\
One requirement is to not hard code the list of filenames into the script, this
is where shell globbing/wildcards can help (we suggest looking these up to learn
more). This requirement is so that you can run your master script in any
directory with files including ``test'' in the name and it should
Just Work\textsuperscript{TM}.
\\\\
In your submission repository, create this script file under
\code{<repo path>/testing/runner.sh}.
Make this file executable: Git is able to track these file permissions.
(If you using WSL and are doing this on your Windows filesystem, it's likely
that everything is considered executable. That's because the Windows filesystem
doesn't have these permissions/modes. Look up how to get Git to set these
bits from the Repository's standpoint.)


\begin{minipage}[t]{0.5\textwidth}
\begin{lstlisting}[numbers=left]
#!/bin/bash

# loop through all files with `test` in the name
# (learning more about for loops and shell globbing/wildcards will help for this)

    # for each file, execute it
    # (you may need to execute the file with another program that will handle the
    # timeout case)

    # perhaps save the exit status of the previous execution into a variable

    # check the exit status for timeout, print "TIMEOUT" if so

    # check the exit status for failure, print "FAILURE" if so

    # check the exit status for success, print "SUCCESS" if so

\end{lstlisting}
\end{minipage}

\subsection*{Things to keep in mind:}
\begin{itemize}
  \item[$\square$] How does the \texttt{exit} command work? (Hint: How is this similar to
    \texttt{return} in C/C++ ?)
  \item[$\square$] Are you directly executing each test file (e.g. \code{./test-example.sh})?
  \item[$\square$] How can a test case report to our test running script whether the target program passed or failed?
  \item[$\square$] How can you tell if a program is running too long?
\end{itemize}


\newpage
\section{Programming with POSIX (10)}
In this week's lecture exit survey, I asked if you think you could write a shell. No matter what your answer was,
I believe that you are capable of writing a basic shell :)
\\\\
I briefly mentioned in lecture how proccesses are created in Unix by \code{fork}-ing and \code{exec}-ing.
Let's showcase some POSIX programming and get some practice reading \code{man} pages with this exercise.
In this exercise you'll be creating ``$\mu{}$Shell'', or ``\code{mush}'', using C or C++ (whichever you prefer).
\code{mush} is a simple, minimalist shell whose only job is to execute the commands presented to it.

Its specifications are:
\begin{itemize}
  \item Presents a prompt of ``\code{<username>:<current working directory>\$~}'' on \textbf{standard output}.
        \\For example, for a \code{USER} ``doe'': ``\code{doe:/home/doe\$~}''.
        Note the space at the end. Since users type in their command after this, don't print a newline.
        Assume that the current working directory can only be represented by at most 255 characters.
  \item Assume that the entered input has at most 255 characters and that there will be at most 15 arguments.
  \item If the entered input is empty, prompts the user again.
  \item Stops, prints a newline, and exits with a 0 if an \code{EOF} character is encountered with an empty line.
        You can enter this with Ctrl-D at a terminal (try it out and see what happens with Bash or Zsh!).
  \item Stops and exits with a 0 if the command is \code{exit} with no additional argument.
        If there is an additional argument in the form of an integer, it exits with that integer value.
        You may assume that this additional argument will always be an integer.
  \item Changes the current working directory if the command is \code{cd};
        if no path is specified, the current working directory is set to \code{HOME}.
        \code{PWD} does \textbf{not have to} reflect this change.
        If the directory does not exist, prints ``\code{mush:~cd:~no~such~file~or~directory~'<directory~path>'}''
        on \textbf{standard error}.
        \\For example: ``\code{mush:~cd:~no~such~file~or~directory~'/emoh/doe'}''.
        This string should include a newline at the end so that the prompt appears on the next line.
  \item Executes the entered command and with its arguments.
        These commands are either in the \code{PATH} or specified with a path (i.e. has a forward slash in it).
        That means you do not have to implement any other shell built-ins besides \code{exit} and \code{cd}.
  \item Waits for the command run to be complete (see \code{waitpid}).
  \item If the command does not exist, prints ``\code{mush:~command~'<command~name>'~not~found}'' on \textbf{standard error}.
        \\For example: ``\code{mush:~command~'iamnotacommand'~not~found}''.
        This string should include a newline at the end so that the prompt appears on the next line.
\end{itemize}
Note that there are no built-in commands (besides \code{exit} and \code{cd}), job control, file redirection,
or signal handling specified (if you want to, you can do them for personal edification).

Some helpful functions (the string processing ones are more for C; if you're using C++ you
might have other mechanisms that fulfill the same role):
\begin{itemize}
  \item \code{getenv}
  \item \code{getcwd}
  \item \code{fgets}
    \begin{itemize}
      \item \code{fgets} has a gotcha where it'll include the newline character. Be sure to deal with it accordingly
    \end{itemize}
  \item \code{strtok} and its reentrant sibling \code{strtok\_r}
    \begin{itemize}
      \item \code{strtok(\_r)} has a gotcha where additional invocations on the
            same string have the \code{str} argument be \code{NULL}.
    \end{itemize}
  \item \code{strcmp}
    \begin{itemize}
      \item Note that 0 is returned when strings match.
    \end{itemize}
  \item \code{chdir}
    \begin{itemize}
      \item Note that \code{chdir} does not change the \code{PWD} environment variable for you
            (you don't have to worry about \code{PWD}.
    \end{itemize}
  \item \code{fork}
    \begin{itemize}
      \item Take note of how the return value differs between the parent and child process.
    \end{itemize}
  \item \code{execvp}
    \begin{itemize}
      \item The \code{man} pages for \code{execve} and \code{execvp} may offer some more info.
    \end{itemize}
  \item \code{waitpid}
\end{itemize}
You can see documentation for these functions by using \code{man}.
Sometimes, there may be multiple \code{man}pages for a given function.
\code{man}pages have multiple sections: sections 2 and 3 are the programmer's manual,
with 2 being the operating system API and 3 being about library functions.
You may often see things like \code{fork(2)}: this refers to \code{fork} under section 2.
You can specify a section to look at as an argument: \code{man 2 fork}.

Here are some helpful variables/macros for error checking:
\begin{itemize}
  \item \code{errno}
  \item \code{ENOENT}
\end{itemize}
You can read about them in the \code{errno} \code{man} page: \code{man 3 errno}.

Below is an example way to structure the program. Remember that there are many different solutions possible:
\begin{minipage}[t]{0.5\textwidth}
\begin{lstlisting}[numbers=left]
// forever loop
  // print prompt
  // receive user input
  // parse input
  // handle EOF
  // handle "exit" and "cd"
  // fork
    // child
      // execute command
      // handle errors
    // parent
      // wait for child
\end{lstlisting}
\end{minipage}

In the file archive you downloaded, you can find a Makefile and starter file for 
your preferred language in \code{shell/}.
You may only use the C standard library, the C++ standard library, and any POSIX function.
This can be implemented in surprisingly little code:
it's possible to do this in less than 50 lines of plain old C!
\\{\footnotesize{}For me the receiving and parsing input was the most difficult part of this.}\\
\\\\
In your submission repository, put the Makefile and any other source code files involved
in compilation under \code{<repo path>/shell/}.


\subsection*{Things to keep in mind:}
\begin{itemize}
  \item[$\square$] Does it present the correct prompt \textbf{on standard output}?
  \item[$\square$] Does it execute commands with arguments?
  \item[$\square$] Does it print the command not found message?
  \item[$\square$] Does it handle empty input?
  \item[$\square$] Does it print a newline and return 0 when an EOF is encountered??
  \item[$\square$] Does it handle both cases of \code{exit}?
  \item[$\square$] Does it change directories using \code{cd}?
  \item[$\square$] Does it print the directory not found message with \code{cd} \textbf{on standard error}?
  \item[$\square$] Does it print the command not found message \textbf{on standard error}?
  \item[$\square$] Why should the parent handle \code{exit} and \code{cd} and not the child?
\end{itemize}

\newpage
\section*{Report}
Create a file \code{report.txt} in your repository's root: \code{<repo path>/report.txt}.
On the first line of the file, put down an estimate of how long you took to do this assignment
in minutes as an integer (e.g. ``37'', ``84'': just numbers, no letters).
On the second line and onwards of the file, put down what you learned (if anything)
by doing this assignment. If you already knew how to do all of this, just put ``N/A''.

\end{document}
