1 /* vi: set sw=4 ts=4: */
3 * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
5 * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
9 # service-name port/protocol [aliases ...]
10 discard 9/udp sink null
12 service-name: case sensitive friendly name of the service
13 port: decimal port number
14 protocol: protocols(5) compatible entry
15 aliases: case sensitive optional space or tab separated list of other names
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
26 #include "internal/parse_config.h"
28 #include <bits/uClibc_mutex.h>
29 __UCLIBC_MUTEX_STATIC(mylock
, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
);
32 #define MAXALIASES 8 /* we seldomly need more than 1 alias */
33 #define MAXTOKENS (MINTOKENS + MAXALIASES + 1)
34 #define BUFSZ (255) /* one line */
35 #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
37 static parser_t
*servp
= NULL
;
38 static struct servent serve
;
39 static char *servbuf
= NULL
;
40 static size_t servbuf_sz
= SBUFSIZE
;
41 static smallint serv_stayopen
;
43 void setservent(int stayopen
)
45 __UCLIBC_MUTEX_LOCK(mylock
);
48 servp
= config_open(_PATH_SERVICES
);
51 __UCLIBC_MUTEX_UNLOCK(mylock
);
53 libc_hidden_def(setservent
)
57 __UCLIBC_MUTEX_LOCK(mylock
);
63 __UCLIBC_MUTEX_UNLOCK(mylock
);
65 libc_hidden_def(endservent
)
67 int getservent_r(struct servent
*result_buf
,
68 char *buf
, size_t buflen
, struct servent
**result
)
71 const size_t aliaslen
= sizeof(char *) * MAXTOKENS
;
76 || (buflen
- aliaslen
) < BUFSZ
+ 1)
79 __UCLIBC_MUTEX_LOCK(mylock
);
82 setservent(serv_stayopen
);
87 servp
->data_len
= aliaslen
;
88 servp
->line_len
= buflen
- aliaslen
;
89 /* <name>[[:space:]]<port>/<proto>[[:space:]][<aliases>] */
90 if (!config_read(servp
, &tok
, MAXTOKENS
- 1, MINTOKENS
, "# \t/", PARSE_NORMAL
)) {
93 result_buf
->s_name
= *(tok
++);
94 result_buf
->s_port
= htons((u_short
) atoi(*(tok
++)));
95 result_buf
->s_proto
= *(tok
++);
96 result_buf
->s_aliases
= tok
;
100 __UCLIBC_MUTEX_UNLOCK(mylock
);
105 libc_hidden_def(getservent_r
)
107 static void __initbuf(void)
110 servbuf
= malloc(SBUFSIZE
);
115 struct servent
*getservent(void)
117 struct servent
*result
;
120 getservent_r(&serve
, servbuf
, servbuf_sz
, &result
);
124 int getservbyname_r(const char *name
, const char *proto
,
125 struct servent
*result_buf
, char *buf
, size_t buflen
,
126 struct servent
**result
)
131 __UCLIBC_MUTEX_LOCK(mylock
);
132 setservent(serv_stayopen
);
133 while (!(ret
= getservent_r(result_buf
, buf
, buflen
, result
))) {
134 if (strcmp(name
, result_buf
->s_name
) == 0)
136 for (cp
= result_buf
->s_aliases
; *cp
; cp
++)
137 if (strcmp(name
, *cp
) == 0)
141 if (proto
== 0 || strcmp(result_buf
->s_proto
, proto
) == 0)
146 __UCLIBC_MUTEX_UNLOCK(mylock
);
147 return *result
? 0 : ret
;
149 libc_hidden_def(getservbyname_r
)
151 struct servent
*getservbyname(const char *name
, const char *proto
)
153 struct servent
*result
;
156 getservbyname_r(name
, proto
, &serve
, servbuf
, servbuf_sz
, &result
);
161 int getservbyport_r(int port
, const char *proto
,
162 struct servent
*result_buf
, char *buf
,
163 size_t buflen
, struct servent
**result
)
167 __UCLIBC_MUTEX_LOCK(mylock
);
168 setservent(serv_stayopen
);
169 while (!(ret
= getservent_r(result_buf
, buf
, buflen
, result
))) {
170 if (result_buf
->s_port
!= port
)
172 if (proto
== 0 || strcmp(result_buf
->s_proto
, proto
) == 0)
177 __UCLIBC_MUTEX_UNLOCK(mylock
);
178 return *result
? 0 : ret
;
180 libc_hidden_def(getservbyport_r
)
182 struct servent
*getservbyport(int port
, const char *proto
)
184 struct servent
*result
;
187 getservbyport_r(port
, proto
, &serve
, servbuf
, servbuf_sz
, &result
);
190 libc_hidden_def(getservbyport
)