/*
 * worker.c
 *
 * This program will modify the image contents and then inform image.c.
 * 
 * By Kamran Karimi
 */
 
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/dipc.h>
#include <errno.h>
#include <sys/signal.h>
#include <string.h>
#include "image.h"

int semid;
int shmid;
int num;
char (*image)[COLUMN];

/* this array will be used to change the image */
static char change[4] = {'/', '|', '\\', '-' };

/* these are ignored. see image.c for more info.

static void shm_sig_handler(int signo)
{
 if(signo == DIPC_SIG_READER)
  fprintf(stderr,"Worker#%d: BECAME A READER!\n", num);
 else if(signo == DIPC_SIG_WRITER)
  fprintf(stderr,"Worker#%d: BECAME A WRITER!\n", num); 
 else
  fprintf(stderr,"Worker#%d: SIGNAL %d\n", num, signo);  
}
*/

int main(int argc, char **argv)
{
 int semid;
 int shmid;
 int i, j;
 struct sigaction sact;
 struct sembuf sem[2];
 
 if(argc != 2)
 {
  printf("USAGE: %s <Number Of This Process>\n",argv[0]);
  exit(0);
 }
 
 sact.sa_handler = SIG_IGN; /* shm_sig_handler; */
 sigemptyset(&sact.sa_mask);
 sact.sa_flags = 0;
  
 if(sigaction(DIPC_SIG_READER, &sact, NULL) < 0)
 {
  fprintf(stderr,"Worker#%d:  ERROR: Can't Catch Signal", num);
  fprintf(stderr,"  BECAUSE: %s\n",strerror(errno));
 }
 
 if(sigaction(DIPC_SIG_WRITER, &sact, NULL) < 0)
 {
  fprintf(stderr,"Worker#%d:  ERROR: Can't Catch Signal", num);
  fprintf(stderr,"  BECAUSE: %s\n",strerror(errno));
 }

 num = atoi(argv[1]);
 semid = semget(SEM_KEY, 2, SEM_MODE);
 if(semid < 0)
 {
  fprintf(stderr,"Worker#%d: semget() failed: BECAUSE %s\n",
                                                 num,strerror(errno));
  exit(20);
 }
 /* sem[0] for initialization, sem[1] for result */
 fprintf(stderr,"Worker#%d: semaphor prepared\n", num);
 shmid = shmget(SHM_KEY, SHM_SIZE, SHM_MODE);
 if(shmid < 0) 
 {
  fprintf(stderr,"Worker#%d: shmget() failed: BECAUSE %s\n",
                                                 num,strerror(errno));
  exit(20);
 }
 image = (char (*)[])shmat(shmid,0,0);
 if(image == (char (*)[]) -1)
 {
  fprintf(stderr,"Worker#%d: shmat() failed BECAUSE %s\n",
                                               num, strerror(errno));
  exit(20);
 }
 fprintf(stderr,"Worker#%d: waiting for semaphore\n",num);
 sem[0].sem_num = 0;
 sem[0].sem_op = -1;
 sem[0].sem_flg = 0;
 
 if(semop(semid, &sem[0], 1) < 0)
 {
  fprintf(stderr,"Worker#%d: semop() failed BECAUSE %s\n", 
                                          num, strerror(errno)); 
  exit(20);
 }
 fprintf(stderr,"Worker#%d: I can now access the image\n", num);

 for(i = bounds[num].row1; i < bounds[num].row2; i++)
 {
  for(j = bounds[num].col1; j < bounds[num].col2; j++)
   image[i][j] = change[num];
 } 

 fprintf(stderr,"Worker#%d: Now let the original task get the results\n", num);
 sem[1].sem_num = 1;
 sem[1].sem_op = 1;
 sem[1].sem_flg = 0;

 if(semop(semid, &sem[1], 1) < 0)
 {
  fprintf(stderr,"Worker#%d: semop() failed BECAUSE %s\n", 
                                          num, strerror(errno)); 
  exit(20);
 }  
 shmdt((char *)image);
 fprintf(stderr,"Worker#%d: done!\n", num);
 exit(0);
}
