Watt-32 tcp/ip  2.2 dev-rel.10
getserv.c
Go to the documentation of this file.
1 
6 /* Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  * must display the following acknowledgement:
18  * This product includes software developed by Gisle Vanem
19  * Bergen, Norway.
20  *
21  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  *
33  * 20.aug 1996 - Created
34  */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 
41 #include "wattcp.h"
42 #include "strings.h"
43 #include "misc.h"
44 #include "run.h"
45 #include "language.h"
46 #include "netaddr.h"
47 #include "pcconfig.h"
48 #include "get_xby.h"
49 
50 #if defined(USE_BSD_API)
51 
52 #include <sys/socket.h>
53 #include <netdb.h>
54 
55 static struct _servent *serv0 = NULL;
56 static char *servFname = NULL;
57 static FILE *servFile = NULL;
58 static BOOL servClose = FALSE;
59 
60 /* For DOSX targets we use a small hash table to speed-up searches.
61  */
62 #if (DOSX)
63  #define PORT_HASH_SIZE 256 /* must be 2^n */
64  #define GET_HASH(p) port_hash [(p) & (PORT_HASH_SIZE-1)]
65  #define SET_HASH(se) port_hash [se->s_port & (PORT_HASH_SIZE-1)] = se
66  static struct _servent *port_hash [PORT_HASH_SIZE];
67 #else
68  #define GET_HASH(p) serv0
69  #define SET_HASH(p) ((void)0)
70 #endif
71 
72 #define MAX_SERVLEN 20
73 #define MAX_PROTLEN 20
74 
75 static __inline struct servent *fill_servent (const struct _servent *s)
76 {
77  static struct servent ret;
78  static char name [MAX_SERVLEN];
79  static char prot [MAX_PROTLEN];
80  static char *aliases [MAX_SERV_ALIASES+1];
81 
82  memcpy (&aliases, s->s_aliases, sizeof(aliases));
83  ret.s_name = _strlcpy (name, s->s_name, sizeof(name));
84  ret.s_proto = _strlcpy (prot, s->s_proto, sizeof(prot));
85  ret.s_aliases = aliases;
86  ret.s_port = s->s_port;
87  h_errno = NETDB_SUCCESS;
88  return (&ret);
89 }
90 
91 static void _endservent (void)
92 {
93  endservent();
94 }
95 
96 /*
97  * Read the \i services file and build linked-list.
98  */
99 void W32_CALL ReadServFile (const char *fname)
100 {
101  static BOOL been_here = FALSE;
102 
103  if (!fname || !*fname)
104  return;
105 
106  if (been_here) /* loading multiple services files */
107  {
108  free (servFname);
109  FCLOSE (servFile);
110  servFile = NULL;
111  }
112  servFname = strdup (fname);
113  if (!servFname)
114  return;
115 
116  setservent (1);
117  if (!servFile)
118  return;
119 
120  been_here = TRUE;
121 
122  while (1)
123  {
124  struct servent *s = getservent();
125  struct _servent *s2;
126  int i;
127 
128  if (!s)
129  break;
130 
131  s2 = (struct _servent*) calloc (sizeof(*s2), 1);
132  if (!s2)
133  {
134  outs (servFname);
135  outsnl (_LANG(" too big!"));
136  return;
137  }
138  for (i = 0; s->s_aliases[i]; i++)
139  s2->s_aliases[i] = strdup (s->s_aliases[i]);
140  s2->s_port = s->s_port;
141  s2->s_name = strdup (s->s_name);
142  s2->s_proto = strdup (s->s_proto);
143 
144  if (!s2->s_name || !s2->s_proto)
145  break;
146 
147  s2->s_next = serv0;
148  serv0 = s2;
149  SET_HASH (s2);
150  }
151  rewind (servFile);
152  RUNDOWN_ADD (_endservent, 255);
153 }
154 
155 /*
156  * Return name of \i /etc/services file.
157  */
158 const char * W32_CALL GetServFile (void)
159 {
160  return (servFname);
161 }
162 
163 /*
164  * Close the \i /etc/services file.
165  */
166 void W32_CALL CloseServFile (void)
167 {
168  FCLOSE (servFile);
169  servFile = NULL;
170 }
171 
172 /*
173  * Reopen the \i /etc/services file.
174  */
175 void W32_CALL ReopenServFile (void)
176 {
177  ReadServFile (servFname);
178 }
179 
180 /*------------------------------------------------------------------*/
181 
182 struct servent * W32_CALL getservent (void)
183 {
184  static struct _servent s;
185  char *name, *proto, *alias, *tok_buf = NULL;
186  WORD port;
187  int i;
188 
189  if (!netdb_init() || !servFile)
190  {
191  h_errno = NO_DATA;
192  return (NULL);
193  }
194 
195  while (1)
196  {
197  char buf[2*MAX_NAMELEN], *tok;
198 
199  if (!fgets(buf,sizeof(buf),servFile))
200  {
201  h_errno = NO_DATA;
202  return (NULL);
203  }
204 
205  tok = strltrim (buf);
206  if (*tok == '#' || *tok == ';' || *tok == '\n')
207  continue;
208 
209  /* # Service port/prot alias(es)
210  * #-------------------------------------------
211  * rtmp 1/ddp <- we only support "udp"/"tcp"
212  * echo 7/tcp
213  * echo 7/udp
214  * discard 9/tcp sink null
215  * discard 9/udp sink null
216  */
217 
218  name = strtok_r (tok, " \t", &tok_buf);
219  tok = strtok_r (NULL, "/ \t\n", &tok_buf);
220  if (!tok)
221  continue;
222  port = intel16 (atoi(tok));
223  proto = strtok_r (NULL, " \t\n", &tok_buf);
224  if (name && port && proto &&
225  (!stricmp(proto,"udp") || !stricmp(proto,"tcp")))
226  break;
227  }
228 
229  if (servClose)
230  endservent();
231 
232  memset (&s, 0, sizeof(s));
233  s.s_name = name;
234  s.s_proto = proto;
235  s.s_port = port;
236 
237  alias = strtok_r (NULL, " \t\n", &tok_buf);
238 
239  for (i = 0; alias && i < MAX_SERV_ALIASES; i++)
240  {
241  static char aliases [MAX_SERV_ALIASES][MAX_SERVLEN];
242 
243  if (*alias == '#' || *alias == ';')
244  break;
245 
246  s.s_aliases[i] = _strlcpy (aliases[i], alias, sizeof(aliases[i]));
247  alias = strtok_r (NULL, " \t\n", &tok_buf);
248  }
249  return fill_servent (&s);
250 }
251 
252 /*------------------------------------------------------------------*/
253 
254 struct servent * W32_CALL getservbyname (const char *serv, const char *proto)
255 {
256  const struct _servent *s;
257  int i;
258 
259  if (!netdb_init() || !serv) /* proto == NULL is okay */
260  {
261  h_errno = NO_DATA;
262  return (NULL);
263  }
264 
265  for (s = serv0; s; s = s->s_next)
266  {
267  BOOL chk_prot = FALSE;
268 
269  if (s->s_name && !stricmp(s->s_name,serv))
270  chk_prot = TRUE;
271 
272  else for (i = 0; s->s_aliases[i]; i++)
273  if (!stricmp(serv,s->s_aliases[i]))
274  {
275  chk_prot = TRUE;
276  break;
277  }
278  if (chk_prot && (!proto || !stricmp(proto,s->s_proto)))
279  return fill_servent (s);
280  }
281  h_errno = NO_DATA;
282  return (NULL);
283 }
284 
285 /*------------------------------------------------------------------*/
286 
287 struct servent * W32_CALL getservbyport (int port, const char *proto)
288 {
289  const struct _servent *s;
290 
291  if (!netdb_init() || !proto) /* proto == NULL is okay */
292  {
293  h_errno = NO_DATA;
294  return (NULL);
295  }
296 
297  for (s = GET_HASH(port); s; s = s->s_next)
298  if (s->s_port == port &&
299  (!proto || !stricmp(s->s_proto,proto)))
300  return fill_servent (s);
301  h_errno = NO_DATA;
302  return (NULL);
303 }
304 
305 /*------------------------------------------------------------------*/
306 
307 void W32_CALL setservent (int stayopen)
308 {
309  servClose = (stayopen == 0);
310  if (!netdb_init() || !servFname)
311  return;
312 
313  if (!servFile)
314  FOPEN_TXT (servFile, servFname);
315  else rewind (servFile);
316 }
317 
318 /*------------------------------------------------------------------*/
319 
320 void W32_CALL endservent (void)
321 {
322  struct _servent *s, *next;
323 
324  if (_watt_fatal_error)
325  return;
326 
327  if (servFname)
328  free (servFname);
329  if (servFile)
330  FCLOSE (servFile);
331  servFname = NULL;
332  servFile = NULL;
333 
334  for (s = serv0; s; s = next)
335  {
336  int i;
337  for (i = 0; s->s_aliases[i]; i++)
338  free (s->s_aliases[i]);
339  next = s->s_next;
340  free (s->s_name);
341  free (s->s_proto);
342  free (s);
343  }
344  serv0 = NULL;
345  servClose = TRUE;
346 }
347 #endif /* USE_BSD_API */
348 
349 #if defined(TEST_PROG)
350 
351 #include "pcdbug.h"
352 #include "sock_ini.h"
353 
354 int main (void)
355 {
356  const struct _servent *s;
357  int i;
358 
359  dbug_init();
360  sock_init();
361 
362  printf ("\n%s entries:\n", servFname);
363 
364  for (s = serv0; s; s = s->s_next)
365  {
366  printf ("proto %-6.6s port %4d name %-10.10s Aliases:",
367  s->s_proto, intel16(s->s_port), s->s_name);
368  for (i = 0; s->s_aliases[i]; i++)
369  printf (" %s", s->s_aliases[i]);
370  puts ("");
371  }
372  fflush (stdout);
373  return (0);
374 }
375 #endif /* TEST_PROG */
376 
377 
char * strltrim(const char *s)
Return pointer to first non-blank (space/tab) in a string.
Definition: strings.c:243
Definition: netdb.h:122
Core definitions.
char * _strlcpy(char *dst, const char *src, size_t len)
Similar to strncpy(), but always returns 'dst' with 0-termination.
Definition: strings.c:226
BOOL _watt_fatal_error
Definition: misc.c:60
int netdb_init(void)
Called from most <netdb.h> functions in case watt_sock_init() wasn't called first to initialise things...
Definition: pcconfig.c:1215
int main(int argc, char **argv)
Definition: echo.c:223