birq.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * birq
  3. *
  4. * Balance IRQ
  5. *
  6. */
  7. #ifdef HAVE_CONFIG_H
  8. #include "config.h"
  9. #endif /* HAVE_CONFIG_H */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <sys/types.h>
  14. #include <errno.h>
  15. #include <assert.h>
  16. #include <string.h>
  17. #include <signal.h>
  18. #include <syslog.h>
  19. #include <fcntl.h>
  20. #ifdef HAVE_GETOPT_H
  21. #include <getopt.h>
  22. #endif
  23. #include <sys/poll.h>
  24. #include <sys/socket.h>
  25. #include <linux/types.h>
  26. #include <linux/netlink.h>
  27. #include "lub/log.h"
  28. #include "nl.h"
  29. #ifndef VERSION
  30. #define VERSION 1.0.0
  31. #endif
  32. #define QUOTE(t) #t
  33. #define version(v) printf("%s\n", v)
  34. #define BIRQ_PIDFILE "/var/run/birq.pid"
  35. /* Global signal vars */
  36. static volatile int sigterm = 0;
  37. static void sighandler(int signo);
  38. static void help(int status, const char *argv0);
  39. static struct options *opts_init(void);
  40. static void opts_free(struct options *opts);
  41. static int opts_parse(int argc, char *argv[], struct options *opts);
  42. /* Command line options */
  43. struct options {
  44. char *pidfile;
  45. int debug; /* Don't daemonize in debug mode */
  46. int log_facility;
  47. };
  48. /*--------------------------------------------------------- */
  49. int main(int argc, char **argv)
  50. {
  51. int retval = -1;
  52. struct options *opts = NULL;
  53. int pidfd = -1;
  54. int rescan = 0; /* sysfs rescan needed */
  55. /* Signal vars */
  56. struct sigaction sig_act;
  57. sigset_t sig_set;
  58. /* NetLink vars */
  59. int nl = -1; /* NetLink socket */
  60. /* Parse command line options */
  61. opts = opts_init();
  62. if (opts_parse(argc, argv, opts))
  63. goto err;
  64. /* Initialize syslog */
  65. openlog(argv[0], LOG_CONS, opts->log_facility);
  66. syslog(LOG_ERR, "Start daemon.\n");
  67. /* Init NetLink socket */
  68. if ((nl = nl_init()) < 0)
  69. goto err;
  70. /* Fork the daemon */
  71. if (!opts->debug) {
  72. /* Daemonize */
  73. if (daemon(0, 0) < 0) {
  74. syslog(LOG_ERR, "Can't daemonize\n");
  75. goto err;
  76. }
  77. /* Write pidfile */
  78. if ((pidfd = open(opts->pidfile,
  79. O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
  80. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
  81. syslog(LOG_WARNING, "Can't open pidfile %s: %s",
  82. opts->pidfile, strerror(errno));
  83. } else {
  84. char str[20];
  85. snprintf(str, sizeof(str), "%u\n", getpid());
  86. if (write(pidfd, str, strlen(str)) < 0)
  87. syslog(LOG_WARNING, "Can't write to %s: %s",
  88. opts->pidfile, strerror(errno));
  89. close(pidfd);
  90. }
  91. }
  92. /* Set signal handler */
  93. sigemptyset(&sig_set);
  94. sigaddset(&sig_set, SIGTERM);
  95. sigaddset(&sig_set, SIGINT);
  96. sigaddset(&sig_set, SIGQUIT);
  97. sig_act.sa_flags = 0;
  98. sig_act.sa_mask = sig_set;
  99. sig_act.sa_handler = &sighandler;
  100. sigaction(SIGTERM, &sig_act, NULL);
  101. sigaction(SIGINT, &sig_act, NULL);
  102. sigaction(SIGQUIT, &sig_act, NULL);
  103. /* Main loop */
  104. while (!sigterm) {
  105. int n;
  106. n = nl_poll(nl, 5);
  107. if (n < 0) {
  108. if (-2 == n) /* EINTR */
  109. continue;
  110. break;
  111. }
  112. if (n > 0) {
  113. rescan = 1;
  114. continue;
  115. }
  116. if (rescan) {
  117. fprintf(stdout, "Rescanning...\n");
  118. rescan = 0;
  119. }
  120. }
  121. retval = 0;
  122. err:
  123. /* Close NetLink socket */
  124. nl_close(nl);
  125. /* Remove pidfile */
  126. if (pidfd >= 0) {
  127. if (unlink(opts->pidfile) < 0) {
  128. syslog(LOG_ERR, "Can't remove pid-file %s: %s\n",
  129. opts->pidfile, strerror(errno));
  130. }
  131. }
  132. /* Free command line options */
  133. opts_free(opts);
  134. syslog(LOG_ERR, "Stop daemon.\n");
  135. return retval;
  136. }
  137. /*--------------------------------------------------------- */
  138. /*
  139. * Signal handler for temination signals (like SIGTERM, SIGINT, ...)
  140. */
  141. static void sighandler(int signo)
  142. {
  143. sigterm = 1;
  144. }
  145. /*--------------------------------------------------------- */
  146. /* Initialize option structure by defaults */
  147. static struct options *opts_init(void)
  148. {
  149. struct options *opts = NULL;
  150. opts = malloc(sizeof(*opts));
  151. assert(opts);
  152. opts->debug = 0; /* daemonize by default */
  153. opts->pidfile = strdup(BIRQ_PIDFILE);
  154. opts->log_facility = LOG_DAEMON;
  155. return opts;
  156. }
  157. /*--------------------------------------------------------- */
  158. /* Free option structure */
  159. static void opts_free(struct options *opts)
  160. {
  161. if (opts->pidfile)
  162. free(opts->pidfile);
  163. free(opts);
  164. }
  165. /*--------------------------------------------------------- */
  166. /* Parse command line options */
  167. static int opts_parse(int argc, char *argv[], struct options *opts)
  168. {
  169. static const char *shortopts = "hvp:dO:";
  170. #ifdef HAVE_GETOPT_H
  171. static const struct option longopts[] = {
  172. {"help", 0, NULL, 'h'},
  173. {"version", 0, NULL, 'v'},
  174. {"pid", 1, NULL, 'p'},
  175. {"debug", 0, NULL, 'd'},
  176. {"facility", 1, NULL, 'O'},
  177. {NULL, 0, NULL, 0}
  178. };
  179. #endif
  180. optind = 1;
  181. while(1) {
  182. int opt;
  183. #ifdef HAVE_GETOPT_H
  184. opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  185. #else
  186. opt = getopt(argc, argv, shortopts);
  187. #endif
  188. if (-1 == opt)
  189. break;
  190. switch (opt) {
  191. case 'p':
  192. if (opts->pidfile)
  193. free(opts->pidfile);
  194. opts->pidfile = strdup(optarg);
  195. break;
  196. case 'd':
  197. opts->debug = 1;
  198. break;
  199. case 'O':
  200. if (lub_log_facility(optarg, &(opts->log_facility))) {
  201. fprintf(stderr, "Error: Illegal syslog facility %s.\n", optarg);
  202. help(-1, argv[0]);
  203. exit(-1);
  204. }
  205. break;
  206. case 'h':
  207. help(0, argv[0]);
  208. exit(0);
  209. break;
  210. case 'v':
  211. version(VERSION);
  212. exit(0);
  213. break;
  214. default:
  215. help(-1, argv[0]);
  216. exit(-1);
  217. break;
  218. }
  219. }
  220. return 0;
  221. }
  222. /*--------------------------------------------------------- */
  223. /* Print help message */
  224. static void help(int status, const char *argv0)
  225. {
  226. const char *name = NULL;
  227. if (!argv0)
  228. return;
  229. /* Find the basename */
  230. name = strrchr(argv0, '/');
  231. if (name)
  232. name++;
  233. else
  234. name = argv0;
  235. if (status != 0) {
  236. fprintf(stderr, "Try `%s -h' for more information.\n",
  237. name);
  238. } else {
  239. printf("Usage: %s [options]\n", name);
  240. printf("Daemon to store user configuration (i.e. commands). "
  241. "The part of the klish project.\n");
  242. printf("Options:\n");
  243. printf("\t-v, --version\tPrint version.\n");
  244. printf("\t-h, --help\tPrint this help.\n");
  245. printf("\t-d, --debug\tDebug mode. Don't daemonize.\n");
  246. printf("\t-p <path>, --pid=<path>\tFile to save daemon's PID to.\n");
  247. printf("\t-O, --facility\tSyslog facility. Default is DAEMON.\n");
  248. }
  249. }