aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/Makefile.in19
-rw-r--r--winsup/cygwin/cygwin.din6
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/netdb.cc431
5 files changed, 455 insertions, 11 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 8fc1548..8b5b145 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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[]
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 94dac23..bddc628 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -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
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 94a0dd6..4a2a949 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -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
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index b2ac4f9..26a03b5 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -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
index 0000000..d449a7d
--- /dev/null
+++ b/winsup/cygwin/netdb.cc
@@ -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 ()");
+}