QUESTION
1
1. Kelly is a 36-year-old female who has a history of type 2 diabetes, several respiratory infections as a child, and two full-term pregnancies (5 and 7 years ago). Two days ago, she began feeling a burning sensation when urinating. Her pain is progressively getting worse. Kelly assumes that she has a urinary tract infection (UTI) and makes an appointment at her primary clinic to seek relief.
A urinary tract infection could affect all of the following organs, except:
Spleen |
|
Kidneys |
|
Bladder |
|
Urethra |
1 points
QUESTION 2
1. Kelly’s physician orders a urinalysis. If she has a UTI, which of the following will most likely be abnormal?
pH |
Hemoglobin |
Specific Gravity |
Leukocytes |
1 points
QUESTION 3
1. Having female anatomy is a major risk factor for UTIs. Briefly describe, in your own words, why this is true.
1 points
QUESTION 4
1. Aside from being female, which other risk factor is mentioned in Kelly’s history?
1 points
QUESTION 5
1. Kelly’s physician determines that her infection has reached her bladder. What is this called?
Urethritis |
Cystitis |
Pyelonephritis |
Ureter itis |
1 points
QUESTION 6
1. Aside from Kelly’s complaint, which other symptoms are likely for her condition? (Select all that apply.)
Strong urge to urinate |
Frequent urination in small amounts |
Red, pink, or light brown colored urine |
Right upper quadrant pain |
Cloudy urine |
Pelvic pain |
1 points
QUESTION 7
1. Which of the following would be a sign that Kelly’s UTI has reached her kidneys?
upper back and flank pain |
Headache/migraine |
Pelvic pressure/pain |
Incontinence |
1 points
QUESTION 8
1. Which of the following choices is the most common cause of UTIs?
Viruses |
Bacteria |
Yeast |
Fungi |
1 points
QUESTION 9
1. Kelly will likely be prescribed short-course antibiotics for treatment. She may also be prescribed an analgesic. How would this help her, physiologically?
1 points
QUESTION 10
1. List and describe 3 steps Kelly can take to prevent UTIs in the future.
1 points
QUESTION 11
1. Daniel is a 52-year-old male with a history of obesity and diabetes. He had gastric bypass surgery 6 years ago and has been maintaining normal blood glucose levels and a BMI of 25 for the last 4 years. Daniel was able to stop taking medication for his diabetes, but still takes a daily multivitamin. He has had symptoms of Irritable Bowel Syndrome intermittently for 6 months, including abdominal pain and constipation. Within the last week, he has developed new symptoms that are more severe than the abdominal pain in the past. Daniel’s pain radiates into his groin and inferior to the ribs on his right side. The pain fluctuates in intensity, but is so severe that it’s debilitating at times. This morning, his pain was accompanied by nausea and vomiting, so he decided to seek emergency care.
The emergency department physician suspects that Daniel may have kidney stones. Where could the kidney stone be located?
Ureter |
Renal pelvis |
All of these choices are possibilities |
1 points
QUESTION 12
1. An x-ray confirms the presence of multiple kidney stones. If Daniel is not treated, what are possible complications? List and briefly describe 2 possible complications.
1 points
QUESTION 13
1. Why might Daniel’s doctor ask him about his diet? Briefly explain how his diet might be related to his condition.
1 points
QUESTION 14
1. Aside from the symptoms mentioned in Daniel’s history, which of the following are common symptoms of nephrolithiasis? (Select all that apply.)
Bright yellow urine |
Pink or red urine |
Frequent urination |
Fever and/or chills |
Urinating small quantities |
1 points
QUESTION 15
1. Why might Daniel’s doctor recommend that he stop taking his daily multivitamin?
Calcium found in supplements may have an effect on his future risk of developing kidney stones. |
The Vitamin C in his supplement may have contributed to his kidney stone development. |
Potassium intake is closely related to the development of kidney stones. |
The iron in his supplement is likely affecting his glomerular filtration rate. |
1 points
QUESTION 16
1. Which parts of Daniel’s history contribute to his risk for kidney stones?
1 points
QUESTION 17
1. Kidney stones have many causes. The stones are commonly composed of all the following substances, except:
Calcium |
Uric acid |
Cystine |
Bile |
1 points
QUESTION 18
1. Daniel has small stones that are lodged in the left renal pelvis. His doctor recommends passing them naturally. Which of the following choices describes the path that these stones must take to exit the body?
Distal convoluted tubule- Ureter- Bladder |
Loop of Henle- Proximal convoluted tubule- Urethra- Bladder |
Urethra- Bladder- Ureter |
Ureter- Bladder- Urethra |
1 points
QUESTION 19
1. Daniel has a large stone lodged in his right ureter that requires treatment via a procedure called extracorporeal shockwave lithotripsy. Which of the following statements describes this procedure?
Surgical removal of a kidney stone via small scopes and instruments. |
Removal of a kidney stone by passing a small tube through the urethra and bladder. |
Using soundwaves to break up stones into smaller pieces that can then pass naturally. |
Removal of the parathyroid glands which are allowing calcium buildup in the kidneys. |
1 points
QUESTION 20
1. List and briefly describe 3 steps Daniel can take to prevent future renal lithiasis.
1 points
#ifndef _parse_h_
#define _parse_h_
#include
char* cmd;
char** argv; /* NULL terminated array of strings */
} Task;
typedef struct {
Task* tasks; /* ordered list of tasks to pipe */
int ntasks; /* # of tasks in the parse */
char* infile; /* filename of ‘infile’ */
char* outfile; /* filename of ‘outfile’ */
int background; /* run process in background? */
int invalid_syntax; /* parse failed */
} Parse;
Parse* parse_cmdline (char* cmdline);
void parse_destroy (Parse** P);
void parse_debug (Parse* P);
#endif /* _parse_h_ */
#ifndef _builtin_h_
#define _builtin_h_
#include “parse.h”
int is_builtin (char* cmd);
void builtin_execute (Task T);
int builtin_which (Task T);
#endif /* _builtin_h_ */
#include
#include
#include
#include
#include “builtin.h”
#include “parse.h”
static char* builtin[] = {
“exit”, /* exits the shell */
“which”, /* displays full path to command */
NULL
};
int is_builtin (char* cmd)
{
int i;
for (i=0; builtin[i]; i++) {
if (!strcmp (cmd, builtin[i]))
return 1;
}
return 0;
}
void builtin_execute (Task T)
{
if (!strcmp (T.cmd, “exit”)) {
exit (EXIT_SUCCESS);
}
else {
printf (“pssh: builtin command: %s (not implemented!)\n”, T.cmd);
}
}
#include
#include
#include
#include
#include
#include “builtin.h”
#include “parse.h”
/*******************************************
* Set to 1 to view the command line parse *
*******************************************/
#define DEBUG_PARSE 0
void print_banner ()
{
printf (” ________ \n”);
printf (“_________________________ /_ \n”);
printf (“___ __ \\_ ___/_ ___/_ __ \\ \n”);
printf (“__ /_/ /(__ )_(__ )_ / / / \n”);
printf (“_ .___//____/ /____/ /_/ /_/ \n”);
printf (“/_/ Type ‘exit’ or ctrl+c to quit\n\n”);
}
/* returns a string for building the prompt
*
* Note:
* If you modify this function to return a string on the heap,
* be sure to free() it later when appropirate! */
static char* build_prompt ()
{
return “$ “;
}
/* return true if command is found, either:
* – a valid fully qualified path was supplied to an existing file
* – the executable file was found in the system’s PATH
* false is returned otherwise */
static int command_found (const char* cmd)
{
char* dir;
char* tmp;
char* PATH;
char* state;
char probe[PATH_MAX];
int ret = 0;
if (access (cmd, X_OK) == 0)
return 1;
PATH = strdup (getenv(“PATH”));
for (tmp=PATH; ; tmp=NULL) {
dir = strtok_r (tmp, “:”, &state);
if (!dir)
break;
strncpy (probe, dir, PATH_MAX-1);
strncat (probe, “/”, PATH_MAX-1);
strncat (probe, cmd, PATH_MAX-1);
if (access (probe, X_OK) == 0) {
ret = 1;
break;
}
}
free (PATH);
return ret;
}
/* Called upon receiving a successful parse.
* This function is responsible for cycling through the
* tasks, and forking, executing, etc as necessary to get
* the job done! */
void execute_tasks (Parse* P)
{
unsigned int t;
for (t = 0; t < P->ntasks; t++) {
if (is_builtin (P->tasks[t].cmd)) {
builtin_execute (P->tasks[t]);
}
else if (command_found (P->tasks[t].cmd)) {
printf (“pssh: found but can’t exec: %s\n”, P->tasks[t].cmd);
}
else {
printf (“pssh: command not found: %s\n”, P->tasks[t].cmd);
break;
}
}
}
int main (int argc, char** argv)
{
char* cmdline;
Parse* P;
print_banner ();
while (1) {
cmdline = readline (build_prompt());
if (!cmdline) /* EOF (ex: ctrl-d) */
exit (EXIT_SUCCESS);
P = parse_cmdline (cmdline);
if (!P)
goto next;
if (P->invalid_syntax) {
printf (“pssh: invalid syntax\n”);
goto next;
}
#if DEBUG_PARSE
parse_debug (P);
#endif
execute_tasks (P);
next:
parse_destroy (&P);
free(cmdline);
}
}
TARGET = pssh
CC = gcc
LIBS = -lreadline
CFLAGS = -g -Wall
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $@
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $@
clean:
-rm -f *.o
-rm -f $(TARGET)
/* Author: James A. Shackleford
*
* A simple shell command parser. If you are familiar with
* using bash, zsh, tcsh, etc. then you already understand
* what this does.
*
* Parses the following syntax:
*
* ~$ command_1 [< infile] [| command_n]* [> outfile] [&]
*
* and produces a correspondingly populated Parse structure on the heap
*
* Note:
* – Items in brackets [ ] are optional
* – Items in starred brackets [ ]* are optional but can be repeated
* – Non-bracketed items are required
*
* Examples of valid syntax:
*
* ~$ echo “foo!!!!!!!” > foo.txt
* ~$ wc -l < somefile.txt > numlines.txt
* ~$ ls -lh | grep 8.*K | wc -l
* ~$ gvim &
**********************************************************************/
#include
#include
#include
#include
#include “parse.h”
typedef struct {
char* cmd;
char** argv;
char* input_fn;
char* output_fn;
} Unit;
static char ops[] = {‘>’, ‘<', '|', '\0'};
static void trim (char* s)
{
size_t start, end;
if (!s)
return;
end = strlen (s);
for (start=0; isspace (s[start]); ++start);
if (s[start]) {
while (end > 0 && isspace(s[end-1]))
–end;
memmove(s, &s[start], end-start);
}
s[end-start] = ‘\0’;
}
static int is_background (char* cmdline)
{
size_t last;
int ret = 0;
trim (cmdline);
last = strlen (cmdline) – 1;
if (‘&’ == cmdline[last]) {
cmdline[last] = ‘\0’;
ret = 1;
}
return ret;
}
static int is_empty (char* cmdline)
{
trim (cmdline);
if (!cmdline || !strlen(cmdline))
return 1;
return 0;
}
static int is_op (char c)
{
int i;
for (i=0; ops[i]; i++)
if (c == ops[i])
return 1;
return 0;
}
static int has_trailing (char needle, char* haystack)
{
trim (haystack);
if (haystack[0] == needle ||
haystack[strlen(haystack)-1] == needle) {
return 1;
}
return 0;
}
static unsigned int count_char (char needle, char* haystack)
{
unsigned int c = 0;
while (*haystack)
if (*haystack++ == needle)
c++;
return c;
}
static unsigned int count_args (char* unit)
{
unsigned int n = 0;
for (; *unit; unit++) {
if (isspace((unsigned char)(*unit))) {
while (isspace((unsigned char)(*++unit)));
if (*unit == ‘\”‘) {
do {
unit++;
} while (*unit != ‘\”‘);
n++;
} else if (*unit == ‘\”) {
do {
unit++;
} while (*unit != ‘\”);
n++;
} else if (!isspace((unsigned char)(*unit))) {
n++;
}
}
}
return n;
}
static int valid_syntax (Parse* P, Unit* U, int i)
{
if (!U)
return 0;
if (U->input_fn && ((i != 0) || is_empty(U->input_fn)))
return 0;
if (U->output_fn && ((i != P->ntasks-1) || is_empty(U->output_fn)))
return 0;
if (!U->cmd || !*U->cmd)
return 0;
return 1;
}
static char* parse_unary (char op, char* unit)
{
char *start, *end, *arg;
for (start=NULL; *unit; unit++)
if (*unit == op) {
start = ++unit;
break;
}
if (!start)
return NULL;
for (end=start; *end; end++)
if (is_op(*end))
break;
arg = strndup (start, end – start);
arg[end – start] = ‘\0’;
trim (arg);
start–;
memset (start, ‘ ‘, end – start);
return arg;
}
static char* argtok (char* str, char** state)
{
char* ret;
char seek_ch;
if (!str)
str = *state;
if (!*str)
return NULL;
trim(str);
seek_ch = *str == ‘\”‘ ? ‘\”‘ :
*str == ‘\” ? ‘\” :
‘ ‘;
ret = seek_ch == ‘ ‘ ? str : ++str;
str = strchr (str, seek_ch);
if (str)
*str = ‘\0’;
*state = str ? ++str : (ret + strlen(ret));
return ret;
}
static void parse_command (Unit* U, char* unit)
{
unsigned int argc, n;
char *str, *token, *state;
trim (unit);
argc = count_args (unit)+1; /* +1 for command */
U->argv = malloc ((argc+1) * sizeof(*U->argv));
U->argv[argc] = NULL;
for (n=0, str=unit; ; n++, str=NULL) {
token = argtok (str, &state);
if (!token)
break;
U->argv[n] = strdup (token);
}
U->cmd = U->argv[0];
}
static Unit* parse_unit (char* unit)
{
Unit* U;
int infiles = count_char (‘<', unit);
int outfiles = count_char ('>‘, unit);
if (infiles > 1 || outfiles > 1)
return NULL;
if (count_char (‘\”, unit) % 2)
return NULL;
if (count_char (‘\”‘, unit) % 2)
return NULL;
U = malloc (sizeof(*U));
U->cmd = NULL;
U->argv = NULL;
if (infiles)
U->input_fn = parse_unary (‘<', unit);
else
U->input_fn = NULL;
if (outfiles)
U->output_fn = parse_unary (‘>’, unit);
else
U->output_fn = NULL;
parse_command (U, unit);
return U;
}
static void unit_destroy (Unit** U)
{
int i;
if (!*U)
return;
if ((*U)->input_fn)
free ((*U)->input_fn);
if ((*U)->output_fn)
free ((*U)->output_fn);
if ((*U)->argv) {
for (i=0; (*U)->argv[i]; i++)
free ((*U)->argv[i]);
free ((*U)->argv);
}
free (*U);
*U = NULL;
}
static void parse_add_unit (Parse* P, Unit* U, int i)
{
if (!valid_syntax (P, U, i)) {
P->invalid_syntax = 1;
goto out;
}
P->tasks[i].cmd = U->cmd;
if (U->argv) {
P->tasks[i].argv = U->argv;
U->argv = NULL;
}
if (U->input_fn && (i == 0)) {
P->infile = U->input_fn;
U->input_fn = NULL;
}
if (U->output_fn && (i == P->ntasks-1)) {
P->outfile = U->output_fn;
U->output_fn = NULL;
}
out:
unit_destroy (&U);
}
static Parse* parse_new ()
{
Parse* P = malloc (sizeof(*P));
P->tasks = NULL;
P->ntasks = 0;
P->infile = NULL;
P->outfile = NULL;
P->background = 0;
P->invalid_syntax = 0;
return P;
}
static void parse_init (Parse* P, char* cmdline)
{
P->background = is_background (cmdline);
if (count_char (‘&’, cmdline)) {
P->invalid_syntax = 1;
return;
}
if (has_trailing (‘|’, cmdline)) {
P->invalid_syntax = 1;
return;
}
P->ntasks = count_char (‘|’, cmdline) + 1;
P->tasks = malloc (P->ntasks * sizeof (*P->tasks));
memset (P->tasks, 0, P->ntasks * sizeof (*P->tasks));
}
void parse_destroy (Parse** P)
{
int i, j;
if (!*P)
return;
if ((*P)->infile)
free ((*P)->infile);
if ((*P)->outfile)
free ((*P)->outfile);
if ((*P)->tasks) {
for (i=0; i<(*P)->ntasks; i++) {
if ((*P)->tasks[i].argv) {
for (j=0; (*P)->tasks[i].argv[j]; j++)
free ((*P)->tasks[i].argv[j]);
free ((*P)->tasks[i].argv);
}
}
free ((*P)->tasks);
}
free (*P);
*P = NULL;
}
Parse* parse_cmdline (char* cmdline)
{
char *str, *token, *state;
int i;
Unit* U;
Parse* P;
if (is_empty (cmdline))
return NULL;
P = parse_new ();
parse_init (P, cmdline);
for (i=0, str=cmdline; !P->invalid_syntax; i++, str=NULL) {
token = strtok_r (str, “|”, &state);
if (!token)
break;
U = parse_unit (token);
parse_add_unit (P, U, i);
}
return P;
}
void parse_debug (Parse* P)
{
int i, j;
fprintf (stderr, “==[ DEBUG: PARSE ]==================================\n”);
fprintf (stderr, “Run in Background? %s\n”, P->background ? “Yes” : “No”);
if (P->infile)
fprintf (stderr, “infile: %s\n”, P->infile);
if (P->outfile)
fprintf (stderr, “outfile: %s\n”, P->outfile);
fprintf (stderr, “ntasks: %i\n”, P->ntasks);
for (i=0; i
fprintf (stderr, “Task %i\n”, i);
fprintf (stderr, ” – cmd: [%s]\n”, P->tasks[i].cmd);
if (P->tasks[i].argv)
for (j=0; P->tasks[i].argv[j]; j++)
fprintf (stderr, ” + arg[%i]: [%s]\n”, j, P->tasks[i].argv[j]);
}
fprintf (stderr, “==================================[ DEBUG: PARSE ]==\n”);
}
ECEC-
3
5
3 Systems Programming
Project
1
– Writing a Basic Shell
START THIS NOW — YOU WILL NEED THE FULL TIME
The Big Idea
In this assignment you will be developing a user shell (i.e. command line interface) similar to bash. Upon
completion, your shell must be able to perform the following operations:
• Display the current working directory within the prompt (before the dollar sign):
/home/jshack/pssh$
• Run a single command with optional input and output redirection. Command line arguments must be
supported. For example:
/home/jshack/pssh$ ./my_prog arg1 arg
2
arg3
/home/jshack/pssh$ ls -l > directory_contents.txt
/home/jshack/pssh$ grep -n “test” < input.txt > output.txt
• Run multiple pipelined commands with optional input and output redirection. Naturally, command
line arguments to programs must still be supported. For example:
/home/jshack/pssh$ ./my_prog arg1 arg2 arg3 | wc -l > out.txt
/home/jshack/pssh$ ls -lh | awk ‘{print $9 ” is ” $5}’
/home/jshack/pssh$ ps aux | grep bash | grep -v grep | awk ‘{print $2}’
• Implement the builtin command ‘exit’, which will terminate the shell:
/home/jshack/pssh$ exit
• Implement the builtin command ‘which’. This command accepts 1 parameter (a program name),
searches the system PATH for the program, and prints its full path to stdout if found (or simply
nothing if it is not found). If a fully qualified path or relative path is supplied to an executable
program, then that path should simply be printed to stdout. If the supplied program name is another
builtin command, your shell should indicate that in a message printed to stdout. The behavior should
be identical to bash’s builtin which command. For example:
/home/jshack/pssh$ which ls
/bin/ls
/home/jshack/pssh$ which lakjasdlkfjasdlkfj
/home/jshack/pssh$ which exit
exit: shell built-in command
/home/jshack/pssh$ which which
which: shell built-in command
/home/jshack/pssh$ which man
/usr/bin/man
1
The Parser
Writing a command line shell is obviously going to require that you be able to parse the text the user types
at the prompt into a more meaningful structure that is easier for you (the developer) to handle. Since text
processing is not the major focus of this course (hint: it’s actually systems programming), I have provided
you with a parser as well as a basic skeleton for your shell program. I call this shell program skeleton the
Pretty Simple SHell (pssh). The main input loop looks like this:
…
#define DEBUG_PARSE 0
…
while (1) {
cmdline = readline (build_prompt());
if (!cmdline) /* EOF (ex: ctrl-d) */
exit (EXIT_SUCCESS);
P = parse_cmdline (cmdline);
if (!P)
goto next;
if (P->invalid_syntax) {
printf (“pssh: invalid syntax\n”);
goto next;
}
#if DEBUG_PARSE
parse_debug (P);
#endif
execute_tasks (P);
next:
parse_destroy (&P);
free(cmdline);
}
…
As you can see, our command line shell reads input from the user one line at a time via readline(), which
returns a char* pointing to memory allocated on the heap containing a NULL terminated string of what the
user typed in before hitting Enter. This is passed to the provided parse cmdline() API function I have
provided to you. The implementation can be found in parse.c and the API function declarations can be
found in parse.h. The parse cmdline() API returns a Parse*, which points to heap memory. The Parse
structure is defined in parse.h as follows:
typedef struct {
Task* tasks; /* ordered list of tasks to pipe */
int ntasks; /* # of tasks in the parse */
char* infile; /* filename of ‘infile’ */
char* outfile; /* filename of ‘outfile’ */
int background; /* run process in background? */
int invalid_syntax; /* parse failed */
} Parse;
2
as is the Task structure:
typedef struct {
char* cmd;
char** argv; /* NULL terminated array of strings */
} Task;
As you can see, the Parse data structure contains all of the parsed information from a command line with
following anatomy:
command_1 [< infile] [| command_n]* [> outfile] [&]
where:
• Items in brackets [ ] are optional
• Items in starred brackets [ ]* are optional but can be repeated
• Non-bracketed items are required
In other words, I have done all the “hard work” for you. Your job will simply to be to take a Parse structure
and implement all of the process creation and management logic generally provided by a shell. In order
to make it obvious how to work with a Parse structure, I have provided the parse debug() API function,
which simply prints the contents of a Parse to the screen. Your job, for this project, largely involves
writing logic for the provided execute tasks() function in pssh.c. I highly recommend you start by
simply getting the execution of single commands working.
Executing Single Commands
Naturally, this is a simple fork() and exec() problem. Get this working first. Also, remember that exec()
is not a real function, but is rather a term used to refer to the family of exec functions: execl(), execlp(),
execle(), execv(), execvp(), execvpe(). Read the manual page for exec to figure out which one you
want to use!
~$ man 3 exec
Once your pssh is capable of executing simple commands with arguments, such as:
$ ls -l
you need to add support for input and output redirection using the < and > command line operators… just
like in bash! This is actually easier than in seems. Hint: you will need to modify the file descriptors tables.
Once you have this working, you will be able to do great things like:
$ ls -l > directory.txt
$ grep “some phrase” < somefile.txt
(Hint: man 2 open and man 2 dup2)
Great job! Next step is connecting multiple commands together with pipes!
3
Executing Multiple Pipelined Commands
This is actually very similar to what we did in lecture using the dup2() system call. In fact, it is nearly
exactly the same – just far more practical. Unlike our example in lecture, you must be able to pipeline more
than just two processes – you must pipeline all of the commands in the tasks array found in the Parse
structure. You’re going to need a for-loop – spend some time planning it out well before writing it!
Adding the Built-in Commands
Since it simply ends the pssh process, the built-in command exit is going to be the easiest. Implement that
first. Now, the which command is going to be a little bit more complicated. I recommend looking at the
command found() function in pssh.c and use that as a working base. Also, be sure to read the manual page
for the access() system call:
~$ man access
Keep in mind that, with the exception of exit, any built-in command should support input and output
redirection. For example, the following should work:
$ which man > man_location.txt
$ cat man_location.txt
/usr/bin/man
This may sound more challenging than it actually is. Did you figure it out?
Building the Code
The provided code uses a Makefile to help build the code. All you need to do to build the program is run
the make command within the source directory:
~/src/pssh$ ls
builtin.c Makefile parse.h
builtin.h parse.c pssh.c
~/src/pssh$ make
gcc -g -Wall -c builtin.c -o builtin.o
gcc -g -Wall -c parse.c -o parse.o
gcc -g -Wall -c pssh.c -o pssh.o
gcc builtin.o parse.o pssh.o -Wall -lreadline -o pssh
~/src/pssh$ ls
builtin.c Makefile parse.o pssh.o
builtin.h parse.c pssh
builtin.o parse.h pssh.c
and just like that, all of the necessary steps to produce the pssh executable will be automatically ran. If you
want to delete all of the intermediate object files and the pssh executable, simply run make clean within
the source directory:
~/src/pssh$ ls
builtin.c Makefile parse.o pssh.o
builtin.h parse.c pssh
builtin.o parse.h pssh.c
~/src/pssh$ make clean
rm -f *.o
rm -f pssh
~/src/pssh$ ls
builtin.c Makefile parse.h
builtin.h parse.c pssh.c
4
Having Trouble Getting Started?
If you are having trouble getting started, remember that the main ideas here are manipulating process file
descriptor tables and pipelining processes – that is, have the parent process connect the input and output
of a series of sibling child processes together using pipes. You will implement this logic in execute tasks()
in the pssh.c source file. (Although, you will probably need to make small changes elsewhere in pssh.c
and builtin.c to accommodate your specific approach, and that’s okay!) In fact, writing a few small
helper functions that each do a small, specific job well (and reliably) will probably make your code in
execute tasks() much easier to write and manage.
The most important thing to get right before starting is understanding the Parse data structure returned by
parse cmdline(). Start by enabling the parser’s debugging output by setting DEBUG PARSE to 1, compile,
and run ./pssh. Now, try a few of the example commands given on Page 1 of this document to see the
anatomy of the parse. Refer to parse.h while doing this.
Next, read the function debug parse() in parse.c to see how the debug output was generated – this will
show you how to work with the Parse structure that is passed in to execute tasks(), which is where most
of your code for this project will go.
Note: You do not need to modify anything in parse.c – that part is done. Reading it may be fun and
educational, though.
Submitting Your Project
Once you have implemented all of the required features described in this document, submit your code by
doing the following:
• Run make clean in your source directory. We must be able to build your shell from source (and we
don’t want your precompiled executables or intermediate object files). If your code does not at
the very least compile, you will receive a zero.
• Create a zip file containing your code and a README.txt file.
• Name your zip file pssh.zip
• Upload your zip file using the Blackboard Learn submission link found on the course website.
Failure to follow these simple steps will result in your project not being graded.
Now, have fun and don’t forget to be awesome!
Due in 3 Weeks: Saturday, Feb 13th before midnight.
5
We provide professional writing services to help you score straight A’s by submitting custom written assignments that mirror your guidelines.
Get result-oriented writing and never worry about grades anymore. We follow the highest quality standards to make sure that you get perfect assignments.
Our writers have experience in dealing with papers of every educational level. You can surely rely on the expertise of our qualified professionals.
Your deadline is our threshold for success and we take it very seriously. We make sure you receive your papers before your predefined time.
Someone from our customer support team is always here to respond to your questions. So, hit us up if you have got any ambiguity or concern.
Sit back and relax while we help you out with writing your papers. We have an ultimate policy for keeping your personal and order-related details a secret.
We assure you that your document will be thoroughly checked for plagiarism and grammatical errors as we use highly authentic and licit sources.
Still reluctant about placing an order? Our 100% Moneyback Guarantee backs you up on rare occasions where you aren’t satisfied with the writing.
You don’t have to wait for an update for hours; you can track the progress of your order any time you want. We share the status after each step.
Although you can leverage our expertise for any writing task, we have a knack for creating flawless papers for the following document types.
Although you can leverage our expertise for any writing task, we have a knack for creating flawless papers for the following document types.
From brainstorming your paper's outline to perfecting its grammar, we perform every step carefully to make your paper worthy of A grade.
Hire your preferred writer anytime. Simply specify if you want your preferred expert to write your paper and we’ll make that happen.
Get an elaborate and authentic grammar check report with your work to have the grammar goodness sealed in your document.
You can purchase this feature if you want our writers to sum up your paper in the form of a concise and well-articulated summary.
You don’t have to worry about plagiarism anymore. Get a plagiarism report to certify the uniqueness of your work.
Join us for the best experience while seeking writing assistance in your college life. A good grade is all you need to boost up your academic excellence and we are all about it.
We create perfect papers according to the guidelines.
We seamlessly edit out errors from your papers.
We thoroughly read your final draft to identify errors.
Work with ultimate peace of mind because we ensure that your academic work is our responsibility and your grades are a top concern for us!
Dedication. Quality. Commitment. Punctuality
Here is what we have achieved so far. These numbers are evidence that we go the extra mile to make your college journey successful.
We have the most intuitive and minimalistic process so that you can easily place an order. Just follow a few steps to unlock success.
We understand your guidelines first before delivering any writing service. You can discuss your writing needs and we will have them evaluated by our dedicated team.
We write your papers in a standardized way. We complete your work in such a way that it turns out to be a perfect description of your guidelines.
We promise you excellent grades and academic excellence that you always longed for. Our writers stay in touch with you via email.