getservice.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
  4. *
  5. * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  6. */
  7. /* /etc/services
  8. # service-name port/protocol [aliases ...]
  9. discard 9/udp sink null
  10. service-name: case sensitive friendly name of the service
  11. port: decimal port number
  12. protocol: protocols(5) compatible entry
  13. aliases: case sensitive optional space or tab separated list of other names
  14. */
  15. #include <features.h>
  16. #include <netdb.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <netinet/in.h>
  20. #include <arpa/inet.h>
  21. #include <errno.h>
  22. #include <unistd.h>
  23. #include "internal/parse_config.h"
  24. #include <bits/uClibc_mutex.h>
  25. __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
  26. #define MAXALIASES 35
  27. #define BUFSZ (80) /* one line */
  28. #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES))
  29. static parser_t *servp = NULL;
  30. static struct servent serve;
  31. static char *servbuf = NULL;
  32. static size_t servbuf_sz = SBUFSIZE;
  33. static smallint serv_stayopen;
  34. void setservent(int stayopen)
  35. {
  36. __UCLIBC_MUTEX_LOCK(mylock);
  37. if (servp)
  38. config_close(servp);
  39. servp = config_open(_PATH_SERVICES);
  40. if (stayopen)
  41. serv_stayopen = 1;
  42. __UCLIBC_MUTEX_UNLOCK(mylock);
  43. }
  44. libc_hidden_def(setservent)
  45. void endservent(void)
  46. {
  47. __UCLIBC_MUTEX_LOCK(mylock);
  48. if (servp) {
  49. config_close(servp);
  50. servp = NULL;
  51. }
  52. serv_stayopen = 0;
  53. __UCLIBC_MUTEX_UNLOCK(mylock);
  54. }
  55. libc_hidden_def(endservent)
  56. int getservent_r(struct servent *result_buf,
  57. char *buf, size_t buflen, struct servent **result)
  58. {
  59. char **alias;
  60. char **serv_aliases;
  61. char **tok = NULL;
  62. const size_t aliaslen = sizeof(*serv_aliases) * MAXALIASES;
  63. int ret = ENOENT;
  64. *result = NULL;
  65. if (buflen < aliaslen
  66. || (buflen - aliaslen) < BUFSZ + 1)
  67. goto DONE_NOUNLOCK;
  68. __UCLIBC_MUTEX_LOCK(mylock);
  69. if (servp == NULL)
  70. setservent(serv_stayopen);
  71. if (servp == NULL)
  72. goto DONE;
  73. servp->data = buf;
  74. servp->data_len = aliaslen;
  75. servp->line_len = buflen - aliaslen;
  76. /* <name>[[:space:]]<port>/<proto>[[:space:]][<aliases>] */
  77. if (!config_read(servp, &tok, MAXALIASES, 3, "# \t/", PARSE_NORMAL)) {
  78. ret = ERANGE;
  79. goto DONE;
  80. }
  81. result_buf->s_name = *(tok++);
  82. result_buf->s_port = htons((u_short) atoi(*(tok++)));
  83. result_buf->s_proto = *(tok++);
  84. result_buf->s_aliases = alias = serv_aliases = tok;
  85. *result = result_buf;
  86. ret = 0;
  87. DONE:
  88. __UCLIBC_MUTEX_UNLOCK(mylock);
  89. DONE_NOUNLOCK:
  90. errno = ret;
  91. return errno;
  92. }
  93. libc_hidden_def(getservent_r)
  94. static void __initbuf(void)
  95. {
  96. if (servbuf)
  97. servbuf_sz += BUFSZ;
  98. servbuf = realloc(servbuf, servbuf_sz);
  99. if (!servbuf)
  100. abort();
  101. }
  102. struct servent *getservent(void)
  103. {
  104. struct servent *result;
  105. do {
  106. __initbuf();
  107. } while (getservent_r(&serve, servbuf, servbuf_sz, &result) == ERANGE);
  108. return result;
  109. }
  110. int getservbyname_r(const char *name, const char *proto,
  111. struct servent *result_buf, char *buf, size_t buflen,
  112. struct servent **result)
  113. {
  114. register char **cp;
  115. int ret;
  116. __UCLIBC_MUTEX_LOCK(mylock);
  117. setservent(serv_stayopen);
  118. while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
  119. if (strcmp(name, result_buf->s_name) == 0)
  120. goto gotname;
  121. for (cp = result_buf->s_aliases; *cp; cp++)
  122. if (strcmp(name, *cp) == 0)
  123. goto gotname;
  124. continue;
  125. gotname:
  126. if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
  127. break;
  128. }
  129. if (!serv_stayopen)
  130. endservent();
  131. __UCLIBC_MUTEX_UNLOCK(mylock);
  132. return *result ? 0 : ret;
  133. }
  134. libc_hidden_def(getservbyname_r)
  135. struct servent *getservbyname(const char *name, const char *proto)
  136. {
  137. struct servent *result;
  138. do {
  139. __initbuf();
  140. } while (getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result)
  141. == ERANGE);
  142. return result;
  143. }
  144. int getservbyport_r(int port, const char *proto,
  145. struct servent *result_buf, char *buf,
  146. size_t buflen, struct servent **result)
  147. {
  148. int ret;
  149. __UCLIBC_MUTEX_LOCK(mylock);
  150. setservent(serv_stayopen);
  151. while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
  152. if (result_buf->s_port != port)
  153. continue;
  154. if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
  155. break;
  156. }
  157. if (!serv_stayopen)
  158. endservent();
  159. __UCLIBC_MUTEX_UNLOCK(mylock);
  160. return *result ? 0 : ret;
  161. }
  162. libc_hidden_def(getservbyport_r)
  163. struct servent *getservbyport(int port, const char *proto)
  164. {
  165. struct servent *result;
  166. do {
  167. __initbuf();
  168. } while (getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result)
  169. == ERANGE);
  170. return result;
  171. }
  172. libc_hidden_def(getservbyport)