1 /* $NetBSD: gai_strerror.c,v 1.1.1.1 2009/04/12 15:33:35 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 2001 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <port_before.h> 21 #include <netdb.h> 22 #include <port_after.h> 23 24 #ifdef DO_PTHREADS 25 #include <pthread.h> 26 #include <stdlib.h> 27 #endif 28 29 static const char *gai_errlist[] = { 30 "no error", 31 "address family not supported for name",/*%< EAI_ADDRFAMILY */ 32 "temporary failure", /*%< EAI_AGAIN */ 33 "invalid flags", /*%< EAI_BADFLAGS */ 34 "permanent failure", /*%< EAI_FAIL */ 35 "address family not supported", /*%< EAI_FAMILY */ 36 "memory failure", /*%< EAI_MEMORY */ 37 "no address", /*%< EAI_NODATA */ 38 "unknown name or service", /*%< EAI_NONAME */ 39 "service not supported for socktype", /*%< EAI_SERVICE */ 40 "socktype not supported", /*%< EAI_SOCKTYPE */ 41 "system failure", /*%< EAI_SYSTEM */ 42 "bad hints", /*%< EAI_BADHINTS */ 43 "bad protocol", /*%< EAI_PROTOCOL */ 44 "unknown error" /*%< Must be last. */ 45 }; 46 47 static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist)); 48 49 #define EAI_BUFSIZE 128 50 51 const char * 52 gai_strerror(int ecode) { 53 #ifndef DO_PTHREADS 54 static char buf[EAI_BUFSIZE]; 55 #else /* DO_PTHREADS */ 56 #ifndef LIBBIND_MUTEX_INITIALIZER 57 #define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER 58 #endif 59 static pthread_mutex_t lock = LIBBIND_MUTEX_INITIALIZER; 60 static pthread_key_t key; 61 static int once = 0; 62 char *buf; 63 #endif 64 65 if (ecode >= 0 && ecode < (gai_nerr - 1)) 66 return (gai_errlist[ecode]); 67 68 #ifdef DO_PTHREADS 69 if (!once) { 70 if (pthread_mutex_lock(&lock) != 0) 71 goto unknown; 72 if (!once) { 73 if (pthread_key_create(&key, free) != 0) { 74 (void)pthread_mutex_unlock(&lock); 75 goto unknown; 76 } 77 once = 1; 78 } 79 if (pthread_mutex_unlock(&lock) != 0) 80 goto unknown; 81 } 82 83 buf = pthread_getspecific(key); 84 if (buf == NULL) { 85 buf = malloc(EAI_BUFSIZE); 86 if (buf == NULL) 87 goto unknown; 88 if (pthread_setspecific(key, buf) != 0) { 89 free(buf); 90 goto unknown; 91 } 92 } 93 #endif 94 /* 95 * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...). 96 * It is safe until message catalogs are used. 97 */ 98 sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode); 99 return (buf); 100 101 #ifdef DO_PTHREADS 102 unknown: 103 return ("unknown error"); 104 #endif 105 } 106 107 /*! \file */ 108