* Europagate, 1995
*
* $Log: monitor.c,v $
- * Revision 1.5 1995/05/03 07:37:42 adam
+ * Revision 1.6 1995/05/03 09:16:17 adam
+ * Minor changes.
+ *
+ * Revision 1.5 1995/05/03 07:37:42 adam
* CCL commands stop/continue implemented. New functions gw_res_{int,bool}
* are used when possible.
*
static int max_process = 1;
static int got_sighup = 0;
static int got_term = 0;
+static int got_int = 0;
const char *default_res = "default.res";
+/*
+ * reread_resources: reread monitor resources. The static variable,
+ * max_process, is updated.
+ */
static void reread_resources (void)
{
if (monitor_res)
}
struct ke_info {
- pid_t pid;
- int id;
- GIP gip;
- struct str_queue *queue;
- struct ke_info *next;
+ int id; /* email user-id */
+ pid_t pid; /* pid of email kernel child */
+ GIP gip; /* fifo information */
+ struct str_queue *queue; /* message queue */
+ struct ke_info *next; /* link to next */
};
-struct ke_info *ke_info_list = NULL;
+/* list of email kernel infos */
+static struct ke_info *ke_info_list = NULL;
+/*
+ * ke_info_add: add/lookup of email kernel info.
+ * id: email user-id to search for.
+ * return: pointer to info structure.
+ */
struct ke_info *ke_info_add (int id)
{
struct ke_info **kip;
free (ki);
}
+/*
+ * catch_child: catch SIGCHLD. Set email kernel pid to -1
+ * to indicate that child has exited
+ */
static void catch_child (int num)
{
pid_t pid;
signal (SIGCHLD, catch_child);
}
+/*
+ * catch_int: catch SIGHUP.
+ */
static void catch_hup (int num)
{
got_sighup = 1;
signal (SIGHUP, catch_hup);
}
+/*
+ * catch_int: catch SIGTERM.
+ */
static void catch_term (int num)
{
got_term = 1;
signal (SIGTERM, catch_term);
}
+/*
+ * catch_int: catch SIGINT.
+ */
+static void catch_int (int num)
+{
+ got_int = 1;
+ signal (SIGINT, catch_int);
+}
+
+/*
+ * pipe_handle: handle SIGPIPE when transferring message to kernel
+ */
static void pipe_handle (int dummy)
{
longjmp (retry_jmp, 1);
}
+/*
+ * start_kernel: start email kernel.
+ * argc: argc of email kernel
+ * argv: argv of email kernel
+ * id: email user-id
+ * return: pid of email kernel child
+ */
static pid_t start_kernel (int argc, char **argv, int id)
{
pid_t pid;
return pid;
}
+/*
+ * deliver: deliver message to child (email kernel).
+ * argc: exec argc to child (if it need to be started)
+ * argv: exec argv to child (if it need to be started)
+ * id: email userid
+ * queue: message queue to be transferred
+ * gip: pointer to FIFO info. if *gip is NULL prior invocation
+ * it will be created (initialized) and the pointer will be
+ * updated.
+ * pidp: pointer to pid. Will hold process-id of child (if it need to
+ * be started)
+ * dont_exec: if non-zero a child will never be started; otherwise child
+ * will be started if not already running.
+ * return: 0 if message couldn't be transferred, i.e. dont_exec is non-zero
+ * and the child is not already running.
+ * 1 if message was transferred and the child was already running.
+ * 2 if message was transferred and the child was started and
+ * dont_exec was zero.
+ * 3 serious error. Permissions denied or kernel couldn't be
+ * started at all.
+ */
static int deliver (int argc, char **argv, int id, struct str_queue *queue,
GIP *gip, pid_t *pidp, int dont_exec)
{
setjmp (retry_jmp);
++pass;
if (pass == 1)
- {
- gipc_close (*gip);
- r = gipc_open (*gip, fifo_server_name, 0);
+ { /* assume child is running */
+ gipc_close (*gip); /* shut down existing FIFOs */
+ r = gipc_open (*gip, fifo_server_name, 0); /* try re-open ... */
}
else if (pass == 2)
- {
+ { /* assume child is NOT running */
pid_t pid;
if (dont_exec)
- {
+ { /* we aren't allowed to start */
signal (SIGPIPE, oldsig);
return 0;
}
mknod (fifo_server_name, S_IFIFO|0666, 0);
pid = start_kernel (argc, argv, id);
- if (pidp)
+ if (pidp) /* set pid of child */
*pidp = pid;
r = gipc_open (*gip, fifo_server_name, 1);
}
else
- {
+ { /* message couldn't be transferred */
signal (SIGPIPE, oldsig);
gw_log (GW_LOG_WARN, module, "Cannot start kernel");
- return 0;
+ return 3;
}
- if (r < 0)
+ if (r < 0) /* gipc_open fail? */
{
if (r == -2)
- {
gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-2");
- longjmp (retry_jmp, 1);
- }
else if (r == -1)
- {
gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "r==-1");
- longjmp (retry_jmp, 1);
- }
else
- {
gw_log (GW_LOG_WARN|GW_LOG_ERRNO, module, "gipc_open");
- }
+ longjmp (retry_jmp, 1); /* yet another pass */
}
- index = 0;
+ index = 0; /* transfer. may be interrupted */
while ((msg = str_queue_get (queue, index++)))
gip_wline (*gip, msg);
signal (SIGPIPE, oldsig);
- return pass;
+ return pass; /* successful transfer */
}
+/*
+ * monitor_events: Event loop of monitor
+ * argc: argc of monitor (used in exec of Email kernel children)
+ * argv: argv of monitor (used in exec of Email kernel children)
+ */
static void monitor_events (int argc, char **argv)
{
GIP gip_m;
unlink (MONITOR_FIFO_C);
exit (0);
}
+ if (got_int)
+ {
+ gw_log (GW_LOG_STAT, module, "Got SIGINT. Exiting...");
+ unlink (MONITOR_FIFO_S);
+ unlink (MONITOR_FIFO_C);
+ exit (0);
+ }
+ /* deliver any unsent messages to Email kernels */
for (ki = ke_info_list; ki; ki = ki->next)
{
if (!ki->queue)
gw_log (GW_LOG_DEBUG, module, "Transfer mail to %d", ki->id);
r = deliver (argc, argv, ki->id, ki->queue, &ki->gip, &ki->pid,
no_process >= max_process);
- if (r == 2)
+ if (r == 2) /* new child was spawned? */
++no_process;
- if (r == 1 || r == 2)
+ if (r == 1 || r == 2) /* transfer at all? */
str_queue_rm (&ki->queue);
}
FD_ZERO (&set_r);
if (ki->gip)
{
if (ki->pid == -1)
- {
+ { /* child has exited */
gw_log (GW_LOG_DEBUG, module, "Close of %d", ki->id);
gipc_close (ki->gip);
gipc_destroy (ki->gip);
ki->gip = NULL;
}
else if ((fd = gip_infileno (ki->gip)) != -1)
- {
+ { /* read select on child FIFO */
gw_log (GW_LOG_DEBUG, module, "set fd %d", fd);
FD_SET (fd, &set_r);
if (fd > fd_max)
if (r != -1)
break;
if (errno != EINTR)
- {
+ { /* select aborted. And it was not due to interrupt */
gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, module, "select");
exit (1);
}
+ /* select was interrupted. Probably child has died */
gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, module, "select");
}
+ /* go through list of Email kernels. See if any message has arrived */
gw_log (GW_LOG_DEBUG, module, "Testing ke_info_list");
for (ki = ke_info_list; ki; ki = ki->next)
{
}
}
}
+ /* see if any message from eti has arrived */
gw_log (GW_LOG_DEBUG, module, "Testing gip_m_fd %d", gip_m_fd);
if (FD_ISSET (gip_m_fd, &set_r))
{
}
}
+/*
+ * main: main of monitor
+ */
int main (int argc, char **argv)
{
int argno = 0;
signal (SIGCHLD, catch_child);
signal (SIGHUP, catch_hup);
signal (SIGTERM, catch_term);
+ signal (SIGINT, catch_int);
#if 0
gw_log_file (GW_LOG_ALL, "monitor.log");
#endif