1 /* netdb.cc: network database related routines.
3 Copyright 2002, 2003, 2007 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 /* Locate and open a system network database file. relative_path
17 should be one of the following values:
23 It is the callers responsibility to close the file. */
25 open_system_file (const char *relative_path
)
27 /* system dir path is never longer. */
28 char win32_name
[MAX_PATH
];
30 if (!GetSystemDirectory (win32_name
, MAX_PATH
))
32 strcat (win32_name
, "\\drivers\\etc\\");
33 strcat (win32_name
, relative_path
);
34 debug_printf ("netdb file to open %s", win32_name
);
35 FILE *result
= fopen (win32_name
, "rt");
36 debug_printf ("handle to netdb file %p", result
);
43 return open_system_file ("protocol");
46 /* Wrapper for open_system_file(), fixing the constant name
47 "services". Returns the open file. */
51 return open_system_file ("services");
54 /* Read an entire line up till the next \n character. Memory for the
55 line is dynamically allocated, and the caller must call free() to
56 deallocate it. When the end of file is reached, NULL is returned. */
58 get_entire_line (FILE *fd
)
60 static const int BUFF_SIZE
= 1024;
63 char buffer
[BUFF_SIZE
];
67 line_fragment
*fragment_list_head
= NULL
;
68 line_fragment
*fragment
= NULL
;
69 int fragment_count
= 0;
74 line_fragment
*new_fragment
= (line_fragment
*) malloc (sizeof (line_fragment
));
75 paranoid_printf ("line fragment allocated %p", new_fragment
);
76 if (!fragment_list_head
)
77 fragment_list_head
= new_fragment
;
79 fragment
->next
= new_fragment
;
80 fragment
= new_fragment
;
81 fragment
->next
= NULL
;
82 *fragment
->buffer
= '\0';
83 result
= fgets (fragment
->buffer
, BUFF_SIZE
, fd
);
86 while (result
&& !strchr (fragment
->buffer
, '\n'));
88 if (*fragment_list_head
->buffer
!= '\0')
90 char *concatenated_line
= (char *) calloc (fragment_count
* BUFF_SIZE
, sizeof (char));
91 paranoid_printf ("concatenated line allocated %p", concatenated_line
);
92 *concatenated_line
= '\0';
93 fragment
= fragment_list_head
;
94 while (fragment
!= NULL
)
96 line_fragment
*previous
= fragment
;
97 strcat (concatenated_line
, fragment
->buffer
);
98 fragment
= fragment
->next
;
101 return concatenated_line
;
105 fragment
= fragment_list_head
;
106 while (fragment
!= NULL
)
108 line_fragment
*previous
= fragment
;
109 fragment
= fragment
->next
;
116 /* Characters representing whitespace. Used by parse_* routines to
118 static const NO_COPY
char *SPACE
= " \t\n\r\f";
120 /* Parse a list aliases from a network database file. Returns a
121 char** structure terminated by a NULL. */
123 parse_alias_list (char ***aliases
, char **lasts
)
130 alias_t
*alias_list_head
= NULL
, *alias_list_tail
= NULL
;
133 alias
= strtok_r (NULL
, SPACE
, lasts
);
138 alias_t
*new_alias
= (alias_t
*) malloc (sizeof (alias_t
));
139 paranoid_printf ("new alias alloc %p", new_alias
);
140 if (!alias_list_head
)
141 alias_list_head
= new_alias
;
143 alias_list_tail
->next
= new_alias
;
144 new_alias
->next
= NULL
;
145 new_alias
->alias_name
= alias
;
146 alias_list_tail
= new_alias
;
147 alias
= strtok_r (NULL
, SPACE
, lasts
);
150 *aliases
= (char**) calloc (alias_count
+ 1, sizeof (char *));
151 paranoid_printf ("aliases alloc %p", *aliases
);
153 char **current_entry
= *aliases
;
154 while (alias_list_head
)
156 alias_t
*previous
= alias_list_head
;
157 *current_entry
= strdup (alias_list_head
->alias_name
);
158 paranoid_printf ("*current entry strdup %p", *current_entry
);
159 alias_list_head
= alias_list_head
->next
;
164 *current_entry
= NULL
;
167 /* Read the next line from svc_file, and parse it into the structure
168 pointed to by sep. sep can point to stack or static data, but it's
169 members will be overwritten with pointers to dynamically allocated
170 heap data accommodating parsed data. It is the responsibility of the
171 caller to free up the allocated structures. The function returns true
172 to indicate that a line was successfully read and parsed. False is
173 used to indicate that no more lines can be read and parsed. This
174 should also interpreted as end of file. */
176 parse_services_line (FILE *svc_file
, struct servent
*sep
)
179 while ((line
= get_entire_line (svc_file
)))
181 char *name
, *port
, *protocol
, *lasts
;
183 line
[strcspn (line
, "#")] = '\0'; // truncate at comment marker.
184 name
= strtok_r (line
, SPACE
, &lasts
);
190 port
= strtok_r (NULL
, SPACE
, &lasts
);
191 protocol
= strchr (port
, '/');
193 sep
->s_name
= strdup (name
);
194 paranoid_printf ("sep->s_name strdup %p", sep
->s_name
);
195 sep
->s_port
= atoi (port
);
196 sep
->s_proto
= strdup (protocol
);
197 paranoid_printf ("sep->s_proto strdup %p", sep
->s_proto
);
198 /* parse_alias_list relies on side effects. Read the comments
200 parse_alias_list (& sep
->s_aliases
, &lasts
);
207 static FILE *svc_file
= NULL
;
208 static long int svc_read_pos
= 0;
209 static struct servent current_servent
;
211 /* Steps through a struct servent, and frees all of the internal
214 free_servent (struct servent
*sep
)
218 char ** current
= sep
->s_aliases
;
219 while (current
&& *current
)
224 free (sep
->s_aliases
);
228 sep
->s_aliases
= NULL
;
232 cygwin_setservent (int stay_open
)
237 svc_file
= open_services_file ();
238 free_servent (¤t_servent
);
240 syscall_printf ("setservent (%d)", stay_open
);
243 extern "C" struct servent
*
244 cygwin_getservent (void)
251 fd
= open_services_file ();
254 syscall_printf ("%p = getservent()", NULL
);
257 fseek (fd
, svc_read_pos
, SEEK_SET
);
259 free_servent (¤t_servent
);
260 bool found
= parse_services_line (fd
, ¤t_servent
);
263 svc_read_pos
= ftell (fd
);
266 struct servent
*result
;
268 result
= ¤t_servent
;
271 syscall_printf ("%p = getservent()", result
);
276 cygwin_endservent (void)
283 free_servent (¤t_servent
);
285 syscall_printf ("endservent ()");
288 /* Read the next line from proto_file, and parse it into the structure
289 pointed to by pep. pep can point to stack or static data, but it's
290 members will be overwritten with pointers to dynamically allocated
291 heap data accommodating parsed data. It is the responsibility of the
292 caller to free up the allocated structures. The function returns true
293 to indicate that a line was successfully read and parsed. False is
294 used to indicate that no more lines can be read and parsed. This
295 should also interpreted as end of file. */
297 parse_protocol_line (FILE *proto_file
, struct protoent
*pep
)
300 while ((line
= get_entire_line (proto_file
)))
302 char *name
, *protocol
, *lasts
;
304 line
[strcspn (line
, "#")] = '\0'; // truncate at comment marker.
305 name
= strtok_r (line
, SPACE
, &lasts
);
311 protocol
= strtok_r (NULL
, SPACE
, &lasts
);
312 pep
->p_name
= strdup (name
);
313 paranoid_printf ("pep->p_name strdup %p", pep
->p_name
);
314 pep
->p_proto
= atoi (protocol
);
315 /* parse_alias_list relies on side effects. Read the comments
317 parse_alias_list (& pep
->p_aliases
, &lasts
);
324 static FILE *proto_file
= NULL
;
325 static long int proto_read_pos
= 0;
326 static struct protoent current_protoent
;
328 /* Steps through a struct protoent, and frees all the internal
331 free_protoent (struct protoent
*pep
)
334 char ** current
= pep
->p_aliases
;
335 while (current
&& *current
)
340 free (pep
->p_aliases
);
343 pep
->p_aliases
= NULL
;
347 cygwin_setprotoent (int stay_open
)
353 proto_file
= open_protocol_file ();
355 free_protoent (¤t_protoent
);
357 syscall_printf ("setprotoent (%d)", stay_open
);
360 extern "C" struct protoent
*
361 cygwin_getprotoent (void)
369 fd
= open_protocol_file ();
372 syscall_printf ("%p = getprotoent()", NULL
);
375 fseek (fd
, proto_read_pos
, SEEK_SET
);
377 free_protoent (¤t_protoent
);
379 bool found
= parse_protocol_line (fd
, ¤t_protoent
);
382 proto_read_pos
= ftell (fd
);
386 struct protoent
*result
;
388 result
= ¤t_protoent
;
392 syscall_printf ("%p = getprotoent()", result
);
397 cygwin_endprotoent (void)
405 free_protoent (¤t_protoent
);
407 syscall_printf ("endprotoent ()");