summaryrefslogtreecommitdiff
path: root/src/inivyd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/inivyd.c')
-rw-r--r--src/inivyd.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/inivyd.c b/src/inivyd.c
new file mode 100644
index 0000000..56d7106
--- /dev/null
+++ b/src/inivyd.c
@@ -0,0 +1,221 @@
+/*
+ * IvyDaemon, an Ivy gateway for short-lived agents
+ *
+ * Copyright (C) 1999
+ * Centre d'Études de la Navigation Aérienne
+ *
+ * Main file for the super-daemon
+ *
+ * Author(s): Stephane Chatty <chatty@cenatoulouse.dgac.fr>
+ * from code by Patrick Amar <pa@lri.fr>
+ *
+ * $Id$
+ *
+ * Please refer to file version.h for the
+ * copyright notice regarding this software
+ *
+ */
+
+/*
+ * Le super-demon wixd.
+ *
+ * Il est normalement lance par inetd, avec la chaussette SOCK_DGRAM
+ * sur le descripteur 0, ou alors, si le symbole FROMBOOT est defini, il est
+ * lance depuis /etc/rc.local.
+ *
+ * Le serveur wixd:
+ * Il envoie un paquet connmsg de type MSG_SERVER contenant le numero
+ * de port sur lequel il a connecte sa chaussette.
+ *
+ * Les clients wix (wx, wxcat, etc ...):
+ * Ils envoient un paquet connmsg de type MSG_CLIENT ou ils demandent
+ * le port.
+ *
+ * L'identification de l'emetteur du paquet est le numero d'utilisateur.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include "ivyd.h"
+
+
+const char* const dumpfilename = "/usr/tmp/wixd.db";
+const int dumpfilemode = 0644;
+const char* const servicename = "ivyd";
+const char* const port_env_variable = "INIVYD_PORT";
+const int default_port = 3006;
+
+/*
+ * Definition de la table geree par le super-demon
+ */
+
+typedef struct {
+ short s_port; /* le port sur lequel le client communique avec son serveur */
+ short s_uid; /* le numero de processus du serveur wixd */
+} serverinfo;
+
+#define TABSIZ 64 /* 64 connections simultanees, ca devrait aller */
+serverinfo si_table [TABSIZ];
+
+/*
+ * GetInfo (name)
+ *
+ * Rend l'information concernant l'utilisateur uid.
+ */
+
+serverinfo*
+GetInfo (int uid)
+{
+ register serverinfo *si;
+ register serverinfo *res = 0;
+
+ for (si = si_table; si - si_table < TABSIZ; ++si) {
+ if (si->s_port == 0) {
+ if (! res)
+ res = si;
+ continue;
+ }
+ if (si->s_uid != uid)
+ continue;
+ res = si;
+ break;
+ }
+ return res;
+}
+
+/*
+ * DumpInfo ()
+ *
+ * Dumps to a file the contents of the table
+ */
+
+int
+DumpInfo ()
+{
+ register serverinfo *si;
+ register int fd = creat (dumpfilename, dumpfilemode);
+ char buf [512];
+
+ if (fd == -1)
+ return 0;
+
+ for (si = si_table; si - si_table < TABSIZ; ++si) {
+ if (! si->s_port)
+ continue;
+ (void) sprintf (buf, "user %5d, port %d\n", si->s_uid, ntohs (si->s_port));
+ (void) write (fd, buf, strlen (buf));
+ }
+ (void) close (fd);
+ return 1;
+}
+
+
+void
+SigHup (int sig)
+{
+ DumpInfo ();
+}
+
+void
+main (int argc, const char **argv)
+{
+ struct servent *serv;
+ u_short serv_port = 0;
+ struct sockaddr_in from;
+ int fromlen;
+ struct connmsg msg;
+ register serverinfo *si;
+ int boot = 0;
+ int debug = 0;
+
+ (void) signal (SIGHUP, SigHup);
+
+ serv = getservbyname (servicename, 0);
+
+ if (! serv) {
+ char *pp = getenv (port_env_variable);
+ serv_port = htons (pp ? atoi (pp) : default_port);
+ if (serv_port <= 0)
+ exit (0);
+ } else
+ serv_port = serv -> s_port;
+
+ ++argv;
+ while (argc > 1) {
+ if (strcmp (*argv, "-boot") == 0 || strcmp (*argv, "-b") == 0)
+ boot = 1;
+ else if (strcmp (*argv, "-debug") == 0 || strcmp (*argv, "-d") == 0)
+ debug = 1;
+ else
+ fprintf (stderr, "bad option %s\n", *argv);
+ ++argv;
+ --argc;
+ }
+
+ if (boot) {
+ if (!debug) {
+ int s;
+
+ if (fork ())
+ exit (0);
+
+ /* on ferme tous les descripteurs */
+ for (s = getdtablesize (); --s >= 0;)
+ close (s);
+
+ /* et on se debarrasse du terminal de controle */
+ if (-1 != open ("/dev/tty", 2)) {
+ (void) ioctl (0, TIOCNOTTY, 0);
+ close (0);
+ }
+ } else
+ close (0);
+
+ /*
+ * Ouvre la chaussette et l'attache a bon port
+ */
+ if (-1 == socket (AF_INET, SOCK_DGRAM, 0))
+ exit (1);
+ memset (&from, 0, sizeof from);
+ from.sin_family = AF_INET;
+ from.sin_port = serv_port;
+ from.sin_addr.s_addr = INADDR_ANY;
+ if (-1 == bind (0, &from, sizeof from))
+ exit (1);
+ }
+
+ for (;;) {
+ fromlen = sizeof from;
+ if (recvfrom (0, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&from, &fromlen) <= 0) {
+ if (errno == EINTR)
+ continue;
+ exit (1);
+ }
+ si = GetInfo (msg.msg_uid);
+ switch (msg.msg_type) {
+ case MSG_SERVER:
+ si->s_port = msg.msg_port;
+ si->s_uid = msg.msg_uid;
+ break;
+
+ case MSG_CLIENT:
+ msg.msg_port = si->s_port;
+ msg.msg_type = MSG_REPLY;
+ (void) sendto (0, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&from, fromlen);
+ break;
+ }
+
+ }
+}
+