/* This file is part of Mailfromd.
Copyright (C) 2007, 2008 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 of the License, 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/>. */
#include "pies.h"
#define TYPE_COMPONENT 0
#define TYPE_RETR 1
enum prog_status
{
status_enabled, /* Component enabled. prog->pid!=0 shows if it is
actually running */
status_disabled, /* Component is disabled. */
status_listener, /* Component is an inetd listener */
status_sleeping, /* Component is sleeping. An attempt to start it will
be made at prog->v.p.timestamp + SLEEPTIME */
status_stopping, /* Component is being stopped */
};
struct prog
{
struct prog *next, *prev;
int type;
pid_t pid; /* PID */
char *tag; /* Entry tag (for diagnostics purposes) */
int idx; /* Numeric identifier */
char **prereq;
int facility;
union
{
struct
{
struct component *comp;
int argc; /* Number of elements in comp->argv */
int socket;
struct prog *redir[2]; /* Pointers to redirectors */
time_t timestamp; /* Time of last startup */
size_t count; /* Number of failed starts since timestamp */
enum prog_status status; /* Current component status */
} p;
struct
{
struct prog *master;
} r;
} v;
};
#define IS_PROG(p) ((p)->type == TYPE_COMPONENT)
static int numprog;
static struct prog *proghead, *progtail;
static pies_depmap_t depmap;
static int recompute_alarm;
static struct prog *
prog_lookup_by_pid (pid_t pid)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
if (prog->pid == pid)
break;
return prog;
}
static struct prog *
prog_lookup_by_socket (int fd)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
if (IS_PROG (prog) && prog->v.p.socket == fd)
break;
return prog;
}
struct prog *
prog_lookup_by_tag (const char *tag)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
if (strcmp (prog->tag, tag) == 0)
break;
return prog;
}
struct component *
progman_lookup_component (const char *tag)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
if (IS_PROG (prog) && strcmp (prog->tag, tag) == 0)
return prog->v.p.comp;
return NULL;
}
struct prog *
prog_lookup_by_idx (unsigned idx)
{
struct prog *prog;
for (prog = proghead; prog; prog = prog->next)
if (prog->idx == idx)
break;
return prog;
}
static void prog_stop (struct prog *prog, int sig);
static int prog_start_prerequisites (struct prog *prog);
void
link_prog (struct prog *pp, int prepend)
{
if (prepend)
{
if (proghead)
proghead->prev = pp;
pp->prev = NULL;
pp->next = proghead;
proghead = pp;
if (!progtail)
progtail = pp;
}
else
{
pp->next = NULL;
pp->prev = progtail;
if (progtail)
progtail->next = pp;
else
proghead = pp;
progtail = pp;
}
}
void
unlink_prog (struct prog *pp)
{
struct prog *x;
if (x = pp->prev)
x->next = pp->next;
else
proghead = pp->next;
if (x = pp->next)
x->prev = pp->prev;
else
progtail = pp->prev;
}
void
destroy_prog (struct prog **pp)
{
unlink_prog (*pp);
free (*pp);
*pp = NULL;
}
static char *
redir_tag (struct prog *master, int type)
{
static char *redirstr[2] = { "stdout", "stderr" };
char *str = NULL;
if (type < MU_ARRAY_SIZE(redirstr))
asprintf (&str, "%s/%s", master->tag, redirstr[type]);
else
asprintf (&str, "%s/%d", master->tag, type);
if (!str)
xalloc_die ();
return str;
}
static struct prog *
register_redir (int type, struct prog *master)
{
char *tag = redir_tag (master, type);
char *pstr;
struct prog *pp = xzalloc (sizeof (*pp) + strlen (tag) + 1 +
2 * sizeof (char**)
|