In: Computer Science
For the second phase of your final project, you will provide the functionality to your command interpreter. In this phase, you will add the functionality for command recognition and implement the HELP, QUIT, COPY, LIST, CD, SHOW and RUN functions.
Recall that some commands have no arguments, some have one and some have two and so your interface must handle a variable number of parameters.
Your command interpreter should do the following.
Display a prompt for the user.
If the entered command is invalid or if the number of parameters to that command is incorrect your program will print the error message and then redisplay the prompt.
If the command is valid, your program will carry out the command.
Here are specifics for each of the commands.
HELP
List the valid commands and their proper syntax. E.g.
You rang? > HELP
The valid commands are:
RUN executable-file
LIST
LIST directory
COPY old-filename new-filename
HELP
QUIT
SHOW file
Simply prints the given file to standard output.
QUIT
Terminates the session. E.g.
You rang? > QUIT
Goodbye.
COPY old-filename new-filename
Creates a copy of the source file.
When you implement the COPY command, you should verify that the source file exists and is readable. If the destination file exists you should ask the user if they wish to overwrite it before opening it to write. Once both files have been successfully opened simple read the characters on at a time from the source file and write them to the destination file.
CD directory
Changes the working directory to the argument if it is a valid directory name.
Your shell should display a message indicating the new directory upon successful execution o the command. You will need to use the chdir and getcwd commands as illustrated in the sample program chDir.cpp
LIST
Displays the files in a directory
Your LIST command takes either no arguments or one argument. The contents of the directory specified by the argument should be listed or in the case of no argument, the contents of the current directory should be listed. The syntax is:
LIST
or
LIST directory
The algorithm for LIST is reasonable simple.
Open the directory
Read the first entry in the directory
While not all of the directory has been displayed
Display the entry just read
Read the next entry
Close the directory
Working with directories is a relatively low-level operation. To access the contents of a directory we need to use a collection of system calls declared in the <dirent.h> header file.
opendir( dname ) is passed a c-string dname and returns a pointer to the directory dname (type DIR*) if it is found and NULL otherwise.
readdir( dPointer ) is passed a DIR* and returns a pointer to the next entry in the directory linked to dPointer or NULL if there are no more entries.
closedir( dPointer ) closes the link to the directory
The directory entries are of type dirent, a structure that contains the member d_name, which contains the name of the current entry.
Refer to chapter 17 of your UNIX text for more on programming with directories.
RUN executable-file
Executes the given program.
Your RUN command takes one argument. The executable file specified by the argument should be run and when finished, the prompt displayed. The syntax is:
RUN executable-file
The algorithm for RUN would be as follows.
Fork a child process.
Execute the program in the child process.
Have the parent wait until the child is finished before continuing.
This will require the following library functions
fork( ) creates a child process and returns the PID of the child process to the parent. The child gets 0.
execl( list of cstrings ) executes a program in the current process — the first argument is the path to the executable file, the remaining arguments are the strings of the command line
wait( ) causes the parent to block until the child finishes
Refer to chapter 18 of your UNIX text for more extensive discussion of these concepts.
As always, your program should:
Be readable with appropriate documentation and formatting
import os
from os import listdir
from os.path import isfile, join
while True:
print("You rang?> ",end="")
a = input()
if a == "QUIT" :
print ("Goodbye")
exit(0)
elif a == "HELP" :
print("The valid commands are:\nSHOW file\nCD directory\nRUN executable-file\nLIST\nLIST directory\nCOPY old-filename new-filename\nHELP\nQUIT")
elif "SHOW" in a:
if ".txt" in a:
a = a.split()[1]
else:
a = a.split()[1]+".txt"
try:
with open(a) as f:
print(f.read())
except Exception as e:
print ("Error : " + str(e))
elif "CD" in a:
try:
os.chdir(a.split()[1])
except Exception as e:
print("Error : "+str(e))
finally:
print("Current directory : "+os.getcwd())
elif "RUN" in a:
fname = a.split()[1]
try:
arg = dict(a.split()[2:])
except:
arg = {}
#for windows : exec(open("./"+fname).read(),arg)
try:
n = os.fork()
except Exception as e:
print("Error in fork :"+str(e))
else:
if n==0:
try:
exec(open("./"+fname).read(),arg)
except Exception as e:
print("Error in file execution : "+str(e))
else:
os.wait()
elif a == "LIST":
files = [f for f in listdir(os.getcwd()) if isfile(join(os.getcwd(), f))]
for i in files:
print(i)
elif "LIST" in a:
dr = list(a.split()[1:])
dr = ' '.join(dr)
print(dr)
files = [f for f in listdir(dr) if isfile(join(dr, f))]
for i in files:
print(i)
elif "COPY" in a:
src,dest = a.split()[1:]
try:
with open(src,"r") as f:
a = f.read()
except Exception as e:
print("Error with source file : "+str(e))
else:
if os.path.exists(dest):
print("Destination file aready exists. Press Y to overwrite, N to cancel")
if(input()=="N"):
continue
try:
with open(dest,"w") as f:
f.write(a)
except Exception as e:
print("Error with destination file : "+str(e))
else:
print("File copied")
else : print("Not a viable command. Enter HELP for list of commands")