Code Search for Developers
 
 
  

misc_init.c from EmStar at Krugle


Show misc_init.c syntax highlighted

/*
 *
 * Copyright (c) 2003 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
 

/*
 * misc_init: Iniitalization function that all em* programs call.
 * Configures log levels, figures out if we're running inside the
 * simulator, parses out command-line options that are common to all
 * programs, etc.
 *
 * $Id: misc_init.c,v 1.35 2006/10/17 20:38:52 jhicks Exp $
 */

char misc_init_cvsid[] = "$Id: misc_init.c,v 1.35 2006/10/17 20:38:52 jhicks Exp $";


#include <misc.h>
#include "emrun/emsim.h"

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/time.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>

#include <emrun/emrun.h>

node_id_t my_node_id = 0;
node_id_t my_node_id_real = 0;
int am_group_id = 0;
int my_sim_group = 0;
loc_t my_loc = { 0.0, 0.0, 0.0 };
int elog_loglevel_set_on_cmdline = 0;

/******************************************************************/


static void check_versions(int *argc, char **argv, char *app_tag)
{
  /* this comes from misc_version.c */
  extern char *libmisc_tag;

  /* if the cvs tags don't match, complain! */
  if (strcmp(libmisc_tag, app_tag)) {
    printf("library tag (%s) does not match app tag (%s)!!\n", libmisc_tag, app_tag);
    printf("delete all your obj files (e.g., make clean) and rebuild!\n");
    exit(1);
  }

  /* if a -v was given on the command line, print version and exit */
  if (misc_parse_out_switch(argc, argv, "version", 'v')) {
    printf("%s release: %s\n", argv[0], app_tag);
    exit(1);
  }
}


static void configure_logging(int *argc, char **argv)
{
  char *arg;
  int orig_level = elog_loglevel;
  extern int elog_in_emrun;

  /* Test to see if we're running under emrun or not.  If not, set a
   * flag so that we do our own pretty message formatting */
  if (ioctl(STDERR_FILENO, EMRUN_IOCTL_TEST) < 0)
    elog_in_emrun = 0;
  else
    elog_in_emrun = 1;

  /* Check to see if a loglevel was passed from the environment */
  loglevel_from_env(EMSTAR_LOGLEVEL_ENVNAME, &elog_loglevel);

  /* Now see if a loglevel was passed on the command-line; takes
   * precedence over the environment variable */
  if ((arg = misc_parse_out_option(argc, argv, "stdout_loglevel", 'o')) != NULL) {
    int orig = elog_loglevel;
    if (get_loglevel_by_name(arg, &elog_loglevel) < 0)
      elog(LOG_ERR, "invalid loglevel (-o) argument: %s", arg);
    else {
      if (orig != elog_loglevel)
	elog_loglevel_set_on_cmdline = 1;
    }
  }

  if (elog_loglevel != orig_level)
    elog(LOG_INFO, "setting local loglevel filtering to %s", loglevel_name(elog_loglevel));
}


static void parse_position(char *buf)
{
  sscanf(buf, "%f %f %f", &my_loc.x, &my_loc.y, &my_loc.z);
}

/*
 * Determine our node group and ID, either by virtue of running in the
 * simulator, or from a configuration file on a real node
 */
static void get_node_id(char **argv)
{
  char buf[128], *arg;

  /* get our group id, if set */
  if ((arg = getenv("SIM_GROUP")) != NULL) {
    if ((my_sim_group = atoi(arg)) <= 0) {
      elog(LOG_EMERG, "invalid SIM_GROUP '%s' set in environment", arg);
      exit(1);
    }
    elog(LOG_DEBUG(0), "running in simulator group %d", my_sim_group);
  }

  /* get our node id */
  if ((arg = getenv("SIM_ID")) != NULL) {
    /* we're running in the simulator */
    if ((my_node_id = atoi(arg)) <= 0) {
      elog(LOG_EMERG, "invalid SIM_ID '%s' set in environment", arg);
      exit(1);
    }
    sim_init(argv[0]); /* sets in_sim = 1 */
  } else {
    /* not in sim - try to read the node's config file */
    if (read_from_file("/etc/id", buf, sizeof(buf)-1) < 0)
      elog(LOG_ERR, "can't read node id from /etc/id: %m");
    else if (sscanf(buf, "%d", &my_node_id) != 1 || my_node_id <= 0)
      elog(LOG_ERR, "invalid node id from /etc/id: '%s'", buf);

    if (read_from_file("/etc/groupid", buf, sizeof(buf)-1) < 0)
      elog(LOG_WARNING, "can't read am group id from /etc/groupid: %m, using default");
    else if (sscanf(buf, "%d", &am_group_id) != 1 || am_group_id <= 0) {
      elog(LOG_WARNING, "invalid am group id from /etc/groupid: '%s', using default", buf);
    }
  }

  /* Declaring yourself in a group is now legal, even not in sim */
  if (!in_sim && my_sim_group > 0) 
    elog(LOG_WARNING, "*** Running in non-sim grouped mode, in group %d", my_sim_group);


  /* If this node has a manually configured position (either from a
   * config file in /etc, or revealed from the simulator), then get it */
  if ((arg = getenv("SIM_LOC")) != NULL)
    parse_position(arg);
  else if (read_from_file("/etc/location", buf, sizeof(buf)-1) > 0)
    parse_position(buf);

  my_node_id_real = my_node_id;
}
      

/*
 * A place for other option checks on startup 
 */
static void check_options(int *argc, char **argv)
{
  char *opt;

  if ((opt = misc_parse_out_option(argc, argv, "startdir", 0)) != NULL)
    if (chdir(opt) < 0) {
      elog(LOG_EMERG, "can't chdir to %s: %m", opt);
      exit(1);
    }
}


/*
 * become a daemon, i.e. fork off from the shell and run in the background
 */
static void become_daemon()
{
  int fork_retval = fork();
    
  if (fork_retval < 0) {
    elog(LOG_ALERT, "couldn't fork: %m");
    exit(1);
  }

  if (fork_retval > 0) {
    /* parent: just exit */
    exit(0);
  }
    
  /* child: daemonize */
  elog_loglevel = LOG_OFF;
  // chdir("/");  (see below)
  setpgrp();
  close(0);
  close(1);
  close(2);

  /* Traditionally, unix daemons chdir to / so that they don't prevent
   * filesystems from being unmounted.  But, we will assume that
   * unmounts to happen too often in embedded systems, and the fact
   * that all the relative paths change by chdiring to / is confusing.
   * So I removed it.  --jelson 29 jan 2004 */
}


void misc_usage(char **usage, char **expl)
{
  *usage = "[-h] [-o <loglevel>] [-v] [--startdir <dir>] [--daemon] [-G <sim_group>] [-N <node_id>]";
  *expl =
    "  --help: Print this message\n"
    "  -o <loglevel>: set the default stdout loglevel\n"
    "  -v: report version information\n"
    "  --daemon: startup as a daemon (detach)\n"
    "  --startdir: chdir to <dir> before running; useful with --daemon\n"
    "  --group_id <id>: Overrides the SIM_GROUP environment variable\n"
    "  --node_id <id>:  Overrides the node ID in /etc/id or SIM_ID\n"
    "  --stop-on-startup: stop in misc_init() and wait for GDB to attach\n" 
    "  --enable-remote: make devices available over the network via FUSDNet\n"
    ;
}


void misc_print_usage(const char *proc_name, char *usage, char *expl)
{
  char *m_usage;
  char *m_expl;

  misc_usage(&m_usage, &m_expl);
  fprintf(stderr, "\nUsage: %s (%s)\n", proc_name, CVSTAG);
  fprintf(stderr, "  %s\n  %s\n\n", m_usage, usage);
  fprintf(stderr, "%s%s\n", m_expl, expl);  
}


/* process name */
static char proc_name[PATH_MAX+1];
static char *proc_name_nopath;

const char *misc_proc_name()
{
  return proc_name;
}

const char *misc_proc_name_nopath()
{
  return proc_name_nopath;
}


/*
 * Initialization common to all EmStar programs.  Configures node IDs,
 * log levels, etc.
 */
void misc_init(int *argc, char **argv, char *app_tag)
{
  struct timeval tv;
  uint32_t shift;
  int group;
  int node;

  /* save time of start of program */
  misc_time_set_start(NULL);

  /* we have to save this now, because it gets overwritten by [3] if
   * we're in simulator mode */
  strcpy(proc_name, argv[0]);
  proc_name_nopath = strrchr(proc_name, '/');
  if (proc_name_nopath) proc_name_nopath++;
  else proc_name_nopath = proc_name;

  /* Check to make sure library version matches program version; and,
   * process the -v option if it was given */
  check_versions(argc, argv, app_tag);

  /* Get loglevels from the environment and command-line options */
  configure_logging(argc, argv);

  /* Check for miscellaneous options */
  check_options(argc, argv);

  /* See if we should go into daemon mode */
  if (misc_parse_out_switch(argc, argv, "daemon", 0))
    become_daemon();

  /* are we allowing remote access? */
  if (misc_parse_out_switch(argc, argv, "enable-remote", 0)) {

    /* set global flag */
    fusdnet_export_devs = 1;

    /* warning message before blocking.. */
    elog(LOG_NOTICE, "Enabling remote access to this service... checking for fusdnet");
    if (fusd_postreg_block("fusd/net/.int") < 0) {
      elog(LOG_CRIT, "Blocking waitfor failed!  Aborting.");
      exit(1);
    }
    elog(LOG_NOTICE, "FUSDnet OK!");
  }

  /* Read node ID, group ID, and location */
  get_node_id(argv);

  /* override from command line */
  if (misc_parse_option_as_int(argc, argv, "group_id", 'G', &group) == 0) {
    my_sim_group = group;
  }
  if (misc_parse_option_as_int(argc, argv, "node_id", 'N', &node) == 0) {
    my_node_id = node;
    if (my_sim_group) in_sim = 1;
  }

  /* seed the random number generator */
  gettimeofday(&tv, NULL);
  shift = (my_node_id << 16) | (my_node_id >> 16);
  srandom(shift ^ my_node_id ^ tv.tv_usec);

  /* startup trap mode */
  if (misc_parse_out_switch(argc, argv, "stop-on-startup", 0)) {
    elog(LOG_CRIT, "PID %u (exec %s, node %d, group%d) is stopped, "
	 "waiting for you to attach via GDB!", 
	 getpid(), argv[0], my_node_id, my_sim_group);
    kill(getpid(), 19);
  }

  /* check for trap arg */
  if (misc_parse_out_switch(argc, argv, "trap", 0)) {
    setenv("EMRUN_TRAP", "1", 0);
  }
  
  /* print a startup message */
  if (in_sim) {
    if (my_node_id == SIM_COMPONENT_ID)
      elog_g(LOG_INFO, "*** starting simulator component %s (pid %d)", proc_name, getpid());
    else
      elog_g(LOG_INFO, "*** starting %s (pid %d) as SIMULATED node id %d", 
	     proc_name, getpid(), my_node_id);
  } else {
    if (my_sim_group > 0)
      elog_g(LOG_INFO, "*** starting %s (pid %d) (node id %d, group id %d)",
	   proc_name, getpid(), my_node_id, my_sim_group);
    else
      elog_g(LOG_INFO, "*** starting %s (pid %d) (node id %d)", 
	     proc_name, getpid(), my_node_id);
  }
}





See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  elog.c
  elog_emit.c
  file.c
  misc_angles.c
  misc_buf.c
  misc_crc32.c
  misc_filename.c
  misc_hash.c
  misc_init.c
  misc_lock.c
  misc_math.c
  misc_namelist.c
  misc_network.c
  misc_nmea.c
  misc_opt.c
  misc_parse.c
  misc_proc.c
  misc_random.c
  misc_ringbuff.c
  misc_serial.c
  misc_signals.c
  misc_sim.c
  misc_time.c
  misc_types.c
  misc_version.c
  string.c