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