\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

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

\title{Advanced Exercises Set 2\\More Shells}
\author{EECS 201 Winter 2020}
\date{}
\maketitle

\section*{Submission Instructions}
To receive credit for this assignment you will need to stop by someone's office hours,
demo your running code/system, and answer some questions.
You may choose the exercises that you wish to do from this set.
Each exercise is denoted by its point count.
\textbf{Extra credit is given for early turn-ins of advanced exercises. These details can be found on the website under the advanced homework grading policy.}

\section{Pretty \texttt{PS1} (5)}

% I use a complex color here to see if folks won't find simpler expressions
% (hopefully)
Open a new terminal and try the following commands in order:

\begin{minipage}[t]{0.5\textwidth}
\begin{lstlisting}[numbers=left]
echo -e "\\033[44;3;70;38;5;214m"
<hit enter again>
PS1="Hello World -- "
echo -e "\\033[44;3;70;38;5;214m"
pwd
ls
pwd
echo -e "\\033[44;3;70;38;5;214m"
ls --color=none
pwd
reset
\end{lstlisting}
\end{minipage}
\begin{minipage}[t]{0.5\textwidth}
  \begin{lstlisting}[numbers=left,firstnumber=12]
pwd
bash --norc
echo -e "\\033[44;3;70;38;5;214m"
ls
pwd
ls --color=auto
pwd
exit
PS1="\\033[44;3;70;38;5;214mHello Again -- "
ls
\end{lstlisting}
\end{minipage}

\noindent
What happened to your terminal as you ran these commands?
Play around with some other forms of \texttt{PS1} and other colors, see what
happens. Why does calling \texttt{ls} sometimes reset things?

\medskip
\noindent
Create a custom \texttt{PS1} for yourself. Look into some of the options for
\texttt{PS1}, you will need to explain why you added the options you did and
decided against options you didn't choose.

\medskip
\noindent
Extend your PS1 by writing a \texttt{bash} function the changes your prompt in a way
that is not built-in to \texttt{bash}. Some examples: Add an asterisk if your are in a
git repository with uncommitted changes. Change the color if you are currently
in a shared directory (i.e. in a Dropbox folder). Change the color if the
current directory will not be saved across a reboot (i.e. if you are you are
somewhere in the \texttt{/tmp} directory). Change the color if the last command failed.
\\\\
A shell variable that may be helpful is \texttt{PROMPT\_COMMAND}.
Remember that \texttt{man}pages offer a lot of useful info!
Interestingly, the Arch wiki has a lot of useful information on various utilities...

\subsection*{Submission checkoff:}
\begin{itemize}
  \item[$\square$] Explain what \texttt{PS1} does
  \item[$\square$] Explain what you did to customize \texttt{PS1} and
    \textbf{why} you chose the customizations that you did.
    \begin{itemize}
      \item[$\square$] Explain how your custom function works.
    \end{itemize}
  \item[$\square$] Explain what the \texttt{PS2} variable controls. Change
    \texttt{PS2} from the default and show an example.
  \item[$\square$] Type \texttt{set -x}. Then type \texttt{ls}. Explain
    all of the output.
\end{itemize}


\newpage
\section{Understanding Tab Completions (5)}

\medskip
\noindent
Open a new terminal and try typing the following (note $<$tab$>$ means press
the tab key):

\begin{lstlisting}[numbers=left]
p<tab><tab>
y
<ctrl-c>
pi<tab><tab>
pin<tab><tab>
ping<tab><tab>
ping <tab><tab>
PATH=<enter>
p<tab><tab>
\end{lstlisting}

\medskip
\noindent
In addition to finding programs, tab completions can help you to use a program
correctly by hinting at what arguments a program accepts, try this:

\begin{lstlisting}[numbers=left,firstnumber=10]
# Open a new terminal (or manually set your PATH correctly again)
ping <tab><tab>
ping -<tab><tab>
ping -I <tab><tab>
ping -Q <tab><tab>
ping -Q 0 <tab><tab>
\end{lstlisting}

\noindent
Today, most programs include tab completion support, but this is a remarkably
manual process. Check out the contents of the
\texttt{/usr/share/bash-completion/completions/} directory.

\medskip
\noindent
Now take a look at \texttt{/usr/share/bash-completion/completions/ping}.
There's a lot going on in this example, but try to see if you can understand
some of how the completions are working. What do you think the result of
\texttt{ping~-T~$<$tab$><$tab$>$} will be?

\medskip
\noindent
(Hint: \texttt{||} in bash means ``if the previous thing failed, do the next
thing''. What's the output of \texttt{echo \$OSTYPE}? Will that equality pass
or fail?)


\subsection*{Submission checkoff:}
\begin{itemize}
  \item[$\square$] Why is the list of tab completions different between lines
    1 and 9?
  \item[$\square$] What is the default tab completion behavior for a program
    if no custom completion function has been written?
\end{itemize}


\pagebreak


\section{Testing Made Easier (5)}

\medskip
\noindent
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.

\noindent
Go ahead and download some files from this URL, extract them, and take a look.
You should see 3 files. \texttt{testPass.sh}, \texttt{testFail.sh}, and
\texttt{testTimeout.sh}. These files will pass/fail according to their names.
You should not need to modify their contents.

%%% TODO: Change semester
\begin{Verbatim}[fontsize=\footnotesize]
  > wget https://www.eecs.umich.edu/courses/eecs201/files/assignments/adv2-files.tar.gz
  > # e(X)tract (Z)ipped (F)ile
  > tar xzf adv2-files.tar.gz
\end{Verbatim}

\noindent
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 ``PASSED'', ``FAILED''. Your
script should also stop programs from running for more than 3 seconds and
print ``TIMEOUT''.

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}.


\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)

    # save the return code of the previous execution into a variable

    # check the return code for timeout, print "TIMEOUT" if so

    # check the return code for failure, print "FAILURE" if so

    # check the return code for success, print "SUCCESS" if so

\end{lstlisting}
\end{minipage}

\subsection*{Submission checkoff:}
\begin{itemize}
  \item[$\square$] How does the \texttt{exit} command work? (Hint: How is this similar to
    \texttt{return} in C/C++ ?)
  \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?
  \item[$\square$] Can you demo your code?
\end{itemize}


\newpage
\section{Programming with POSIX (5)}
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 \texttt{fork}-ing and \texttt{exec}-ing.
Let's showcase some POSIX programming and get some practice reading \texttt{man} pages with this exercise.
In this exercise you'll be creating ``$\mu{}$Shell'', or ``\texttt{mush}'' using C/C++ (your choice on either).
\texttt{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 ``\texttt{<username>:<current working directory>\$ }''.
        \\For example, for a \texttt{USER} ``doe'': ``\texttt{doe:/home/doe\$ }''.
        Note the space at the end.
        Assume that the current working directory can only be represented by at most 127 characters.
  \item Assume that the entered input has at most 127 characters and that there will be at most 15 arguments.
  \item Stops and exits with a 0 if the command is \texttt{exit}
  \item Changes the current working directory if the command is \texttt{cd};
        if no path is specified, the current working directory is set to \texttt{HOME}.
        \texttt{PWD} does \textbf{not have to} reflect this change.
        If the directory does not exist, prints ``\texttt{mush: no such file or directory '<directory path>'}''.
        \\For example: ``\texttt{mush: no such file or directory '/emoh/doe'}''.
  \item Executes the entered command and with its arguments.
        These commands are either in the \texttt{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 \texttt{exit} and \texttt{cd}.
  \item If the entered input is empty, prompts the user again.
  \item If the command does not exist, prints ``\texttt{mush: command '<command name>' not found}''.
        \\For example: ``\texttt{mush: command 'iamnotacommand' not found}''.
\end{itemize}
Note that there are no built-in commands besides \texttt{exit} and \texttt{cd}, job control, file redirection, or signal handling specified (if you want to, you can do them for personal edification).

Some helpful functions:
\begin{itemize}
  \item \texttt{getenv}
  \item \texttt{getcwd}
  \item \texttt{fgets}
    \begin{itemize}
      \item \texttt{fgets} has a gotcha where it'll include the newline character. Be sure to deal with it accordingly
    \end{itemize}
  \item \texttt{strtok} and its reentrant sibling \texttt{strtok\_r}
    \begin{itemize}
      \item \texttt{strtok(\_r)} has a gotcha where additional invocations on the
            same string have the \texttt{str} argument be \texttt{NULL}.
    \end{itemize}
  \item \texttt{strcmp}
    \begin{itemize}
      \item Note that 0 is returned when strings match.
    \end{itemize}
  \item \texttt{chdir}
    \begin{itemize}
      \item Note that \texttt{chdir} does not change the \texttt{PWD} environment variable for you.
    \end{itemize}
  \item \texttt{fork}
    \begin{itemize}
      \item Take note of how the return value differs between the parent and child process.
    \end{itemize}
  \item \texttt{execvp}
    \begin{itemize}
      \item The \texttt{man} page for \texttt{execve} may offer some more info.
    \end{itemize}
  \item \texttt{waitpid}
\end{itemize}
You can see documentation for these functions by using \texttt{man}.

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

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 "exit" and "cd"
  // fork
    // child
      // execute command
      // handle errors
    // parent
      // wait for child
\end{lstlisting}
\end{minipage}

This can be implemented in surprisingly little code:
it's possible to do this in 50 lines of plain old C even with the header includes!
\\{\footnotesize{}For me the receiving and parsing input was the most difficult part of this.}

\subsection*{Submission checkoff:}
\begin{itemize}
  \item[$\square$] Demonstrate that it presents the correct prompt.
  \item[$\square$] Demonstrate that it can execute commands with arguments.
  \item[$\square$] Demonstrate that it can print the command not found message.
  \item[$\square$] Demonstrate that it can handle empty input.
  \item[$\square$] Demonstrate that it can exit using \texttt{exit}, with an exit code of 0.
  \item[$\square$] Demonstrate that it can change directories using \texttt{cd}.
  \item[$\square$] Demonstrate that it can print the directory not found message with \texttt{cd}.
  \item[$\square$] Why should the parent handle \texttt{exit} and \texttt{cd} and not the child?
  \item[$\square$] How was this taste of systems programming? Did you enjoy it?
                   Did you learn anything from this experience?
\end{itemize}

\end{document}
