************************************ 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 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 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 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 #include 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 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 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]