OSDN Git Service

* netdb.cc: New file.
authorcgf <cgf>
Wed, 4 Dec 2002 20:44:16 +0000 (20:44 +0000)
committercgf <cgf>
Wed, 4 Dec 2002 20:44:16 +0000 (20:44 +0000)
* Makeile.in (DLL_OFILES): Add reference to the new netdb.cc file.
* cygwin.din : Add new aliased exports for service and protocol enumerations in
netdb.cc.

winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/cygwin.din
winsup/cygwin/include/cygwin/version.h
winsup/cygwin/netdb.cc [new file with mode: 0644]

index 8fc1548..8b5b145 100644 (file)
@@ -1,3 +1,10 @@
+2002-12-04  Craig McGeachie  <slapdau@yahoo.com.au>
+
+       * netdb.cc: New file.
+       * Makeile.in (DLL_OFILES): Add reference to the new netdb.cc file.
+       * cygwin.din : Add new aliased exports for service and protocol
+       enumerations in netdb.cc.
+
 2002-11-26  Thomas Pfaff  <tpfaff@gmx.net>
 
        * cxx.cc: New file. Implement new, new[], delete and delete[]
index 94dac23..bddc628 100644 (file)
@@ -135,16 +135,15 @@ DLL_OFILES:=assert.o autoload.o cxx.o cygheap.o cygserver_client.o \
        fhandler_raw.o fhandler_registry.o fhandler_serial.o \
        fhandler_socket.o fhandler_tape.o fhandler_termios.o \
        fhandler_tty.o fhandler_virtual.o fhandler_windows.o \
-       fhandler_zero.o fnmatch.o fork.o glob.o grp.o heap.o init.o \
-       ioctl.o ipc.o localtime.o malloc.o malloc_wrapper.o \
-       miscfuncs.o mmap.o msg.o net.o ntea.o passwd.o path.o pinfo.o \
-       pipe.o poll.o pthread.o regcomp.o regerror.o regexec.o \
-       regfree.o registry.o resource.o scandir.o sched.o sec_acl.o \
-       sec_helper.o security.o select.o sem.o shared.o shm.o signal.o \
-       sigproc.o smallprint.o spawn.o strace.o strsep.o sync.o \
-       syscalls.o sysconf.o syslog.o termios.o thread.o times.o tty.o \
-       uinfo.o uname.o v8_regexp.o v8_regerror.o v8_regsub.o wait.o \
-       wincap.o window.o \
+       fhandler_zero.o fnmatch.o fork.o glob.o grp.o heap.o init.o ioctl.o \
+       ipc.o localtime.o malloc.o malloc_wrapper.o miscfuncs.o mmap.o msg.o \
+       net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o pthread.o \
+       regcomp.o regerror.o regexec.o regfree.o registry.o resource.o \
+       scandir.o sched.o sec_acl.o sec_helper.o security.o select.o sem.o \
+       shared.o shm.o signal.o sigproc.o smallprint.o spawn.o strace.o \
+       strsep.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \
+       times.o tty.o uinfo.o uname.o v8_regexp.o v8_regerror.o v8_regsub.o \
+       wait.o wincap.o window.o \
        $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
 
 GMON_OFILES:=gmon.o mcount.o profil.o
index 94a0dd6..4a2a949 100644 (file)
@@ -1308,3 +1308,9 @@ acltotext
 _acltotext = acltotext
 aclfromtext
 _aclfromtext = aclfromtext
+setprotoent = cygwin_setprotoent
+setservent = cygwin_setservent
+getservent = cygwin_getservent
+getprotoent = cygwin_getprotoent
+endprotoent = cygwin_endprotoent
+endservent = cygwin_endservent
index b2ac4f9..26a03b5 100644 (file)
@@ -165,12 +165,13 @@ details. */
        65: Export siginterrupt
        66: Export nl_langinfo
        67: Export pthread_getsequence_np
+       68: Export netdb stuff
      */
 
      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 67
+#define CYGWIN_VERSION_API_MINOR 68
 
      /* There is also a compatibity version number associated with the
        shared memory regions.  It is incremented when incompatible
diff --git a/winsup/cygwin/netdb.cc b/winsup/cygwin/netdb.cc
new file mode 100644 (file)
index 0000000..d449a7d
--- /dev/null
@@ -0,0 +1,431 @@
+/* netdb.cc: network database related routines.
+
+   Copyright 2002 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <windows.h>
+#include <sys/cygwin.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netdb.h>
+
+/* Locate and open a system network database file.  relative_path
+ should be one of the following values:
+ "protocol"
+ "services"
+ "networks"
+ "hosts"
+
+ This routine will try to locate these files based on system type.
+ Currently the only distinction made is between NT and non-NT systems.
+
+ It is the callers responsibility to close the file.  */
+static FILE *
+open_system_file (const char *relative_path)
+{
+  char win32_name[MAX_PATH];
+  char posix_name[MAX_PATH];
+  if (wincap.is_winnt ())
+    {
+      if (!GetSystemDirectory (win32_name, MAX_PATH))
+       return NULL;
+      strcat (win32_name, "\\drivers\\etc\\");
+    }
+  else
+    {
+      if (!GetWindowsDirectory (win32_name, MAX_PATH))
+       return NULL;
+      strcat (win32_name, "\\");
+    }
+  strcat (win32_name, relative_path);
+  cygwin_conv_to_full_posix_path (win32_name, posix_name);
+  debug_printf ("netdb file to open %s", win32_name);
+  FILE *result = fopen (posix_name, "rt");
+  debug_printf ("handle to netdb file %p", result);
+  return result;
+}
+
+inline static FILE *
+open_protocol_file ()
+{
+  return open_system_file ("protocol");
+}
+
+/* Wrapper for open_system_file(), fixing the constant name
+"services".  Returns the open file. */
+inline static FILE *
+open_services_file ()
+{
+  return open_system_file ("services");
+}
+
+/* Read an entire line up till the next \n character.  Memory for the
+line is dynamically allocated, and the caller must call free() to
+deallocate it.  When the end of file is reached, NULL is returned.  */
+static char *
+get_entire_line (FILE *fd)
+{
+  static const int BUFF_SIZE = 1024;
+  struct line_fragment
+  {
+    char buffer[BUFF_SIZE];
+    line_fragment *next;
+  };
+
+  line_fragment *fragment_list_head = NULL;
+  line_fragment *fragment = NULL;
+  int fragment_count = 0;
+  char *result;
+
+  do
+    {
+      line_fragment *new_fragment = (line_fragment *) malloc (sizeof (line_fragment));
+      paranoid_printf ("line fragment allocated %p", new_fragment);
+      if (!fragment_list_head)
+       fragment_list_head = new_fragment;
+      if (fragment)
+       fragment->next = new_fragment;
+      fragment = new_fragment;
+      fragment->next = NULL;
+      *fragment->buffer = '\0';
+      result = fgets (fragment->buffer, BUFF_SIZE, fd);
+      ++fragment_count;
+    }
+  while (result && !strchr (fragment->buffer, '\n'));
+
+  if (*fragment_list_head->buffer != '\0')
+    {
+      char *concatenated_line = (char *) calloc (fragment_count * BUFF_SIZE , sizeof (char));
+      paranoid_printf ("concatenated line allocated %p", concatenated_line);
+      *concatenated_line = '\0';
+      fragment = fragment_list_head;
+      while (fragment != NULL)
+       {
+         line_fragment *previous = fragment;
+         strcat (concatenated_line, fragment->buffer);
+         fragment = fragment->next;
+         free (previous);
+       }
+      return concatenated_line;
+    }
+  else
+    {
+      fragment = fragment_list_head;
+      while (fragment != NULL)
+       {
+         line_fragment *previous = fragment;
+         fragment = fragment->next;
+         free (previous);
+       }
+      return NULL;
+    }
+}
+
+/* Characters representing whitespace.  Used by parse_* routines to
+delimit tokens.  */
+static const NO_COPY char *SPACE = " \t\n\r\f";
+
+/* Parse a list aliases from a network database file.  Returns a
+char** structure terminated by a NULL.
+
+N.B. This routine relies on side effects due to the nature of
+strtok().  strtok() initially takes a char * pointing to the start of
+a line, and then NULL to indicate continued processing.  strtok() does
+not provide a mechanism for getting pointer to the unprocessed portion
+of a line.  Alias processing is done part way through a line after
+strtok().  This routine relies on further calls to strtok(), passing
+NULL as the first parameter, returning alias names from the line. */
+static void
+parse_alias_list (char ***aliases)
+{
+  struct alias_t
+  {
+    char *alias_name;
+    alias_t *next;
+  };
+  alias_t *alias_list_head = NULL, *alias_list_tail = NULL;
+  char *alias;
+  int alias_count = 0;
+  alias = strtok (NULL, SPACE);
+
+  while (alias)
+    {
+      ++alias_count;
+      alias_t *new_alias = (alias_t *) malloc (sizeof (alias_t));
+      paranoid_printf ("new alias alloc %p", new_alias);
+      if (!alias_list_head)
+       alias_list_head = new_alias;
+      if (alias_list_tail)
+       alias_list_tail->next = new_alias;
+      new_alias->next = NULL;
+      new_alias->alias_name = alias;
+      alias_list_tail = new_alias;
+      alias = strtok (NULL, SPACE);
+    }
+
+  *aliases = (char**) calloc (alias_count + 1, sizeof (char *));
+  paranoid_printf ("aliases alloc %p", *aliases);
+
+  char **current_entry = *aliases;
+  while (alias_list_head)
+    {
+      alias_t *previous = alias_list_head;
+      *current_entry = strdup (alias_list_head->alias_name);
+      paranoid_printf ("*current entry strdup %p", *current_entry);
+      alias_list_head = alias_list_head->next;
+      free (previous);
+      ++current_entry;
+    }
+
+  *current_entry = NULL;
+}
+
+/* Read the next line from svc_file, and parse it into the structure
+pointed to by sep.  sep can point to stack or static data, but it's
+members will be overwritten with pointers to dynamically allocated
+heap data accommodating parsed data.  It is the responsibility of the
+caller to free up the allocated structures. The function returns true
+to indicate that a line was successfully read and parsed.  False is
+used to indicate that no more lines can be read and parsed.  This
+should also interpreted as end of file. */
+static bool
+parse_services_line (FILE *svc_file, struct servent *sep)
+{
+  char *line;
+  while ((line = get_entire_line (svc_file)))
+    {
+      char *name, *port, *protocol;
+
+      line[strcspn (line, "#")] = '\0'; // truncate at comment marker.
+      name = strtok (line, SPACE);
+      if (!name)
+       {
+         free (line);
+         continue;
+       }
+      port = strtok (NULL, SPACE);
+      protocol = strchr (port, '/');
+      *protocol++ = '\0';
+      sep->s_name = strdup (name);
+      paranoid_printf ("sep->s_name strdup %p", sep->s_name);
+      sep->s_port = atoi (port);
+      sep->s_proto = strdup (protocol);
+      paranoid_printf ("sep->s_proto strdup %p", sep->s_proto);
+      /* parse_alias_list relies on side effects.  Read the comments
+        for that function.*/
+      parse_alias_list (& sep->s_aliases);
+      free (line);
+      return true;
+    }
+  return false;
+}
+
+static FILE *svc_file = NULL;
+static long int svc_read_pos = 0;
+static struct servent current_servent;
+
+/* Steps through a struct servent, and frees all of the internal
+structures.*/
+static void
+free_servent (struct servent *sep)
+{
+  free (sep->s_name);
+  free (sep->s_proto);
+  char ** current = sep->s_aliases;
+  while (current && *current)
+    {
+      free (*current);
+      ++current;
+    }
+  free (sep->s_aliases);
+  sep->s_name = NULL;
+  sep->s_port = 0;
+  sep->s_proto = NULL;
+  sep->s_aliases = NULL;
+}
+
+extern "C" void
+cygwin_setservent (int stay_open)
+{
+  if (svc_file)
+    fclose (svc_file);
+  if (stay_open)
+    svc_file = open_services_file ();
+  free_servent (&current_servent);
+  svc_read_pos = 0;
+  syscall_printf ("setservent (%d)", stay_open);
+}
+
+extern "C" struct servent *
+cygwin_getservent (void)
+{
+  FILE *fd;
+  if (svc_file)
+    fd = svc_file;
+  else
+    {
+      fd = open_services_file ();
+      if (!fd)
+       {
+         syscall_printf ("%p = getservent()", NULL);
+         return NULL;
+       }
+      fseek (fd, svc_read_pos, SEEK_SET);
+    }
+  free_servent (&current_servent);
+  bool found = parse_services_line (fd, &current_servent);
+  if (!svc_file)
+    {
+      svc_read_pos = ftell (fd);
+      fclose (fd);
+    }
+  struct servent *result;
+  if (found)
+    result = &current_servent;
+  else
+    result = NULL;
+  syscall_printf ("%p = getservent()", result);
+  return result;
+}
+
+extern "C" void
+cygwin_endservent (void)
+{
+  if (svc_file)
+    {
+      fclose (svc_file);
+      svc_file = NULL;
+    }
+  free_servent (&current_servent);
+  svc_read_pos = 0;
+  syscall_printf ("endservent ()");
+}
+
+/* Read the next line from proto_file, and parse it into the structure
+pointed to by pep.  pep can point to stack or static data, but it's
+members will be overwritten with pointers to dynamically allocated
+heap data accommodating parsed data.  It is the responsibility of the
+caller to free up the allocated structures. The function returns true
+to indicate that a line was successfully read and parsed.  False is
+used to indicate that no more lines can be read and parsed.  This
+should also interpreted as end of file. */
+static bool
+parse_protocol_line (FILE *proto_file, struct protoent *pep)
+{
+  char *line;
+  while ((line = get_entire_line (proto_file)))
+    {
+      char *name, *protocol;
+
+      line[strcspn (line, "#")] = '\0'; // truncate at comment marker.
+      name = strtok (line, SPACE);
+      if (!name)
+       {
+         free (line);
+         continue;
+       }
+      protocol = strtok (NULL, SPACE);
+      pep->p_name = strdup (name);
+      paranoid_printf ("pep->p_name strdup %p", pep->p_name);
+      pep->p_proto = atoi (protocol);
+      /* parse_alias_list relies on side effects.  Read the comments
+        for that function.*/
+      parse_alias_list (& pep->p_aliases);
+      free (line);
+      return true;
+    }
+  return false;
+}
+
+static FILE *proto_file = NULL;
+static long int proto_read_pos = 0;
+static struct protoent current_protoent;
+
+/* Steps through a struct protoent, and frees all the internal
+structures.  */
+static void
+free_protoent (struct protoent *pep)
+{
+  free (pep->p_name);
+  char ** current = pep->p_aliases;
+  while (current && *current)
+    {
+      free (*current);
+      ++current;
+    }
+  free (pep->p_aliases);
+  pep->p_name = NULL;
+  pep->p_proto = 0;
+  pep->p_aliases = NULL;
+}
+
+extern "C" void
+cygwin_setprotoent (int stay_open)
+{
+  if (proto_file)
+    fclose (proto_file);
+
+  if (stay_open)
+    proto_file = open_protocol_file ();
+
+  free_protoent (&current_protoent);
+  proto_read_pos = 0;
+  syscall_printf ("setprotoent (%d)", stay_open);
+}
+
+extern "C" struct protoent *
+cygwin_getprotoent (void)
+{
+  FILE *fd;
+
+  if (proto_file)
+    fd = proto_file;
+  else
+    {
+      fd = open_protocol_file ();
+      if (!fd)
+       {
+         syscall_printf ("%p = getprotoent()", NULL);
+         return NULL;
+       }
+      fseek (fd, proto_read_pos, SEEK_SET);
+    }
+  free_protoent (&current_protoent);
+
+  bool found = parse_protocol_line (fd, &current_protoent);
+  if (!proto_file)
+    {
+      proto_read_pos = ftell (fd);
+      fclose (fd);
+    }
+
+  struct protoent *result;
+  if (found)
+    result =  &current_protoent;
+  else
+    result =  NULL;
+
+  syscall_printf ("%p = getprotoent()", result);
+  return result;
+}
+
+extern "C" void
+cygwin_endprotoent (void)
+{
+  if (proto_file)
+    {
+      fclose (proto_file);
+      proto_file = NULL;
+    }
+
+  free_protoent (&current_protoent);
+  proto_read_pos = 0;
+  syscall_printf ("endprotoent ()");
+}