Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Unix shell This is what I have so far: #include <sys/wait.h> #include <sys/types

ID: 3744873 • Letter: U

Question

Unix shell

This is what I have so far:

#include <sys/wait.h>

#include <sys/types.h>

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

/*

Function Declarations for builtin shell commands:

*/

int lsh_cd(char **args);

int lsh_help(char **args);

int lsh_exit(char **args);

/*

List of builtin commands, followed by their corresponding functions.

*/

char *builtin_str[] = {

"cd",

"help",

"exit"

};

int (*builtin_func[]) (char **) = {

&lsh_cd,

&lsh_help,

&lsh_exit

};

int lsh_num_builtins() {

return sizeof(builtin_str) / sizeof(char *);

}

/*

Builtin function implementations.

*/

/**

@brief Bultin command: change directory.

@param args List of args. args[0] is "cd". args[1] is the directory.

@return Always returns 1, to continue executing.

*/

int lsh_cd(char **args)

{

if (args[1] == NULL) {

fprintf(stderr, "lsh: expected argument to "cd" ");

} else {

if (chdir(args[1]) != 0) {

perror("lsh");

}

}

return 1;

}

/**

@brief Builtin command: print help.

@param args List of args. Not examined.

@return Always returns 1, to continue executing.

*/

int lsh_help(char **args)

{

int i;

printf("Stephen Brennan's LSH ");

printf("Type program names and arguments, and hit enter. ");

printf("The following are built in: ");

for (i = 0; i < lsh_num_builtins(); i++) {

printf(" %s ", builtin_str[i]);

}

printf("Use the man command for information on other programs. ");

return 1;

}

/**

@brief Builtin command: exit.

@param args List of args. Not examined.

@return Always returns 0, to terminate execution.

*/

int lsh_exit(char **args)

{

return 0;

}

/**

@brief Launch a program and wait for it to terminate.

@param args Null terminated list of arguments (including program).

@return Always returns 1, to continue execution.

*/

int lsh_launch(char **args)

{

pid_t pid;

int status;

pid = fork();

if (pid == 0) {

// Child process

if (execvp(args[0], args) == -1) {

perror("lsh");

}

exit(EXIT_FAILURE);

} else if (pid < 0) {

// Error forking

perror("lsh");

} else {

// Parent process

do {

waitpid(pid, &status, WUNTRACED);

} while (!WIFEXITED(status) && !WIFSIGNALED(status));

}

return 1;

}

/**

@brief Execute shell built-in or launch program.

@param args Null terminated list of arguments.

@return 1 if the shell should continue running, 0 if it should terminate

*/

int lsh_execute(char **args)

{

int i;

if (args[0] == NULL) {

// An empty command was entered.

return 1;

}

for (i = 0; i < lsh_num_builtins(); i++) {

if (strcmp(args[0], builtin_str[i]) == 0) {

return (*builtin_func[i])(args);

}

}

return lsh_launch(args);

}

#define LSH_RL_BUFSIZE 1024

/**

@brief Read a line of input from stdin.

@return The line from stdin.

*/

char *lsh_read_line(void)

{

int bufsize = LSH_RL_BUFSIZE;

int position = 0;

char *buffer = malloc(sizeof(char) * bufsize);

int c;

if (!buffer) {

fprintf(stderr, "lsh: allocation error ");

exit(EXIT_FAILURE);

}

while (1) {

// Read a character

c = getchar();

if (c == EOF) {

exit(EXIT_SUCCESS);

} else if (c == ' ') {

buffer[position] = '';

return buffer;

} else {

buffer[position] = c;

}

position++;

// If we have exceeded the buffer, reallocate.

if (position >= bufsize) {

bufsize += LSH_RL_BUFSIZE;

buffer = realloc(buffer, bufsize);

if (!buffer) {

fprintf(stderr, "lsh: allocation error ");

exit(EXIT_FAILURE);

}

}

}

}

#define LSH_TOK_BUFSIZE 64

#define LSH_TOK_DELIM " "

/**

@brief Split a line into tokens (very naively).

@param line The line.

@return Null-terminated array of tokens.

*/

char **lsh_split_line(char *line)

{

int bufsize = LSH_TOK_BUFSIZE, position = 0;

char **tokens = malloc(bufsize * sizeof(char*));

char *token, **tokens_backup;

if (!tokens) {

fprintf(stderr, "lsh: allocation error ");

exit(EXIT_FAILURE);

}

token = strtok(line, LSH_TOK_DELIM);

while (token != NULL) {

tokens[position] = token;

position++;

if (position >= bufsize) {

bufsize += LSH_TOK_BUFSIZE;

tokens_backup = tokens;

tokens = realloc(tokens, bufsize * sizeof(char*));

if (!tokens) {

free(tokens_backup);

fprintf(stderr, "lsh: allocation error ");

exit(EXIT_FAILURE);

}

}

token = strtok(NULL, LSH_TOK_DELIM);

}

tokens[position] = NULL;

return tokens;

}

/**

@brief Loop getting input and executing it.

*/

void lsh_loop(void)

{

char *line;

char **args;

int status;

do {

printf("> ");

line = lsh_read_line();

args = lsh_split_line(line);

status = lsh_execute(args);

free(line);

free(args);

} while (status);

}

/**

@brief Main entry point.

@param argc Argument count.

@param argv Argument vector.

@return status code

*/

int main(int argc, char **argv)

{

// Load config files, if any.

// Run command loop.

lsh_loop();

// Perform any shutdown/cleanup.

return EXIT_SUCCESS;

}

I need path, parallel and redirect part. Thank you in advance!

rogram Specifications Basic Shell: dash Your basic shell, called dash (short for DAllas SHell), is basically an interactive loop: it repeatedly prints a prompt dash> (note the space after the greater-than sign), parses the input, executes the command specified on that line of input, and waits for the command to finish. This is repeated until the user types exit. The name of your final executable should be dash. The shell can be invoked with either no arguments or a single argument; anything else is an error. Here is the no-argument way: prompt> ./dash dash> At this point, dash is running, and ready to accept commands. Type away! The mode above is called interactive mode, and allows the user to type commands directly. The shell also supports a batch mode, which instead reads input from a batch file and executes commands from therein. Here is how you run the shell with a batch file named batch.txt: prompt> ./dash batch.txt One difference between batch and interactive modes: in interactive mode, a prompt is printed (dash>). In batch mode, no prompt should be printed. You should structure your shell such that it creates a process for each new command (the exception are built-in commands, discussed below). Your basic shell should be able to parse a command and run the program corresponding to the command. For example, if the user types 1s -la /tmp, your shell should run the program /bin/1s with the given arguments -la and /tmp (how does the shell know to run /bin/1s? It's something called the shell path; more on this below).

Explanation / Answer

ANSWER:

Basic lifetime of a shell :

Basic loop of a shell :

Reading a line :

Reading a line from stdin sounds so simple, but in C it can be a hassle. The sad thing is that you don’t know ahead of time how much text a user will enter into their shell. You can’t simply allocate a block and hope they don’t exceed it. Instead, you need to start with a block, and if they do exceed it, reallocate with more space. This is a common strategy in C, and we’ll use it to implement lsh_read_line().

Next, we see whether the next character will go outside of our current buffer size. If so, we reallocate our buffer (checking for allocation errors) before continuing. And that’s really it.

Those who are intimately familiar with newer versions of the C library may note that there is a getline() function in stdio.h that does most of the work we just implemented. To be completely honest, I didn’t know it existed until after I wrote this code. This function was a GNU extension to the C library until 2008, when it was added to the specification, so most modern Unixes should have it now. I’m leaving my existing code the way it is, and I encourage people to learn it this way first before using getline. You’d be robbing yourself of a learning opportunity if you didn’t! Anyhow, with getline, the function becomes trivial:

Parsing the line :

If this code looks suspiciously similar to lsh_read_line(), it’s because it is! We are using the same strategy of having a buffer and dynamically expanding it. But this time, we’re doing it with a null-terminated array of pointers instead of a null-terminated array of characters.

How shells start processes :

This might sound like a problem. Typically, when you want to run a new process, you don’t just want another copy of the same program – you want to run a different program. That’s what the exec() system call is all about. It replaces the current running program with an entirely new one. This means that when you call exec, the operating system stops your process, loads up the new program, and starts that one in its place. A process never returns from an exec() call (unless there’s an error).

With these two system calls, we have the building blocks for how most programs are run on Unix. First, an existing process forks itself into two separate ones. Then, the child uses exec() to replace itself with a new program. The parent process can continue doing other things, and it can even keep tabs on its children, using the system call wait().

Phew! That’s a lot of information, but with all that background, the following code for launching a program will actually make sense:

Shell Builtins :

Putting together builtins and processes :

The last missing piece of the puzzle is to implement lsh_execute(), the function that will either launch either a builtin, or a process. If you’re reading this far, you’ll know that we’ve set ourselves up for a really simple function:

Putting it all together

That’s all the code that goes into the shell. If you’ve read along, you should understand completely how the shell works. To try it out (on a Linux machine), you would need to copy these code segments into a file (main.c), and compile it. Make sure to only include one implementation of lsh_read_line(). You’ll need to include the following headers at the top. I’ve added notes so that you know where each function comes from.

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote