getservice.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 smallint serv_stayopen;
  33. void setservent(int stayopen)
  34. {
  35. __UCLIBC_MUTEX_LOCK(mylock);
  36. if (servp)
  37. config_close(servp);
  38. servp = config_open(_PATH_SERVICES);
  39. if (stayopen)
  40. serv_stayopen = 1;
  41. __UCLIBC_MUTEX_UNLOCK(mylock);
  42. }
  43. libc_hidden_def(setservent)
  44. void endservent(void)
  45. {
  46. __UCLIBC_MUTEX_LOCK(mylock);
  47. if (servp) {
  48. config_close(servp);
  49. servp = NULL;
  50. }
  51. serv_stayopen = 0;
  52. __UCLIBC_MUTEX_UNLOCK(mylock);
  53. }
  54. libc_hidden_def(endservent)
  55. int getservent_r(struct servent *result_buf,
  56. char *buf, size_t buflen, struct servent **result)
  57. {
  58. char **alias, *cp = NULL;
  59. char **serv_aliases;
  60. char **tok = NULL;
  61. const size_t aliaslen = sizeof(*serv_aliases) * MAXALIASES;
  62. int ret = ERANGE;
  63. *result = NULL;
  64. if (buflen < aliaslen
  65. || (buflen - aliaslen) < BUFSZ + 1)
  66. goto DONE_NOUNLOCK;
  67. __UCLIBC_MUTEX_LOCK(mylock);
  68. ret = ENOENT;
  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, 4, 3, "# \t/", PARSE_NORMAL)) {
  78. goto DONE;
  79. }
  80. result_buf->s_name = *(tok++);
  81. result_buf->s_port = htons((u_short) atoi(*(tok++)));
  82. result_buf->s_proto = *(tok++);
  83. result_buf->s_aliases = alias = serv_aliases = tok;
  84. cp = *alias;
  85. while (cp && *cp) {
  86. if (alias < &serv_aliases[MAXALIASES - 1])
  87. *alias++ = cp;
  88. cp = strpbrk(cp, " \t");
  89. if (cp != NULL)
  90. *cp++ = '\0';
  91. }
  92. *alias = NULL;
  93. *result = result_buf;
  94. ret = 0;
  95. DONE:
  96. __UCLIBC_MUTEX_UNLOCK(mylock);
  97. DONE_NOUNLOCK:
  98. errno = ret;
  99. return errno;
  100. }
  101. libc_hidden_def(getservent_r)
  102. static void __initbuf(void)
  103. {
  104. if (!servbuf) {
  105. servbuf = malloc(SBUFSIZE);
  106. if (!servbuf)
  107. abort();
  108. }
  109. }
  110. struct servent *getservent(void)
  111. {
  112. struct servent *result;
  113. __initbuf();
  114. getservent_r(&serve, servbuf, SBUFSIZE, &result);
  115. return result;
  116. }
  117. int getservbyname_r(const char *name, const char *proto,
  118. struct servent *result_buf, char *buf, size_t buflen,
  119. struct servent **result)
  120. {
  121. register char **cp;
  122. int ret;
  123. __UCLIBC_MUTEX_LOCK(mylock);
  124. setservent(serv_stayopen);
  125. while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
  126. if (strcmp(name, result_buf->s_name) == 0)
  127. goto gotname;
  128. for (cp = result_buf->s_aliases; *cp; cp++)
  129. if (strcmp(name, *cp) == 0)
  130. goto gotname;
  131. continue;
  132. gotname:
  133. if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
  134. break;
  135. }
  136. if (!serv_stayopen)
  137. endservent();
  138. __UCLIBC_MUTEX_UNLOCK(mylock);
  139. return *result ? 0 : ret;
  140. }
  141. libc_hidden_def(getservbyname_r)
  142. struct servent *getservbyname(const char *name, const char *proto)
  143. {
  144. struct servent *result;
  145. __initbuf();
  146. getservbyname_r(name, proto, &serve, servbuf, SBUFSIZE, &result);
  147. return result;
  148. }
  149. int getservbyport_r(int port, const char *proto,
  150. struct servent *result_buf, char *buf,
  151. size_t buflen, struct servent **result)
  152. {
  153. int ret;
  154. __UCLIBC_MUTEX_LOCK(mylock);
  155. setservent(serv_stayopen);
  156. while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
  157. if (result_buf->s_port != port)
  158. continue;
  159. if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
  160. break;
  161. }
  162. if (!serv_stayopen)
  163. endservent();
  164. __UCLIBC_MUTEX_UNLOCK(mylock);
  165. return *result ? 0 : ret;
  166. }
  167. libc_hidden_def(getservbyport_r)
  168. struct servent *getservbyport(int port, const char *proto)
  169. {
  170. struct servent *result;
  171. __initbuf();
  172. getservbyport_r(port, proto, &serve, servbuf, SBUFSIZE, &result);
  173. return result;
  174. }
  175. libc_hidden_def(getservbyport)