/contrib/bind9/lib/isc/result.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 214 lines · 159 code · 28 blank · 27 comment · 14 complexity · 239f6fb590f22c0a2c7114370d2a0909 MD5 · raw file

  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. /* $Id$ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <isc/lib.h>
  23. #include <isc/msgs.h>
  24. #include <isc/mutex.h>
  25. #include <isc/once.h>
  26. #include <isc/resultclass.h>
  27. #include <isc/util.h>
  28. typedef struct resulttable {
  29. unsigned int base;
  30. unsigned int last;
  31. const char ** text;
  32. isc_msgcat_t * msgcat;
  33. int set;
  34. ISC_LINK(struct resulttable) link;
  35. } resulttable;
  36. static const char *text[ISC_R_NRESULTS] = {
  37. "success", /*%< 0 */
  38. "out of memory", /*%< 1 */
  39. "timed out", /*%< 2 */
  40. "no available threads", /*%< 3 */
  41. "address not available", /*%< 4 */
  42. "address in use", /*%< 5 */
  43. "permission denied", /*%< 6 */
  44. "no pending connections", /*%< 7 */
  45. "network unreachable", /*%< 8 */
  46. "host unreachable", /*%< 9 */
  47. "network down", /*%< 10 */
  48. "host down", /*%< 11 */
  49. "connection refused", /*%< 12 */
  50. "not enough free resources", /*%< 13 */
  51. "end of file", /*%< 14 */
  52. "socket already bound", /*%< 15 */
  53. "reload", /*%< 16 */
  54. "lock busy", /*%< 17 */
  55. "already exists", /*%< 18 */
  56. "ran out of space", /*%< 19 */
  57. "operation canceled", /*%< 20 */
  58. "socket is not bound", /*%< 21 */
  59. "shutting down", /*%< 22 */
  60. "not found", /*%< 23 */
  61. "unexpected end of input", /*%< 24 */
  62. "failure", /*%< 25 */
  63. "I/O error", /*%< 26 */
  64. "not implemented", /*%< 27 */
  65. "unbalanced parentheses", /*%< 28 */
  66. "no more", /*%< 29 */
  67. "invalid file", /*%< 30 */
  68. "bad base64 encoding", /*%< 31 */
  69. "unexpected token", /*%< 32 */
  70. "quota reached", /*%< 33 */
  71. "unexpected error", /*%< 34 */
  72. "already running", /*%< 35 */
  73. "ignore", /*%< 36 */
  74. "address mask not contiguous", /*%< 37 */
  75. "file not found", /*%< 38 */
  76. "file already exists", /*%< 39 */
  77. "socket is not connected", /*%< 40 */
  78. "out of range", /*%< 41 */
  79. "out of entropy", /*%< 42 */
  80. "invalid use of multicast address", /*%< 43 */
  81. "not a file", /*%< 44 */
  82. "not a directory", /*%< 45 */
  83. "queue is full", /*%< 46 */
  84. "address family mismatch", /*%< 47 */
  85. "address family not supported", /*%< 48 */
  86. "bad hex encoding", /*%< 49 */
  87. "too many open files", /*%< 50 */
  88. "not blocking", /*%< 51 */
  89. "unbalanced quotes", /*%< 52 */
  90. "operation in progress", /*%< 53 */
  91. "connection reset", /*%< 54 */
  92. "soft quota reached", /*%< 55 */
  93. "not a valid number", /*%< 56 */
  94. "disabled", /*%< 57 */
  95. "max size", /*%< 58 */
  96. "invalid address format", /*%< 59 */
  97. "bad base32 encoding", /*%< 60 */
  98. "unset", /*%< 61 */
  99. };
  100. #define ISC_RESULT_RESULTSET 2
  101. #define ISC_RESULT_UNAVAILABLESET 3
  102. static isc_once_t once = ISC_ONCE_INIT;
  103. static ISC_LIST(resulttable) tables;
  104. static isc_mutex_t lock;
  105. static isc_result_t
  106. register_table(unsigned int base, unsigned int nresults, const char **text,
  107. isc_msgcat_t *msgcat, int set)
  108. {
  109. resulttable *table;
  110. REQUIRE(base % ISC_RESULTCLASS_SIZE == 0);
  111. REQUIRE(nresults <= ISC_RESULTCLASS_SIZE);
  112. REQUIRE(text != NULL);
  113. /*
  114. * We use malloc() here because we we want to be able to use
  115. * isc_result_totext() even if there is no memory context.
  116. */
  117. table = malloc(sizeof(*table));
  118. if (table == NULL)
  119. return (ISC_R_NOMEMORY);
  120. table->base = base;
  121. table->last = base + nresults - 1;
  122. table->text = text;
  123. table->msgcat = msgcat;
  124. table->set = set;
  125. ISC_LINK_INIT(table, link);
  126. LOCK(&lock);
  127. ISC_LIST_APPEND(tables, table, link);
  128. UNLOCK(&lock);
  129. return (ISC_R_SUCCESS);
  130. }
  131. static void
  132. initialize_action(void) {
  133. isc_result_t result;
  134. RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
  135. ISC_LIST_INIT(tables);
  136. result = register_table(ISC_RESULTCLASS_ISC, ISC_R_NRESULTS, text,
  137. isc_msgcat, ISC_RESULT_RESULTSET);
  138. if (result != ISC_R_SUCCESS)
  139. UNEXPECTED_ERROR(__FILE__, __LINE__,
  140. "register_table() %s: %u",
  141. isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
  142. ISC_MSG_FAILED, "failed"),
  143. result);
  144. }
  145. static void
  146. initialize(void) {
  147. isc_lib_initmsgcat();
  148. RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
  149. }
  150. const char *
  151. isc_result_totext(isc_result_t result) {
  152. resulttable *table;
  153. const char *text, *default_text;
  154. int index;
  155. initialize();
  156. LOCK(&lock);
  157. text = NULL;
  158. for (table = ISC_LIST_HEAD(tables);
  159. table != NULL;
  160. table = ISC_LIST_NEXT(table, link)) {
  161. if (result >= table->base && result <= table->last) {
  162. index = (int)(result - table->base);
  163. default_text = table->text[index];
  164. /*
  165. * Note: we use 'index + 1' as the message number
  166. * instead of index because isc_msgcat_get() requires
  167. * the message number to be > 0.
  168. */
  169. text = isc_msgcat_get(table->msgcat, table->set,
  170. index + 1, default_text);
  171. break;
  172. }
  173. }
  174. if (text == NULL)
  175. text = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET,
  176. 1, "(result code text not available)");
  177. UNLOCK(&lock);
  178. return (text);
  179. }
  180. isc_result_t
  181. isc_result_register(unsigned int base, unsigned int nresults,
  182. const char **text, isc_msgcat_t *msgcat, int set)
  183. {
  184. initialize();
  185. return (register_table(base, nresults, text, msgcat, set));
  186. }