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