From 838ad58232c99010e3171c1c0c6988f7e5f6f078 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Wed, 4 Dec 2002 20:44:17 +0000 Subject: * 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. --- winsup/cygwin/ChangeLog | 7 + winsup/cygwin/Makefile.in | 19 +- winsup/cygwin/cygwin.din | 6 + winsup/cygwin/include/cygwin/version.h | 3 +- winsup/cygwin/netdb.cc | 431 +++++++++++++++++++++++++++++++++ 5 files changed, 455 insertions(+), 11 deletions(-) create mode 100644 winsup/cygwin/netdb.cc 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 + + * 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 * 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 +#include +#include +#include +#include +#include + +/* 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 (¤t_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 (¤t_servent); + bool found = parse_services_line (fd, ¤t_servent); + if (!svc_file) + { + svc_read_pos = ftell (fd); + fclose (fd); + } + struct servent *result; + if (found) + result = ¤t_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 (¤t_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 (¤t_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 (¤t_protoent); + + bool found = parse_protocol_line (fd, ¤t_protoent); + if (!proto_file) + { + proto_read_pos = ftell (fd); + fclose (fd); + } + + struct protoent *result; + if (found) + result = ¤t_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 (¤t_protoent); + proto_read_pos = 0; + syscall_printf ("endprotoent ()"); +} -- cgit v1.1