symon.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /* $Id: symon.c,v 1.30 2003/10/10 15:20:01 dijkstra Exp $ */
  2. /*
  3. * Copyright (c) 2001-2002 Willem Dijkstra
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * - Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * - Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following
  14. * disclaimer in the documentation and/or other materials provided
  15. * with the distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include <sys/param.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <limits.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <sysexits.h>
  39. #include <syslog.h>
  40. #include <unistd.h>
  41. #include "data.h"
  42. #include "error.h"
  43. #include "symon.h"
  44. #include "symonnet.h"
  45. #include "net.h"
  46. #include "readconf.h"
  47. #include "xmalloc.h"
  48. __BEGIN_DECLS
  49. void alarmhandler(int);
  50. void exithandler(int);
  51. void huphandler(int);
  52. void set_stream_use(struct muxlist *);
  53. __END_DECLS
  54. int flag_hup = 0;
  55. /* map stream types to inits and getters */
  56. struct funcmap streamfunc[] = {
  57. {MT_IO, 0, init_io, gets_io, get_io}, /* gets_io obtains entire io state,
  58. * get_io = just a copy */
  59. {MT_CPU, 0, init_cpu, NULL, get_cpu},
  60. {MT_MEM, 0, init_mem, NULL, get_mem},
  61. {MT_IF, 0, init_if, NULL, get_if},
  62. {MT_PF, 0, init_pf, NULL, get_pf},
  63. {MT_DEBUG, 0, init_debug, NULL, get_debug},
  64. {MT_PROC, 0, init_proc, gets_proc, get_proc},
  65. {MT_MBUF, 0, init_mbuf, NULL, get_mbuf},
  66. {MT_SENSOR, 0, init_sensor, NULL, get_sensor},
  67. {MT_EOT, 0, NULL, NULL}
  68. };
  69. void
  70. set_stream_use(struct muxlist *mul) {
  71. struct mux *mux;
  72. struct stream *stream;
  73. int i;
  74. for (i = 0; i < MT_EOT; i++)
  75. streamfunc[i].used = 0;
  76. SLIST_FOREACH(mux, mul, muxes) {
  77. SLIST_FOREACH(stream, &mux->sl, streams)
  78. streamfunc[stream->type].used = 1;
  79. }
  80. }
  81. /* alarmhandler that gets called every SYMON_INTERVAL */
  82. void
  83. alarmhandler(int s)
  84. {
  85. /* EMPTY */
  86. }
  87. void
  88. exithandler(int s)
  89. {
  90. info("received signal %d - quitting", s);
  91. exit(1);
  92. }
  93. void
  94. huphandler(int s)
  95. {
  96. info("hup received");
  97. flag_hup = 1;
  98. }
  99. /*
  100. * Symon is a system measurement utility.
  101. *
  102. * The main goals symon hopes to accomplish are:
  103. * - to take fine grained measurements of system parameters
  104. * - with minimal performance impact
  105. * - in a secure way.
  106. *
  107. * Measurements are processed by a second program called symux. symon and symux
  108. * communicate via udp.
  109. */
  110. int
  111. main(int argc, char *argv[])
  112. {
  113. struct muxlist mul, newmul;
  114. struct itimerval alarminterval;
  115. struct stream *stream;
  116. struct mux *mux;
  117. FILE *f;
  118. char *cfgfile;
  119. char *cfgpath;
  120. char *stringptr;
  121. int maxstringlen;
  122. int ch;
  123. int i;
  124. SLIST_INIT(&mul);
  125. /* reset flags */
  126. flag_debug = 0;
  127. flag_daemon = 0;
  128. cfgfile = SYMON_CONFIG_FILE;
  129. while ((ch = getopt(argc, argv, "dvf:")) != -1) {
  130. switch (ch) {
  131. case 'd':
  132. flag_debug = 1;
  133. break;
  134. case 'f':
  135. if (optarg && optarg[0] != '/') {
  136. /* cfg path needs to be absolute, we will be a daemon soon */
  137. if ((cfgpath = getwd(NULL)) == NULL)
  138. fatal("could not get working directory");
  139. maxstringlen = strlen(cfgpath) + strlen(optarg) + 1;
  140. cfgfile = xmalloc(maxstringlen);
  141. strncpy(cfgfile, cfgpath, maxstringlen);
  142. stringptr = cfgfile + strlen(cfgpath);
  143. stringptr[0] = '/';
  144. stringptr++;
  145. strncpy(stringptr, optarg, maxstringlen - (cfgfile - stringptr));
  146. cfgfile[maxstringlen] = '\0';
  147. free(cfgpath);
  148. }
  149. else
  150. cfgfile = xstrdup(optarg);
  151. break;
  152. case 'v':
  153. info("symon version %s", SYMON_VERSION);
  154. default:
  155. info("usage: %s [-d] [-v] [-f cfgfile]", __progname);
  156. exit(EX_USAGE);
  157. }
  158. }
  159. /* parse configuration file */
  160. if (!read_config_file(&mul, cfgfile))
  161. fatal("configuration contained errors; quitting");
  162. setegid(getgid());
  163. setgid(getgid());
  164. if (flag_debug != 1) {
  165. if (daemon(0, 0) != 0)
  166. fatal("daemonize failed");
  167. flag_daemon = 1;
  168. /* record pid */
  169. f = fopen(SYMON_PID_FILE, "w");
  170. if (f) {
  171. fprintf(f, "%u\n", (u_int) getpid());
  172. fclose(f);
  173. }
  174. }
  175. info("symon version %s", SYMON_VERSION);
  176. if (flag_debug == 1)
  177. info("program id=%d", (u_int) getpid());
  178. /* setup signal handlers */
  179. signal(SIGALRM, alarmhandler);
  180. signal(SIGHUP, huphandler);
  181. signal(SIGINT, exithandler);
  182. signal(SIGQUIT, exithandler);
  183. signal(SIGTERM, exithandler);
  184. /* prepare crc32 */
  185. init_crc32();
  186. /* init modules */
  187. SLIST_FOREACH(mux, &mul, muxes) {
  188. connect2mux(mux);
  189. SLIST_FOREACH(stream, &mux->sl, streams) {
  190. (streamfunc[stream->type].init) (stream->args);
  191. }
  192. }
  193. set_stream_use(&mul);
  194. /* setup alarm */
  195. timerclear(&alarminterval.it_interval);
  196. timerclear(&alarminterval.it_value);
  197. alarminterval.it_interval.tv_sec =
  198. alarminterval.it_value.tv_sec = SYMON_INTERVAL;
  199. if (setitimer(ITIMER_REAL, &alarminterval, NULL) != 0) {
  200. fatal("alarm setup failed -- %s", strerror(errno));
  201. }
  202. for (;;) { /* FOREVER */
  203. sleep(SYMON_INTERVAL); /* alarm will always interrupt sleep */
  204. if (flag_hup == 1) {
  205. flag_hup = 0;
  206. SLIST_INIT(&newmul);
  207. if (!read_config_file(&newmul, cfgfile)) {
  208. info("new configuration contains errors; keeping old configuration");
  209. free_muxlist(&newmul);
  210. }
  211. else {
  212. free_muxlist(&mul);
  213. mul = newmul;
  214. info("read configuration file '%.100s' succesfully", cfgfile);
  215. /* init modules */
  216. SLIST_FOREACH(mux, &mul, muxes) {
  217. connect2mux(mux);
  218. SLIST_FOREACH(stream, &mux->sl, streams) {
  219. (streamfunc[stream->type].init) (stream->args);
  220. }
  221. }
  222. set_stream_use(&mul);
  223. }
  224. }
  225. else {
  226. /* populate for modules that get all their measurements in one go */
  227. for (i = 0; i < MT_EOT; i++)
  228. if (streamfunc[i].used && (streamfunc[i].gets != NULL))
  229. (streamfunc[i].gets) ();
  230. SLIST_FOREACH(mux, &mul, muxes) {
  231. prepare_packet(mux);
  232. SLIST_FOREACH(stream, &mux->sl, streams)
  233. stream_in_packet(stream, mux);
  234. finish_packet(mux);
  235. send_packet(mux);
  236. }
  237. }
  238. }
  239. /* NOTREACHED */
  240. return (EX_SOFTWARE);
  241. }