************************************

  1)  You have been assigned the task of  producing an accounting of how 
      many 15-minute intervals contain active executions of the programs 
      zork, adventure, or doom over a 24-hour period on your local UNIX 
      system and how many of each. For example, in the first interval there 
      may be 3 active zorks, 0 adventure programs and 1 doom program. 
      In the second 15-minute interval there are 3 zork programs running, 
      2 adventure programs and 1 doom program, and so on. You decide that 
      you will write a C shell script that will collect the data you require.  
      Show this script.

  2)  There are several qualifiers that may be used in the declarations of 
      variables in C. Briefly explain what effect each of the following 
      qualifiers have on the variable they are associated with: extern, 
      static, register, const, unsigned 

  3)  What is the output of the following C program: 

	#include <stdio.h>
	int f1(int (*f)(int));
	int f2(int i);
	main()
	{
	   printf("Answer: %d\n", f1(f2));
   	   return 0;
	}

	int f1(int (*f)(int))
	{
	   int n= 0;
	   while((*f)(n)) n++;
	   return n;
	}

	int f2(int i)
	{
	   return i * i  + i - 12;
	}


  4)  The following loop is supposed to delete all nodes from a list and 
      release the memory  that they occupy. Unfortunately, the loop is 
      incorrect. Explain  any errors and correct the code segment.

         for( p = first; p != NULL; p = p-> next )
            free( p );

  5)  Let TMAK be the following macro:
         #define  TMAK(c) ('a'<=(c)&&(c)<='z'?(c)-'a'+'A':(c))

      Let s be a string and let i be an int variable. Show the output 
      produced by the following code fragment

         strcpy(s, "abcd");	
         i = 0;
         putchar(TMAK(s[++i]));

  6)  Write a fragment of C code necessary to create a pair of UNIX 
      processes with a pair of pipes between them, such that bidirectional
      communication is established using stdin and stdout.  eg:

                  stdout        stdin
       -------------  =========>>  -------------
       | PROCESS A |               | PROCESS B |
       -------------  <<========   -------------
		  stdin         stdout

  7)  Write a csh script to print the name of the computer with the lightest
      "load".  The load is a number indicating how busy a given computer is.
      The "ruptime" program gives the current load of a list of computers
      available on the network, as shown below.  Use the second of the three
      load numbers to make decisions in your script.  A load of 0.0 is
      thus a light load, while one of 3.0 would be a heavy load.  If two
      computers have an equal load, the one with fewer users should be
      assumed to be the better.

      "ruptime" output:
        agrajag.cdf     down 26+02:17
        amber.cdf         up  1+07:07,     2 users,  load 0.00, 0.00, 0.01
        amethyst.cdf      up    22:46,     3 users,  load 0.04, 0.03, 0.07
        anjie.cdf       down  1+09:55
        axiomset.cdf      up  1+07:49,     2 users,  load 0.05, 0.03, 0.03
        babel.cdf       down  1+09:57
        benjy.cdf       down  1+09:54
        clique.cdf        up  1+02:25,     3 users,  load 0.07, 0.07, 0.05

      Here are some hints: "grep -v blah" prints only lines *not* containing
      "blah".  "sort +n" will perform an ascending sort of lines based upon
      field n.

  8)  Write a C function that has the header
         char *insert_items( int num, struct item *head, int count )
      This function inserts new integers into a linked list of integers.
      The list is kept in asceding order.  Each element of the list is
      of type:
	struct item {
           int num;
           struct item *next;
        }

      The function call inserts count copies of num into the list pointed
      to by head.  For example, given the list 12 73 75 75 100, the call
      insert_items( 15, head, 3 ); returns the modified list 12 15 15 15 73
      75 75 100.  The end of the list is marked using a NULL next pointer.

************************************

The UNIX command line
     who | sort
uses a pipe.  Look at the following fragment of a C program, intended to 
have the equivalent functionality.

The parent process executes who, while the child executes sort.  In the space 
provided below, write the C code for "Section A" and "Section B" to allow the 
child and parent to communicate properly.

#include <stdio.h>
int main()
{
   int pid, fd[2];
   pipe( fd );
   if( (pid=fork()) == 0 )
   {
      /* Section A: place appropriate code here: */





      execlp( "sort", "sort", (char *) 0 );
   }
   else
   {
      /* Section B: place appropriate code here: */





      execlp( "who", "who", (char *) 0 );
   }
}
=============================================================================
Write a signal handler for SIGINT that keeps track of how many times it's 
been called.  When it is called for a third time, your program should 
terminate.  Also show the command to set up (instantiate) your signal handler.
=============================================================================
What is the difference between a process and a program?
=============================================================================
What is the difference between an INET domain socket and a UNIX domain socket?
=============================================================================
How do permission flags relate to directories? (i.e. what effect do r, w, 
and x permissions have on a directory?)
=============================================================================
Write a C program that creates two children.  The first child prints out 
its own process id and terminates.  The second process executes a program 
MOO.  The main program terminates when both its children have terminated.
=============================================================================
Explain the following services of Unix: sigset(), pause(), kill(), alarm()
=============================================================================
Show how in Unix alarm and pause can be used to implement the sleep command.

************************************

Question 1 [10 marks]

The UNIX command line
     who | sort
uses a pipe.  Look at the following fragment of a C program, intended to 
have the equivalent functionality.

The parent process executes who, while the child executes sort.  In the space 
provided below, write the C code for "Section A" and "Section B" to allow the 
child and parent to communicate properly.


#include <stdio.h>
int main()
{
   int pid, fd[2];
   pipe( fd );
   if( (pid=fork()) == 0 )
   {
      /* Section A: place appropriate code here: */
		                                       
		  

		                                       
      execlp( "sort", "sort", (char *) 0 );
   }
   else
   {
      /* Section B: place appropriate code here: */


		                                       
      execlp( "who", "who", (char *) 0 );
   }
}

Question 2 [10 marks (5 each)]

In the previous question involving C code for a child process and a parent 
process communicating via a pipe, there was no statement of the form

   wait( &status );

(where status is a variable of type int) as the last statement in the 
block of code for the parent process.

a) Explain why, in general, the parent executes a  wait() statement.

b) Explain why, in this case, the parent does not execute a  wait() statement

Question 3 [10 marks]

Write a signal handler for SIGINT that keeps track of how many times it's 
been called.  When it is called for a third time, your program should 
terminate.  Also show the command to set up (instantiate) your signal handler.

Question 4 [5 marks]

Which of the following should not be put in a header file?  Why not?
         i)  function prototypes
         ii)  function declarations
        iii)  macro definitions
        iv)  type definitions

Question 5 [10 marks]

Suppose that a program consists of three source files: main.c, file1.c, 
file2.c, plus two header files head1.h and head2.h.  All three source files 
include head1.h, but only file1.c and file2.c include head2.h.  Write a 
makefile for this program, assuming that the executable file is to be named 
demo.

Question 6 [20 marks]

Write a csh script named "recent" which accepts a program name as an argument 
and lists all programs by that name found in the directories listed in the 
PATH environment variable.  At the end, the shell script should execute the 
first instance of the program that it found, and print the status code 
returned by that program.  You should do basic error checking.  The PATH 
environment variable contains the list of all directories to search for 
executable programs, separated by colons, e.g.:

   echo $path
   /u/culhane/bin:/local/bin:/local/bin/X11

For example, if there was a program 'ls' in both /u/culhane/bin and /local/bin,
the output of the command "recent ls" would be:

   /u/culhane/bin/ls
   /u/local/bin/ls
   Executing /u/culhane/bin/ls
      (output of ls)
   Returned status code: 0

Question 7 [10 marks]

What is the output of the following C program?

	#include <setjmp.h>
	#include <stdio.h>

	static jmp_buf env;
	
	void f1( void );
	void f2( void );

	int main()
	{
	   int ret;

	   ret = setjmp( env );
	   printf( "setjmp returned %d\n", ret );
	   if( ret !=0 )
           {
	      printf( "Program terminates: longjmp called\n" );
	      return( 0 );
	   }
	   f1();
	   printf( "Program terminates normally\n" );
	   return( 0 );
	}

	void f1( void )
	{
	   printf( "f1 begins\n" );
	   f2();
	   printf( "f1 returns\n" );
	}

	void f2( void )
	{
	   printf( "f2 begins\n" );
	   longjmp( env, 1 );
	   printf( "f2 returns\n" );
	}

Question 8 [15 marks (5 each)]

For each of the errors below, explain the cause and describe how to fix the 
problem.  Also classify each error as being a compile-time error,  link-time 
error,  or  run-time error.

  a)  ./toy
   ld.so.1: ./toy: fatal: libforms.so.0.86: can't open file: errno=2


  b)  gcc Client.c
   Undefined                       first referenced
    symbol                             in file
    socket                              /var/tmp/cca001_01.o
    connect                             /var/tmp/cca001_01.o
   ld: fatal: Symbol referencing errors. No output written to a.out


c)   ld: fatal: symbol 'X_ServerPid' is multiply defined:
           (file iserver.o and file xserver.o);
   ld: fatal: File processing errors.  No output written to IServer
   *** Error code 1
   make: Fatal error: Command failed for target 'IServer'

Question 9 [20 marks]

Write a parent program that forks four child processes that each sleep a 
random number of seconds.  The parent process should wait for a child process 
to terminate.  Once a child process has terminated, the parent process should 
terminate the remaining children by issuing a SIGTERM signal to each.  Be sure 
to verify (via the wait system call) that each child process terminated 
received the SIGTERM signal.

Question 10 [10 marks]

What does the following system call do?

    sigset( SIGKILL, myKillHandler );

After the above system call has been issued, what happens when a SIGKILL 
signal is generated?  Why?

Question 11 [60 marks (5 each)]

a) What is the difference between a process and a program?

b) What is the difference between a file descriptor and a file stream?

c) What is the difference between an INET domain socket and a UNIX domain 
   socket?

d) What is the difference between libX11.a  and libX11.so in the directory
    /usr/openwin/lib/ ? 

e) What is a profiler, and how can it improve your programs?

f) Describe the stages that a client and a server go through to establish a 
   socket connection.

g) How do permission flags relate to directories? (i.e. what effect do r, w, 
   and x permissions have on a directory?)

h) What is errno?  How is it useful?

i) In what situations is the select() system call useful?

j) Describe what is the effect of the following system call.
      shmctl( shmID, IPC_RMID, (struct shmid_ds *) NULL );

k) Describe what is the effect of the following system call.
      semctl( semID, semNum, IPC_RMID );

l) Describe how one may deal with the fact that the following system call is 
   interruptible by signals.
      semop( semID, semOp, 1 );


************************************

Question 1 [15 marks]
   Consider the following program, named "strange.c": 

      #include <stdio.h>
      void main()
      {
         printf( "Hi\n" );
         fork();
      }

   It is compiled  with the command  "gcc strange.c -o strange".

   When run as "./strange", the output on the screen is:

      Hi

   However, when run as "./strange > out", the contents of the file "out" is:

      Hi
      Hi

   a) Explain the difference in the output. [7 marks]

   b) List two ways to fix this problem. [8 marks]


Question 2 [10 marks]
   The C library function "unsigned sleep(unsigned seconds)" is interruptible 
   by signals.  Given that it returns the number of unslept seconds, write 
   a function called MySleep() that is immune to interrupts:

      unsigned MySleep(unsigned seconds) {




      }


Question 3 [10 marks]
   Suppose that a program consists of three source files: main.c, file1.c, 
   file2.c, plus two header files head1.h and head2.h.  All three source 
   files include head1.h, but only file1.c and file2.c include head2.h.  
   Write a makefile for this program, assuming that the executable file is 
   to be named demo.


Question 4 [10 marks]
   Write a csh script named "fact" which takes one argument n. The script 
   should write to standard output the value of  n! (n factorial). This may 
   be calculated using the formula:

      0! = 1
      n! = n * (n-1)!


Question 5 [15 marks]
   Write a C program to count how many processes it can create. It should 
   repeatedly create new processes until it fails. Then it should print the 
   number of processes created and exit. 


Question 6 [15 marks]
   Write a C program that creates a pipe and two children.  The first child 
   reads a single line of text from standard input, writes it to the pipe, 
   and terminates. The second reads from the pipe, prints what it obtains 
   to standard output, and terminates.  The main program terminates when both 
   its children have terminated.


Question 7 [10 marks]
   Suppose that the global variable "x" is an integer in process A.  
   Process B is the parent of A, and B knows A's process id.

   a) Give the system call that B can issue to send an appropriate 
      signal to A. [3 marks]

   b) Give a program fragment to show how A can react to receiving this 
      signal by printing out the value of x. [7 marks]


Question 8 [10 marks (5 each)]
   For each of the errors and warnings below, explain the cause and describe 
   how to fix the problem.  Also classify each error as being a "compile-time
   error" or a "link-time error".

   a) gcc client2.c -lsocket
        Undefined                       first referenced
         symbol                             in file
        gethostbyname                       /var/tmp/cca006.S1.o  (symbol
                     belongs to implicit dependency /usr/lib/libnsl.so.1)
        ld: fatal: Symbol referencing errors. No output written to a.out

   b) gcc math2.c -lm
        math2.c: In function 'main':
        math2.c:6: warning: type mismatch in implicit declaration for
                            built-in function 'sqrt'


Question 9 [10 marks]
   Write a C function called GetUID() that takes a filename as a parameter 
   and returns the user identity uid (a positive integer) of the owner of 
   the file. It should return a suitable error value if the information 
   cannot be obtained.  Hint: the synopsis of the stat() system call is:

      int stat(const char *path, struct stat *buf);

   and the definition of "struct stat" in <sys/stat.h> is:

      struct  stat {
              dev_t       st_dev;
              ino_t       st_ino;
              mode_t      st_mode;
              uid_t       st_uid;
              gid_t       st_gid;
              off_t       st_size;
              timestruc_t st_atime;
              timestruc_t st_mtime;
              timestruc_t st_ctime;
              long        st_blksize;
              long        st_blocks;
              char        st_fstype[_ST_FSTYPSZ];
      };


Question 10 [75 marks]
   a) True or False: Signaling is always between exactly two processes.[2 marks]
   b) True or False: Race conditions can be safely ignored. [2 marks]
   c) What does it mean to say that an operation is atomic? [2 marks]
   d) What's the difference between the system calls execl() and execlp()? 
      [2 marks]
   e) What is the quickest way to move to the end of a file? [3 marks]
   f) How can a parent find out how its children died? [4 marks]
   g) What happens when a process tries to overflow a pipe? [4 marks]
   h) List two situations where RCS or SCCS are useful. [4 marks]
   i) How can you make sure that the two concurrent processes do not access a 
      shared data structure at the same time? [4 marks]
   j) What is a profiler, and how can it improve your programs? [4 marks]
   k) What is errno?  How is it useful? [4 marks]
   l) Draw a diagram representing the stages that a client and a server go 
      through to establish a socket connection. [4 marks]
   m) Describe what is the effect of the following system call. [4 marks]
      shmctl( shmID, IPC_RMID, (struct shmid_ds *) NULL );
   n) Describe what is the effect of the following system call. [4 marks]
      semctl( semID, semNum, IPC_RMID );
   o) Describe how one may deal with the fact that the following system call 
      is interruptible by signals. [4 marks]
         semop( semID, semOp, 1 ); 
   p) Process P1 executes the statement "X = 7;", and process P2 executes 
      the statement "X = 11;", where X is a shared variable.  Does this 
      represent a race condition?  Explain. [4 marks]
   q) When using memory mapped i/o to allocate N bytes to be used as shared 
      memory, why is it necessary to initially write a byte in the Nth position
      of the file? [4 marks]
   r) What is the difference between the stat() and lstat() system calls?  
      In what situations is lstat() safer to use than stat()? [4 marks]
   s) When is the use of the standard i/o function popen() most appropriate? 
      [4 marks]
   t) When is the use of the C library function select() most appropriate? 
      [4 marks]
   u) In conjunction with signal handlers, what additional control do the 
      C library functions setjmp() and  longjmp() give? [4 marks]