]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/lib/isc/result.c
MFC r363988:
[FreeBSD/stable/9.git] / contrib / bind9 / lib / isc / result.c
1 /*
2  * Copyright (C) 2004, 2005, 2007, 2008, 2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <stddef.h>
25 #include <stdlib.h>
26
27 #include <isc/lib.h>
28 #include <isc/msgs.h>
29 #include <isc/mutex.h>
30 #include <isc/once.h>
31 #include <isc/resultclass.h>
32 #include <isc/util.h>
33
34 typedef struct resulttable {
35         unsigned int                            base;
36         unsigned int                            last;
37         const char **                           text;
38         isc_msgcat_t *                          msgcat;
39         int                                     set;
40         ISC_LINK(struct resulttable)            link;
41 } resulttable;
42
43 static const char *description[ISC_R_NRESULTS] = {
44         "success",                              /*%< 0 */
45         "out of memory",                        /*%< 1 */
46         "timed out",                            /*%< 2 */
47         "no available threads",                 /*%< 3 */
48         "address not available",                /*%< 4 */
49         "address in use",                       /*%< 5 */
50         "permission denied",                    /*%< 6 */
51         "no pending connections",               /*%< 7 */
52         "network unreachable",                  /*%< 8 */
53         "host unreachable",                     /*%< 9 */
54         "network down",                         /*%< 10 */
55         "host down",                            /*%< 11 */
56         "connection refused",                   /*%< 12 */
57         "not enough free resources",            /*%< 13 */
58         "end of file",                          /*%< 14 */
59         "socket already bound",                 /*%< 15 */
60         "reload",                               /*%< 16 */
61         "lock busy",                            /*%< 17 */
62         "already exists",                       /*%< 18 */
63         "ran out of space",                     /*%< 19 */
64         "operation canceled",                   /*%< 20 */
65         "socket is not bound",                  /*%< 21 */
66         "shutting down",                        /*%< 22 */
67         "not found",                            /*%< 23 */
68         "unexpected end of input",              /*%< 24 */
69         "failure",                              /*%< 25 */
70         "I/O error",                            /*%< 26 */
71         "not implemented",                      /*%< 27 */
72         "unbalanced parentheses",               /*%< 28 */
73         "no more",                              /*%< 29 */
74         "invalid file",                         /*%< 30 */
75         "bad base64 encoding",                  /*%< 31 */
76         "unexpected token",                     /*%< 32 */
77         "quota reached",                        /*%< 33 */
78         "unexpected error",                     /*%< 34 */
79         "already running",                      /*%< 35 */
80         "ignore",                               /*%< 36 */
81         "address mask not contiguous",          /*%< 37 */
82         "file not found",                       /*%< 38 */
83         "file already exists",                  /*%< 39 */
84         "socket is not connected",              /*%< 40 */
85         "out of range",                         /*%< 41 */
86         "out of entropy",                       /*%< 42 */
87         "invalid use of multicast address",     /*%< 43 */
88         "not a file",                           /*%< 44 */
89         "not a directory",                      /*%< 45 */
90         "queue is full",                        /*%< 46 */
91         "address family mismatch",              /*%< 47 */
92         "address family not supported",         /*%< 48 */
93         "bad hex encoding",                     /*%< 49 */
94         "too many open files",                  /*%< 50 */
95         "not blocking",                         /*%< 51 */
96         "unbalanced quotes",                    /*%< 52 */
97         "operation in progress",                /*%< 53 */
98         "connection reset",                     /*%< 54 */
99         "soft quota reached",                   /*%< 55 */
100         "not a valid number",                   /*%< 56 */
101         "disabled",                             /*%< 57 */
102         "max size",                             /*%< 58 */
103         "invalid address format",               /*%< 59 */
104         "bad base32 encoding",                  /*%< 60 */
105         "unset",                                /*%< 61 */
106         "multiple",                             /*%< 62 */
107         "would block",                          /*%< 63 */
108 };
109
110 #define ISC_RESULT_RESULTSET                    2
111 #define ISC_RESULT_UNAVAILABLESET               3
112
113 static isc_once_t                               once = ISC_ONCE_INIT;
114 static ISC_LIST(resulttable)                    tables;
115 static isc_mutex_t                              lock;
116
117 static isc_result_t
118 register_table(unsigned int base, unsigned int nresults, const char **text,
119                isc_msgcat_t *msgcat, int set)
120 {
121         resulttable *table;
122
123         REQUIRE(base % ISC_RESULTCLASS_SIZE == 0);
124         REQUIRE(nresults <= ISC_RESULTCLASS_SIZE);
125         REQUIRE(text != NULL);
126
127         /*
128          * We use malloc() here because we we want to be able to use
129          * isc_result_totext() even if there is no memory context.
130          */
131         table = malloc(sizeof(*table));
132         if (table == NULL)
133                 return (ISC_R_NOMEMORY);
134         table->base = base;
135         table->last = base + nresults - 1;
136         table->text = text;
137         table->msgcat = msgcat;
138         table->set = set;
139         ISC_LINK_INIT(table, link);
140
141         LOCK(&lock);
142
143         ISC_LIST_APPEND(tables, table, link);
144
145         UNLOCK(&lock);
146
147         return (ISC_R_SUCCESS);
148 }
149
150 static void
151 initialize_action(void) {
152         isc_result_t result;
153
154         RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
155         ISC_LIST_INIT(tables);
156
157         result = register_table(ISC_RESULTCLASS_ISC, ISC_R_NRESULTS,
158                                 description, isc_msgcat, ISC_RESULT_RESULTSET);
159         if (result != ISC_R_SUCCESS)
160                 UNEXPECTED_ERROR(__FILE__, __LINE__,
161                                  "register_table() %s: %u",
162                                  isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
163                                                 ISC_MSG_FAILED, "failed"),
164                                  result);
165 }
166
167 static void
168 initialize(void) {
169         isc_lib_initmsgcat();
170         RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
171 }
172
173 const char *
174 isc_result_totext(isc_result_t result) {
175         resulttable *table;
176         const char *text, *default_text;
177         int index;
178
179         initialize();
180
181         LOCK(&lock);
182
183         text = NULL;
184         for (table = ISC_LIST_HEAD(tables);
185              table != NULL;
186              table = ISC_LIST_NEXT(table, link)) {
187                 if (result >= table->base && result <= table->last) {
188                         index = (int)(result - table->base);
189                         default_text = table->text[index];
190                         /*
191                          * Note: we use 'index + 1' as the message number
192                          * instead of index because isc_msgcat_get() requires
193                          * the message number to be > 0.
194                          */
195                         text = isc_msgcat_get(table->msgcat, table->set,
196                                               index + 1, default_text);
197                         break;
198                 }
199         }
200         if (text == NULL)
201                 text = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET,
202                                       1, "(result code text not available)");
203
204         UNLOCK(&lock);
205
206         return (text);
207 }
208
209 isc_result_t
210 isc_result_register(unsigned int base, unsigned int nresults,
211                     const char **text, isc_msgcat_t *msgcat, int set)
212 {
213         initialize();
214
215         return (register_table(base, nresults, text, msgcat, set));
216 }