Browse Source

Add base binary birq

Serj Kalichev 10 years ago
parent
commit
7090e2de97
4 changed files with 388 additions and 1 deletions
  1. 4 1
      Makefile.am
  2. 320 0
      birq.c
  3. 51 0
      log.c
  4. 13 0
      log.h

+ 4 - 1
Makefile.am

@@ -18,7 +18,10 @@ lib_LTLIBRARIES =
 lib_LIBRARIES =
 nobase_include_HEADERS =
 
-birq_SOURCES = birq.c
+birq_SOURCES = \
+	birq.c \
+	log.h \
+	log.c
 
 EXTRA_DIST = \
 	LICENCE \

+ 320 - 0
birq.c

@@ -0,0 +1,320 @@
+/*
+ * birq
+ *
+ * Balance IRQ
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <fcntl.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#include "log.h"
+
+#ifndef VERSION
+#define VERSION 1.0.0
+#endif
+#define QUOTE(t) #t
+#define version(v) printf("%s\n", v)
+
+#define BIRQ_PIDFILE "/var/run/birq.pid"
+
+/* Global signal vars */
+static volatile int sigterm = 0;
+static void sighandler(int signo);
+
+static void help(int status, const char *argv0);
+int daemonize(int nochdir, int noclose);
+struct options *opts_init(void);
+void opts_free(struct options *opts);
+static int opts_parse(int argc, char *argv[], struct options *opts);
+
+/* Command line options */
+struct options {
+	char *pidfile;
+	char *chroot;
+	int debug; /* Don't daemonize in debug mode */
+	int log_facility;
+};
+
+/*--------------------------------------------------------- */
+int main(int argc, char **argv)
+{
+	int retval = -1;
+	struct options *opts = NULL;
+	int pidfd = -1;
+
+	/* Signal vars */
+	struct sigaction sig_act, sigpipe_act;
+	sigset_t sig_set, sigpipe_set;
+
+	/* Parse command line options */
+	opts = opts_init();
+	if (opts_parse(argc, argv, opts))
+		goto err;
+
+	/* Initialize syslog */
+	openlog(argv[0], LOG_CONS, opts->log_facility);
+	syslog(LOG_ERR, "Start daemon.\n");
+
+	/* Fork the daemon */
+	if (!opts->debug) {
+		/* Daemonize */
+		if (daemonize(0, 0) < 0) {
+			syslog(LOG_ERR, "Can't daemonize\n");
+			goto err;
+		}
+
+		/* Write pidfile */
+		if ((pidfd = open(opts->pidfile,
+			O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
+			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
+			syslog(LOG_WARNING, "Can't open pidfile %s: %s",
+				opts->pidfile, strerror(errno));
+		} else {
+			char str[20];
+			snprintf(str, sizeof(str), "%u\n", getpid());
+			if (write(pidfd, str, strlen(str)) < 0)
+				syslog(LOG_WARNING, "Can't write to %s: %s",
+					opts->pidfile, strerror(errno));
+			close(pidfd);
+		}
+	}
+
+#ifdef HAVE_CHROOT
+	/* Chroot */
+	if (opts->chroot) {
+		if (chroot(opts->chroot) < 0) {
+			syslog(LOG_ERR, "Can't chroot to %s: %s",
+				opts->chroot, strerror(errno));
+			goto err;
+		}
+	}
+#endif
+
+	/* Set signal handler */
+	sigemptyset(&sig_set);
+	sigaddset(&sig_set, SIGTERM);
+	sigaddset(&sig_set, SIGINT);
+	sigaddset(&sig_set, SIGQUIT);
+
+	sig_act.sa_flags = 0;
+	sig_act.sa_mask = sig_set;
+	sig_act.sa_handler = &sighandler;
+	sigaction(SIGTERM, &sig_act, NULL);
+	sigaction(SIGINT, &sig_act, NULL);
+	sigaction(SIGQUIT, &sig_act, NULL);
+
+	/* Ignore SIGPIPE */
+	sigemptyset(&sigpipe_set);
+	sigaddset(&sigpipe_set, SIGPIPE);
+	sigpipe_act.sa_flags = 0;
+	sigpipe_act.sa_mask = sigpipe_set;
+	sigpipe_act.sa_handler = SIG_IGN;
+	sigaction(SIGPIPE, &sigpipe_act, NULL);
+
+
+
+
+	retval = 0;
+err:
+	/* Remove pidfile */
+	if (pidfd >= 0) {
+		if (unlink(opts->pidfile) < 0) {
+			syslog(LOG_ERR, "Can't remove pid-file %s: %s\n",
+			opts->pidfile, strerror(errno));
+		}
+	}
+
+	/* Free command line options */
+	opts_free(opts);
+
+	syslog(LOG_ERR, "Stop daemon.\n");
+
+	return retval;
+}
+
+/*--------------------------------------------------------- */
+/*
+ * Signal handler for temination signals (like SIGTERM, SIGINT, ...)
+ */
+static void sighandler(int signo)
+{
+	sigterm = 1;
+}
+
+/*--------------------------------------------------------- */
+/* Implement own simple daemon() to don't use Non-POSIX */
+int daemonize(int nochdir, int noclose)
+{
+	int fd;
+	int pid;
+
+	pid = fork();
+	if (-1 == pid)
+		return -1;
+	if (pid > 0)
+		_exit(0); /* Exit parent */
+	if (setsid() == -1)
+		return -1;
+	if (!nochdir) {
+		if (chdir("/"))
+			return -1;
+	}
+	if (!noclose) {
+		fd = open("/dev/null", O_RDWR, 0);
+		if (fd < 0)
+			return -1;
+		dup2(fd, STDIN_FILENO);
+		dup2(fd, STDOUT_FILENO);
+		dup2(fd, STDERR_FILENO);
+		if (fd > 2)
+			close(fd);
+	}
+
+	return 0;
+}
+
+/*--------------------------------------------------------- */
+/* Initialize option structure by defaults */
+struct options *opts_init(void)
+{
+	struct options *opts = NULL;
+
+	opts = malloc(sizeof(*opts));
+	assert(opts);
+	opts->debug = 0; /* daemonize by default */
+	opts->pidfile = strdup(BIRQ_PIDFILE);
+	opts->chroot = NULL;
+	opts->log_facility = LOG_DAEMON;
+
+	return opts;
+}
+
+/*--------------------------------------------------------- */
+/* Free option structure */
+void opts_free(struct options *opts)
+{
+	if (opts->pidfile)
+		free(opts->pidfile);
+	if (opts->chroot)
+		free(opts->chroot);
+	free(opts);
+}
+
+/*--------------------------------------------------------- */
+/* Parse command line options */
+static int opts_parse(int argc, char *argv[], struct options *opts)
+{
+	static const char *shortopts = "hvp:dr:O:";
+#ifdef HAVE_GETOPT_H
+	static const struct option longopts[] = {
+		{"help",	0, NULL, 'h'},
+		{"version",	0, NULL, 'v'},
+		{"pid",		1, NULL, 'p'},
+		{"debug",	0, NULL, 'd'},
+		{"chroot",	1, NULL, 'r'},
+		{"facility",	1, NULL, 'O'},
+		{NULL,		0, NULL, 0}
+	};
+#endif
+	optind = 1;
+	while(1) {
+		int opt;
+#ifdef HAVE_GETOPT_H
+		opt = getopt_long(argc, argv, shortopts, longopts, NULL);
+#else
+		opt = getopt(argc, argv, shortopts);
+#endif
+		if (-1 == opt)
+			break;
+		switch (opt) {
+		case 'p':
+			if (opts->pidfile)
+				free(opts->pidfile);
+			opts->pidfile = strdup(optarg);
+			break;
+		case 'r':
+#ifdef HAVE_CHROOT
+			if (opts->chroot)
+				free(opts->chroot);
+			opts->chroot = strdup(optarg);
+#else
+			fprintf(stderr, "Error: The --chroot option is not supported.\n");
+			return -1;
+#endif
+			break;
+		case 'd':
+			opts->debug = 1;
+			break;
+		case 'O':
+			if (parse_log_facility(optarg, &(opts->log_facility))) {
+				fprintf(stderr, "Error: Illegal syslog facility %s.\n", optarg);
+				help(-1, argv[0]);
+				exit(-1);
+			}
+			break;
+		case 'h':
+			help(0, argv[0]);
+			exit(0);
+			break;
+		case 'v':
+			version(VERSION);
+			exit(0);
+			break;
+		default:
+			help(-1, argv[0]);
+			exit(-1);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*--------------------------------------------------------- */
+/* Print help message */
+static void help(int status, const char *argv0)
+{
+	const char *name = NULL;
+
+	if (!argv0)
+		return;
+
+	/* Find the basename */
+	name = strrchr(argv0, '/');
+	if (name)
+		name++;
+	else
+		name = argv0;
+
+	if (status != 0) {
+		fprintf(stderr, "Try `%s -h' for more information.\n",
+			name);
+	} else {
+		printf("Usage: %s [options]\n", name);
+		printf("Daemon to store user configuration (i.e. commands). "
+			"The part of the klish project.\n");
+		printf("Options:\n");
+		printf("\t-v, --version\tPrint version.\n");
+		printf("\t-h, --help\tPrint this help.\n");
+		printf("\t-d, --debug\tDebug mode. Don't daemonize.\n");
+		printf("\t-p <path>, --pid=<path>\tFile to save daemon's PID to.\n");
+		printf("\t-r <path>, --chroot=<path>\tDirectory to chroot.\n");
+		printf("\t-O, --facility\tSyslog facility. Default is DAEMON.\n");
+	}
+}

+ 51 - 0
log.c

@@ -0,0 +1,51 @@
+#include "log.h"
+#include <syslog.h>
+#include <strings.h>
+
+int parse_log_facility(const char *str, int *facility)
+{
+	if (!strcasecmp(str, "local0"))
+		*facility = LOG_LOCAL0;
+	else if (!strcasecmp(str, "local1"))
+		*facility = LOG_LOCAL1;
+	else if (!strcasecmp(str, "local2"))
+		*facility = LOG_LOCAL2;
+	else if (!strcasecmp(str, "local3"))
+		*facility = LOG_LOCAL3;
+	else if (!strcasecmp(str, "local4"))
+		*facility = LOG_LOCAL4;
+	else if (!strcasecmp(str, "local5"))
+		*facility = LOG_LOCAL5;
+	else if (!strcasecmp(str, "local6"))
+		*facility = LOG_LOCAL6;
+	else if (!strcasecmp(str, "local7"))
+		*facility = LOG_LOCAL7;
+	else if (!strcasecmp(str, "auth"))
+		*facility = LOG_AUTH;
+	else if (!strcasecmp(str, "authpriv"))
+		*facility = LOG_AUTHPRIV;
+	else if (!strcasecmp(str, "cron"))
+		*facility = LOG_CRON;
+	else if (!strcasecmp(str, "daemon"))
+		*facility = LOG_DAEMON;
+	else if (!strcasecmp(str, "ftp"))
+		*facility = LOG_FTP;
+	else if (!strcasecmp(str, "kern"))
+		*facility = LOG_KERN;
+	else if (!strcasecmp(str, "lpr"))
+		*facility = LOG_LPR;
+	else if (!strcasecmp(str, "mail"))
+		*facility = LOG_MAIL;
+	else if (!strcasecmp(str, "news"))
+		*facility = LOG_NEWS;
+	else if (!strcasecmp(str, "syslog"))
+		*facility = LOG_SYSLOG;
+	else if (!strcasecmp(str, "user"))
+		*facility = LOG_USER;
+	else if (!strcasecmp(str, "uucp"))
+		*facility = LOG_UUCP;
+	else
+		return -1;
+
+	return 0;
+}

+ 13 - 0
log.h

@@ -0,0 +1,13 @@
+#ifndef _log_h
+#define _log_h
+
+#include <syslog.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+int parse_log_facility(const char *str, int *facility);
+
+#endif
+