Download | Plain Text | Line Numbers


/*
 * Name:         logd (server)
 * Author:       Manuel Mausz, 0728348
 * Description:  Server reads log messages from shared memory (written from
 *               client) and prints message to stdout
 * Created:      25.04.2009
 * Exercise:     2e
 */
 
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "global.h"
 
/* global variables */
volatile static int shmid  = -1;  /* shared memory id */
volatile static int semid1 = -1;  /* semaphore#1 id */
volatile static int semid2 = -1;  /* semaphore#2 id */
volatile static shm_t *shmdata = (shm_t *) -1; /* data pointer to shm */
 
/*
 * NAME: sighandler
 * PURPOSE:
 * signal handler sets global error flag to 1
 *
 * PARAMETERS:
 * int signum ... signal number
 *
 * RETURN VALUE:
 * void
 *
 * GLOBAL VARS:
 * error
 */
static void sighandler(int signum)
{
#ifdef DEBUG
  (void) printf("signal %d received\n", signum);
#endif
  error = 1;
}
 
/*
 * NAME: usage
 * PURPOSE:
 * prints program usage to stderr and terminates with EXIT_FAILURE
 *
 * PARAMETERS:
 * void
 *
 * RETURN VALUE:
 * void
 *
 * GLOBAL VARS:
 * me
 */
static void usage(void)
{
  (void) fprintf(stderr, "Usage: %s\n", me);
  (void) bailout(NULL);
}
 
/*
 * NAME: free_resources
 * PURPOSE:
 * frees allocated resources
 *
 * PARAMETERS:
 * void
 *
 * RETURN VALUE:
 * void
 */
void free_resources(void)
{
#ifdef DEBUG
  printf("freeing resources...\n");
#endif
 
  /* remove semaphore#1 */
  if (semid1 != -1)
  {
    if (semrm(semid1) == -1)
    {
      semid1 = -1;
      bailout("Unable to remove semaphore#1");
    }
    semid1 = -1;
  }
 
  /* remove semaphore#2 */
  if (semid2 != -1)
  {
    if (semrm(semid2) == -1)
    {
      semid2 = -1;
      bailout("Unable to remove semaphore#2");
    }
    semid2 = -1;
  }
 
  /* detach from memory segmnet */
  if (shmdata != (shm_t *) -1)
  {
    if (shmdt((void *)shmdata) == -1)
    {
      shmdata = (shm_t *) -1;
      bailout("Unable to detach from shared memory segment");
    }
    shmdata = (shm_t *) -1;
  }
 
  /* remove shared memory segment */
  if (shmid != -1)
  {
    if (shmctl(shmid, IPC_RMID, NULL) == -1)
    {
      shmid = -1;
      bailout("Unable to remove shared memory segment");
    }
    shmid = -1;
  }
}
 
/*
 * NAME: main
 * PURPOSE:
 * install signal handler, allocate resources
 * and read from shared memory segment
 * mutual exclusion is accomplished using 2 semaphores
 *
 * PARAMETERS:
 * standard parameters of main
 *
 * RETURN VALUE:
 * int ... 0 on success, 1 on error
 *
 * GLOBAL VARS:
 * me, error
 */
int main(int argc, char *argv[])
{
  struct sigaction new_action, old_action;
 
  /* save me */
  me = argv[0];
 
  /* install signal handler */
  new_action.sa_handler = sighandler;
  sigemptyset(&new_action.sa_mask);
  new_action.sa_flags = 0; /* to avoid restart of blocking syscalls */
  INSTALL_SIGNAL(SIGINT,   new_action, old_action)
  INSTALL_SIGNAL(SIGQUIT,  new_action, old_action)
  INSTALL_SIGNAL(SIGTERM,  new_action, old_action)
 
  /* check cmdline options */
  if (argc > 1)
    (void) usage();
 
  /* allocate resources */
#ifdef DEBUG
  (void) printf("allocating resources...\n");
#endif
  if (!error && (shmid = shmget(SHM_KEY, sizeof(shm_t), SHM_PERMS | IPC_CREAT | IPC_EXCL)) == -1)
    (void) bailout("Unable to allocate shared memory segment");
  if (!error && (shmdata = shmat(shmid, NULL, 0)) == (shm_t *) -1)
    (void) bailout("Unable to attach to shared memory segment");
  if (!error && (semid1 = seminit(SEM_KEY1, SEM_PERMS, 0)) == -1)
    (void) bailout("Unable to create semaphore#1");
  if (!error && (semid2 = seminit(SEM_KEY2, SEM_PERMS, 1)) == -1)
    (void) bailout("Unable to create semaphore#2");
 
  while(!error)
  {
    /* wait for semaphore#1 */
    if (P(semid1) == -1 && !error)
      bailout("Unable to wait for semaphore#1");
 
    /* print message to stdout */
    if (!error)
      printf("%s\n", shmdata->msg);
 
    /* signal semaphore#2 */
    if (V(semid2) == -1 && !error)
      bailout("Unable to signal semaphore#2");
  }
 
  /* free resources */
  (void) free_resources();
 
  return (error) ? 1 : 0;
}
 
/* vim: set et sw=2 ts=2: */