Back to index

glibc  2.9
hurdsock.c
Go to the documentation of this file.
00001 /* _hurd_socket_server - Find the server for a socket domain.
00002    Copyright (C) 1991,92,93,94,95,97,99 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <hurd.h>
00021 #include <sys/socket.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <hurd/paths.h>
00025 #include <stdio.h>
00026 #include "stdio-common/_itoa.h"
00027 #include <cthreads.h>              /* For `struct mutex'.  */
00028 #include "hurdmalloc.h"            /* XXX */
00029 
00030 static struct mutex lock;
00031 
00032 static file_t *servers;
00033 static int max_domain = -1;
00034 
00035 /* Return a port to the socket server for DOMAIN.
00036    Socket servers translate nodes in the directory _SERVERS_SOCKET
00037    (canonically /servers/socket).  These naming point nodes are named
00038    by the simplest decimal representation of the socket domain number,
00039    for example "/servers/socket/3".
00040 
00041    Socket servers are assumed not to change very often.
00042    The library keeps all the server socket ports it has ever looked up,
00043    and does not look them up in /servers/socket more than once.  */
00044 
00045 socket_t
00046 _hurd_socket_server (int domain, int dead)
00047 {
00048   socket_t server;
00049 
00050   HURD_CRITICAL_BEGIN;
00051   __mutex_lock (&lock);
00052 
00053   if (domain > max_domain)
00054     {
00055       error_t save = errno;
00056       file_t *new = realloc (servers, (domain + 1) * sizeof (file_t));
00057       if (new != NULL)
00058        {
00059          do
00060            new[++max_domain] = MACH_PORT_NULL;
00061          while (max_domain < domain);
00062          servers = new;
00063        }
00064       else
00065        /* No space to cache the port; we will just fetch it anew below.  */
00066        errno = save;
00067     }
00068 
00069   if (dead && domain <= max_domain)
00070     {
00071       /* The user says the port we returned earlier (now in SERVERS[DOMAIN])
00072         was dead.  Clear the cache and fetch a new one below.  */
00073       __mach_port_deallocate (__mach_task_self (), servers[domain]);
00074       servers[domain] = MACH_PORT_NULL;
00075     }
00076 
00077   if (domain > max_domain || servers[domain] == MACH_PORT_NULL)
00078     {
00079       char name[sizeof (_SERVERS_SOCKET) + 100];
00080       char *np = &name[sizeof (name)];
00081       *--np = '\0';
00082       np = _itoa (domain, np, 10, 0);
00083       *--np = '/';
00084       np -= sizeof (_SERVERS_SOCKET) - 1;
00085       memcpy (np, _SERVERS_SOCKET, sizeof (_SERVERS_SOCKET) - 1);
00086       server = __file_name_lookup (np, 0, 0);
00087       if (domain <= max_domain)
00088        servers[domain] = server;
00089     }
00090   else
00091     server = servers[domain];
00092 
00093   if (server == MACH_PORT_NULL && errno == ENOENT)
00094     /* If the server node is absent, we don't support that protocol.  */
00095     errno = EAFNOSUPPORT;
00096 
00097   __mutex_unlock (&lock);
00098   HURD_CRITICAL_END;
00099 
00100   return server;
00101 }
00102 
00103 static void
00104 init (void)
00105 {
00106   int i;
00107 
00108   __mutex_init (&lock);
00109 
00110   for (i = 0; i < max_domain; ++i)
00111     servers[i] = MACH_PORT_NULL;
00112 
00113   (void) &init;                    /* Avoid "defined but not used" warning.  */
00114 }
00115 text_set_element (_hurd_preinit_hook, init);