getservice.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 MINTOKENS 3
  27. #define MAXALIASES 8 /* we seldomly need more than 1 alias */
  28. #define MAXTOKENS (MINTOKENS + MAXALIASES + 1)
  29. #define BUFSZ (255) /* one line */
  30. #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
  31. static parser_t *servp = NULL;
  32. static struct servent serve;
  33. static char *servbuf = NULL;
  34. static size_t servbuf_sz = SBUFSIZE;
  35. static smallint serv_stayopen;
  36. void setservent(int stayopen)
  37. {
  38. __UCLIBC_MUTEX_LOCK(mylock);
  39. if (servp)
  40. config_close(servp);
  41. servp = config_open(_PATH_SERVICES);
  42. if (stayopen)
  43. serv_stayopen = 1;
  44. __UCLIBC_MUTEX_UNLOCK(mylock);
  45. }
  46. libc_hidden_def(setservent)
  47. void endservent(void)
  48. {
  49. __UCLIBC_MUTEX_LOCK(mylock);
  50. if (servp) {
  51. config_close(servp);
  52. servp = NULL;
  53. }
  54. serv_stayopen = 0;
  55. __UCLIBC_MUTEX_UNLOCK(mylock);
  56. }
  57. libc_hidden_def(endservent)
  58. int getservent_r(struct servent *result_buf,
  59. char *buf, size_t buflen, struct servent **result)
  60. {
  61. char **tok = NULL;
  62. const size_t aliaslen = sizeof(char *) * MAXTOKENS;
  63. int ret = ERANGE;
  64. *result = NULL;
  65. if (buflen < aliaslen
  66. || (buflen - aliaslen) < BUFSZ + 1)
  67. goto DONE_NOUNLOCK;
  68. __UCLIBC_MUTEX_LOCK(mylock);
  69. ret = ENOENT;
  70. if (servp == NULL)
  71. setservent(serv_stayopen);
  72. if (servp == NULL)
  73. goto DONE;
  74. servp->data = buf;
  75. servp->data_len = aliaslen;
  76. servp->line_len = buflen - aliaslen;
  77. /* <name>[[:space:]]<port>/<proto>[[:space:]][<aliases>] */
  78. if (!config_read(servp, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) {
  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 = 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 = malloc(SBUFSIZE);
  98. if (!servbuf)
  99. abort();
  100. }
  101. struct servent *getservent(void)
  102. {
  103. struct servent *result;
  104. __initbuf();
  105. getservent_r(&serve, servbuf, servbuf_sz, &result);
  106. return result;
  107. }
  108. int getservbyname_r(const char *name, const char *proto,
  109. struct servent *result_buf, char *buf, size_t buflen,
  110. struct servent **result)
  111. {
  112. register char **cp;
  113. int ret;
  114. __UCLIBC_MUTEX_LOCK(mylock);
  115. setservent(serv_stayopen);
  116. while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
  117. if (strcmp(name, result_buf->s_name) == 0)
  118. goto gotname;
  119. for (cp = result_buf->s_aliases; *cp; cp++)
  120. if (strcmp(name, *cp) == 0)
  121. goto gotname;
  122. continue;
  123. gotname:
  124. if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
  125. break;
  126. }
  127. if (!serv_stayopen)
  128. endservent();
  129. __UCLIBC_MUTEX_UNLOCK(mylock);
  130. return *result ? 0 : ret;
  131. }
  132. libc_hidden_def(getservbyname_r)
  133. struct servent *getservbyname(const char *name, const char *proto)
  134. {
  135. struct servent *result;
  136. __initbuf();
  137. getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result);
  138. return result;
  139. }
  140. int getservbyport_r(int port, const char *proto,
  141. struct servent *result_buf, char *buf,
  142. size_t buflen, struct servent **result)
  143. {
  144. int ret;
  145. __UCLIBC_MUTEX_LOCK(mylock);
  146. setservent(serv_stayopen);
  147. while (!(ret = getservent_r(result_buf, buf, buflen, result))) {
  148. if (result_buf->s_port != port)
  149. continue;
  150. if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0)
  151. break;
  152. }
  153. if (!serv_stayopen)
  154. endservent();
  155. __UCLIBC_MUTEX_UNLOCK(mylock);
  156. return *result ? 0 : ret;
  157. }
  158. libc_hidden_def(getservbyport_r)
  159. struct servent *getservbyport(int port, const char *proto)
  160. {
  161. struct servent *result;
  162. __initbuf();
  163. getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result);
  164. return result;
  165. }
  166. libc_hidden_def(getservbyport)