diff options
author | Simon Josefsson <simon@josefsson.org> | 2006-05-12 10:02:14 +0000 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2006-05-12 10:02:14 +0000 |
commit | dd92699c22e89329f7be8e1cd3a580107f956098 (patch) | |
tree | 569f860873935ffa188ea232ef138f3f1e53ed54 | |
parent | 249474059250a2ad27c48e8071046058ee0da5bd (diff) | |
download | gnutls-dd92699c22e89329f7be8e1cd3a580107f956098.tar.gz |
Add getaddrinfo.
-rw-r--r-- | gl/Makefile.am | 8 | ||||
-rw-r--r-- | gl/gai_strerror.c | 80 | ||||
-rw-r--r-- | gl/getaddrinfo.c | 237 | ||||
-rw-r--r-- | gl/getaddrinfo.h | 120 | ||||
-rw-r--r-- | gl/m4/getaddrinfo.m4 | 75 | ||||
-rw-r--r-- | gl/m4/gnulib-cache.m4 | 4 | ||||
-rw-r--r-- | gl/m4/gnulib-comp.m4 | 9 | ||||
-rw-r--r-- | gl/m4/strdup.m4 | 17 | ||||
-rw-r--r-- | gl/strdup.c | 56 | ||||
-rw-r--r-- | gl/strdup.h | 29 |
10 files changed, 632 insertions, 3 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am index 6a70ba2286..bc49798890 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -8,7 +8,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl gc gc-arcfour gc-arctwo gc-des gc-hmac-md5 gc-md2 gc-md4 gc-md5 gc-pbkdf2-sha1 gc-random gc-rijndael gc-sha1 getline getpass gettext inet_ntop maintainer-makefile memmem memmove minmax readline snprintf socklen stdint +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl gc gc-arcfour gc-arctwo gc-des gc-hmac-md5 gc-md2 gc-md4 gc-md5 gc-pbkdf2-sha1 gc-random gc-rijndael gc-sha1 getaddrinfo getline getpass gettext inet_ntop maintainer-makefile memmem memmove minmax readline snprintf socklen stdint AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies @@ -51,6 +51,12 @@ endif ## end gnulib module gc +## begin gnulib module getaddrinfo + +libgnu_la_SOURCES += getaddrinfo.h + +## end gnulib module getaddrinfo + ## begin gnulib module gettext # This is for those projects which use "gettextize --intl" to put a source-code diff --git a/gl/gai_strerror.c b/gl/gai_strerror.c new file mode 100644 index 0000000000..faf2379596 --- /dev/null +++ b/gl/gai_strerror.c @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef _LIBC +# include "getaddrinfo.h" +#endif + +#include <stdio.h> +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif + +#ifdef _LIBC +# include <libintl.h> +#else +# include "gettext.h" +# define _(String) gettext (String) +# define N_(String) String +#endif + +static struct + { + int code; + const char *msg; + } +values[] = + { + { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, + { EAI_AGAIN, N_("Temporary failure in name resolution") }, + { EAI_BADFLAGS, N_("Bad value for ai_flags") }, + { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, + { EAI_FAMILY, N_("ai_family not supported") }, + { EAI_MEMORY, N_("Memory allocation failure") }, + { EAI_NODATA, N_("No address associated with hostname") }, + { EAI_NONAME, N_("Name or service not known") }, + { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, + { EAI_SOCKTYPE, N_("ai_socktype not supported") }, + { EAI_SYSTEM, N_("System error") }, +#ifdef __USE_GNU + { EAI_INPROGRESS, N_("Processing request in progress") }, + { EAI_CANCELED, N_("Request canceled") }, + { EAI_NOTCANCELED, N_("Request not canceled") }, + { EAI_ALLDONE, N_("All requests done") }, + { EAI_INTR, N_("Interrupted by a signal") }, + { EAI_IDN_ENCODE, N_("Parameter string not correctly encoded") } +#endif + }; + +const char * +gai_strerror (int code) +{ + size_t i; + for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i) + if (values[i].code == code) + return _(values[i].msg); + + return _("Unknown error"); +} +#ifdef _LIBC +libc_hidden_def (gai_strerror) +#endif diff --git a/gl/getaddrinfo.c b/gl/getaddrinfo.c new file mode 100644 index 0000000000..add1446006 --- /dev/null +++ b/gl/getaddrinfo.c @@ -0,0 +1,237 @@ +/* Get address information (partial implementation). + Copyright (C) 1997, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + Contributed by Simon Josefsson <simon@josefsson.org>. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "getaddrinfo.h" + +#if HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif + +/* Get calloc. */ +#include <stdlib.h> + +/* Get memcpy. */ +#include <string.h> + +#include <stdbool.h> + +#include "gettext.h" +#define _(String) gettext (String) +#define N_(String) String + +#include "strdup.h" + +static inline bool +validate_family (int family) +{ + /* FIXME: Support more families. */ +#if HAVE_IPV4 + if (family == PF_INET) + return true; +#endif +#if HAVE_IPV6 + if (family == PF_INET6) + return true; +#endif + if (family == PF_UNSPEC) + return true; + return false; +} + +/* Translate name of a service location and/or a service name to set of + socket addresses. */ +int +getaddrinfo (const char *restrict nodename, + const char *restrict servname, + const struct addrinfo *restrict hints, + struct addrinfo **restrict res) +{ + struct addrinfo *tmp; + struct servent *se = NULL; + struct hostent *he; + void *storage; + size_t size; +#if HAVE_IPV6 + struct v6_pair { + struct addrinfo addrinfo; + struct sockaddr_in6 sockaddr_in6; + }; +#endif +#if HAVE_IPV4 + struct v4_pair { + struct addrinfo addrinfo; + struct sockaddr_in sockaddr_in; + }; +#endif + + if (hints && (hints->ai_flags & ~AI_CANONNAME)) + /* FIXME: Support more flags. */ + return EAI_BADFLAGS; + + if (hints && !validate_family (hints->ai_family)) + return EAI_FAMILY; + + if (hints && + hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM) + /* FIXME: Support other socktype. */ + return EAI_SOCKTYPE; /* FIXME: Better return code? */ + + if (!nodename) + /* FIXME: Support server bind mode. */ + return EAI_NONAME; + + if (servname) + { + const char *proto = + (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp"; + + /* FIXME: Use getservbyname_r if available. */ + se = getservbyname (servname, proto); + + if (!se) + return EAI_SERVICE; + } + + /* FIXME: Use gethostbyname_r if available. */ + he = gethostbyname (nodename); + if (!he || he->h_addr_list[0] == NULL) + return EAI_NONAME; + + switch (he->h_addrtype) + { +#if HAVE_IPV6 + case PF_INET6: + size = sizeof (struct v6_pair); + break; +#endif + +#if HAVE_IPV4 + case PF_INET: + size = sizeof (struct v4_pair); + break; +#endif + + default: + return EAI_NODATA; + } + + storage = calloc (1, size); + if (!storage) + return EAI_MEMORY; + + switch (he->h_addrtype) + { +#if HAVE_IPV6 + case PF_INET6: + { + struct v6_pair *p = storage; + struct sockaddr_in6 *sinp = &p->sockaddr_in6; + tmp = &p->addrinfo; + + if (se) + sinp->sin6_port = se->s_port; + + if (he->h_length != sizeof (sinp->sin6_addr)) + { + free (storage); + return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ + } + + memcpy (&sinp->sin6_addr, he->h_addr_list[0], sizeof sinp->sin6_addr); + + tmp->ai_addr = (struct sockaddr *) sinp; + tmp->ai_addrlen = sizeof *sinp; + } + break; +#endif + +#if HAVE_IPV4 + case PF_INET: + { + struct v4_pair *p = storage; + struct sockaddr_in *sinp = &p->sockaddr_in; + tmp = &p->addrinfo; + + if (se) + sinp->sin_port = se->s_port; + + if (he->h_length != sizeof (sinp->sin_addr)) + { + free (storage); + return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */ + } + + memcpy (&sinp->sin_addr, he->h_addr_list[0], sizeof sinp->sin_addr); + + tmp->ai_addr = (struct sockaddr *) sinp; + tmp->ai_addrlen = sizeof *sinp; + } + break; +#endif + + default: + free (storage); + return EAI_NODATA; + } + + if (hints && hints->ai_flags & AI_CANONNAME) + { + const char *cn; + if (he->h_name) + cn = he->h_name; + else + cn = nodename; + + tmp->ai_canonname = strdup (cn); + if (!tmp->ai_canonname) + { + free (storage); + return EAI_MEMORY; + } + } + + tmp->ai_protocol = (hints) ? hints->ai_protocol : 0; + tmp->ai_socktype = (hints) ? hints->ai_socktype : 0; + tmp->ai_addr->sa_family = he->h_addrtype; + + /* FIXME: If more than one address, create linked list of addrinfo's. */ + + *res = tmp; + + return 0; +} + +/* Free `addrinfo' structure AI including associated storage. */ +void +freeaddrinfo (struct addrinfo *ai) +{ + while (ai) + { + struct addrinfo *cur; + + cur = ai; + ai = ai->ai_next; + + if (cur->ai_canonname) free (cur->ai_canonname); + free (cur); + } +} diff --git a/gl/getaddrinfo.h b/gl/getaddrinfo.h new file mode 100644 index 0000000000..eb0b718c37 --- /dev/null +++ b/gl/getaddrinfo.h @@ -0,0 +1,120 @@ +/* Get address information. + Copyright (C) 1996-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Contributed by Simon Josefsson <simon@josefsson.org>. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef GETADDRINFO_H +# define GETADDRINFO_H + +/* sys/socket.h in i386-unknown-freebsd4.10 and + powerpc-apple-darwin5.5 require sys/types.h, so include it first. + Then we'll also get 'socklen_t' and 'struct sockaddr' which are + used below. */ +# include <sys/types.h> +/* Get all getaddrinfo related declarations, if available. */ +# include <sys/socket.h> +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif + +# ifndef HAVE_STRUCT_ADDRINFO + +/* Structure to contain information about address of a service provider. */ +struct addrinfo +{ + int ai_flags; /* Input flags. */ + int ai_family; /* Protocol family for socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol for socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address for socket. */ + char *ai_canonname; /* Canonical name for service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +# endif + +/* Possible values for `ai_flags' field in `addrinfo' structure. */ +# ifndef AI_PASSIVE +# define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */ +# define AI_CANONNAME 0x0002 /* Request for canonical name. */ +# define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ +# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ +# define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */ +# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose + returned address type.. */ +# endif + +/* Error values for `getaddrinfo' function. */ +# ifndef EAI_BADFLAGS +# define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */ +# define EAI_NONAME -2 /* NAME or SERVICE is unknown. */ +# define EAI_AGAIN -3 /* Temporary failure in name resolution. */ +# define EAI_FAIL -4 /* Non-recoverable failure in name res. */ +# define EAI_NODATA -5 /* No address associated with NAME. */ +# define EAI_FAMILY -6 /* `ai_family' not supported. */ +# define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */ +# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +# define EAI_MEMORY -10 /* Memory allocation failure. */ +# define EAI_OVERFLOW -12 /* Argument buffer overflow. */ +#endif +# ifndef EAI_ADDRFAMILY +/* Not defined on mingw32. XXX May be incorrect? Perhaps it is never + returned? */ +# define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */ +# endif +# ifndef EAI_SYSTEM +/* Not defined on mingw32. XXX May be incorrect? Perhaps it is never + returned? */ +# define EAI_SYSTEM -11 /* System error returned in `errno'. */ +# endif + +# ifdef __USE_GNU +# ifndef EAI_INPROGRESS +# define EAI_INPROGRESS -100 /* Processing request in progress. */ +# define EAI_CANCELED -101 /* Request canceled. */ +# define EAI_NOTCANCELED -102 /* Request not canceled. */ +# define EAI_ALLDONE -103 /* All requests done. */ +# define EAI_INTR -104 /* Interrupted by a signal. */ +# define EAI_IDN_ENCODE -105 /* IDN encoding failed. */ +# endif +# endif + +# if !HAVE_DECL_GETADDRINFO +/* Translate name of a service location and/or a service name to set of + socket addresses. + For more details, see the POSIX:2001 specification + <http://www.opengroup.org/susv3xsh/getaddrinfo.html>. */ +extern int getaddrinfo (const char *restrict nodename, + const char *restrict servname, + const struct addrinfo *restrict hints, + struct addrinfo **restrict res); +# endif + +# if !HAVE_DECL_FREEADDRINFO +/* Free `addrinfo' structure AI including associated storage. + For more details, see the POSIX:2001 specification + <http://www.opengroup.org/susv3xsh/getaddrinfo.html>. */ +extern void freeaddrinfo (struct addrinfo *ai); +# endif + +# if !HAVE_DECL_GAI_STRERROR +/* Convert error return from getaddrinfo() to a string. + For more details, see the POSIX:2001 specification + <http://www.opengroup.org/susv3xsh/gai_strerror.html>. */ +extern const char *gai_strerror (int ecode); +# endif + +#endif /* GETADDRINFO_H */ diff --git a/gl/m4/getaddrinfo.m4 b/gl/m4/getaddrinfo.m4 new file mode 100644 index 0000000000..c367190784 --- /dev/null +++ b/gl/m4/getaddrinfo.m4 @@ -0,0 +1,75 @@ +# getaddrinfo.m4 serial 9 +dnl Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_GETADDRINFO], +[ + AC_MSG_NOTICE([checking how to do getaddrinfo]) + + AC_SEARCH_LIBS(getaddrinfo, [nsl socket]) + AC_CHECK_FUNCS(getaddrinfo,, [ + AC_CACHE_CHECK(for getaddrinfo in ws2tcpip.h and -lws2_32, + gl_cv_w32_getaddrinfo, [ + gl_cv_w32_getaddrinfo=no + am_save_LIBS="$LIBS" + LIBS="$LIBS -lws2_32" + AC_TRY_LINK([ +#ifdef HAVE_WS2TCPIP_H +#define WINVER 0x0501 +#include <ws2tcpip.h> +#endif +], [getaddrinfo(0, 0, 0, 0);], gl_cv_w32_getaddrinfo=yes) + LIBS="$am_save_LIBS"]) + if test "$gl_cv_w32_getaddrinfo" = "yes"; then + LIBS="$LIBS -lws2_32" + else + AC_LIBOBJ(getaddrinfo) + fi + ]) + + AC_REPLACE_FUNCS(gai_strerror) + gl_PREREQ_GETADDRINFO +]) + +# Prerequisites of lib/getaddrinfo.h and lib/getaddrinfo.c. +AC_DEFUN([gl_PREREQ_GETADDRINFO], [ + AC_SEARCH_LIBS(gethostbyname, [inet nsl]) + AC_SEARCH_LIBS(getservbyname, [inet nsl socket xnet]) + AC_REQUIRE([gl_C_RESTRICT]) + AC_REQUIRE([gl_SOCKET_FAMILIES]) + AC_REQUIRE([gl_HEADER_SYS_SOCKET]) + AC_REQUIRE([AC_C_INLINE]) + AC_REQUIRE([AC_GNU_SOURCE]) + AC_CHECK_HEADERS_ONCE(netinet/in.h netdb.h) + AC_CHECK_DECLS([getaddrinfo, freeaddrinfo, gai_strerror],,,[ + /* sys/types.h is not needed according to POSIX, but the + sys/socket.h in i386-unknown-freebsd4.10 and + powerpc-apple-darwin5.5 required it. */ +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef HAVE_WS2TCPIP_H +#define WINVER 0x0501 +#include <ws2tcpip.h> +#endif +]) + AC_CHECK_TYPES([struct addrinfo],,,[ +#include <sys/types.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef HAVE_WS2TCPIP_H +#define WINVER 0x0501 +#include <ws2tcpip.h> +#endif +]) +]) diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4 index cdb9c30809..9f1876452c 100644 --- a/gl/m4/gnulib-cache.m4 +++ b/gl/m4/gnulib-cache.m4 @@ -15,10 +15,10 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl gc gc-arcfour gc-arctwo gc-des gc-hmac-md5 gc-md2 gc-md4 gc-md5 gc-pbkdf2-sha1 gc-random gc-rijndael gc-sha1 getline getpass gettext inet_ntop maintainer-makefile memmem memmove minmax readline snprintf socklen stdint +# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl gc gc-arcfour gc-arctwo gc-des gc-hmac-md5 gc-md2 gc-md4 gc-md5 gc-pbkdf2-sha1 gc-random gc-rijndael gc-sha1 getaddrinfo getline getpass gettext inet_ntop maintainer-makefile memmem memmove minmax readline snprintf socklen stdint # Specification in the form of a few gnulib-tool.m4 macro invocations: -gl_MODULES([gc gc-arcfour gc-arctwo gc-des gc-hmac-md5 gc-md2 gc-md4 gc-md5 gc-pbkdf2-sha1 gc-random gc-rijndael gc-sha1 getline getpass gettext inet_ntop maintainer-makefile memmem memmove minmax readline snprintf socklen stdint]) +gl_MODULES([gc gc-arcfour gc-arctwo gc-des gc-hmac-md5 gc-md2 gc-md4 gc-md5 gc-pbkdf2-sha1 gc-random gc-rijndael gc-sha1 getaddrinfo getline getpass gettext inet_ntop maintainer-makefile memmem memmove minmax readline snprintf socklen stdint]) gl_AVOID([]) gl_SOURCE_BASE([gl]) gl_M4_BASE([gl/m4]) diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4 index 61da4d7c2a..f39eb2c1f7 100644 --- a/gl/m4/gnulib-comp.m4 +++ b/gl/m4/gnulib-comp.m4 @@ -42,6 +42,7 @@ AC_DEFUN([gl_INIT], gl_GC_RANDOM gl_GC_RIJNDAEL gl_GC_SHA1 + gl_GETADDRINFO gl_FUNC_GETDELIM gl_FUNC_GETLINE gl_FUNC_GETPASS @@ -59,6 +60,7 @@ AC_DEFUN([gl_INIT], gl_TYPE_SOCKLEN_T AM_STDBOOL_H gl_STDINT_H + gl_FUNC_STRDUP gl_HEADER_SYS_SOCKET gl_FUNC_VASNPRINTF gl_XSIZE @@ -79,10 +81,13 @@ AC_DEFUN([gl_FILE_LIST], [ lib/des.c lib/des.h lib/dummy.c + lib/gai_strerror.c lib/gc-gnulib.c lib/gc-libgcrypt.c lib/gc-pbkdf2-sha1.c lib/gc.h + lib/getaddrinfo.c + lib/getaddrinfo.h lib/getdelim.c lib/getdelim.h lib/getline.c @@ -125,6 +130,8 @@ AC_DEFUN([gl_FILE_LIST], [ lib/socket_.h lib/stdbool_.h lib/stdint_.h + lib/strdup.c + lib/strdup.h lib/vasnprintf.c lib/vasnprintf.h lib/xsize.h @@ -147,6 +154,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/gc-rijndael.m4 m4/gc-sha1.m4 m4/gc.m4 + m4/getaddrinfo.m4 m4/getdelim.m4 m4/getline.m4 m4/getpass.m4 @@ -194,6 +202,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/stdbool.m4 m4/stdint.m4 m4/stdint_h.m4 + m4/strdup.m4 m4/sys_socket_h.m4 m4/uintmax_t.m4 m4/ulonglong.m4 diff --git a/gl/m4/strdup.m4 b/gl/m4/strdup.m4 new file mode 100644 index 0000000000..42325ab9ee --- /dev/null +++ b/gl/m4/strdup.m4 @@ -0,0 +1,17 @@ +# strdup.m4 serial 6 +dnl Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_STRDUP], +[ + AC_LIBSOURCES([strdup.c, strdup.h]) + + AC_REPLACE_FUNCS(strdup) + AC_CHECK_DECLS_ONCE(strdup) + gl_PREREQ_STRDUP +]) + +# Prerequisites of lib/strdup.c. +AC_DEFUN([gl_PREREQ_STRDUP], [:]) diff --git a/gl/strdup.c b/gl/strdup.c new file mode 100644 index 0000000000..84df5b8043 --- /dev/null +++ b/gl/strdup.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1991, 1996, 1997, 1998, 2002, 2003, 2004 Free Software + Foundation, Inc. + + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef _LIBC +/* Get specification. */ +# include "strdup.h" +#endif + +#include <stdlib.h> +#include <string.h> + +#undef __strdup +#undef strdup + +#ifndef weak_alias +# define __strdup strdup +#endif + +/* Duplicate S, returning an identical malloc'd string. */ +char * +__strdup (const char *s) +{ + size_t len = strlen (s) + 1; + void *new = malloc (len); + + if (new == NULL) + return NULL; + + return (char *) memcpy (new, s, len); +} +#ifdef libc_hidden_def +libc_hidden_def (__strdup) +#endif +#ifdef weak_alias +weak_alias (__strdup, strdup) +#endif diff --git a/gl/strdup.h b/gl/strdup.h new file mode 100644 index 0000000000..bbf2f49917 --- /dev/null +++ b/gl/strdup.h @@ -0,0 +1,29 @@ +/* strdup.h -- duplicate a string + Copyright (C) 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef STRDUP_H_ +#define STRDUP_H_ + +/* Get strdup declaration, if available. */ +#include <string.h> + +#if defined HAVE_DECL_STRDUP && !HAVE_DECL_STRDUP && !defined strdup +/* Duplicate S, returning an identical malloc'd string. */ +extern char *strdup (const char *s); +#endif + +#endif /* STRDUP_H_ */ |