Commit 1819c2db 1819c2db46ba750821f072a83b019e2f1355867d by Sergey Poznyakoff

* mailbox/cfg_driver.c (mu_cfg_tree_reduce): Format parse tree

before scanning the tree.
* mailbox/cfg_parser.y (block rule): Accept empty blocks.
(parse_param): bail out if callback is not declared when it
should.
* mailbox/daemon.c (mu_daemon_create_pidfile)
(mu_daemon_remove_pidfile): If running with UID=0 and EUID != 0,
temporarily switch to EUID=0 for accessing pidfile (when
creating or deleting).
1 parent a3bd178c
2008-11-15 Sergey Poznyakoff <gray@gnu.org.ua>
* mailbox/cfg_driver.c (mu_cfg_tree_reduce): Format parse tree
before scanning the tree.
* mailbox/cfg_parser.y (block rule): Accept empty blocks.
(parse_param): bail out if callback is not declared when it
should.
* mailbox/daemon.c (mu_daemon_create_pidfile)
(mu_daemon_remove_pidfile): If running with UID=0 and EUID != 0,
temporarily switch to EUID=0 for accessing pidfile (when
creating or deleting).
2008-11-12 Sergey Poznyakoff <gray@gnu.org.ua>
* mailbox/cfg_parser.y (mu_cfg_format_error): Raise
......
......@@ -581,6 +581,16 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
{
int rc = 0;
if (flags & MU_PARSE_CONFIG_DUMP)
{
mu_stream_t stream;
mu_stdio_stream_create (&stream, stderr,
MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
mu_stream_open (stream);
mu_cfg_format_parse_tree (stream, parse_tree);
mu_stream_destroy (&stream, NULL);
}
if (root_container)
{
struct include_data idata;
......@@ -598,16 +608,6 @@ mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, const char *progname,
mu_config_destroy_container (&cont);
}
if (flags & MU_PARSE_CONFIG_DUMP)
{
mu_stream_t stream;
mu_stdio_stream_create (&stream, stderr,
MU_STREAM_NO_CHECK|MU_STREAM_NO_CLOSE);
mu_stream_open (stream);
mu_cfg_format_parse_tree (stream, parse_tree);
mu_stream_destroy (&stream, NULL);
}
return rc;
}
......
......@@ -224,7 +224,14 @@ simple : ident vallist ';'
}
;
block : ident tag '{' stmtlist '}' opt_sc
block : ident tag '{' '}' opt_sc
{
$$ = mu_cfg_alloc_node (mu_cfg_node_tag, &$1.locus,
$1.name, $2,
NULL);
}
| ident tag '{' stmtlist '}' opt_sc
{
$$ = mu_cfg_alloc_node (mu_cfg_node_tag, &$1.locus,
$1.name, $2,
......@@ -1126,6 +1133,13 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
{
mu_debug_set_locus (sdata->tree->debug, node->locus.file,
node->locus.line);
if (!param->callback)
{
_mu_cfg_perror (sdata->tree->debug, &node->locus,
_("INTERNAL ERROR: %s: callback not defined"),
node->tag);
abort ();
}
if (param->callback (sdata->tree->debug, tgt, node->label))
return 1;
......
......@@ -30,41 +30,115 @@
#include <mailutils/daemon.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/nls.h>
#include <mu_umaxtostr.h>
static char *pidfile;
static pid_t current_pid;
/* Return 0 if DIR is writable for EUID/EGID.
Otherwise, return error code. */
static int
ewraccess (const char *dir)
{
struct stat st;
if (stat (dir, &st))
return errno;
if ((st.st_mode & S_IWOTH)
|| (st.st_gid == getegid () && (st.st_mode & S_IWGRP))
|| (st.st_uid == geteuid () && (st.st_mode & S_IWUSR)))
return 0;
else
return EACCES;
}
/* Return 0 if DIR is writable. If necessary and possible, raise to
EUID 0, in that case return prior EUID in the memory location pointed to
by PUID. */
static int
access_dir (const char *dir, uid_t *puid)
{
int ec = ewraccess (dir);
if (ec)
{
if (ec == EACCES && access (dir, W_OK) == 0)
{
uid_t uid = geteuid ();
/* See if we can become root */
if (uid && getuid () == 0 && seteuid (0) == 0)
{
*puid = uid;
return 0;
}
}
}
return ec;
}
int
mu_daemon_create_pidfile (const char *filename)
{
char *p;
const char *pid_string;
int fd;
uid_t uid = 0;
int rc;
if (filename[0] != '/')
{
return EINVAL; /* failure */
}
return EINVAL;
if (pidfile)
free (pidfile);
pidfile = strdup (filename);
if (!pidfile)
return ENOMEM;
/* Determine the hosting directory name */
p = strrchr (pidfile, '/');
if (pidfile == p)
{
free (pidfile);
pidfile = NULL;
/* Sorry, pidfiles in root dir are not allowed */
return EINVAL;
}
/* Check if we have write access to the directory */
*p = 0;
rc = access_dir (pidfile, &uid);
if (rc)
{
/* Nope, clean up and return */
free (pidfile);
pidfile = NULL;
return rc;
}
/* Restore directory separator */
*p = '/';
unlink (pidfile);
current_pid = getpid ();
if ((fd = open (pidfile, O_WRONLY | O_CREAT
| O_TRUNC | O_EXCL, 0644)) == -1)
if ((fd = open (pidfile, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644)) != -1)
{
return errno; /* failure */
pid_string = mu_umaxtostr (0, current_pid);
write (fd, pid_string, strlen (pid_string));
close (fd);
atexit (mu_daemon_remove_pidfile);
}
else
{
rc = errno;
free (pidfile);
pidfile = NULL;
}
/* Restore previous EUID value. */
if (uid)
seteuid (uid);
pid_string = mu_umaxtostr (0, current_pid);
write (fd, pid_string, strlen (pid_string));
close (fd);
atexit (mu_daemon_remove_pidfile);
return 0;
return rc;
}
void
......@@ -72,7 +146,32 @@ mu_daemon_remove_pidfile (void)
{
if (getpid () == current_pid)
{
unlink (pidfile);
int rc;
uid_t uid = 0;
/* Determine the hosting directory name */
char *p = strrchr (pidfile, '/');
if (pidfile == p)
{
/* Should not happen */
abort ();
}
/* Check if we have write access to the directory */
*p = 0;
rc = access_dir (pidfile, &uid);
*p = '/';
if (rc == 0)
{
if (unlink (pidfile) && errno != ENOENT)
rc = errno;
else
rc = 0;
}
if (rc)
mu_error (_("cannot remove pidfile %s: %s"),
pidfile, mu_strerror (rc));
free (pidfile);
pidfile = NULL;
}
......