From b4869652775416dde95cfc103d4b03b04828bf60 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Thu, 2 Jul 2015 01:02:06 +0200
Subject: kike: resolve the path to PID files better
---
common.c | 43 +++++++++++++++++++++++++++++++++++++++++++
kike.c | 35 ++++++++++++++++++++---------------
2 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/common.c b/common.c
index cc6221e..7b845d8 100644
--- a/common.c
+++ b/common.c
@@ -90,6 +90,49 @@ strncasecmp_ascii (const char *a, const char *b, size_t n)
return 0;
}
+static char *
+resolve_relative_runtime_filename (const char *filename)
+{
+ struct str path;
+ str_init (&path);
+
+ const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
+ if (runtime_dir && *runtime_dir == '/')
+ str_append (&path, runtime_dir);
+ else
+ get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
+ str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename);
+
+ // Try to create the file's ancestors
+ const char *last_slash = strrchr (path.str, '/');
+ if (last_slash && last_slash != path.str)
+ {
+ char *copy = xstrndup (path.str, last_slash - path.str);
+ (void) mkdir_with_parents (copy, NULL);
+ free (copy);
+ }
+ return str_steal (&path);
+}
+
+static char *
+resolve_filename (const char *filename, char *(*relative_cb) (const char *))
+{
+ // Absolute path is absolute
+ if (*filename == '/')
+ return xstrdup (filename);
+
+ // We don't want to use wordexp() for this as it may execute /bin/sh
+ if (*filename == '~')
+ {
+ // Paths to home directories ought to be absolute
+ char *expanded = try_expand_tilde (filename + 1);
+ if (expanded)
+ return expanded;
+ print_debug ("failed to expand the home directory in `%s'", filename);
+ }
+ return relative_cb (filename);
+}
+
// --- Logging -----------------------------------------------------------------
static void
diff --git a/kike.c b/kike.c
index b5bda0a..c5c36da 100644
--- a/kike.c
+++ b/kike.c
@@ -31,15 +31,7 @@
static struct config_item g_config_table[] =
{
- // TODO: use XDG_RUNTIME_DIR if relative. The last fallback is:
- //
- // "$XDG_DATA_HOME defines the base directory relative to which user
- // specific data files should be stored. If $XDG_DATA_HOME is either not
- // set or empty, a default equal to $HOME/.local/share should be used."
- //
- // Note that when using XDG_RUNTIME_DIR, it either needs to have access
- // time bumped every 6 hours, or have the sticky bit set.
- { "pid_file", NULL, "Full path for the PID file" },
+ { "pid_file", NULL, "Path or name of the PID file" },
{ "server_name", NULL, "Server name" },
{ "server_info", "My server", "Brief server description" },
{ "motd", NULL, "MOTD filename" },
@@ -3671,14 +3663,12 @@ irc_initialize_server_name (struct server_context *ctx, struct error **e)
}
static bool
-irc_lock_pid_file (struct server_context *ctx, struct error **e)
+lock_pid_file (const char *path, struct error **e)
{
- const char *path = str_map_find (&ctx->config, "pid_file");
- if (!path)
- return true;
-
+ // When using XDG_RUNTIME_DIR, the file needs to either have its
+ // access time bumped every 6 hours, or have the sticky bit set
int fd = open (path, O_RDWR | O_CREAT,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* 644 */);
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* 644 */ | S_ISVTX /* sticky */);
if (fd < 0)
{
error_set (e, "can't open `%s': %s", path, strerror (errno));
@@ -3695,6 +3685,7 @@ irc_lock_pid_file (struct server_context *ctx, struct error **e)
if (fcntl (fd, F_SETLK, &lock))
{
error_set (e, "can't lock `%s': %s", path, strerror (errno));
+ xclose (fd);
return false;
}
@@ -3706,6 +3697,7 @@ irc_lock_pid_file (struct server_context *ctx, struct error **e)
|| write (fd, pid.str, pid.len) != (ssize_t) pid.len)
{
error_set (e, "can't write to `%s': %s", path, strerror (errno));
+ xclose (fd);
return false;
}
str_free (&pid);
@@ -3715,6 +3707,19 @@ irc_lock_pid_file (struct server_context *ctx, struct error **e)
return true;
}
+static bool
+irc_lock_pid_file (struct server_context *ctx, struct error **e)
+{
+ const char *path = str_map_find (&ctx->config, "pid_file");
+ if (!path)
+ return true;
+
+ char *resolved = resolve_filename (path, resolve_relative_runtime_filename);
+ bool result = lock_pid_file (resolved, e);
+ free (resolved);
+ return result;
+}
+
static int
irc_listen (struct addrinfo *gai_iter)
{
--
cgit v1.2.3-70-g09d2