/src/ntp-dev/lib/isc/result.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2004, 2005, 2007, 2008, 2012 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 *text[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 | | }; |
107 | | |
108 | 0 | #define ISC_RESULT_RESULTSET 2 |
109 | 0 | #define ISC_RESULT_UNAVAILABLESET 3 |
110 | | |
111 | | static isc_once_t once = ISC_ONCE_INIT; |
112 | | static ISC_LIST(resulttable) tables; |
113 | | static isc_mutex_t lock; |
114 | | |
115 | | static isc_result_t |
116 | | register_table(unsigned int base, unsigned int nresults, const char **txt, |
117 | | isc_msgcat_t *msgcat, int set) |
118 | 0 | { |
119 | 0 | resulttable *table; |
120 | |
|
121 | 0 | REQUIRE(base % ISC_RESULTCLASS_SIZE == 0); |
122 | 0 | REQUIRE(nresults <= ISC_RESULTCLASS_SIZE); |
123 | 0 | REQUIRE(txt != NULL); |
124 | | |
125 | | /* |
126 | | * We use malloc() here because we we want to be able to use |
127 | | * isc_result_totext() even if there is no memory context. |
128 | | */ |
129 | 0 | table = malloc(sizeof(*table)); |
130 | 0 | if (table == NULL) |
131 | 0 | return (ISC_R_NOMEMORY); |
132 | 0 | table->base = base; |
133 | 0 | table->last = base + nresults - 1; |
134 | 0 | table->text = txt; |
135 | 0 | table->msgcat = msgcat; |
136 | 0 | table->set = set; |
137 | 0 | ISC_LINK_INIT(table, link); |
138 | |
|
139 | 0 | LOCK(&lock); |
140 | |
|
141 | 0 | ISC_LIST_APPEND(tables, table, link); |
142 | |
|
143 | 0 | UNLOCK(&lock); |
144 | |
|
145 | 0 | return (ISC_R_SUCCESS); |
146 | 0 | } |
147 | | |
148 | | static void |
149 | 0 | initialize_action(void) { |
150 | 0 | isc_result_t result; |
151 | |
|
152 | 0 | RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS); |
153 | 0 | ISC_LIST_INIT(tables); |
154 | |
|
155 | 0 | result = register_table(ISC_RESULTCLASS_ISC, ISC_R_NRESULTS, text, |
156 | 0 | isc_msgcat, ISC_RESULT_RESULTSET); |
157 | 0 | if (result != ISC_R_SUCCESS) |
158 | 0 | UNEXPECTED_ERROR(__FILE__, __LINE__, |
159 | 0 | "register_table() %s: %u", |
160 | 0 | isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, |
161 | 0 | ISC_MSG_FAILED, "failed"), |
162 | 0 | result); |
163 | 0 | } |
164 | | |
165 | | static void |
166 | 0 | initialize(void) { |
167 | 0 | isc_lib_initmsgcat(); |
168 | 0 | RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); |
169 | 0 | } |
170 | | |
171 | | const char * |
172 | 0 | isc_result_totext(isc_result_t result) { |
173 | 0 | resulttable *table; |
174 | 0 | const char *txt, *default_text; |
175 | 0 | int idx; |
176 | |
|
177 | 0 | initialize(); |
178 | |
|
179 | 0 | LOCK(&lock); |
180 | |
|
181 | 0 | txt = NULL; |
182 | 0 | for (table = ISC_LIST_HEAD(tables); |
183 | 0 | table != NULL; |
184 | 0 | table = ISC_LIST_NEXT(table, link)) { |
185 | 0 | if (result >= table->base && result <= table->last) { |
186 | 0 | idx = (int)(result - table->base); |
187 | 0 | default_text = table->text[idx]; |
188 | | /* |
189 | | * Note: we use 'idx + 1' as the message number |
190 | | * instead of idx because isc_msgcat_get() requires |
191 | | * the message number to be > 0. |
192 | | */ |
193 | 0 | txt = isc_msgcat_get(table->msgcat, table->set, |
194 | 0 | idx + 1, default_text); |
195 | 0 | break; |
196 | 0 | } |
197 | 0 | } |
198 | 0 | if (txt == NULL) |
199 | 0 | txt = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET, |
200 | 0 | 1, "(result code text not available)"); |
201 | |
|
202 | 0 | UNLOCK(&lock); |
203 | |
|
204 | 0 | return (txt); |
205 | 0 | } |
206 | | |
207 | | isc_result_t |
208 | | isc_result_register(unsigned int base, unsigned int nresults, |
209 | | const char **txt, isc_msgcat_t *msgcat, int set) |
210 | 0 | { |
211 | 0 | initialize(); |
212 | |
|
213 | 0 | return (register_table(base, nresults, txt, msgcat, set)); |
214 | 0 | } |