aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO9
-rw-r--r--gnulib.modules5
-rw-r--r--src/Makefile.am5
-rw-r--r--src/apop.c84
-rw-r--r--src/graph.c17
-rw-r--r--src/main.c19
-rw-r--r--src/output.c11
-rw-r--r--src/readconfig.c23
-rw-r--r--src/report.c37
-rw-r--r--src/server.c193
-rw-r--r--src/tagr.h41
-rw-r--r--src/udb.c90
-rw-r--r--src/xhostname.c56
13 files changed, 499 insertions, 91 deletions
diff --git a/TODO b/TODO
index b2edd7c..b17d5e1 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,2 @@
-Tagr TODO list. 2009-04-28
+Tagr TODO list. 2009-04-29
Copyright (C) 2009 Sergey Poznyakoff
@@ -5,5 +5,10 @@ Copyright (C) 2009 Sergey Poznyakoff
-S: +OK tagr ready
+Currently implemented are:
+
+S: +OK <msgid>
+C: AUTH name digest
+S: +OK
C: SAMPLE id 1240903636 12345 3456
S: +OK accepted
+...
C: QUIT
diff --git a/gnulib.modules b/gnulib.modules
index d4887b3..0a23f34 100644
--- a/gnulib.modules
+++ b/gnulib.modules
@@ -4,2 +4,5 @@
argp
+c-ctype
+c-strcase
+crypto/md5
fprintftime
@@ -19 +22,3 @@ xalloc
xalloc-die
+xgetdomainname
+xgethostname \ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
index 0db1eb6..996c541 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,2 +19,3 @@ sbin_PROGRAMS=tagr
tagr_SOURCES=\
+ apop.c\
graph.c\
@@ -32,3 +33,5 @@ tagr_SOURCES=\
stat.c\
- tagr.h
+ tagr.h\
+ udb.c\
+ xhostname.c
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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <tagr.h>
+
+#include <md5.h>
+
+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
@@ -75,3 +75,3 @@ 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,
@@ -92,3 +92,2 @@ draw_graph (FILE *fp,
unsigned long ymax = mon->max_rate;
- time_t start;
@@ -145,3 +144,3 @@ draw_graph (FILE *fp,
/* Incoming traffic */
- for (i = n - 1, start = 0; i > 0; i--)
+ for (i = n - 1; i > 0; i--)
{
@@ -150,4 +149,4 @@ draw_graph (FILE *fp,
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);
@@ -174,3 +173,3 @@ draw_graph (FILE *fp,
gdImageSetBrush (graph, brush_out);
- for (i = n - 1, start = 0; i > 0; i--)
+ for (i = n - 1; i > 0; i--)
{
@@ -179,4 +178,4 @@ draw_graph (FILE *fp,
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);
@@ -247,3 +246,3 @@ draw_graph (FILE *fp,
- grid = grid_create (xgrid, dataq, 0, xmax, &now);
+ grid = grid_create (xgrid, dataq, 0, xmax, &start);
if (grid)
diff --git a/src/main.c b/src/main.c
index 181e9d2..5fcb825 100644
--- a/src/main.c
+++ b/src/main.c
@@ -59,4 +59,3 @@ char *user;
char *basedir;
-int port;
-int sockfd;
+char *hostname;
int foreground = 0;
@@ -65,2 +64,3 @@ int verbose_level;
static int rebuild_option;
+static int rebuild_last_option;
@@ -90,2 +90,3 @@ enum {
OPT_READ,
+ OPT_REBUILD_LAST
};
@@ -110,2 +111,4 @@ static struct argp_option options[] = {
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},
@@ -278,2 +281,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
break;
+
+ case OPT_REBUILD_LAST:
+ rebuild_option = 1;
+ rebuild_last_option = 1;
+ break;
@@ -670,3 +678,3 @@ main (int argc, char **argv)
argp_program_version_hook = tagr_version;
-
+
if (!isatty (2))
@@ -684,2 +692,4 @@ main (int argc, char **argv)
user = user_option;
+ if (!hostname)
+ hostname = tagr_local_hostname ();
@@ -744,3 +754,4 @@ main (int argc, char **argv)
if (rebuild_option)
- rebuild (1);
+ rebuild (TAGR_UPD_FORCE
+ | (rebuild_last_option ? TAGR_UPD_LASTTIME : 0));
diff --git a/src/output.c b/src/output.c
index 4b6e206..e2e8b92 100644
--- a/src/output.c
+++ b/src/output.c
@@ -179,3 +179,4 @@ do_update_output (struct monitor *mon, struct image_descr *dscr,
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);
@@ -238,3 +239,3 @@ int
update_output (struct monitor *mon, struct traffic_record *tr,
- time_t timestamp, int force_update)
+ time_t timestamp, int flags)
{
@@ -247,3 +248,4 @@ update_output (struct monitor *mon, struct traffic_record *tr,
pp_value_t *p;
-
+ int force_update = flags & TAGR_UPD_FORCE;
+
if (!force_update)
@@ -254,2 +256,5 @@ update_output (struct monitor *mon, struct traffic_record *tr,
+ if (flags & TAGR_UPD_LASTTIME)
+ timestamp = tr->last.time;
+
rc = do_update_output (mon, &img_day,
diff --git a/src/readconfig.c b/src/readconfig.c
index e75cae4..a514691 100644
--- a/src/readconfig.c
+++ b/src/readconfig.c
@@ -28,2 +28,3 @@
#include <obstack.h>
+#include <c-strcase.h>
#include <tagr.h>
@@ -335,3 +336,3 @@ cb_facility (enum grecs_callback_command cmd,
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)
{
@@ -457,3 +458,7 @@ static struct grecs_keyword tagr_kw[] = {
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"),
@@ -472,2 +477,13 @@ static struct grecs_keyword tagr_kw[] = {
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 },
@@ -514,4 +530,3 @@ static struct grecs_keyword tagr_kw[] = {
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
@@ -35,2 +35,5 @@
+unsigned lock_retry_count_option = 5;
+unsigned lock_retry_timeout_option = 1;
+
static char *dbname;
@@ -47,9 +50,16 @@ 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)
@@ -253,3 +263,3 @@ 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)
{
@@ -275,4 +285,3 @@ update_monitor (datum key, time_t timestamp, int force)
{
- update_output (mon, tr, tr->last.time /*FIXME: must be now? */,
- force);
+ update_output (mon, tr, timestamp, flags);
free (tr);
@@ -284,3 +293,3 @@ update_monitor (datum key, time_t timestamp, int force)
void
-rebuild (int force)
+rebuild (int flags)
{
@@ -289,3 +298,3 @@ rebuild (int force)
time_t now = time (NULL);
-
+
verbose (1, _("rebuild initiated"));
@@ -296,4 +305,4 @@ rebuild (int force)
{
- 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);
diff --git a/src/server.c b/src/server.c
index 82aae0e..e514f37 100644
--- a/src/server.c
+++ b/src/server.c
@@ -39,4 +39,7 @@
#include <inttypes.h>
+#include <c-strcase.h>
#include <wordsplit.h>
+unsigned stream_idle_timeout = 10;
+
struct tagr_server
@@ -50,3 +53,3 @@ struct tagr_server
-struct tagr_server *server_head, *server_tail;
+static struct tagr_server *server_head, *server_tail;
@@ -196,4 +199,5 @@ subprocess (void (*fun) (void *data), void *data, int fd)
{
- signal (SIGHUP, SIG_IGN);
- signal (SIGCHLD, SIG_IGN);
+ signal (SIGHUP, SIG_DFL);
+ signal (SIGCHLD, SIG_DFL);
+ signal (SIGALRM, SIG_DFL);
child = 1;
@@ -304,3 +308,3 @@ tcp_open (struct tagr_server *srv)
-static void
+void
trim_crlf (char *buf)
@@ -346,2 +350,108 @@ convert_ulong (const char *str, unsigned long *pt)
+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
@@ -350,16 +460,24 @@ 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);
@@ -367,4 +485,4 @@ tcp_server_loop (void *data)
{
- 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;
@@ -373,38 +491,15 @@ tcp_server_loop (void *data)
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);
@@ -413,4 +508,4 @@ tcp_server_loop (void *data)
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
@@ -22,2 +22,11 @@
+#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"
@@ -53,2 +62,9 @@ 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;
@@ -145,5 +161,5 @@ extern int log_print_severity;
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);
@@ -220,5 +236,9 @@ 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 */
@@ -244,3 +264,3 @@ void scale_sample (struct monitor *mon,
int update_output (struct monitor *mon, struct traffic_record *tr,
- time_t timestamp, int force);
+ time_t timestamp, int flags);
@@ -290,5 +310,16 @@ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <wordsplit.h>
+#include <tagr.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <xalloc.h>
+#include <xgethostname.h>
+#include <xgetdomainname.h>
+
+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;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.