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_key_t key = PTHREAD_ONCE_KEY_NP;
63 	char *buf;
64 #endif
65 
66 	if (ecode >= 0 && ecode < (gai_nerr - 1))
67 		return (gai_errlist[ecode]);
68 
69 #ifdef DO_PTHREADS
70 	if (pthread_key_create_once_np(&key, free) != 0)
71 		goto unknown;
72 	buf = pthread_getspecific(key);
73 	if (buf == NULL) {
74 		buf = malloc(EAI_BUFSIZE);
75 		if (buf == NULL)
76 			goto unknown;
77 		if (pthread_setspecific(key, buf) != 0) {
78 			free(buf);
79 			goto unknown;
80 		}
81 	}
82 #endif
83 	/*
84 	 * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...).
85 	 * It is safe until message catalogs are used.
86 	 */
87 	sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode);
88 	return (buf);
89 
90 #ifdef	DO_PTHREADS
91 unknown:
92 	return ("unknown error");
93 #endif
94 }
95