aboutsummaryrefslogtreecommitdiff
path: root/pies
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-11-13 19:02:54 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-11-13 19:02:54 +0000
commit20bec15fe6bc356b8ed3e8ee8469b5f10f34b04b (patch)
treedbe37e84739cbdd57c7ffc6cb4c59ea6d2f6830e /pies
parent2f82db82c0a25c310ef25d0ea761a97e706293ea (diff)
downloadpies-20bec15fe6bc356b8ed3e8ee8469b5f10f34b04b.tar.gz
pies-20bec15fe6bc356b8ed3e8ee8469b5f10f34b04b.tar.bz2
Implement file output redirection.
* pies/pies.h (enum retr_type): New constants. (struct retranslator): New type. (struct component): Change type of retr to struct retranslator. All uses updated. * pies/pies.c (_cb_retr): Takes two arguments: redirection type and file name or syslog priority. (make_full_name): New function. (component_verify): Check retr file names. * pies/progman.c (redirect_to_file): New function. (open_retranslator): Handle file redirects. (prog_start): Open /dev/null in wronly mode. * pies/meta1gram.y (create_retr_node): New function. (translate_node_list): Create default "stderr" statement.
Diffstat (limited to 'pies')
-rw-r--r--pies/meta1gram.y39
-rw-r--r--pies/pies.c169
-rw-r--r--pies/pies.h25
-rw-r--r--pies/progman.c55
4 files changed, 229 insertions, 59 deletions
diff --git a/pies/meta1gram.y b/pies/meta1gram.y
index ac72d16..91bcb6d 100644
--- a/pies/meta1gram.y
+++ b/pies/meta1gram.y
@@ -333,6 +333,28 @@ create_string_node (const char *tag, const char *str, mu_cfg_locus_t *locus)
}
static mu_cfg_node_t *
+create_retr_node (const char *tag, const char *dir,
+ const char *name, mu_cfg_locus_t *locus)
+{
+ mu_config_value_t *val = create_value (MU_CFG_ARRAY);
+ val->v.arg.c = 2;
+ val->v.arg.v = mu_alloc (2 * sizeof (val->v.arg.v[0]));
+
+ val->v.arg.v[1].type = MU_CFG_STRING;
+ val->v.arg.v[0].v.string = meta1_string ("file", 4);
+
+ val->v.arg.v[1].type = MU_CFG_STRING;
+ meta1_line_begin ();
+ meta1_line_add (dir, strlen (dir));
+ meta1_line_add ("/", 1);
+ meta1_line_add (name, strlen (name));
+ meta1_line_add (".log", 4);
+ val->v.arg.v[1].v.string = meta1_line_finish ();
+
+ return alloc_node (mu_cfg_node_param, locus, tag, val, NULL);
+}
+
+static mu_cfg_node_t *
translate_node (mu_cfg_node_t *src)
{
mu_cfg_node_t *dst = NULL;
@@ -350,8 +372,11 @@ translate_node (mu_cfg_node_t *src)
return dst;
}
+#define META1_QUEUE_DIR() \
+ (meta1_queue_dir ? meta1_queue_dir : "/var/spool/meta1")
+
static mu_cfg_node_t *
-translate_node_list (mu_cfg_node_t *src)
+translate_node_list (mu_cfg_node_t *src, const char *name)
{
mu_cfg_node_t *head = NULL, *tail = NULL;
mu_cfg_locus_t *locus = &src->locus;
@@ -377,12 +402,14 @@ translate_node_list (mu_cfg_node_t *src)
tail->next = node;
tail = node;
- node = create_string_node ("chdir",
- meta1_queue_dir ?
- meta1_queue_dir : "/var/spool/meta1",
- locus);
+ node = create_string_node ("chdir", META1_QUEUE_DIR (), locus);
+ tail->next = node;
+ tail = node;
+
+ node = create_retr_node ("stderr", META1_QUEUE_DIR (), name, locus);
tail->next = node;
tail = node;
+
}
return head;
}
@@ -397,7 +424,7 @@ translate_component (mu_cfg_node_t *src)
val->v.string = meta1_string (src->tag, strlen (src->tag));
dst = alloc_node (mu_cfg_node_tag, &src->locus,
"component", val,
- translate_node_list (src->node));
+ translate_node_list (src->node, val->v.string));
}
return dst;
}
diff --git a/pies/pies.c b/pies/pies.c
index 46df904..7f1ed35 100644
--- a/pies/pies.c
+++ b/pies/pies.c
@@ -461,15 +461,83 @@ _cb_facility (mu_debug_t debug, void *data, mu_config_value_t *val)
static int
_cb_retr (mu_debug_t debug, void *data, mu_config_value_t *arg)
{
- if (mu_cfg_assert_value_type (arg, MU_CFG_STRING, debug))
- return 1;
- if (mu_string_to_syslog_priority (arg->v.string, data))
+ struct retranslator *rp = data;
+ static struct mu_kwd retrtab[] = {
+ { "null", retr_null },
+ { "syslog", retr_syslog },
+ { "file", retr_file },
+ { NULL }
+ };
+ int res;
+
+ switch (arg->type)
{
- mu_cfg_format_error (debug, MU_DEBUG_ERROR,
- _("Unknown syslog priority `%s'"),
- arg);
- return 1;
+ case MU_CFG_STRING:
+ if (strcmp (arg->v.string, "null") == 0)
+ {
+ rp->type = retr_null;
+ break;
+ }
+ rp->type = retr_syslog;
+ if (mu_string_to_syslog_priority (arg->v.string, &rp->v.prio))
+ {
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR,
+ _("Unknown syslog priority `%s'"),
+ arg);
+ return 0;
+ }
+ break;
+
+ case MU_CFG_ARRAY:
+ if (mu_cfg_assert_value_type (&arg->v.arg.v[0], MU_CFG_STRING, debug))
+ return 0;
+ if (mu_kwd_xlat_name (retrtab, arg->v.arg.v[0].v.string, &res))
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR,
+ _("%s: unrecognised retranslator type"),
+ arg->v.arg.v[0].v.string);
+ else
+ {
+ if (res != retr_null)
+ {
+ if (arg->v.arg.c != 2)
+ {
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR,
+ _("wrong number of arguments"));
+ return 0;
+ }
+ if (mu_cfg_assert_value_type (&arg->v.arg.v[1], MU_CFG_STRING,
+ debug))
+ return 0;
+
+ switch (res)
+ {
+ case retr_null:
+ break;
+
+ case retr_syslog:
+ if (mu_string_to_syslog_priority (arg->v.arg.v[1].v.string,
+ &rp->v.prio))
+ {
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR,
+ _("Unknown syslog priority `%s'"),
+ arg->v.arg.v[1].v.string);
+ return 0;
+ }
+ break;
+
+ case retr_file:
+ rp->v.file = xstrdup (arg->v.arg.v[1].v.string);
+ break;
+ }
+ }
+ rp->type = res;
+ }
+ break;
+
+ default:
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR, _("unexpected list"));
}
+
return 0;
}
@@ -594,17 +662,17 @@ struct mu_cfg_param component_cfg_param[] = {
N_("arg") },
{ "stdout", mu_cfg_callback, NULL,
mu_offsetof (struct component, retr[RETR_OUT]), _cb_retr,
- N_("Redirect program's standard output to the given syslog priority."),
- /* TRANSLATORS: The words between '{' and '}' are keywords, do not
- translate them. */
- N_("prio: {emerg | alert | crit | err | warning | notice | info | debug}")
+ N_("Redirect program's standard output to the given file or "
+ "syslog priority."),
+ /* TRANSLATORS: file and syslog are keywords. Do not translate them. */
+ N_("type: {file | syslog}> <channel: string")
},
{ "stderr", mu_cfg_callback, NULL,
mu_offsetof (struct component, retr[RETR_ERR]), _cb_retr,
- N_("Redirect program's standard error to the given syslog priority."),
- /* TRANSLATORS: The words between '{' and '}' are keywords, do not
- translate them. */
- N_("prio: {emerg | alert | crit | err | warning | notice | info | debug}")
+ N_("Redirect program's standard error to the given file or "
+ "syslog priority."),
+ /* TRANSLATORS: file and syslog are keywords. Do not translate them. */
+ N_("type: {file | syslog}> <channel: string")
},
{ "user", mu_cfg_string, NULL,
mu_offsetof (struct component, privs.user), NULL,
@@ -635,11 +703,27 @@ struct mu_cfg_param component_cfg_param[] = {
{ NULL }
};
+static char *
+make_full_name (const char *dir, const char *file)
+{
+ char *p;
+ size_t len = strlen (dir);
+
+ while (len > 0 && dir[len-1] == '/')
+ len--;
+ p = xmalloc (len + 1 + strlen (file) + 1);
+ memcpy (p, dir, len);
+ p[len++] = '/';
+ strcpy (p + len, file);
+ return p;
+}
+
static int
component_verify (struct component *comp, mu_debug_t debug)
{
int header = 0;
-#define COMPERR(s) \
+ int i;
+#define COMPERR(fmt, arg) \
do \
{ \
if (!header) \
@@ -648,43 +732,35 @@ component_verify (struct component *comp, mu_debug_t debug)
_("in component %s:"), comp->tag); \
header = 1; \
} \
- mu_cfg_format_error (debug, MU_DEBUG_ERROR, "%s", s); \
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR, fmt, arg); \
} \
while (0)
if (!comp->argv)
- COMPERR (_("missing command line"));
+ COMPERR ("%s", _("missing command line"));
if (comp->pass_fd_socket && comp->mode != pies_comp_pass_fd)
- COMPERR (_("pass-fd-socket ignored: wrong mode"));
+ COMPERR ("%s", _("pass-fd-socket ignored: wrong mode"));
switch (comp->mode)
{
case pies_comp_exec:
if (comp->socket_url)
- COMPERR (_("socket ignored: wrong mode"));
+ COMPERR ("%s", _("socket ignored: wrong mode"));
break;
case pies_comp_pass_fd:
if (!comp->pass_fd_socket)
- COMPERR (_("must supply pass-fd-socket in this mode"));
+ COMPERR ("%s", _("must supply pass-fd-socket in this mode"));
else if (comp->pass_fd_socket[0] != '/')
{
if (comp->dir)
{
- char *p;
- size_t len = strlen (comp->dir);
-
- while (len > 0 && comp->dir[len-1] == '/')
- len--;
- p = xmalloc (len + 1 + strlen (comp->pass_fd_socket) + 1);
- memcpy (p, comp->dir, len);
- p[len++] = '/';
- strcpy (p + len, comp->pass_fd_socket);
+ char *p = make_full_name (comp->dir, comp->pass_fd_socket);
free (comp->pass_fd_socket);
comp->pass_fd_socket = p;
}
else
- COMPERR (_("pass-fd-socket must be an absolute "
- "file name or chdir must be specified"));
+ COMPERR ("%s", _("pass-fd-socket must be an absolute "
+ "file name or chdir must be specified"));
}
/* Fall through */
@@ -692,17 +768,36 @@ component_verify (struct component *comp, mu_debug_t debug)
case pies_comp_inetd:
if (!comp->socket_url)
{
- COMPERR (_("socket must be specified in this mode"));
+ COMPERR ("%s", _("socket must be specified in this mode"));
/* FIXME: Memory leak */
return 1;
}
}
- if (comp->mode != pies_comp_exec && comp->retr[RETR_OUT] != -1)
+ if (comp->mode != pies_comp_exec
+ && comp->retr[RETR_OUT].type != retr_null)
+ {
+ COMPERR ("%s", _("stdout retranslation invalid in this mode"));
+ comp->retr[RETR_OUT].type = retr_null;
+ }
+
+ for (i = RETR_OUT; i <= RETR_ERR; i++)
{
- COMPERR (_("stdout retranslation invalid in this mode"));
- comp->retr[RETR_OUT] = -1;
+ if (comp->retr[i].type == retr_file && comp->retr[i].v.file[0] != '/')
+ {
+ if (comp->dir)
+ {
+ char *p = make_full_name (comp->dir, comp->retr[i].v.file);
+ free (comp->retr[i].v.file);
+ comp->retr[i].v.file = p;
+ }
+ else
+ COMPERR (_("%s: must be an absolute "
+ "file name or chdir must be specified"),
+ comp->retr[i].v.file);
+ }
}
+
return header;
#undef COMPERR
}
@@ -728,7 +823,7 @@ component_section_parser (enum mu_cfg_section_stage stage,
{
comp = xzalloc (sizeof (*comp));
comp->facility = mu_log_facility;
- comp->retr[RETR_OUT] = comp->retr[RETR_ERR] = -1;
+ comp->retr[RETR_OUT].type = comp->retr[RETR_ERR].type = retr_null;
comp->tag = node->label ? xstrdup (node->label->v.string) : NULL;
}
*section_data = comp;
diff --git a/pies/pies.h b/pies/pies.h
index 3806f61..806c82f 100644
--- a/pies/pies.h
+++ b/pies/pies.h
@@ -47,13 +47,30 @@
#include "c-ctype.h"
#include "libmf.h"
-#define RETR_OUT 0
-#define RETR_ERR 1
-
#define TESTTIME 2*60
#define SLEEPTIME 5*60
#define MAXSPAWN 10
+#define RETR_OUT 0
+#define RETR_ERR 1
+
+enum retr_type
+{
+ retr_null,
+ retr_syslog,
+ retr_file
+};
+
+struct retranslator
+{
+ enum retr_type type;
+ union
+ {
+ int prio;
+ char *file;
+ } v;
+};
+
typedef struct limits_rec *limits_record_t;
struct pies_privs_data
@@ -121,7 +138,7 @@ struct component
mu_acl_t acl;
/* Retranslators: */
int facility; /* Syslog facility. */
- int retr[2]; /* Priorities for stdout and stderr */
+ struct retranslator retr[2]; /* Retranslators for stdout and stderr */
/* Actions to execute on various exit codes: */
struct action *act[MAX_RETURN_CODE+1];
};
diff --git a/pies/progman.c b/pies/progman.c
index 4fa6c81..215500d 100644
--- a/pies/progman.c
+++ b/pies/progman.c
@@ -213,9 +213,9 @@ progman_register_retranslators ()
if (IS_PROG (prog))
{
struct component *comp = prog->v.p.comp;
- if (comp->retr[RETR_OUT] != -1)
+ if (comp->retr[RETR_OUT].type != retr_null)
register_retr (RETR_OUT, prog);
- if (comp->retr[RETR_ERR] != -1)
+ if (comp->retr[RETR_ERR].type != retr_null)
register_retr (RETR_ERR, prog);
}
}
@@ -246,7 +246,7 @@ register_prog0 (struct component *comp)
comp->act[i] = default_component.act[i];
if (comp->mode != pies_comp_exec)
- comp->retr[RETR_OUT] = -1;
+ comp->retr[RETR_OUT].type = retr_null;
link_prog (newp, 0);
return newp;
@@ -348,24 +348,54 @@ retr_exit (int sig)
}
int
-open_retranslator (struct prog *master, int type)
+redirect_to_file (struct prog *master, int stream)
+{
+ struct passwd *pw;
+ int fd = open (master->v.p.comp->retr[stream].v.file, O_RDWR|O_CREAT,
+ 0644 & ~master->v.p.comp->umask);
+ if (fd == -1)
+ {
+ mu_error (_("cannot open output file %s: %s"),
+ master->v.p.comp->retr[stream].v.file,
+ mu_strerror (errno));
+ return -1;
+ }
+ /* Fix file ownership */
+ pw = getpwnam (master->v.p.comp->privs.user);
+ if (pw)
+ chown (master->v.p.comp->retr[stream].v.file, pw->pw_uid, pw->pw_gid);
+ return fd;
+}
+
+int
+open_retranslator (struct prog *master, int stream)
{
int p[2];
FILE *fp;
char *buf = NULL;
size_t size = 0;
pid_t pid;
- int i;
+ int i, prio;
char *tag;
- if (master->v.p.comp->retr[type] == -1)
- return -1;
+ switch (master->v.p.comp->retr[stream].type)
+ {
+ case retr_null:
+ return -1;
+
+ case retr_file:
+ return redirect_to_file (master, stream);
+
+ case retr_syslog:
+ break;
+ }
+
pipe (p);
switch (pid = fork ())
{
case 0:
/* Retranslator process */
- tag = retr_tag (master->tag, type);
+ tag = retr_tag (master->tag, stream);
mf_proctitle_format ("pies: %s retranslator", tag);
free (tag);
@@ -383,8 +413,9 @@ open_retranslator (struct prog *master, int type)
if (fp == NULL)
exit (1);
openlog (master->tag, LOG_PID, master->facility);
+ prio = master->v.p.comp->retr[stream].v.prio;
while (getline (&buf, &size, fp) > 0)
- syslog (master->v.p.comp->retr[type], "%s", buf);
+ syslog (prio, "%s", buf);
exit (0);
case -1:
@@ -394,7 +425,7 @@ open_retranslator (struct prog *master, int type)
return -1;
default:
- update_retr (type, master, pid);
+ update_retr (stream, master, pid);
close (p[0]);
return p[1];
}
@@ -687,7 +718,7 @@ prog_start (struct prog *prog)
if (retr[RETR_OUT] == -1)
{
close (1);
- open ("/dev/null", O_RDWR);
+ open ("/dev/null", O_WRONLY);
}
else if (retr[RETR_OUT] != 1)
{
@@ -707,7 +738,7 @@ prog_start (struct prog *prog)
if (retr[RETR_ERR] == -1)
{
close (2);
- open ("/dev/null", O_RDWR);
+ open ("/dev/null", O_WRONLY);
}
else if (retr[RETR_ERR] != 1)
{

Return to:

Send suggestions and report system problems to the System administrator.