IC221: Systems Programming (SP14)


Home Policy Calendar Syllabus Resources Piazza

6-Week Practicum Solutions

Table of Contents

Problem 1

BIG IDEA Need to connect the different parts of the compilation process up. First compile to object files using the -c option, and then assemble object files into the binary exectuable. Don't forget the -lreadline flag.

#TODO: Complete the MAkefile to compile rpn
#
#  NOTES:
#  (1) you must use clang as your compiler
#  (2) you must compile to .o object files and combine them into an executable
#  (3) you must have a clean to remove binary and .o files
#  (4) you MAY NOT use Makefile vairables, like CC or CFLAGS
#
#  (hint: don't foget about adding in the readline library via -l)

all: rpn

# COMPLETE BLEOW

rpn: mathlib.o rpn.o
        clang -lreadline mathlib.o rpn.o -o rpn

mathlib.o: mathlib.c
        clang -c mathlib.c -o mathlib.o

rpn.o: rpn.c
        clang -c rpn.c -o rpn.o


clean:
        rm -f mathlib.o rpn.o *~ rpn

Problem 2

BIG IDEA: There exists a pipe between each process. Only the first process the parent requires a dup onto stdout because cat is executed. All other process just use the pipe as is. The only further requirement is that the pipeline is widowed.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[]){

  char * cmd[] = {"cat", NULL};
  int cpid;
  int pfd_1[2] = {-1,-1},pfd_2[2] = {-1,-1};
  char c;

  //TODO: add neccesary pipeline code
  pipe(pfd_1);

  if( (cpid = fork()) ) {
    /* CHILD 1 */

    //TODO: add neccesary pipeline code
    pipe(pfd_2);

    if( (cpid = fork()) ) {
      /* CHILD 2*/

      //TODO: add neccesary pipeline code
      close(pfd_2[1]);
      close(pfd_1[1]);

      //read from pfd_2 and write to stdout
      while(1){
        if(read(pfd_2[0],&c,1)){
          write(1,&c,1);
        }else{
          exit(0);
        }
      }

    }else if(cpid == 0){
      /* CHILD 1 */

      //TODO: add neccesary pipeline code
      close(pfd_1[1]);
      close(pfd_2[0]);

      //read from pfd_1 and write to pfd_2
      while(1){
        if(read(pfd_1[0],&c,1)){
          write(pfd_2[1],&c,1);
        }else{
          exit(0);
        }
      }
    }      

  }else if(cpid == 0){
    /* PARENT */

    close(1);

    //TODO: add neccesary pipeline code
    close(pfd_1[0]);

    dup2(pfd_1[1],1);

    //execute the cat command
    execvp(cmd[0], cmd);
    perror("exec failure");
    _exit(1);
  }

}

Problem 3

BIG IDEA: The pong program must be able to handle any signal numbered 1-32 and also know the pid of the process that sent it the signal. This requires using sigaction() with the SA_SIGINFO flag and also establishing the action with all signals.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

//TODO: Complete the signal handler
//
//   * The arguments to the signal handler function depend on the type
//     of handler, e.g., a basic handler or one that requires a
//     siginfo

//void handler(/* setup arguments */){
void handler(int signum, siginfo_t * info, void * contenxt){

  printf("pong %d\n", info->si_signo);
  kill(info->si_pid, info->si_signo);


  exit(0); //DO NOT EDIT
}

int main(int argc, char * argv[]){

  //DO NOT EDIT
  pid_t cpid; //child pid
  char * cmd_ping[] = {"./ping", NULL}; //cmd_argv
  int i; //iterator
  ///////////////////////

  //TODO: Setup signal handler
  //
  //   * Will need to handle potentiall all signals, except SIGCHLD,
  //     SIGKILL, and SIGSTOP
  //
  //   * Will probably need to use sigaction() insted of signal() to
  //     establish the handler, may want siginfo data

  struct sigaction action;
  action.sa_sigaction=handler;
  action.sa_flags=SA_SIGINFO | SA_RESTART;


  //setup handler for all signals except SIGCHLD
  for(i = 0; i < 32; i++){
    if ( i == SIGCHLD ) continue;
    sigaction(i, &action, NULL);
  }


  //DO NOT EDIT///////////////////////
  if( (cpid = fork()) == 0 ){
    /* CHILD */
    execvp(cmd_ping[0], cmd_ping);
    perror("exec");
    exit(2);
  }else{
    /* PARENT */
    wait(NULL);
  }
  return 0;
  //////////////////////////////////
}