/* * 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 * from code by Patrick Amar * * $Id$ * * Please refer to file version.h for the * copyright notice regarding this software * */ #include #include #include #include #include #include #include #include #include #include #include #include #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); }