From 5a1f674eecba607ffa328484ca34c598690ff8d2 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 29 Apr 2009 18:11:56 +0300 Subject: Fix locking issues. Improve stream interface. * gnulib.modules: Add c-type, c-strcase, crypto/md5, xgetdomainname, xgethostname. * src/Makefile.am (tagr_SOURCES): Add apop.c, udb.c, xhostname.c * src/graph.c (draw_graph): Rename `now' to `start'. * src/main.c (hostname, rebuild_last_option): New globals. (main): Init hostname. * src/output.c (update_output): Change semantics of the last parameter. * src/readconfig.c (cb_facility): Use c_strcasecmp. (tagr_kw): New keywords: hostname, udb-file, lock-count, lock-timeout, idle-timeout. * src/report.c: Fix locking issues. (update_monitor): Change semantics of the last parameter. (rebuild): Likewise. * src/server.c: Rewrite stream interface. * src/tagr.h (TAGR_ARG_UNUSED, TAGR_PRINTFLIKE): New macros. (lock_retry_count_option, lock_retry_timeout_option) (stream_idle_timeout, hostname): New declarations. (TAGR_UPD_FORCE, TAGR_UPD_LASTTIME): New defines. (trim_crlf, tagr_local_hostnamem tagr_auth_init, tagr_auth) (tagr_udb_name) (udb_get_passwordudb_free_password): New declarations. * TODO: Update --- src/Makefile.am | 5 +- src/apop.c | 84 ++++++++++++++++++++++++ src/graph.c | 17 +++-- src/main.c | 19 ++++-- src/output.c | 11 +++- src/readconfig.c | 23 +++++-- src/report.c | 37 +++++++---- src/server.c | 193 +++++++++++++++++++++++++++++++++++++++++-------------- src/tagr.h | 41 ++++++++++-- src/udb.c | 90 ++++++++++++++++++++++++++ src/xhostname.c | 56 ++++++++++++++++ 11 files changed, 487 insertions(+), 89 deletions(-) create mode 100644 src/apop.c create mode 100644 src/udb.c create mode 100644 src/xhostname.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 0db1eb6..996c541 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,6 +17,7 @@ sbin_PROGRAMS=tagr tagr_SOURCES=\ + apop.c\ graph.c\ grid.c\ html.gram.y\ @@ -30,7 +31,9 @@ tagr_SOURCES=\ report.h\ server.c\ stat.c\ - tagr.h + tagr.h\ + udb.c\ + xhostname.c noinst_HEADERS=html.gram.h diff --git a/src/apop.c b/src/apop.c new file mode 100644 index 0000000..ce423a5 --- /dev/null +++ b/src/apop.c @@ -0,0 +1,84 @@ +/* This file is part of tagr. + Copyright (C) 2009 Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +static char *msg_id; + +const char * +tagr_auth_init () +{ + asprintf (&msg_id, "<%lu.%lu@%s>", + (unsigned long) getpid (), + (unsigned long) time (NULL), + hostname); + return msg_id; +} + +static int +verify_apop (const char *password, const char *user_digest) +{ + int i; + struct md5_ctx md5context; + unsigned char md5digest[16]; + char buf[sizeof (md5digest) * 2 + 1]; + char *p; + + md5_init_ctx (&md5context); + md5_process_bytes (msg_id, strlen (msg_id), &md5context); + md5_process_bytes (password, strlen (password), &md5context); + md5_finish_ctx (&md5context, md5digest); + + for (i = 0, p = buf; i < 16; i++, p += 2) + sprintf (p, "%02x", md5digest[i]); + return strcmp (user_digest, buf); +} + +int +tagr_auth (const char *username, const char *authstr) +{ + int rc = 1; + char *password; + + rc = udb_get_password (username, &password); + if (rc == 1) + { + logmsg (L_ERR, _("no such user `%s'"), username); + } + else if (rc == 0) + { + rc = verify_apop (password, authstr); + if (rc) + logmsg (L_ERR, _("authentication failed for `%s'"), + username); + else + verbose (1, _("%s authenticated"), username); + udb_free_password (password); + } + return rc; +} + diff --git a/src/graph.c b/src/graph.c index 1197a7d..02e0586 100644 --- a/src/graph.c +++ b/src/graph.c @@ -73,7 +73,7 @@ draw_vtext (gdImagePtr graph, int color, const char *text) int draw_graph (FILE *fp, struct monitor *mon, - queue_t *dataq, const struct avg_acc *avg, time_t now, + queue_t *dataq, const struct avg_acc *avg, time_t start, int xstep, unsigned long xmax, int growright, struct grid_class *xgrid, struct grid_class *ygrid) @@ -90,7 +90,6 @@ draw_graph (FILE *fp, int full_ysize = graph_ysize + graph_v_margin[0] + graph_v_margin[1]; grid_t grid; unsigned long ymax = mon->max_rate; - time_t start; yscale = (double) graph_ysize / ymax; xscale = (double) graph_xsize / xmax; @@ -143,13 +142,13 @@ draw_graph (FILE *fp, n = queue_count (dataq); /* Incoming traffic */ - for (i = n - 1, start = 0; i > 0; i--) + for (i = n - 1; i > 0; i--) { struct traffic_history th, tnext; scale_sample (mon, queue_get_ptr (dataq, i), &th); - if (start == 0) - start = th.time; + if (th.time > start) + continue; scale_sample (mon, queue_get_ptr (dataq, i - 1), &tnext); if (start - tnext.time > xmax) break; @@ -172,13 +171,13 @@ draw_graph (FILE *fp, /* Outgoing traffic */ gdImageSetBrush (graph, brush_out); - for (i = n - 1, start = 0; i > 0; i--) + for (i = n - 1; i > 0; i--) { struct traffic_history th, tnext; scale_sample (mon, queue_get_ptr (dataq, i), &th); - if (start == 0) - start = th.time; + if (th.time > start) + continue; scale_sample (mon, queue_get_ptr (dataq, i - 1), &tnext); if (start - tnext.time > xmax) break; @@ -245,7 +244,7 @@ draw_graph (FILE *fp, grid_destroy (grid); } - grid = grid_create (xgrid, dataq, 0, xmax, &now); + grid = grid_create (xgrid, dataq, 0, xmax, &start); if (grid) { unsigned long i; diff --git a/src/main.c b/src/main.c index 181e9d2..5fcb825 100644 --- a/src/main.c +++ b/src/main.c @@ -57,12 +57,12 @@ char *configfile = TAGR_CONFIGFILE; char *html_template = TAGR_TEMPLATE; char *user; char *basedir; -int port; -int sockfd; +char *hostname; int foreground = 0; int single_process_option = 0; int verbose_level; static int rebuild_option; +static int rebuild_last_option; static int import_option; static int read_option; @@ -88,6 +88,7 @@ enum { OPT_DUMP_LEX_TRACE, OPT_CONFIG_HELP, OPT_READ, + OPT_REBUILD_LAST }; static struct argp_option options[] = { @@ -108,6 +109,8 @@ static struct argp_option options[] = { N_("read statistics from given FILEs or standard input") }, {"rebuild", 'b', NULL, 0, N_("rebuild graphs using existing statistics"), GRID+1}, + {"rebuild-last", OPT_REBUILD_LAST, NULL, 0, + N_("same as --rebuild, but refer to the last stored sample"), GRID+1}, {"list", 'l', NULL, 0, N_("list contents of the rate database"), GRID+1}, {"show-defaults", OPT_SHOW_DEFAULTS, NULL, 0, N_("Show configuration default values"), GRID+1}, @@ -276,6 +279,11 @@ parse_opt (int key, char *arg, struct argp_state *state) case OPT_READ: read_option = 1; break; + + case OPT_REBUILD_LAST: + rebuild_option = 1; + rebuild_last_option = 1; + break; case OPT_NO_PREPROCESSOR: grecs_preprocessor = NULL; @@ -668,7 +676,7 @@ main (int argc, char **argv) save_argv = argv; argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; argp_program_version_hook = tagr_version; - + if (!isatty (2)) { log_to_stderr = 0; @@ -682,6 +690,8 @@ main (int argc, char **argv) html_template = html_template_option; if (user_option) user = user_option; + if (!hostname) + hostname = tagr_local_hostname (); argc -= index; argv += index; @@ -742,7 +752,8 @@ main (int argc, char **argv) } if (rebuild_option) - rebuild (1); + rebuild (TAGR_UPD_FORCE + | (rebuild_last_option ? TAGR_UPD_LASTTIME : 0)); if (list_option) list_db (); diff --git a/src/output.c b/src/output.c index 4b6e206..e2e8b92 100644 --- a/src/output.c +++ b/src/output.c @@ -177,7 +177,8 @@ do_update_output (struct monitor *mon, struct image_descr *dscr, else { rc = draw_graph (fp, mon, queue, avg, timestamp, dscr->step, - dscr->step*460 /* FIXME: must be queue->size * step */, + dscr->step*460 + /*^ FIXME: must be queue->size * step */, 0, dscr->xgrid, dscr->ygrid); fclose (fp); } @@ -236,7 +237,7 @@ format_timestamp (FILE *fp, union value v, const char *fmt, int prec) int update_output (struct monitor *mon, struct traffic_record *tr, - time_t timestamp, int force_update) + time_t timestamp, int flags) { char *dirname = mkfilename (basedir, mon->dir, NULL); int rc; @@ -245,13 +246,17 @@ update_output (struct monitor *mon, struct traffic_record *tr, char *tabfile = mkfilename (dirname, mon->name, ".tab"); char *htmlname; pp_value_t *p; - + int force_update = flags & TAGR_UPD_FORCE; + if (!force_update) { if (read_symtab (&tab, tabfile)) force_update = 1; } + if (flags & TAGR_UPD_LASTTIME) + timestamp = tr->last.time; + rc = do_update_output (mon, &img_day, &tr->day_hist, NULL, &tab, timestamp, dirname, 1); diff --git a/src/readconfig.c b/src/readconfig.c index e75cae4..a514691 100644 --- a/src/readconfig.c +++ b/src/readconfig.c @@ -26,6 +26,7 @@ #define obstack_chunk_alloc malloc #define obstack_chunk_free free #include +#include #include #define ARG_UNUSED __attribute__ ((__unused__)) @@ -333,7 +334,7 @@ cb_facility (enum grecs_callback_command cmd, str += 4; for (i = 0; xlat_tab[i].name; i++) - if (strcasecmp (str, xlat_tab[i].name) == 0) + if (c_strcasecmp (str, xlat_tab[i].name) == 0) { *iptr = xlat_tab[i].facility; return 0; @@ -455,7 +456,11 @@ static struct grecs_keyword tagr_kw[] = { grecs_type_string, &html_template }, { "pidfile", NULL, N_("Set pid file name"), grecs_type_string, &pidfile }, - + { "hostname", NULL, N_("Set host name"), + grecs_type_string, &hostname }, + { "udb-file", N_("name"), N_("Name of the user database file"), + grecs_type_string, &tagr_udb_name }, + { "server", N_("id: string"), N_("Configure server"), grecs_type_section, NULL, 0, cb_server, NULL, server_kw }, @@ -470,6 +475,17 @@ static struct grecs_keyword tagr_kw[] = { { "log", NULL, N_("Configure logging"), grecs_type_section, NULL, 0, NULL, NULL, log_kw }, + + { "lock-count", NULL, + N_("Set maximum number of attempts to acquire the lock on a database"), + grecs_type_uint, &lock_retry_count_option }, + { "lock-timeout", N_("seconds"), + N_("Set the time span between the two locking attempts"), + grecs_type_uint, &lock_retry_timeout_option }, + + { "idle-timeout", N_("seconds"), + N_("Idle timeout for stream connections"), + grecs_type_uint, &stream_idle_timeout }, { "rate-units", NULL, N_("Name of rate units"), grecs_type_string, &rate_unit }, @@ -512,8 +528,7 @@ static struct grecs_keyword tagr_kw[] = { grecs_type_int, color_in_max, 0, cb_color }, { "color-out-max", NULL, N_("Not implemented") /* FIXME */, grecs_type_int, color_out_max, 0, cb_color }, - - /* FIXME */ + { NULL } }; diff --git a/src/report.c b/src/report.c index 71a735f..ab4cada 100644 --- a/src/report.c +++ b/src/report.c @@ -33,6 +33,9 @@ #include #include +unsigned lock_retry_count_option = 5; +unsigned lock_retry_timeout_option = 1; + static char *dbname; static GDBM_FILE dbf; @@ -45,13 +48,20 @@ tagr_db_report (char *str) int open_db (int flag) { - dbname = xmalloc (strlen (basedir) + 1 + sizeof (TAGR_DBNAME)); - strcpy (dbname, basedir); - strcat (dbname, "/"); - strcat (dbname, TAGR_DBNAME); - dbf = gdbm_open (dbname, 0, - flag == TAGR_DB_WR ? GDBM_WRCREAT : GDBM_READER, - TAGR_DBMODE, tagr_db_report); + unsigned i; + + dbname = mkfilename (basedir, TAGR_DBNAME, NULL); + + for (i = 0; i < lock_retry_count_option; i++) + { + dbf = gdbm_open (dbname, 0, + flag == TAGR_DB_WR ? GDBM_WRCREAT : GDBM_READER, + TAGR_DBMODE, tagr_db_report); + if (dbf || errno != EAGAIN) + break; + sleep (lock_retry_timeout_option); + } + if (dbf == NULL) { logmsg (L_ERR, _("cannot open database %s: %s"), @@ -251,7 +261,7 @@ report (Stat *stat, time_t timestamp) } int -update_monitor (datum key, time_t timestamp, int force) +update_monitor (datum key, time_t timestamp, int flags) { char id[MAX_NAME_LENGTH+1]; struct traffic_record *tr = NULL; @@ -273,8 +283,7 @@ update_monitor (datum key, time_t timestamp, int force) _read_db (key, &tr); if (tr) { - update_output (mon, tr, tr->last.time /*FIXME: must be now? */, - force); + update_output (mon, tr, timestamp, flags); free (tr); } @@ -282,20 +291,20 @@ update_monitor (datum key, time_t timestamp, int force) } void -rebuild (int force) +rebuild (int flags) { datum key; datum content; time_t now = time (NULL); - + verbose (1, _("rebuild initiated")); if (open_db (TAGR_DB_RD) == 0) { key = gdbm_firstkey (dbf); while (key.dptr) { - datum nextkey = gdbm_nextkey ( dbf, key ); - update_monitor (key, now, force); + datum nextkey = gdbm_nextkey (dbf, key); + update_monitor (key, now, flags); free (key.dptr); key = nextkey; } diff --git a/src/server.c b/src/server.c index 82aae0e..e514f37 100644 --- a/src/server.c +++ b/src/server.c @@ -37,8 +37,11 @@ #include #include #include +#include #include +unsigned stream_idle_timeout = 10; + struct tagr_server { struct tagr_server *next; @@ -48,7 +51,7 @@ struct tagr_server struct grecs_sockaddr addr; }; -struct tagr_server *server_head, *server_tail; +static struct tagr_server *server_head, *server_tail; struct server_class { @@ -194,8 +197,9 @@ subprocess (void (*fun) (void *data), void *data, int fd) logmsg (L_ERR, _("cannot fork: %s"), strerror (errno)); else { - signal (SIGHUP, SIG_IGN); - signal (SIGCHLD, SIG_IGN); + signal (SIGHUP, SIG_DFL); + signal (SIGCHLD, SIG_DFL); + signal (SIGALRM, SIG_DFL); child = 1; if (fd != -1) close (fd); @@ -302,7 +306,7 @@ tcp_open (struct tagr_server *srv) return 0; } -static void +void trim_crlf (char *buf) { size_t len = strlen (buf); @@ -344,75 +348,166 @@ convert_ulong (const char *str, unsigned long *pt) return 0; } +static RETSIGTYPE +sig_child_alrm (int sig) +{ + logmsg (L_NOTICE, _("child timed out")); + exit (EX_TEMPFAIL); +} + +enum tagr_dialog_state + { + initial_dialog_state, + auth_dialog_state, + quit_dialog_state + }; + +struct tagr_dialog +{ + enum tagr_dialog_state state; + FILE *in; + FILE *out; +}; + +#define STATEMASK(n) (1u<<(n)) +#define ANYSTATE ((unsigned)~0) + +struct command +{ + const char *name; + unsigned statemask; + int minargs; + int maxargs; + void (*handler) (struct tagr_dialog *, struct command *, + struct wordsplit *); +}; + +static void +cmd_auth (struct tagr_dialog *dlg, struct command *cmd, + struct wordsplit *ws) +{ + if (tagr_auth (ws->ws_wordv[1], ws->ws_wordv[2]) == 0) + { + dlg->state = auth_dialog_state; + fprintf (dlg->out, "+OK welcome, %s\r\n", ws->ws_wordv[1]); + } + else + fprintf (dlg->out, "-ERR authorization failed\r\n"); +} + +static void +cmd_sample (struct tagr_dialog *dlg, struct command *cmd, + struct wordsplit *ws) +{ + Stat st; + time_t t; + + if (strlen (ws->ws_wordv[1]) > MAX_NAME_LENGTH) + { + fprintf (dlg->out, "-ERR id too long\r\n"); + return; + } + + strcpy (st.name, ws->ws_wordv[1]); + if (convert_ts (ws->ws_wordv[2], &t) + || convert_ulong (ws->ws_wordv[3], &st.in) + || convert_ulong (ws->ws_wordv[4], &st.out)) + { + fprintf (dlg->out, "-ERR invalid input\r\n"); + return; + } + + if (open_db (TAGR_DB_WR)) + fprintf (dlg->out, "-TEMP database not available\r\n"); + else + { + report (&st, t); + close_db (); + fprintf (dlg->out, "+OK thank you\r\n"); + } +} + +static void +cmd_quit (struct tagr_dialog *dlg, struct command *cmd, + struct wordsplit *ws) +{ + dlg->state = quit_dialog_state; + fprintf (dlg->out, "+OK bye\r\n"); +} + +static struct command command_tab[] = { + { "AUTH", STATEMASK (initial_dialog_state), 3, 3, cmd_auth }, + { "SAMPLE", STATEMASK (auth_dialog_state), 5, 5, cmd_sample }, + { "QUIT", ANYSTATE, 1, 1, cmd_quit }, + { NULL } +}; + +static struct command * +find_command (const char *name) +{ + struct command *cmd; + + for (cmd = command_tab; cmd->name; cmd++) + if (c_strcasecmp (cmd->name, name) == 0) + return cmd; + return NULL; +} + + static void tcp_server_loop (void *data) { int fd = *(int*)data; - FILE *in = fdopen (fd, "r"); - FILE *out = fdopen (fd, "w"); + struct tagr_dialog dlg; size_t bufsize = 0; char *buf = NULL; - int quit = 0; - - setvbuf (in, NULL, _IOLBF, 0); - setvbuf (out, NULL, _IOLBF, 0); + const char *authid; + + signal (SIGALRM, sig_child_alrm); - fprintf (out, "+OK tagr experimental stream service\r\n"); - while (!quit && getline (&buf, &bufsize, in) > 0) + dlg.state = initial_dialog_state; + dlg.in = fdopen (fd, "r"); + dlg.out = fdopen (fd, "w"); + setvbuf (dlg.in, NULL, _IOLBF, 0); + setvbuf (dlg.out, NULL, _IOLBF, 0); + + authid = tagr_auth_init (); + fprintf (dlg.out, "+OK tagr experimental stream service %s\r\n", authid); + while (dlg.state != quit_dialog_state + && getline (&buf, &bufsize, dlg.in) > 0) { struct wordsplit ws; - + struct command *cmd; + + alarm (stream_idle_timeout); trim_crlf (buf); if (wordsplit (buf, &ws, WRDSF_DEFFLAGS)) { - logmsg (L_ERR, "failed to parse input line"); - fprintf (out, "-ERR parsing failed\r\n"); + logmsg (L_ERR, _("failed to parse input line")); + fprintf (dlg.out, "-ERR parsing failed\r\n"); continue; } if (ws.ws_wordc == 0) - fprintf (out, "-ERR invalid input\r\n"); - else if (strcasecmp (ws.ws_wordv[0], "SAMPLE") == 0 - && ws.ws_wordc == 5) + fprintf (dlg.out, "-ERR invalid input\r\n"); + else if (cmd = find_command (ws.ws_wordv[0])) { - Stat st; - time_t t; - - if (strlen (ws.ws_wordv[1]) > MAX_NAME_LENGTH) - fprintf (out, "-ERR id too long\r\n"); + if (!(STATEMASK (dlg.state) & cmd->statemask)) + fprintf (dlg.out, "-ERR wrong state\r\n"); + else if (ws.ws_wordc < cmd->minargs + || (cmd->maxargs > 0 && ws.ws_wordc > cmd->maxargs)) + fprintf (dlg.out, "-ERR invalid number of arguments\r\n"); else - { - strcpy (st.name, ws.ws_wordv[1]); - if (convert_ts (ws.ws_wordv[2], &t) - || convert_ulong (ws.ws_wordv[3], &st.in) - || convert_ulong (ws.ws_wordv[4], &st.out)) - fprintf (out, "-ERR invalid input\r\n"); - else - { - if (open_db (TAGR_DB_WR)) - fprintf (out, "-ERR database not available\r\n"); - else - { - report (&st, t); - close_db (); - fprintf (out, "+OK thank you\r\n"); - } - } - } - } - else if (strcasecmp (ws.ws_wordv[0], "QUIT") == 0) - { - quit = 1; - fprintf (out, "+OK bye\r\n"); + cmd->handler (&dlg, cmd, &ws); } else - fprintf (out, "-ERR invalid input\r\n"); + fprintf (dlg.out, "-ERR invalid input\r\n"); wordsplit_free (&ws); } free (buf); - fclose (in); - fclose (out); + fclose (dlg.in); + fclose (dlg.out); close (fd); } diff --git a/src/tagr.h b/src/tagr.h index f95a249..f32b014 100644 --- a/src/tagr.h +++ b/src/tagr.h @@ -20,6 +20,15 @@ #include #include +#ifndef TAGR_ARG_UNUSED +# define TAGR_ARG_UNUSED __attribute__ ((__unused__)) +#endif + +#ifndef TAGR_PRINTFLIKE +# define TAGR_PRINTFLIKE(fmt,narg) \ + __attribute__ ((__format__ (__printf__, fmt, narg))) +#endif + #define TAGR_CONFIGFILE SYSCONFDIR "/tagr.conf" #define TAGR_TEMPLATE SYSCONFDIR "/tagr.tmpl" #define TAGR_PIDFILE "/var/run/tagr.pid" @@ -51,6 +60,13 @@ extern unsigned update_interval; extern int single_process_option; extern double cut_out_fraction; +extern unsigned lock_retry_count_option; +extern unsigned lock_retry_timeout_option; + +extern unsigned stream_idle_timeout; + +extern char *hostname; + extern char *user; extern char *basedir; extern char *configfile; @@ -143,9 +159,9 @@ extern int log_print_severity; #define L_CRIT 5 void init_syslog (char *tag); -void logmsg (int level, const char *fmt, ...); -void die (int code, const char *fmt, ...); -void verbose (int level, const char *fmt, ...); +void logmsg (int level, const char *fmt, ...) TAGR_PRINTFLIKE(2,3); +void die (int code, const char *fmt, ...) TAGR_PRINTFLIKE(2,3); +void verbose (int level, const char *fmt, ...) TAGR_PRINTFLIKE(2,3); @@ -218,9 +234,13 @@ void close_db (); void read_db (struct monitor *mon, struct traffic_record **tr); void write_db (struct monitor *mon, struct traffic_record *tr); void list_db (void); -void rebuild (int force); void tr_init (struct traffic_record *tr); +#define TAGR_UPD_FORCE 0x0001 +#define TAGR_UPD_LASTTIME 0x0002 + +void rebuild (int flags); + /* stat.c */ void update_stats (struct monitor *mon, struct traffic_sample *sample, struct traffic_record *tr); @@ -242,7 +262,7 @@ void scale_sample (struct monitor *mon, const struct traffic_history *in, struct traffic_history *out); int update_output (struct monitor *mon, struct traffic_record *tr, - time_t timestamp, int force); + time_t timestamp, int flags); /* graph.c */ @@ -288,7 +308,18 @@ void open_servers (void); void close_servers (void); void server_loop (void); +void trim_crlf (char *buf); + int tagr_idle (void); + +char *tagr_local_hostname (void); +const char *tagr_auth_init (void); +int tagr_auth (const char *username, const char *authstr); + +/* udb.c */ +extern char *tagr_udb_name; +int udb_get_password (const char *username, char **password); +void udb_free_password (char *pass); diff --git a/src/udb.c b/src/udb.c new file mode 100644 index 0000000..aad5982 --- /dev/null +++ b/src/udb.c @@ -0,0 +1,90 @@ +/* This file is part of tagr. + Copyright (C) 2009 Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include +#include +#include +#include + +char *tagr_udb_name = SYSCONFDIR "/tagr.udb"; + +int +udb_get_password (const char *username, char **password) +{ + FILE *fp; + size_t bufsize = 0; + char *buf = NULL; + unsigned line = 0; + int rc = 1; + + fp = fopen (tagr_udb_name, "r"); + if (!fp) + { + logmsg (L_ERR, _("cannot open file %s: %s"), + tagr_udb_name, strerror (errno)); + return -1; + } + + while (rc == 1 && getline (&buf, &bufsize, fp) > 0) + { + struct wordsplit ws; + + line++; + trim_crlf (buf); + if (wordsplit (buf, &ws, WRDSF_DEFFLAGS)) + { + logmsg (L_ERR, _("%s:%u: failed to parse input line"), + tagr_udb_name, line); + } + if (ws.ws_wordc == 0 || ws.ws_wordv[0][0] == '#') + /* next */; + else if (ws.ws_wordc < 2) + { + logmsg (L_WARNING, _("%s:%u: too few words on line"), + tagr_udb_name, line); + } + else if (ws.ws_wordc > 2) + { + logmsg (L_WARNING, _("%s:%u: too many words on line"), + tagr_udb_name, line); + } + else if (strcmp (ws.ws_wordv[0], username) == 0) + { + *password = xstrdup (ws.ws_wordv[1]); + rc = 0; + } + wordsplit_free (&ws); + } + + free (buf); + fclose (fp); + return rc; +} + +void +udb_free_password (char *pass) +{ + char *p; + for (p = pass; *p; p++) + *p = 0; + free (pass); +} diff --git a/src/xhostname.c b/src/xhostname.c new file mode 100644 index 0000000..8ffd499 --- /dev/null +++ b/src/xhostname.c @@ -0,0 +1,56 @@ +/* This file is part of tagr. + Copyright (C) 2009 Max Bouglacoff, Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#include +#include +#include +#include + +char * +tagr_local_hostname () +{ + struct hostent *hp; + char *hostpart = xgethostname (); + char *ret; + + hp = gethostbyname (hostpart); + if (hp) + ret = xstrdup (hp->h_name); + else + { + char *domainpart = xgetdomainname (); + + if (domainpart && domainpart[0] && strcmp(domainpart, "(none)")) + { + ret = xmalloc(strlen( hostpart) + 1 + + strlen (domainpart) + 1); + strcpy(ret, hostpart); + strcat(ret, "."); + strcat(ret, domainpart); + free (hostpart); + } + else + ret = hostpart; + free (domainpart); + } + return ret; +} + -- cgit v1.2.1