代写bash | shell作业 | assignment – shell代做

shell代做

代写bash | shell作业 | assignment – 这道题目是利用shell进行的编程代写任务, 是有一定代表意义的bash/shell等代写方向, 这是值得参考的assignment代写的题目

bash代写 linux shell 代做 script代写

PA1.1. A simple terminal shell After completing this assignment, you should be:

  • Able to use Linux APIs for process creation;
  • Able to use Linux APIs for signal handling;
  • Able to use Linux pipes;
  • Familiar with the Linux process hierarchy.

Special Note

Although this assignment’s autograder tests the most common input issues and produces an initial score, this score may be overwritten by a manual review by the course staff. This manual review will ensure your code works not only based on the simple cases listed in the resulting tests, but also for other considerations listed in the specification and for additional tests. TAs will also review your code quality in terms of clarity and use of comments. Your grade may also be reduced in cases of academic misconduct.

Introduction

A shell, sometimes also called a command-line interpreter, is a program that provides a command line user interface for an operating system, typically through the use of a terminal. These shells read commands from a user and perform operations, such as creating processes, based on these commands. Common shells you may be familiar with include bash, csh and zsh.

In this program you will create a very simple shell, with a subset of the functionality found in modern shells. In particular, your shell must be able to:

  • Read a command line from standard input;
  • Interpret the command line to identify the processes that need to be executed and their arguments;
  • Run the processes identified in the command line, both in foreground and background mode;
  • Support the forwarding ("pipe") of one process’ output to another process’ input;
  • Direct keyboard interrupt signals (e.g, Ctrl-C) to the currently running process.

Your program must run in a Linux environment. If you are not developing your code on Linux, you are encouraged to test it in a Linux environment before submitting. One great way to do that is to use the department’s Remote Lab.

When implementing this assignment you should write small pieces of code and then test and verify their functionality before proceeding. You are strongly encouraged to implement the assignment’s functionality incrementally in the order it is presented in the description.

Provided Files

The following files are provided to you to use during the implementation of this assignment:

  • The starting code for your program’s implementation. o myshell.c
  • Additional files required for the program to run. Your code will be tested assuming these files are not modified at all. o myshell.h o main.c
  • A Makefile containing compilation rules. Running make in a terminal where all files above are in the current directory should cause the program to compile. o Makefile

Implementation details

In essence, your program will read and parse a command line, execute any relevant process, wait (if necessary) until the process finishes, and then repeat the same procedure again. This procedure will continue until the exit or quit command are read, at which point your shell program will terminate. As is customary, a line is any string of characters ending with a line-feed (‘\n’) character.

Before reading a line, your program will show a prompt containing a single > sign followed by a space. This prompt must only be shown if the standard input is a regular terminal (i.e., when isatty(stdin) returns true). This functionality is already provided in the starting code above, you should not modify it.

The command line for a single process call will consist of a program name followed by an optional set of arguments, all separated by white-space characters (see note below). So, for example, the command line:

/usr/bin/ls -al /etc is interpreted as the command /usr/bin/ls, followed by two arguments: – al and /etc. It is also possible to have commands with no arguments, like:

pwd If the command contains a / character (e.g., /usr/bin/ls), it is interpreted as a pathname. If it does not contain such character (e.g., ls), the file is sought in the list of directory pathnames specified in the PATH environment variable. Note that the default libraries for process execution are able to perform this PATH search for you, you are not required to implement it yourself. Just make sure you choose the right variant of exec.

If the command line does not contain a & operator, the program must run in the foreground. In such case, the shell will wait (block) until the executed command completes before showing a new prompt and reading a new command line.

If the command line ends with the & operator, then the command will run in the background. For background processes, the shell will not wait (block) before reading a new command line. In such case, your program will print the message (replacing 9999 with the PID of the child process):

Background process [9999] started.

Before reading a new command line, the shell must verify if any children processes that were previously executed in the background have finished (hint: this can be done with a call to waitpid with the WNOHANG option). For any process that finished, the shell will print the message (replacing 9999 with the PID of the child process):

Background process [9999] finished. If the command line contains one or more & or ; operators in the middle of the line, then the command line will be split into commands at each of these operators, and each command will be treated individually. Commands just before a & operator run in the background, while commands just before a ; operator run in the foreground. For example, the command line:

commandA argA1 argA2 & commandB argB1 argB2 ; commandC argC1 argC2 & commandD argD1 argD

is equivalent to the following sequence:

commandA argA1 argA2 &

commandB argB1 argB2commandC argC1 argC2 & (^) commandD argD1 argD Note that, in the case above, the first command runs in the background (since they end with a & operator); the second command runs in the foreground; the third command runs in the background, but only starts after the second command ends; and the last command again runs in the foreground. If the command line contains one or more | operators, then the commands before and after the operator will be piped to each other. This means that both commands will run in parallel, but the standard output of the command on the left of the

operator will be directed to the standard input of the command on the right. More than one | operator may be present in the same command-line, creating a chain of pipes. For example:

cat /etc/passwd | cut -d: -f7 | sort | uniq -c The command line above reads the list of users of the system, extracts their preferred shell (7th column), sorts them, then counts the number of users using each shell.

If piped commands run in the foreground, the shell only resumes once all commands in the chain complete. If the commands run in the background (i.e., the line ends with a & operator), then the background start message must be printed for all commands in the chain.

Your shell must be able to properly handle keyboard interrupts (i.e., Ctrl-C). In particular, a keyboard interrupt should not, at any point, cause your process to terminate. If there are no foreground processes running, the current line must be ignored and a new prompt must be expected. If there is a foreground process running, the interrupt signal should be sent to that process. If there is more than one foreground process running (e.g., in case of a piped process), the interrupt signal should be sent to the most recent process still running. If there are processes that are pending but have not yet started at the moment of the interrupt (e.g., when using the ; operator), they should not start.

Technical details

Your program must use the Linux APIs like fork and the execve variants directly for any operation related to process creation and code execution. In particular, you are not allowed to use library functions like system, vfork, posix_spawn, clone/clone3, or other functions/libraries with similar functionality.

Your program must not use any library other than the default C or POSIX library. As a rule of thumb, if you require any #include statement other than those provided in the started code, or if you need to modify the Makefile to make your code work, you likely are using a different library. In that case, consult the instructor before proceeding with your implementation.

You must support command lines up to 511-characters long (including the termination line-feed character). If you read a line longer than that, the command line must be ignored, and the following error message must be printed:

Command line too long. If any of the commands fail to execute due to an error in any of the related system calls (fork, execve, pipe, etc.), your program must print a message containing the command name (without arguments), followed by a colon, a space and the system provided message for the error that happened. Note that using perror is a straightforward way to print such a message.

When an error happens in the attempt to execute a command, the command that was directly involved in the error will not proceed. If an error affects multiple commands (e.g., an error returned by the pipe function), then all affected commands

are ignored. All other commands that have not yet executed in the command line should proceed as usual, and commands that already started can proceed. For example, if the command line is:

echo First command ; invalid_command args ; echo Last command then the first command would proceed as usual, the second command (assuming invalid_command does not exist) would cause an error, and the last command would be executed after the error message. The output of the sequence above would typically be something like:

First command invalid_command: No such file or directory Last command Note that, if the error happens on a background process, then the background messages listed above must still proceed. This means that an input like:

invalid_command & would cause an output like:

Process [5528] running in background.

invalid_command: No such file or directory

(^) Process [5528] terminated.

For the purpose of this assignment, a white-space character refers to the same set of characters used in the POSIX isspace function, i.e., space itself (‘ ‘), form-feed (‘\f’), carriage return (‘\r’), horizontal tab (‘\t’) and vertical tab (‘\v’). Multiple white- space characters in sequence are to be treated in the same way as a single one.

White-space characters at the start or end of the command line are to be ignored (including the line-feed character ‘\n’). So a command-line like this:

echo a b c d is to be treated in the same way as:

echo a b c d Any blank command lines (or lines containing only white-space characters) should be ignored. If a command contains the # operator, any text following that operator should be treated as a comment and ignored.

Note that most common shell applications are able to support special characters that interpret arguments in different ways. For example, bash allows quotes for arguments with spaces, backslashes for escaping characters, $ for environment variable expansion, or * and? for filename expansion. You are not required to support these special characters, and may treat commands and arguments as they are seen in the original string. In other words, in a command like:

ls "$HOME/Curriculum Vitae." It is acceptable to execute the command ls where the first argument is "$HOME/Curriculum and the second is Vitae.". In such cases, your shell will not provide the same result as a regular shell, and that is ok. Should you wish to challenge yourself to support such extensions, you are welcome to implement them, but these will not be counted towards your grade.

The | operator has higher precedence over the & or ; operators, as with bash. In other words, if a command has multiple operators, then the | operation takes the closest command as its output, instead of a sequence of commands. So, for example, the command line:

cmdA | cmdB & cmdC | cmdD ; cmdE | cmdF | cmdG is equivalent to:

cmdA | cmdB &

cmdC | cmdDcmdE | cmdF | cmdG (^) For piped commands, you will need to handle file descriptors. While a more extensive description of the functionality of file descriptors in Linux will be done in a future unit of the course, what you need to know for this assignment is that every open file in every Linux process is assigned an integer number which is called its file descriptor. By default, the following file descriptors are available in virtually every Linux process:

  • 0 (or STDIN_FILENO): standard input;
  • 1 (or STDOUT_FILENO): standard output;
  • 2 (or STDERR_FILENO): standard error output.

You will need create a pipe for each pair of piped processes. This can be done with the pipe function, which provides a pair of file descriptors (not linked to a traditional "file", but still called an "open file"). You will also need to replace the standard output and standard input of child processes with the pipe. The most reliable method to do

so is likely the dup2 function, which allows you to duplicate a file descriptor into an existing number (e.g., one of the pipe file descriptors with that of the standard output).

Note that, in some instances (e.g., after calling dup2, or after a fork), there will be instances of the same open "file" (particularly the pipe entrypoints) as multiple file descriptors. You must close the file descriptors that will not be used as soon as possible, to avoid conflicts between the processes. Note that, if multiple file descriptors point to the same open file, closing one of the file descriptors will not affect the others, and the "file" will remain open in the remaining descriptors. Only after all file descriptors are closed (or their corresponding processes finish) is the open file actually released.

Other than SIGINT, you are not required to explicitly handle any other signals, such as SIGSTOP or SIGTERM.

Submitting your file

You must submit your assignment using the boxes below. Once the files are uploaded, you must save your submission for it to be marked.

You may save your submission as many times as you wish before the deadline. Your latest submission will be considered for grades.