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