1 /*
2  * Copyright 1999-2002 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                 pthread_mutex_lock(&lock);
74                 if (!once++)
75                         pthread_key_create(&key, free);
76                 pthread_mutex_unlock(&lock);
77         }
78 
79 	buf = pthread_getspecific(key);
80         if (buf == NULL) {
81 		buf = malloc(EAI_BUFSIZE);
82                 if (buf == NULL)
83                         return ("unknown error");
84                 pthread_setspecific(key, buf);
85         }
86 #endif
87 	/*
88 	 * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...).
89 	 * It is safe until message catalogs are used.
90 	 */
91 	sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode);
92 	return (buf);
93 }
94