Assignment 3, due Sept. 13Solutions
Part of
the homework for 22C:112, Fall 2013
|
On all assignments, your name must be legible as it appears on your University ID card! Assignments are due at the start of class on the day indicated (usually Friday). Exceptions will be by advance arrangement unless there is what lawyers call "an act of God" (something outside your control). Homework must be turned in on paper, either in class or in the teaching assistant's mailbox. Never push late work under someone's door!
a) As written, the code only allows blanks (that is ' ') as delimiters between the arguments of a shell command. What routine would need to be changed and how many lines of code would you need to add or change in order to make the code permit both blanks and tabs (that is, '\t') as delimiters. Do not give the code, just give the routine name and number of lines. (0.5 points)
In parseargv() change
while (command[j] == ' ') j++;to read
while ((command[j] == ' ')||(command[j] == '\t')) j++;and change
while ((command[j] != ' ') && (command[j] != '\000')) {to read
while ((command[j] != ' ') && (command[j] != '\t') && (command[j] != '\000')) {
b) The call to execve in launch() passes NULL as its third parameter (the environment). How would you change this so that it passes the environment that was passed to the caller? Hint: You might want to use man execve and man environ to learn more. Do not give variable definitions. Just give the modified code for the execve statement. (0.5 points)
Change:
execve( argv[0], argv, NULL );to read:
execve( argv[0], argv, environ );
if [ -x thisfile ] then thisfile else if [ -x thatfile ] then thatfile else echo failure fi fi exit
In bash, the [ -x f ] predicate returns true if its argument f is the name of an executable file.
A problem: Write equivalent C code, using execve() to launch either thisfile or thatfile or output the error message failure. Hint: This can be done in 4 lines of reasonably formatted C code; examine how launch() in mush.c works. code would it take> (1.0 points)
Here is a first hack at a solution:
execve( "thisfile", NULL, NULL ); execve( "thatfile", NULL, NULL ); puts( "failure" ); exit();That is a bit rough, since the executed files might expect properly formed arguments and might depend on the environment. Here is a mature solution:
char *thisargv[] = { "thisfile", NULL }; char *thatargv[] = { "thatfile", NULL }; execve( thisargv[0], thisargv, environ ); execve( thatargv[0], thatargv, environ ); puts( "failure" ); exit( EXIT_FAILURE );
int fputc( int c, FILE *f ) { write( *f, &(unsigned char)c, 1 ); return c; } int fgetc( FILE *f ) { unsigned char c; if (read( *f, &c, 1 ) == 1) return (int) c; return EOF; /* if it did not return a character */ }
A Problem: Write very brief (and equally stupid) C implementations for fseek() and ftell(). Do not handle error conditions. The body of each of your routines is likely to be just one line. (1 point)
Here is the stupid code:
int fseek( FILE * f, long offset, int whence ) { lseek( *f, offset, whence ); return 0; } long int ftell( FILE * f ) { return lseek( *f, 0, SEEK_CUR ); }