CSE 451 Assignment 1 FAQ and Tips

Winter 1999


Tips

  1. Try fgets() for getting the user's command.
  2. Try strtok() for parsing the user's command.
  3. Read /usr/include/sys/time.h to learn the mysteries of the timeval struct, which you'll need while using gettimeofday().
  4. The secret to getting the exit status of the exec'd program lies in the file /usr/include/sys/wait.h.

FAQ

Can we use execv instead of execl?

Absolutely. You may use any variant of exec you like. Run "man exec" to find out what variants of exec are available.


Could we use C++ to implement the shell? I mean both C and C++ programs should work, but some of us may feel more comfortable with C++.

C only for this assignment; see the mailing list archive for reasons why.


Are there any parameters on the size of command lines and the number of parameters we will take? In other words, do I have to do something complicated with malloc in order to store my data, or can I do something brain-dead with a fixed size buffer... I was contemplating

char args[64][256]

You may set limits on how long command lines may be and on how many arguments you will accept. Both limits should be reasonably large, so that a typical user would never notice them. If the user's command exceeds one of these limits, your shell should fail gracefully by printing an error message and continuing rather than by dumping core.


I have been working on homework 1 and as you expected my program went off on a rampage and blew up by opening so many processes that I reached my limit. My question is, how do I kill all of those processes? Right now I can't even log onto orcas. What a scary bug. Thanks for your help.

Scary indeed. Don't worry though -- you won't break anything. You've just got your program spawning processes forever. Except, eventually the kernel (which views your process as a data structure) simply says: "No More."

assuming that you've got the parent process stuck in some kind of a loop, you've got to kill the parent process. The easiest way to do this is to get on to a terminal somewhere and look at all of your processes. ps lx will do it. Then, you've got to figure out which one is the parent. All but one of them will share the same PPID field... the PPID in common (parent process ID) is the culprit. kill -9 that process. Example, if the parent is 234, you would type:

kill -9 234

Now, what about if you can't log in. That's an interesting problem for sure. One way around this is to find someone else in the terminal room who is already logged in and offer to buy them a cup of coffee if they are willing to do you a favor. If they say yes, ask them to save all of their files and then, from the shell type:

su me

where "me" is your login.

You will be asked for a passwd; give it.

Then, follow the procedure from above.

Now, how to avoid this in the first place?

  1. Put a conditional around the call to fork. MAke sure you only call fork if you are the parent and there are no currently running children
  2. to be really solid, you might put in a maximum number of times that you are willing to let your shell call fork. Then, increment on each call.


I was wondering if it would be okay to execute programs using the system() function as opposed to some form of exec(). The reason I ask is to avoid parsing the input string. Thanks.

No, you need to use exec() directly. You may actually find some parts of the assignment tricky if you use system() instead of exec(), such as implementing the myshstatus builtin.


Do we have to handle commands like the following:

/bin/ls -l

in our shell? right now mine treats that as two seperate commands.

Yes, you need to handle commands with arguments properly. "/bin/ls -l" should be treated as one command.


What's an easy way to mail my source code as the message body?

type "mail cse451-hw@cs.washington.edu < mysh.c" at your sanjuan or orcas prompt.


How can I make sure that my "myshstatus" command is working properly?

Write a little test program that exits with some non-zero value, like so:

  main() {
    exit(4);
  }

(Better yet, make your test program exit with a value passed on the command line.) Then run your test program from your shell and check with myshstatus that everything looks good.


My program supports exit, myshstatus, myshtime, ls, and users. Does it need to support anything else?

Yes. From your shell's prompt, you should be able to run any executable in the file system, even if you didn't know in advance that that program existed. That means that you should check to see if the user wants to run a builtin (myshstatus, myshtime, or exit) and if not then you should exec whatever program they asked for.