示例#1
0
文件: sbd-cluster.c 项目: krig/sbd
int
servant_cluster(const char *diskname, int mode, const void* argp)
{
    enum cluster_type_e cluster_stack = get_cluster_type();

    crm_system_name = strdup("sbd:cluster");
    cl_log(LOG_INFO, "Monitoring %s cluster health", name_for_cluster_type(cluster_stack));
    set_proc_title("sbd: watcher: Cluster");

    sbd_membership_connect();

    /* stonith_our_uname = cluster.uname; */
    /* stonith_our_uuid = cluster.uuid; */

    mainloop = g_main_new(FALSE);
    notify_timer = g_timeout_add(timeout_loop * 1000, notify_timer_cb, NULL);

    mainloop_add_signal(SIGTERM, cluster_shutdown);
    mainloop_add_signal(SIGINT, cluster_shutdown);
    
    g_main_run(mainloop);
    g_main_destroy(mainloop);
    
    clean_up(0);
    return 0;                   /* never reached */
}
示例#2
0
/* Character generator */
void
chargen_stream (int s, struct servtab *sep)
{
  int len;
  char *rs, text[LINESIZ + 2];

  set_proc_title (sep->se_service, s);

  if (!endring)
    {
      initring ();
      rs = ring;
    }

  text[LINESIZ] = '\r';
  text[LINESIZ + 1] = '\n';
  for (rs = ring;;)
    {
      if ((len = endring - rs) >= LINESIZ)
	memmove (text, rs, LINESIZ);
      else
	{
	  memmove (text, rs, len);
	  memmove (text + len, ring, LINESIZ - len);
	}
      if (++rs == endring)
	rs = ring;
      if (write (s, text, sizeof text) != sizeof text)
	break;
    }
  exit (0);
}
示例#3
0
文件: control.c 项目: Distrotech/frox
/* ------------------------------------------------------------- **
**  Sets up the control connection to the server and initialises
**  session info.
** ------------------------------------------------------------- */
void init_session(int fd, struct sockaddr_in source)
{
	info = init_info(fd, source);

	write_log(INFO, "Connect from %s",
		  sstr_buf(addr2name(info->client_control.address.sin_addr)));

	/*FIXME have a login function which deals with ntp and cache */
	ccp_changedest();
	ntp_changedest();
	info->final_server_address = info->server_control.address;

	write_log(INFO, "... to %s(%s)",
		  inet_ntoa(info->final_server_address.sin_addr),
		  sstr_buf(info->server_name));

#ifdef ENABLE_CHANGEPROC
	set_proc_title("frox: %s <-> %s",
		       inet_ntoa(info->client_control.address.sin_addr),
		       inet_ntoa(info->final_server_address.sin_addr));
#endif
	connect_to_server();

	ntp_senduser();

	run_proxy();
}
示例#4
0
文件: sound.c 项目: Xastir/Xastir
pid_t play_sound(char *sound_cmd, char *soundfile) {
    pid_t sound_pid;
    char command[600];

    sound_pid=0;
    if (strlen(sound_cmd)>3 && strlen(soundfile)>1) {
        if (last_sound_pid==0) {

            // Create a new process to run in
            sound_pid = fork();
            if (sound_pid!=-1) {
                if(sound_pid==0) {
// This is the child process


                    // Go back to default signal handler instead of
                    // calling restart() on SIGHUP
                    (void) signal(SIGHUP,SIG_DFL);


                    // Change the name of the new child process.  So
                    // far this only works for "ps" listings, not
                    // for "top".  This code only works on Linux.
                    // For BSD use setproctitle(3), NetBSD can use
                    // setprogname(2).
#ifdef __linux__
                    init_set_proc_title(my_argc, my_argv, my_envp);
                    set_proc_title("%s", "festival process (xastir)");
                    //fprintf(stderr,"DEBUG: %s\n", Argv[0]);
#endif  // __linux__


                    xastir_snprintf(command,
                        sizeof(command),
                        "%s %s/%s",
                        sound_cmd,
                        SOUND_DIR,
                        soundfile);

                    if (system(command) != 0) {}  // We don't care whether it succeeded
                    exit(0);    // Exits only this process, not Xastir itself
                }
                else {
// This is the parent process
                    last_sound_pid=sound_pid;
                }
            } else
                fprintf(stderr,"Error! trying to play sound\n");
        } else {
            sound_pid=last_sound_pid;
            /*fprintf(stderr,"Sound already running\n");*/
        }
    }
    return(sound_pid);
}
示例#5
0
/* Echo service -- echo data back */
void
echo_stream (int s, struct servtab *sep)
{
  char buffer[BUFSIZE];
  int i;

  set_proc_title (sep->se_service, s);
  while ((i = read (s, buffer, sizeof buffer)) > 0
	 && write (s, buffer, i) > 0)
    ;
  exit (0);
}
示例#6
0
文件: enter.c 项目: avagin/vzctl
static int pty_alloc(int *master, int *slave, struct termios *tios,
	struct winsize *ws)
{
	char name[PATH_MAX];

	if (openpty(master, slave, name, tios, ws) < 0) {
		logger(-1, errno, "Unable to open pty");
		return -1;
	}
	set_proc_title(name);
	logger(2, 0, "Open %s", name);
	return 0;
}
示例#7
0
/* Discard service -- ignore data */
void
discard_stream (int s, struct servtab *sep)
{
  int ret;
  char buffer[BUFSIZE];

  set_proc_title (sep->se_service, s);
  while (1)
    {
      while ((ret = read (s, buffer, sizeof buffer)) > 0)
	;
      if (ret == 0 || errno != EINTR)
	break;
    }
  exit (0);
}
示例#8
0
文件: client.c 项目: jorik041/alexjlz
int main(int argc, char **argv)
{
    alexjlz_log(1, "client started:%s\n", uuid);
    generate_uuid();
    alexjlz_log(1, "uuid generated:%s\n", uuid);
    getOurIP();
    srand(time(NULL) ^ getpid());
    init_rand(time(NULL) ^ getpid());
    set_proc_title(argc, argv, PROC_TITLE);
    alexjlz_log(1, "set proc title success\n");

    while (1)
    {
        if ( daemonize() == 0 )
            break;
        alexjlz_log(3, "daemonize failed\n");
        sleep(3);
    }
    alexjlz_log(3, "daemonize success\n");
    while ( 1 )
    {
        if( (mainCommSock=connect_tcp_server(server, port)) == -1)
        {
            alexjlz_log(3, "connect to server failed\n");
            sleep(5);
            continue;
        }
        alexjlz_log(3, "connect to server success\n");
        if ( ask_for_service( mainCommSock ) == -1 )  // return from this function means connection between client
            // and server are unexpectedly closed
        {
            //fprintf(stdout, "error in client\n");
        }

        if ( check_fd(mainCommSock) )
        {
            close(mainCommSock);
        }
        sleep(3);
    }

    return 0;
}
示例#9
0
int
main(int argc, char** argv, char** envp)
{

	int			c;
	gboolean		daemonize = FALSE;
	gboolean		stop_logd = FALSE;
	gboolean		ask_status= FALSE;
	const char*		cfgfile = NULL;
	pid_t			pid;
	
	cmdname = argv[0];
	while ((c = getopt(argc, argv, "c:dksvh")) != -1){

		switch(c){
			
		case 'd':	/* daemonize */
			daemonize = TRUE;
			break;
		case 'k':	/* stop */
			stop_logd = TRUE;
			break;
		case 's':	/* status */
			ask_status = TRUE;
			break;
		case 'c':	/* config file*/
			cfgfile = optarg;
			break;
		case 'v':
			verbose = TRUE;
			break;
		case 'h':	/*help message */
		default:
			usage();
			exit(1);
		}
		
	}
	
	set_ipc_time_debug_flag(FALSE);
	cl_log_set_uselogd(FALSE);

	if (!cfgfile && access(DEFAULT_CFG_FILE, F_OK) == 0) {
		cfgfile = DEFAULT_CFG_FILE;
	}
	

	/* default one set to "logd"
	 * by setting facility, we enable syslog
	 */
	cl_log_enable_stderr(TRUE);
	cl_log_set_entity(logd_config.entity);
	cl_log_set_facility(logd_config.log_facility);
	
	
	if (ask_status){
		long pid;
		
		if( (pid = cl_read_pidfile(LOGD_PIDFILE)) > 0 ){
			printf("logging daemon is running [pid = %ld].\n", pid);
			exit(LSB_EXIT_OK);
		}else{
			if (pid ==  - LSB_STATUS_VAR_PID) {
				printf("logging daemon is stopped: %s exists.\n"
				       ,	LOGD_PIDFILE);
			}else{
				printf("logging daemon is stopped.\n");
			}
		}
		exit(-pid);
		
	}
	if (stop_logd){
		logd_stop();
		exit(LSB_EXIT_OK);
	}

	logd_make_daemon(daemonize);

	
	if (ipc_channel_pair(chanspair) != IPC_OK){
		cl_perror("cannot create channel pair IPC");
		return -1;
	}
	
	
	if (cfgfile && !parse_config(cfgfile)) {
		FILE* f;
		if ((f = fopen(cfgfile, "r")) != NULL){
			fclose(f);
			cl_log(LOG_ERR, "Config file [%s] is incorrect."
			       ,	cfgfile);
			exit(LSB_EXIT_NOTCONFIGED);
		}
	}
	
	if (strlen(logd_config.debugfile) > 0) {
		cl_log_set_debugfile(logd_config.debugfile);
	}
	if (strlen(logd_config.logfile) > 0) {
		cl_log_set_logfile(logd_config.logfile);
	}
	cl_log_set_syslogprefix(logd_config.syslogprefix);
	cl_log_set_entity(logd_config.entity);
	cl_log_set_facility(logd_config.log_facility);
	
	cl_log(LOG_INFO, "logd started with %s.",
	       cfgfile ? cfgfile : "default configuration");

	if (cl_enable_coredumps(TRUE) < 0){
		cl_log(LOG_ERR, "enabling core dump failed");
	}
	cl_cdtocoredir();

	

	
	chanspair[WRITE_PROC_CHAN]->ops->set_recv_qlen(chanspair[WRITE_PROC_CHAN],
						  LOGD_QUEUE_LEN);
	
	chanspair[READ_PROC_CHAN]->ops->set_send_qlen(chanspair[READ_PROC_CHAN],
						 LOGD_QUEUE_LEN);
	
	if (init_set_proc_title(argc, argv, envp) < 0) {
		cl_log(LOG_ERR, "Allocation of proc title failed.");
                return -1;
        }

	switch(pid = fork()){
	case -1:	
		cl_perror("Can't fork child process!");
		return -1;
	case 0:
		/*child*/
		cl_log_use_buffered_io(1);
		set_proc_title("ha_logd: write process");
		write_msg_process(chanspair[WRITE_PROC_CHAN]);		
		break;
	default:
		/*parent*/
		set_proc_title("ha_logd: read process");
		write_process_pid = pid;
		/* we don't expect to log anything in the parent. */
		cl_log_close_log_files();

		read_msg_process(chanspair[READ_PROC_CHAN]);
		break;
	}
	return 0;
}
示例#10
0
文件: sbd-md.c 项目: credativ/sbd
int servant(const char *diskname, int mode, const void* argp)
{
	struct sector_mbox_s *s_mbox = NULL;
	struct sector_node_s *s_node = NULL;
	struct sector_header_s	*s_header = NULL;
	int mbox;
	int rc = 0;
	time_t t0, t1, latency;
	union sigval signal_value;
	sigset_t servant_masks;
	struct sbd_context *st;
	pid_t ppid;
	char uuid[37];
	const struct servants_list_item *s = argp;

	if (!diskname) {
		cl_log(LOG_ERR, "Empty disk name %s.", diskname);
		return -1;
	}

	cl_log(LOG_INFO, "Servant starting for device %s", diskname);

	/* Block most of the signals */
	sigfillset(&servant_masks);
	sigdelset(&servant_masks, SIGKILL);
	sigdelset(&servant_masks, SIGFPE);
	sigdelset(&servant_masks, SIGILL);
	sigdelset(&servant_masks, SIGSEGV);
	sigdelset(&servant_masks, SIGBUS);
	sigdelset(&servant_masks, SIGALRM);
	/* FIXME: check error */
	sigprocmask(SIG_SETMASK, &servant_masks, NULL);

	atexit(servant_exit);
	servant_inform_parent = 1;

	st = open_device(diskname, LOG_WARNING);
	if (!st) {
		return -1;
	}

	s_header = header_get(st);
	if (!s_header) {
		cl_log(LOG_ERR, "Not a valid header on %s", diskname);
		return -1;
	}

	if (servant_check_timeout_inconsistent(s_header) < 0) {
		cl_log(LOG_ERR, "Timeouts on %s do not match first device",
				diskname);
		return -1;
	}

	if (s_header->minor_version > 0) {
		uuid_unparse_lower(s_header->uuid, uuid);
		cl_log(LOG_INFO, "Device %s uuid: %s", diskname, uuid);
	}

	mbox = slot_allocate(st, local_uname);
	if (mbox < 0) {
		cl_log(LOG_ERR,
		       "No slot allocated, and automatic allocation failed for disk %s.",
		       diskname);
		rc = -1;
		goto out;
	}
	s_node = sector_alloc();
	if (slot_read(st, mbox, s_node) < 0) {
		cl_log(LOG_ERR, "Unable to read node entry on %s",
				diskname);
		exit(1);
	}

	DBGLOG(LOG_INFO, "Monitoring slot %d on disk %s", mbox, diskname);
	if (s_header->minor_version == 0) {
		set_proc_title("sbd: watcher: %s - slot: %d", diskname, mbox);
	} else {
		set_proc_title("sbd: watcher: %s - slot: %d - uuid: %s",
				diskname, mbox, uuid);
	}

	s_mbox = sector_alloc();
	if (s->first_start) {
		if (mode > 0) {
			if (mbox_read(st, mbox, s_mbox) < 0) {
				cl_log(LOG_ERR, "mbox read failed during start-up in servant.");
				rc = -1;
				goto out;
			}
			if (s_mbox->cmd != SBD_MSG_EXIT &&
					s_mbox->cmd != SBD_MSG_EMPTY) {
				/* Not a clean stop. Abort start-up */
				cl_log(LOG_WARNING, "Found fencing message - aborting start-up. Manual intervention required!");
				ppid = getppid();
				sigqueue(ppid, SIG_EXITREQ, signal_value);
				rc = 0;
				goto out;
			}
		}
		DBGLOG(LOG_INFO, "First servant start - zeroing inbox");
		memset(s_mbox, 0, sizeof(*s_mbox));
		if (mbox_write(st, mbox, s_mbox) < 0) {
			rc = -1;
			goto out;
		}
	}

	memset(&signal_value, 0, sizeof(signal_value));

	while (1) {
		struct sector_header_s	*s_header_retry = NULL;
		struct sector_node_s	*s_node_retry = NULL;

		t0 = time(NULL);
		sleep(timeout_loop);

		ppid = getppid();

		if (ppid == 1) {
			/* Our parent died unexpectedly. Triggering
			 * self-fence. */
			do_reset();
		}

		/* These attempts are, by definition, somewhat racy. If
		 * the device is wiped out or corrupted between here and
		 * us reading our mbox, there is nothing we can do about
		 * that. But at least we tried. */
		s_header_retry = header_get(st);
		if (!s_header_retry) {
			cl_log(LOG_ERR, "No longer found a valid header on %s", diskname);
			exit(1);
		}
		if (memcmp(s_header, s_header_retry, sizeof(*s_header)) != 0) {
			cl_log(LOG_ERR, "Header on %s changed since start-up!", diskname);
			exit(1);
		}
		free(s_header_retry);

		s_node_retry = sector_alloc();
		if (slot_read(st, mbox, s_node_retry) < 0) {
			cl_log(LOG_ERR, "slot read failed in servant.");
			exit(1);
		}
		if (memcmp(s_node, s_node_retry, sizeof(*s_node)) != 0) {
			cl_log(LOG_ERR, "Node entry on %s changed since start-up!", diskname);
			exit(1);
		}
		free(s_node_retry);

		if (mbox_read(st, mbox, s_mbox) < 0) {
			cl_log(LOG_ERR, "mbox read failed in servant.");
			exit(1);
		}

		if (s_mbox->cmd > 0) {
			cl_log(LOG_INFO,
			       "Received command %s from %s on disk %s",
			       char2cmd(s_mbox->cmd), s_mbox->from, diskname);

			switch (s_mbox->cmd) {
			case SBD_MSG_TEST:
				memset(s_mbox, 0, sizeof(*s_mbox));
				mbox_write(st, mbox, s_mbox);
				sigqueue(ppid, SIG_TEST, signal_value);
				break;
			case SBD_MSG_RESET:
				do_reset();
				break;
			case SBD_MSG_OFF:
				do_off();
				break;
			case SBD_MSG_EXIT:
				sigqueue(ppid, SIG_EXITREQ, signal_value);
				break;
			case SBD_MSG_CRASHDUMP:
				do_crashdump();
				break;
			default:
				/* FIXME:
				   An "unknown" message might result
				   from a partial write.
				   log it and clear the slot.
				 */
				cl_log(LOG_ERR, "Unknown message on disk %s",
				       diskname);
				memset(s_mbox, 0, sizeof(*s_mbox));
				mbox_write(st, mbox, s_mbox);
				break;
			}
		}
		sigqueue(ppid, SIG_LIVENESS, signal_value);

		t1 = time(NULL);
		latency = t1 - t0;
		if (timeout_watchdog_warn && (latency > timeout_watchdog_warn)) {
			cl_log(LOG_WARNING,
			       "Latency: %d exceeded threshold %d on disk %s",
			       (int)latency, (int)timeout_watchdog_warn,
			       diskname);
		} else if (debug) {
			DBGLOG(LOG_INFO, "Latency: %d on disk %s", (int)latency,
			       diskname);
		}
	}
 out:
	free(s_mbox);
	close_device(st);
	if (rc == 0) {
		servant_inform_parent = 0;
	}
	return rc;
}
示例#11
0
文件: main.c 项目: inouekazu/booth
static int do_server(int type)
{
	int rv = -1;
	static char log_ent[128] = DAEMON_NAME "-";

	rv = setup_config(type);
	if (rv < 0)
		return rv;

	if (!local) {
		log_error("Cannot find myself in the configuration.");
		exit(EXIT_FAILURE);
	}

	if (daemonize) {
		if (daemon(0, 0) < 0) {
			perror("daemon error");
			exit(EXIT_FAILURE);
		}
	}

	/* The lockfile must be written to _after_ the call to daemon(), so
	 * that the lockfile contains the pid of the daemon, not the parent. */
	lock_fd = create_lockfile();
	if (lock_fd < 0)
		return lock_fd;

	atexit(server_exit);

	strcat(log_ent, type_to_string(local->type));
	cl_log_set_entity(log_ent);
	cl_log_enable_stderr(enable_stderr ? TRUE : FALSE);
	cl_log_set_facility(HA_LOG_FACILITY);
	cl_inherit_logging_environment(0);

	log_info("BOOTH %s %s daemon is starting",
			type_to_string(local->type), RELEASE_STR);

	signal(SIGUSR1, (__sighandler_t)tickets_log_info);
	signal(SIGTERM, (__sighandler_t)sig_exit_handler);
	signal(SIGINT, (__sighandler_t)sig_exit_handler);
	/* we'll handle errors there and then */
	signal(SIGPIPE, SIG_IGN);

	set_scheduler();
	/* we don't want to be killed by the OOM-killer */
	if (set_procfs_val("/proc/self/oom_score_adj", "-999"))
		(void)set_procfs_val("/proc/self/oom_adj", "-16");
	set_proc_title("%s %s %s for [%s]:%d",
			DAEMON_NAME,
			cl.configfile,
			type_to_string(local->type),
			local->addr_string,
			booth_conf->port);

	rv = limit_this_process();
	if (rv)
		return rv;

#ifdef COREDUMP_NURSING
	if (cl_enable_coredumps(TRUE) < 0){
		log_error("enabling core dump failed");
	}
	cl_cdtocoredir();
	prctl(PR_SET_DUMPABLE, (unsigned long)TRUE, 0UL, 0UL, 0UL);
#else
	if (chdir(BOOTH_CORE_DIR) < 0) {
		log_error("cannot change working directory to %s", BOOTH_CORE_DIR);
	}
#endif

	signal(SIGCHLD, (__sighandler_t)wait_child);
	rv = loop(lock_fd);

	return rv;
}
示例#12
0
文件: main.c 项目: Ferritt1975/booth
static int do_server(int type)
{
	int rv = -1;
	static char log_ent[128] = DAEMON_NAME "-";

	rv = setup_config(type);
	if (rv < 0)
		return rv;


	if (!local) {
		log_error("Cannot find myself in the configuration.");
		exit(EXIT_FAILURE);
	}

	if (!daemonize) {
		if (daemon(0, 0) < 0) {
			perror("daemon error");
			exit(EXIT_FAILURE);
		}
	}

	/* The lockfile must be written to _after_ the call to daemon(), so
	 * that the lockfile contains the pid of the daemon, not the parent. */
	lock_fd = create_lockfile();
	if (lock_fd < 0)
		return lock_fd;

	atexit(server_exit);

	strcat(log_ent, type_to_string(local->type));
	cl_log_set_entity(log_ent);
	cl_log_enable_stderr(enable_stderr ? TRUE : FALSE);
	cl_log_set_facility(HA_LOG_FACILITY);
	cl_inherit_logging_environment(0);

	log_info("BOOTH %s %s daemon is starting",
			type_to_string(local->type), RELEASE_STR);

	signal(SIGUSR1, (__sighandler_t)tickets_log_info);
	signal(SIGTERM, (__sighandler_t)sig_exit_handler);
	signal(SIGINT, (__sighandler_t)sig_exit_handler);

	set_scheduler();
	set_oom_adj(-16);
	set_proc_title("%s %s %s for [%s]:%d",
			DAEMON_NAME,
			cl.configfile,
			type_to_string(local->type),
			local->addr_string,
			booth_conf->port);

	rv = limit_this_process();
	if (rv)
		return rv;

	if (cl_enable_coredumps(TRUE) < 0){
		cl_log(LOG_ERR, "enabling core dump failed");
	}
	cl_cdtocoredir();
	prctl(PR_SET_DUMPABLE, (unsigned long)TRUE, 0UL, 0UL, 0UL);

	rv = loop(lock_fd);

	return rv;
}
示例#13
0
int
servant_pcmk(const char *diskname, int mode, const void* argp)
{
	int exit_code = 0;
	crm_cluster_t crm_cluster;

	cl_log(LOG_INFO, "Monitoring Pacemaker health");
	set_proc_title("sbd: watcher: Pacemaker");
        setenv("PCMK_watchdog", "true", 1);

        if(debug == 0) {
            /* We don't want any noisy crm messages */
            set_crm_log_level(LOG_CRIT);
        }

#ifdef SUPPORT_PLUGIN
	cluster_stack = get_cluster_type();

	if (cluster_stack != pcmk_cluster_classic_ais) {
		check_ais = 0;
	} else {
		check_ais = 1;
		cl_log(LOG_INFO, "Legacy plug-in detected, AIS quorum check enabled");
		if(is_openais_cluster()) {
		    crm_cluster.destroy = ais_membership_destroy;
		    crm_cluster.cpg.cpg_deliver_fn = ais_membership_dispatch;
		    /* crm_cluster.cpg.cpg_confchg_fn = pcmk_cpg_membership; TODO? */
		    crm_cluster.cpg.cpg_confchg_fn = NULL;
		}

		while (!crm_cluster_connect(&crm_cluster)) {
			cl_log(LOG_INFO, "Waiting to sign in with cluster ...");
			sleep(reconnect_msec / 1000);
		}
	}
#endif

	if (current_cib == NULL) {
		cib = cib_new();

		do {
			exit_code = cib_connect(TRUE);

			if (exit_code != 0) {
				sleep(reconnect_msec / 1000);
			}
		} while (exit_code == -ENOTCONN);

		if (exit_code != 0) {
			clean_up(-exit_code);
		}
	}

	mainloop = g_main_new(FALSE);

	mainloop_add_signal(SIGTERM, mon_shutdown);
	mainloop_add_signal(SIGINT, mon_shutdown);
	timer_id_notify = g_timeout_add(timeout_loop * 1000, mon_timer_notify, NULL);
#ifdef SUPPORT_PLUGIN
	if (check_ais) {
		timer_id_ais = g_timeout_add(timeout_loop * 1000, mon_timer_ais, NULL);
	}
#endif

	g_main_run(mainloop);
	g_main_destroy(mainloop);

	clean_up(0);
	return 0;                   /* never reached */
}
示例#14
0
文件: lmsd.c 项目: piotrbaran2/lms
int main(int argc, char *argv[], char **envp)
{
	QueryHandle *res;
	time_t tt;
	GLOBAL *g;
	INSTANCE *instances;
	int fval = 0, i = 0, reload = 0;
	char *inst, *instance; 
	FILE *pidf;
	openlog(PROGNAME, 0, LOG_INFO | LOG_CRIT | LOG_ERR);
	syslog(LOG_INFO, "LMS Daemon started.");

        // initialize global structure
        g = (GLOBAL *) realloc(NULL, sizeof(GLOBAL));
        g->api_version = APIVERSION;
        g->db = (DB *) realloc(NULL, sizeof(DB));
        g->db->conn = NULL;

	// initialize proces name change 
	init_set_proc_title(argc, argv, envp);

        // configuration load sequence - check if LMSini is set
        configfile = ( getenv("LMSINI") ? getenv("LMSINI") : "/etc/lms/lms.ini" );

    	// read environment and command line
	driver = ( getenv("LMSDBTYPE") ? getenv("DBTYPE") : strdup("mysql") );
	passwd = ( getenv("LMSDBPASS") ? getenv("LMSDBPASS") : "" );
	dbname = ( getenv("LMSDBNAME") ? getenv("LMSDBNAME") : "lms" );
	user = ( getenv("LMSDBUSER") ? getenv("LMSDBUSER") : "lms" );
	port = ( getenv("LMSDBPORT") ? atoi(getenv("LMSDBPORT")) : 0 );
	if( getenv("LMSDBHOST") ) strcpy(host, getenv("LMSDBHOST")); else strcpy(host, "localhost");
	gethostname(dhost, 255);

	// date/time localization according to environement settings
	setlocale(LC_TIME, "");
	
	// command line arguments
	parse_command_line(argc, argv);

        // load configuration file if exist (if not it will use default parameters - only database section)
        ini = config_load(configfile, g->db, dhost, "database");
        // assign variables
        driver = config_getstring(ini, "database", "type", driver);
        passwd = config_getstring(ini, "database", "password", passwd);
        dbname = config_getstring(ini, "database", "database", dbname);
        user = config_getstring(ini, "database", "user", user);
        port = config_getint(ini, "database", "port", port);
        strcpy(host, config_getstring(ini, "database", "host", host));

	// change process name (hide command line args)
	set_proc_title(PROGNAME);

        str_replace(&driver, "postgres", "pgsql"); // postgres in ini file is pgsql
        str_replace(&driver, "mysqli", "mysql");   // mysqli in ini file is mysql

        char dbdrv_path[strlen(LMS_LIB_DIR) + strlen(driver) + 4];
        sprintf(dbdrv_path, LMS_LIB_DIR "/%s.so", driver);

        if( !file_exists(dbdrv_path))
        {
                syslog(LOG_CRIT, "Database driver '%s' does not exist. Could not find '%s'.", driver, dbdrv_path);
                fprintf(stderr, "Database driver '%s' does not exist. Could not find '%s'.\n", driver, dbdrv_path);
                exit(1);
        }

        void    *dbdrv;
        dbdrv = dlopen(dbdrv_path, RTLD_NOW);

        if( !dbdrv )
        {
                char * errMsg = dlerror();
                syslog(LOG_CRIT, "Unable to load database driver '%s': %s", dbdrv_path, errMsg);
                fprintf(stderr, "Unable to load database driver '%s': %s.\n", dbdrv_path, errMsg);
                exit(1);
        }
        else
        {
                syslog(LOG_INFO, "Database driver '%s' loaded.", driver);
        }

	g->db->connect = dlsym(dbdrv, "db_connect");
	g->db->disconnect = dlsym(dbdrv, "db_disconnect");
   	g->db->query = dlsym(dbdrv, "db_query");
	g->db->pquery = dlsym(dbdrv, "db_pquery");
    	g->db->exec = dlsym(dbdrv, "db_exec");
	g->db->pexec = dlsym(dbdrv, "db_pexec");
	g->db->last_insert_id = dlsym(dbdrv, "db_last_insert_id");
	g->db->free = dlsym(dbdrv, "db_free");
    	g->db->begin = dlsym(dbdrv, "db_begin");
    	g->db->commit = dlsym(dbdrv, "db_commit");
	g->db->abort = dlsym(dbdrv, "db_abort");
    	g->db->get_data = dlsym(dbdrv, "db_get_data");
	g->db->nrows = dlsym(dbdrv, "db_nrows");
	g->db->ncols = dlsym(dbdrv, "db_ncols");
	g->db->concat = dlsym(dbdrv, "db_concat");
	g->db->escape = dlsym(dbdrv, "db_escape");
	g->db->colname = dlsym(dbdrv, "db_colname");

        // test database connection
        if( !(g->db->conn = g->db->connect(dbname,user,passwd,host,port,ssl)) )
        {
                fprintf(stderr, "CRITICAL: Could not connect to database. See logs for details.\n");
                termination_handler(1);
        }
        res = g->db->pquery(g->db->conn, "SELECT count(*) FROM dbinfo");
        if( ! g->db->nrows(res) )
        {
                fprintf(stderr, "CRITICAL: Could not query database. See logs for details.\n");
                termination_handler(1);
        }
        g->db->free(&res);
        g->db->disconnect(g->db->conn);


    	g->str_replace = &str_replace;
    	g->str_save = &str_save;
    	g->str_concat = &str_concat;
	g->str_lwc = &str_lwc;
	g->str_upc = &str_upc;
	g->va_list_join = &va_list_join;

    	g->config_getstring = &config_getstring;
	g->config_getint = &config_getint;
	g->config_getbool = &config_getbool;
	g->config_getdouble = &config_getdouble;

	// catch SIGCHLD to catch zombies
	sa.sa_handler = sig_child;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(SIGCHLD, &sa, &orig);

    	// daemonize
    	if ( !quit && !dontfork )
	{
		fval = fork();
        	switch(fval) 
		{
			case -1:
    	    			fprintf(stderr, "Fork error. Exiting.");
            			termination_handler(1);
        		case 0:
				setsid();
				break;
			default:
#ifdef DEBUG1	
	    			syslog(LOG_INFO, "DEBUG: [lmsd] Daemonize. Forked child %d.", fval);
#endif
				if (pidfile != NULL && (pidf = fopen(pidfile, "w")) != NULL)
				{
				    fprintf(pidf, "%d", fval);
				    fclose(pidf);
				}
            			exit(0); // parent exits
        	}
    	}

    	// termination signals handling
    	signal(SIGINT, termination_handler);
    	signal(SIGTERM, termination_handler);

    	// main loop ****************************************************
    	for(;;)
	{
		int i_no = 0;
		
		if( quit ) 
		{
			reload = 1;
			tt = time(0);
		}
		else // daemon mode
		{
			reload = 0;
			tt = cron_sync_sleep();
		}

		// run shell command, i.e. secure connections tuneling
		if( command!=NULL )
		{
#ifdef DEBUG1
			syslog(LOG_INFO, "DEBUG: [lmsd] Executing command: %s.", command);
#endif
			system(command);
		}

		// try to connect to database
		if( !(g->db->conn = g->db->connect(dbname,user,passwd,host,port,ssl)) )
		{
			if( quit ) termination_handler(1);
			continue;
		}

		if( !reload )
		{
			// check reload order
			res = g->db->pquery(g->db->conn, "SELECT reload FROM hosts WHERE name = '?' AND reload != 0", dhost);
			if( g->db->nrows(res) )
			{
				reload = 1;
			}
			g->db->free(&res);
		}
		
		instances = (INSTANCE *) malloc(sizeof(INSTANCE));
		
		// get instances list even if reload == 0
		// maybe we should do that once before main loop, but in
		// this way we can change configuration without daemon restart
		if( iopt ) // from command line...
		{
			inst = strdup(iopt);
			for( instance=strtok(inst," "); instance!=NULL; instance=strtok(NULL, " ") )
			{
				char *name = strdup(instance);
				str_replace(&name, "\\s", " "); // instance name with spaces
				
				res = g->db->pquery(g->db->conn, "SELECT module, crontab FROM daemoninstances, hosts WHERE hosts.id = hostid AND disabled = 0 AND hosts.name = '?' AND daemoninstances.name = '?'", dhost, name);
				if( g->db->nrows(res) )
				{
					char *crontab = g->db->get_data(res, 0, "crontab");
					if( runall || (reload && !strlen(crontab)) || (!quit && crontab_match(tt, crontab)) )
					{
						instances = (INSTANCE *) realloc(instances, sizeof(INSTANCE)*(i_no+1));
						instances[i_no].name = strdup(name);
						instances[i_no].module = strdup(g->db->get_data(res, 0, "module"));
						instances[i_no].crontab = strdup(crontab);
						i_no++;
					}
				} else {
					syslog(LOG_CRIT, "Host '%s' and/or instance '%s' not found in database!", dhost, name);
					fprintf(stderr, "Host '%s' and/or instance '%s' not found in database!\n", dhost, name);
                                }
				g->db->free(&res);
				free(name);
			}
			free(inst);	
		}		
		else // ... or from database
		{
			res = g->db->pquery(g->db->conn, "SELECT module, crontab, daemoninstances.name AS name FROM daemoninstances, hosts WHERE hosts.id = hostid AND disabled = 0 AND hosts.name = '?' ORDER BY priority", dhost);
			for(i=0; i<g->db->nrows(res); i++)
			{
				char *crontab = g->db->get_data(res, i, "crontab");
				if( runall || (reload && !strlen(crontab)) || (!quit && crontab_match(tt, crontab)) )
				{
					instances = (INSTANCE *) realloc(instances, sizeof(INSTANCE)*(i_no+1));
					instances[i_no].name = strdup(g->db->get_data(res, i, "name"));
					instances[i_no].module = strdup(g->db->get_data(res, i, "module"));
					instances[i_no].crontab = strdup(crontab);
					i_no++;
				}
			}
			g->db->free(&res);
		}
		g->db->disconnect(g->db->conn);

		if( i_no )
		{
			// forking reload - we can do a job for longer than one minute
			if( quit )
				fval = 0; // don't fork in "quit mode"
			else
				fval = fork();
			
			if( fval < 0 ) 
			{
        			syslog(LOG_CRIT, "Fork error. Can't reload.");
				if ( quit ) termination_handler(1);
			}
			else if( fval == 0 ) // child or "quit mode"
			{
				set_proc_title(PROGNAME": reload");

				// restore old handler so we can wait for childs executed by modules
				if( !quit )
					sigaction(SIGCHLD, &orig, NULL);
#ifdef DEBUG1
				syslog(LOG_INFO, "DEBUG: [lmsd] Reloading...");
#endif
				// try to connect to database again
				if( !(g->db->conn = g->db->connect(dbname,user,passwd,host,port,ssl)) )
				{
					if( quit ) 
						termination_handler(1);
					else 
						exit(1);
				}
				
				// write reload timestamp and disable reload order
				if( reload )
					g->db->pexec(g->db->conn, "UPDATE hosts SET lastreload = %NOW%, reload = 0 WHERE name = '?'", dhost);
				
				for(i=0; i<i_no; i++)
				{
					MODULE *m;
					MODULE *mod = (MODULE*) malloc(sizeof(MODULE));
					MODULE * (*init)(GLOBAL *, MODULE *);

					char path[strlen(LMS_LIB_DIR) + strlen(instances[i].module) + 4];
			
					// get instance configuration and members
					mod->ini = config_load(configfile, g->db, dhost, instances[i].name);
					mod->instance = strdup(instances[i].name);
					
					// set path to module if not specified
					// be sure that it has .so extension
					str_replace(&instances[i].module, ".so", "");
					
					if( instances[i].module[0] == '/' )
						sprintf(path, "%s.so", instances[i].module);
					else
						sprintf(path, LMS_LIB_DIR "/%s.so", instances[i].module);
					
					mod->file = strdup(path);

					// try to load module
					mod->dlh = dlopen(mod->file, RTLD_NOW);
					if( !mod->dlh ) 
					{
						syslog(LOG_ERR, "Unable to load module '%s': %s", mod->file, dlerror());
						free_module(mod);
						continue;
					}

					// initialize module
					init = dlsym(mod->dlh, "init");
					if( !init ) 
					{
						syslog(LOG_CRIT, "Unable to find initialization function in module '%s'. Is that file really a lmsd module?", mod->file);
						free_module(mod);
						continue;
					}
				
					if( !(m = init(g, mod)))
					{
						syslog(LOG_CRIT, "Unable to initialize module '%s'. Perhaps there is a version mismatch?", mod->file);
						free_module(mod);
						continue;
					}

					syslog(LOG_INFO, "Running module: %s", instances[i].module);
					// now run module
					m->reload(g, m);
					
					// cleanup
					free_module(m);
				}
				
				g->db->disconnect(g->db->conn);
	
				// exit child (reload) thread
				if( !quit ) 
				{
#ifdef DEBUG1
					syslog(LOG_INFO, "DEBUG: [lmsd] Reload finished. Exiting child.");
#endif
					exit(0);
				}
			}
			else 
				sleep(10); // it's important to sleep parent for some time
			
			for(i=0; i<i_no; i++)
			{ 
				free(instances[i].name);
				free(instances[i].module);
				free(instances[i].crontab);
			}
		}

		if( quit ) termination_handler(0);
		
		free(instances);
		
    	} // end of loop **********************************************
	return 0;
}