” 写作CSCI 3120程序、program程序 写作CSCI 3120 Assignment 2Due May 30 by 9:00 AM ADTNOTESYou may wish to create your program using multiple files. And you may wishto use a Makefile. If you have more than one file for this assignment, pleasecreate a tar file containing all files needed to compile and execute your program(including your Makefile, if you use one), and upload that tar file toBrightspace. If you dont use a Makefile and your program requires more thana simple gcc a2.c -o a2 to compile, you must include that information inthe comment at the top of your main program file. BUT in such a case you reallyshould use a Makefile!As always for this course, this assignment must compile and run on the FCSUnix server csci3120.cs.dal.ca. Do not use any of the other FCS serversfor this course.As in A1, this program should follow the C-coding-style-notes (found inthe Assignments and related material folder on Brightspace.[1] As you may know, there are lots of different command shells available for Unix-type systems;ash, bash, csh, dash, fish, ksh, sh, tcsh and zsh immediately come to mind, but Im sureyou can find more. For this question, you will create your own (rudimentary) shell using C. Youcan create your program using any system you like, but your program must compile and run oncsci3120.cs.dal.ca; if it doesnt, the marker is authorized to give you 0, regardless of howmuch work you have put into your program.All of the above shells are complex programs which provide many, many features. This assignmentquestion requires you to only implement a tiny subset of the functionality of a normal shell. BelowI list each type of command-line you are to implement, and how many points each of those piecesis worth. Your shell should prompt the user for input with the prompt $ , as seen below in thesample commands.In the examples below, the input typed by a user is in red, and output by the shell is in black.Your shell should implement the following capabilities. These capabilities are explained furtherbelow, along with simplifying assumptions that your program may make. The first few show sampleoutput from the executed commands, but for brevity some of the rest do not show the output. Trythe commands yourself in your shell to see the sort of output to expect.(i) (1 point) If the command is exit, your shell terminates. This is what a terminal session whichstarts your program and then immediately runs the exit command should look like (whereprompt is whatever prompt you have at your regular shell):prompt ./a2 写作CSCI 3120作业、program课程作业 写作、C/C++语言作业 辅导、 辅导c++编程作业prompt1(ii) (5 points) Run a program which takes no arguments and waitpid() for the executed programto finish, then print another prompt and wait for another command line; examples:$ whooutput of the who command$ dateoutput of the date command(iii) (5 points) Run a program with arguments; examples:$ who am ioutput of the who am i command$ ls -l /etc/passwd /etc/hosts-rw-r–r–. 1 root root 158 Sep 10 2018 /etc/hosts-rw-r–r–. 1 root root 1279 May 6 09:58 /etc/passwd(iv) (5 points) Run a sequence of commands on one line; examples$ date ; sleep 10 ; dateSat May 16 09:05:36 ADT 2020Sat May 16 09:05:46 ADT 2020$ echo The users on the system right now are: ; whoThe users on the system right now are:a list of users starts here(v) (9 points) Run two programs (each with or without arguments) where the output of the firstprogram is piped into the input of the second program; examples$ date | sed s/.*://$ ls -l | grep rwx(vi) (3 points) Implement background jobs; that is, if a command ends with , rather thanyour shell waiting for it to complete, the shell continues on with other commands on the line(if any), or outputs a prompt and waits for another command.$ xz some-big-file-to-be-compressed $ compute-1000000-digits-of-pi sleep 3 ; ps uaxw(vii) (2 points) (If you dont implement this part, you will create Zombies!) Just before printing theprompt, use the waitpid() system call (with the WNOHANG option!) to reap any backgroundjobs which have terminated. (Use -1 as the first argument to waitpid().) If a backgroundjob has terminated, output its process id (pid). In the following example, imagine delaymeans the user has gone away for a few minutes and then returned.$ sleep 10 dateoutput of the date command$ delay whooutput of the who commandProcess 4321 terminated$(viii) (3 bonus points) If there are two commands on a line separated by , execute the secondcommand if and only if it the first command exits with a success indication. (The waitpid()system call returns this information.) Your program only needs to implement this for lineswith exactly two commands; example$ grep root /etc/passwd echo There is root!2root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologinThere is root!$ grep tree /etc/passwd echo There is tree!$Hints, simplifications, and more details:(i) Normal shells dont require space around command separators such as ;, and . Tomake it easier for you to parse the command lines, you may assume that these separators arealways surrounded by white space (the first two may legally be at the very end of a line aswell).(ii) Speaking of parsing the input line, you may use the readline library if you want (and if youknow what that is). But if you dont mind having the minimal line-editing capability providedby the Linux terminal driver (which is considerably less than what shells provide for you),dont worry about it. Im not worrying, and the markers will not expect you to do that.(iii) Normal shells implement wildcard characters, such as *. You definitely do not haveto do those! Or variables. Or I/O redirection. Or programming constructs. Or commandlineediting features (e.g., going back and forth with arrow keys). Or any other feature notmentioned above! Not being able to go back and forth (with arrow keys or control-this orsec-that) will mean you will have to type carefully when testing your shell, or you can copyand paste entire command lines from (say) an editor window into the terminal window runningyour shell.(iv) Although real shells allow arbitrarily complex pipelines (as they are called) using the |,;, and features (and others), (e.g., p1 | p2 | p3 p4 ; p5 p6), forthis assignment you dont have to implement the ability to handle any combination of with either or |. Nor do you have to allow more than one | per line. You do haveto implement the ability to parse and execute lines with more than one and/or ;, suchas p1 ; p2 args ; p3, p1 arg1 arg2 p2 args ; p3 arg1 arg2 and evenp1 arg p2 args ; p3 p4 where, as you might guess, the pis are arbitraryprograms.(v) Ordinary shells do some trickery to avoid having background jobs output text to your screen.You really dont want to try to implement that! So if you use a put a program into thebackground and it outputs text, that output will get mixed in with whatever other output iscoming out (including your $ prompt. Dont let this issue worry you. If you want to seewhat messes can occur, save the following three lines of code into a file called (for example)delay5, execute the command chmod 755 delay5 , and then inside your shell try acommand line like $ ./delay5 and wait 5 seconds to see what happens.#! /bin/shsleep 5echo $0 is now outputting stuff!(vi) Your program should not crash and burn if the user types in an invalid command line. However,as soon as your program detects some syntax it dont handle, it can output a short message,terminate processing of the command line, and go back to the waitpid()/prompt section.(vii) Normal shells allow long command lines. You may make the restriction that the commandline will never be longer than 80 chars. Which, if you think about it, also limits the number3of tokens on a command line. Feel free to use these limitations to simplify the design of yourprogram. (But please try not to do something horrible when a much more elegant solution ismore or less obvious.)(viii) String parsing in C is a bit of a nuisance, unless you decide to get out heavy-duty tools. Forthis assignment, you might find the following code sketch (which is not industrial-strength,and needs some modification for this assignment, but should give you some ideas) useful:char * tok;char cmd_name[MAX_CHARS + 1];…// Read a new line into str, making sure it is MAX_CHARS chars long….// Now parse out the tokens (words) on that line.tok = strtok(str, \t);if (tok == NULL){// Empty line, nothing to process here, go read another line}strcpy(cmd_name, tok);while ((tok = strtok(NULL, \t)) != NULL){// look at the token pointed to by tok and// see if it is a ;, a , or an argument// if a ; or fork()/execvp() the command// and then keep processing the line.// And if you do the bonus part also check for // Keep in mind strcmp() returns 0 if two strings match!// Also note that you have to strcpy() (or equivalent)// the string tok points to into your own character array// before the next call to strtok(), otherwise that token will// be gone forever!}(ix) The shell looks through the directories in your PATH variable to find the first one containingan executable file by the same name as the program name on the command line. Dontbother dealing with that yourself. Rather, instead of plain exec() use execvp(), which willperform the hunt itself. The first argument is a pointer to the command name (cmd_nameabove). The second argument to execvp() is an array of pointers; each pointer of that arraypoints to one of the arguments, and the next element of that array must be set to NULL.(x) You must use execvp() (or one of the other exec() system calls); you are absolutely notallowed to use the system() function.This is a fairly significant piece of work. Dont worry about catching every possible input error auser might make. If your program correctly processes correct input (as above), and it doesnt crashon invalid input, you can be happy.4This is not a programming course, and therefore I am not your programming instructor. But, havingsaid that, here are some suggestions as to how to proceed which I think will help you successfullycomplete this assignment. You dont have to follow them, but I would suggest you consider doingso, unless you are a whiz-bang programmer who doesnt need any help at all.I would strongly suggest you start by writing a program that can output a prompt, read a line oftext, and parse the line of text into individual tokens (using strtok(), or, if you prefer, someother technique). When you can do that and output the tokens to your screen, give yourself a paton the back, copy that code to another file in case of accidents, and carry on.Now might be a good time to think about how you will structure your program so that it can handlemore than one command on a line.After that, extend the program so that it prompts and reads in a loop, until the input line is exit,at which point your program Exits. When you can do that, give yourself a pat on the back, copythat code to another file in case of accidents, and carry on.After that, figure out how to correctly call execvp() for a command with no arguments, and towait() or waitpid() for it to finish. Try that out with commands like who or date and see ifyou get sensible output on your screen. When you can do that, give yourself a pat on the back,copy that code to another file in case of accidents, and carry on.After that, add the ability for the command to have arguments. This is (essentially) just additionalwork with strtok(), strcpy() and copying pointers into an array.After that, add the ability To have multiple commands on one line, separated by ;.The next one (piping from one program to another) is tricky; you might consider whether youwant to do It now, or after everything else is done. You know how to parse a line into commandswith arguments, but now you will have to fork() and execvp() two commands, but only afteryou use pipe() to create an unnamed pipe. In the child processes (after fork() but beforeexecvp()) you must detach standard output (of the first command) from the terminal and sendit to the pipe. Similarly you must detach the standard input of the second command from thekeyboard and instead read from the pipe. You will want to read the man page for dup2(). Keepin mind that standard input (stdin) is file descriptor 0 and standard output (stdout) is filedescriptor 1. Also dont forget to close() unused ends of pipes in all the right places, so thatyour program does not end up with more and more pipes. (But I suggest that you first get pipingworking, then add code to close() unused pipe ends and check you havent broken anything.)Next up: allow so-called background jobs, where a command is followed by . This shouldbe relatively easy, because all you have to do is not waitpid() for the child to finish. Havingdone that, you should next implement the waitpid() functionality for these background jobs.After all the above, the only thing to do is to implement the bonus feature. In this casewaitpid() is your friend, because it returns information you can use to determine whether thefirst command succeeded.EVALUATION:If your program does not compile on csci3120.cs.dal.ca it is worth 0 points, no matter5how good it is otherwise. Similarly, if your program compiles but crashes (when running oncsci3120.cs.dal.ca) on most or all input, it is still worth 0.If your program compiles And runs without crashing on correct input, you will receive points foreach feature you correctly implement, as per the point values above.While there are no points specifically allocated to code style, quality and readability, the markershave the prerogative to deduct marks if they feel your code fails to meet reasonable standards inany of these three areas.如有需要,请加QQ:99515681 或邮箱:99515681@qq.com
“
添加老师微信回复‘’官网 辅导‘’获取专业老师帮助,或点击联系老师1对1在线指导。