Logo Search packages:      
Sourcecode: laptop-net version File versions  Download package

ifd.c

/* -*-C-*-

$Id: ifd.c,v 1.14 2003/07/11 11:52:24 cph Exp $

Copyright 2000,2001,2002,2003 Massachusetts Institute of Technology

This file is part of laptop-net.

Laptop-net is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.

Laptop-net is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with laptop-net; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

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

#include "ifmon.h"
#include "utils.h"

/* Number of seconds between polls. */
#ifndef IFD_DEFAULT_POLL_INTERVAL
#  define IFD_DEFAULT_POLL_INTERVAL 1
#endif

#ifndef IFD_PID_FILE
#  define IFD_PID_FILE "/var/run/ifd.pid"
#endif

static unsigned int poll_interval = IFD_DEFAULT_POLL_INTERVAL;
static const char * program_to_run;
static unsigned int n_managed_ifcs;
static const char ** managed_ifcs;

/* Forward references */
static int ifmon_loop_proc (void *);
static void ifmon_proc (void *, const char *, unsigned int, unsigned int);
static int ifmon_managed_p (void *, const char *);
static void print_status (char *, unsigned int);
static int execute (const char *, const char *);

int
main (int argc, const char ** argv)
{
  const char ** scan_argv = (argv + 1);
  const char ** end_argv = (argv + argc);
  int option_debug = 0;

  /* Process command-line options.  */
  while (scan_argv < end_argv)
    {
      if ((strcmp ((*scan_argv), "--debug")) == 0)
      {
        option_debug = 1;
        scan_argv += 1;
      }
      else
      break;
    }
  if ((end_argv - scan_argv) < 1)
    {
      fprintf (stderr, "Usage: %s [--debug] <program> <interface> ...\n",
             (argv[0]));
      exit (1);
    }

  program_to_run = (*scan_argv++);

  if ((strcmp (program_to_run, "")) == 0)
    program_to_run = 0;

  /* Check that program can be executed. */
  if ((program_to_run != 0) && ((access (program_to_run, X_OK)) < 0))
    {
      perror (program_to_run);
      exit (1);
    }

  managed_ifcs = scan_argv;
  n_managed_ifcs = (end_argv - scan_argv);

  if (!option_debug)
    run_in_background (IFD_PID_FILE);

  openlog ("ifd", LOG_PID, LOG_DAEMON);
  syslog (LOG_INFO, "starting");


  return (run_ifmon (ifmon_loop_proc, ifmon_proc, ifmon_managed_p, 0));
}

static int
ifmon_loop_proc (void * context)
{
  sleep (poll_interval);
  return (0);
}

static void
ifmon_proc (void * context, const char * if_name,
          unsigned int old_status, unsigned int status)
{
  if (program_to_run != 0)
    {
      char cmd [10240];       /* 10240 is max command line length. */
      strcpy (cmd, program_to_run);
      strcat (cmd, " ");
      strcat (cmd, if_name);
      strcat (cmd, " ");
      strcat (cmd, ((ifmon_managed_p (context, if_name))
                ? "managed"
                : "unmanaged"));
      strcat (cmd, " ");
      print_status (cmd, old_status);
      strcat (cmd, " ");
      print_status (cmd, status);
      execute ("network-change script", cmd);
    }
}

static int
ifmon_managed_p (void * context, const char * name)
{
  const char ** scan = managed_ifcs;
  const char ** end = (scan + n_managed_ifcs);
  while (scan < end)
    if ((strcmp ((*scan++), name)) == 0)
      return (1);
  return (0);
}

static void
print_status (char * cmd, unsigned int status)
{
  if (((status & IFMON_STATUS_VALID) != 0)
      && ((status & IFMON_STATUS_AVAILABLE) != 0))
    {
      strcat (cmd,
            (((status & IFMON_STATUS_UP) != 0)
             ? "up,running"
             : "down,stopped"));
      strcat (cmd, ",");
      strcat (cmd,
            (((status & IFMON_STATUS_CONNVALID) == 0)
             ? "unknown"
             : ((status & IFMON_STATUS_CONNECTED) != 0)
             ? "connected"
             : "disconnected"));
    }
  else
    strcat (cmd, "unknown");
}

static int
execute (const char * msg, const char * cmd)
{
  int ret;
  FILE * f;
  char line [256];
  const char * suffix = " 2>&1";
  unsigned int limit = ((sizeof (line)) - ((strlen (suffix)) + 1));
    
  syslog (LOG_INFO, "executing: '%s'", cmd);
  strncpy (line, cmd, limit);
  (line[limit]) = '\0';
  strcat (line, suffix);
  f = (popen (line, "r"));
  while (fgets (line, 255, f))
    {
      (line [(strlen (line)) - 1]) = '\0';
      syslog (LOG_INFO, "+ %s", line);
    }
  ret = (pclose (f));
  if (WIFEXITED (ret))
    {
      if (WEXITSTATUS (ret))
      syslog (LOG_INFO, "%s exited with status %d",
            msg, (WEXITSTATUS (ret)));
      return (WEXITSTATUS (ret));
    }
  else
    {
      syslog (LOG_INFO, "%s exited on signal %d",
            msg, (WTERMSIG (ret)));
      return (-1);
    }
}

Generated by  Doxygen 1.6.0   Back to index