summaryrefslogtreecommitdiff
path: root/src/ivyd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ivyd.c')
-rw-r--r--src/ivyd.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/ivyd.c b/src/ivyd.c
new file mode 100644
index 0000000..5a4f3d0
--- /dev/null
+++ b/src/ivyd.c
@@ -0,0 +1,271 @@
+/*
+ * IvyDaemon, an Ivy gateway for short-lived agents
+ *
+ * Copyright (C) 1999
+ * Centre d'Études de la Navigation Aérienne
+ *
+ * Main file for the server
+ *
+ * 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
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <memory.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "ivy.h"
+#include "ivyd.h"
+
+const char* const servicename = "ivyd";
+const char* const port_env_variable = "INIVYD_PORT";
+const int default_port = DEFAULT_INIVYD_PORT;
+
+static char * HomeDir;
+int debug = 0;
+
+static void
+Usage (const char* progname)
+{
+ fprintf (stderr, "Usage: %s [-b bus][-d]\n", progname);
+ fprintf (stderr, " -d: does not fork so as to facilitate debugging\n");
+ fprintf (stderr, " -b bus: selects Ivy bus on which to relay messages\n");
+ exit (1);
+}
+
+
+/*
+ * Envoie un numero de port au super-serveur de la machine locale
+ */
+int
+SendPort (int port)
+{
+ struct servent *serv;
+ u_short serv_port;
+ struct sockaddr_in sin;
+ struct connmsg msg;
+ int sock;
+ int res;
+
+ 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;
+
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1)
+ return 0;
+
+ memset (&sin, 0, sizeof sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = serv_port;
+ sin.sin_addr.s_addr = LOCALHOST;
+
+ msg.msg_uid = getuid ();
+ msg.msg_port = port;
+ msg.msg_type = MSG_SERVER;
+
+
+ res = sendto (sock, (char *)&msg, sizeof msg, 0, (struct sockaddr *)&sin, sizeof sin);
+
+ /* We only detect local errors, but we have no guarantee that there is someone
+ at the other end. We should fix that someday (by going connected?) */
+
+ if (res == -1)
+ goto failed;
+
+ (void) close (sock);
+ return 1;
+
+failed:
+ (void) close (sock);
+ return 0;
+}
+
+
+int
+InitSocket ()
+{
+ int s, i;
+ struct sockaddr_in addr;
+
+ s = socket (AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ perror ("socket");
+ return 0;
+ }
+
+ memset (&addr, 0, sizeof addr);
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (s, &addr, sizeof (addr)) == -1) {
+ perror ("bind");
+ return 0;
+ }
+
+ i = sizeof addr;
+ if (getsockname (s, &addr, &i) == -1) {
+ perror ("bind");
+ return 0;
+ }
+
+
+ if (debug)
+ printf ("Ivyd listens on port %d\n", ntohs (addr.sin_port));
+
+ if (! SendPort (addr.sin_port)) {
+ fprintf (stderr, "No Ivyd port server. Continuing with port = %d\n",
+ ntohs (addr.sin_port));
+ }
+
+ /* je me debarrasse du terminal de controle */
+
+/* freopen ("/dev/tty", "r+", stderr); */
+ for (i = 0; i < 32; i++)
+ if (i != fileno (stderr) && i != s)
+ close (i);
+
+#ifndef SYSV
+ i = open ("/dev/tty", 0);
+ if (i != -1) {
+ (void) ioctl (i, TIOCNOTTY, 0);
+ close (i);
+ }
+#endif SYSV
+ open ("/dev/null", 2); dup (0);
+
+
+ if (listen (s, 5) == -1) {
+ perror ("listen");
+ return 0;
+ }
+ return s;
+}
+
+
+void
+HandleRequests (void* ch, int fd, void* data)
+{
+ request req;
+ char* p = (char*) &req;
+ int n = sizeof (request);
+ struct sockaddr_in addr;
+ int len = sizeof (addr);
+
+ fprintf (stderr, "REQUEST on %d\n", fd);
+
+ /* retrieve request */
+ while (n > 0) {
+#if 1
+ int l = read (fd, p, n);
+#else
+ int l = recvfrom (fd, p, n, 0, (struct sockaddr*) &addr, &len);
+#endif
+ if (l < 0) {
+ perror ("Error retrieving request from client");
+ exit (0);
+ return;
+ } else if (l == 0) {
+ if (debug)
+ fprintf (stderr, "closing connection for %d\n", fd);
+ IvyChannelClose (ch);
+ close (fd);
+ return;
+ }
+ n -= l;
+ p += l;
+ }
+
+#if 0
+ answer ans;
+ ans.ok = 1;
+ write (
+#endif
+ fprintf (stderr, "REQUEST [%s]\n", req.buffer);
+ IvySendMsg (req.buffer);
+}
+
+void
+HandleConnections (void* ch, int fd, void* data)
+{
+ static struct sockaddr sa;
+ static int acc;
+ int newfd = accept (fd, &sa, &acc);
+ fprintf (stderr, "CONNECTION %d\n", newfd);
+ IvyChannelSetUp (newfd, 0, 0, HandleRequests);
+}
+
+
+void
+main (int argc, char **argv)
+{
+ int sock;
+ char busbuf [128];
+ const char* bus = 0;
+ int c;
+
+ /* handle args */
+ while ((c = getopt (argc, argv, "b:d")) != EOF) {
+ switch (c) {
+ case 'b':
+ strcpy (busbuf, optarg) ;
+ bus = busbuf;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ default:
+ Usage (argv[0]);
+ }
+ }
+
+ /* detach from tty */
+ if (! debug)
+ if (fork ())
+ exit (0);
+
+ /* create server port */
+ sock = InitSocket ();
+
+ signal (SIGTERM, exit); /* pour flinguer le serveur */
+
+#if 0
+ /*
+ * Charger le fichier de personnalisation.
+ */
+ HomeDir = getenv ("HOME");
+
+ if (!HomeDir || !*HomeDir)
+ fprintf (stderr, "%s: No HOME environment variable.\n", argv0);
+ else
+ StartUp (HomeDir);
+#endif
+
+ /* Ivy initialization and main loop */
+ IvyInit ("IVYD", 0, 0, 0, 0, 0, 0);
+ IvyChannelSetUp (sock, 0, 0, HandleConnections);
+ IvyStart (bus);
+ IvyMainLoop (0);
+}
+