Operating Systems - Projects and Exercises
Exercise 5 - I/O Redirection
Your project shell must support i/o-redirection on both stdin and stdout. i.e. the command line:
programname arg1 arg2 < inputfile > outputfile
will execute the program programname with arguments arg1 and arg2, the stdin FILE stream replaced by inputfile and the stdout FILE stream replaced by outputfile.
With output redirection, if the redirection character is > then the outputfile is created if it does not exist and truncated if it does. If the redirection token is >> then outputfile is created if it does not exist and appended to if it does.
Note: you can assume that the redirection symbols, < , > & >> will be delimited from other command line arguments by white space - one or more spaces and/or tabs. This condition and the meanings for the redirection symbols outlined above and in the project differ from that for the standard shell.
I/O redirection is accomplished in the child process immediately after the fork and before the exec command. At this point, the child has inherited all the filehandles of its parent and still has access to a copy of the parent memory. Thus, it will know if redirection is to be performed, and, if it does change the stdin and/or stdout file streams, this will only effect the child not the parent.
You can use open to create file descriptors for inputfile and/or outputfile and then use dup or dup2 to replace either the stdin descriptor (STDIN_FILENO from unistd.h) or the stdout descriptor (STDOUT_FILENO from unistd.h).
However, the easiest way to do this is to use freopen. This function is one of the three functions you can use to open a standard I/O stream.
#include
FILE *fopen(const char *pathname, const char * type);
FILE *freopen(const char * pathname, const char * type, FILE *fp);
FILE *fdopen(int filedes, const char * type);
All three return: file pointer if OK, NULL on error
The differences in these three functions are as follows:
1. fopen opens a specified file.
2. freopen opens a specified file on a specified stream, closing the stream first if it is already open. This function is typically used to open a specified file as one of the predefined streams, stdin, stdout, or stderr.
3. fdopen takes an existing file descriptor (obtained from open, etc) and associates a standard I/O stream with that descriptor - useful for associating pipes etc with an I/O stream.
The type string is the standard open argument:
type Description
r or rb
w or wb
a or ab
r+ or r+b or rb+
w+ or w+b or wb+
a+ or a+b or ab+ open for reading
truncate to 0 length or create for writing
append; open for writing at end of file, or create for writing
open for reading and writing
truncate to 0 length or create for reading and writing
open or create for reading and writing at end of file
where b as part of type allows the standard I/O system to differentiate between a text file and a binary file.
Thus:
freopen("inputfile", "r", stdin);
would open the file inputfile and use it to replace the standard input stream, stdin.
You may want to use the access function to check on existence or not of the files:
#include
int access(const char *pathname, int mode);
Returns: 0 if OK, -1 on error
The mode is the bitwise OR of any of the constants below:
mode Description
R_OK
W_OK
X_OK
F_OK test for read permission
test for write permission
test for execute permission
test for existence of file
Looking at the project specification, stdout redirection should also be possible for the internal commands: dir, environ, echo, & help.
Code should be in 'straight' C using the compiler of your choice (cc or gcc).
Always use nice to execute your test programs at lower priority to ensure they do not inconvenience other users if they go 'haywire'. e.g.:
>nice a.out