Download | Plain Text | Line Numbers


/*
 * Name:         logc (client)
 * Author:       Manuel Mausz, 0728348
 * Description:  Client writes log message from commandline to
 *               shared memory segment.
 * Created:      25.04.2009
 * Exercise:     2e
 */
 
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.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 <message>\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
  /* detach from memory segment */
  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;
  }
}
 
/*
 * NAME: main
 * PURPOSE:
 * install signal handler, allocate resources
 * and write to 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 != 2)
    (void) usage();
 
  /* check message length */
  if (strlen(argv[1]) >= MAX_LEN)
    bailout("Message is too long (maximum: %d)", MAX_LEN);
 
  /* allocate resources */
#ifdef DEBUG
  (void) printf("allocating resources...\n");
#endif
  if (!error && (shmid = shmget(SHM_KEY, sizeof(shm_t), SHM_PERMS)) == -1)
    (void) bailout("Unable to get id of 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 = semgrab(SEM_KEY1)) == -1)
    (void) bailout("Unable to grab semaphore#1");
  if (!error && (semid2 = semgrab(SEM_KEY2)) == -1)
    (void) bailout("Unable to grab semaphore#2");
 
  /* wait for semaphore#2 */
  if (P(semid2) == -1)
    bailout("Unable to wait for semaphore#2");
 
  /* write message to shared memory segment */
  if (!error)
  {
#ifdef DEBUG
    printf("writing message to shared memory segment...\n");
#endif
    (void) strncpy((char *)shmdata->msg, argv[1], MAX_LEN);
    shmdata->msg[MAX_LEN - 1] = '\0';
  }
 
  /* signal semaphore#1 */
  if (V(semid1) == -1)
    bailout("Unable to signal semaphore#1");
 
  /* free resources */
  (void) free_resources();
 
  return (error) ? 1 : 0;
}
 
/* vim: set et sw=2 ts=2: */