1 /* netdb.cc: network database related routines.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 #include <shared_info.h>
15 /* Locate and open a system network database file. relative_path
16 should be one of the following values:
22 It is the callers responsibility to close the file. */
24 open_system_file (const char *relative_path
)
26 /* system dir path is never longer. */
27 char win32_name
[MAX_PATH
];
29 user_shared
->warned_msdos
= true;
30 sys_wcstombs (win32_name
, MAX_PATH
, windows_system_directory
);
31 strcat (win32_name
, "drivers\\etc\\");
32 strcat (win32_name
, relative_path
);
33 FILE *result
= fopen (win32_name
, "rt");
34 debug_printf ("handle to netdb file %s: %p", win32_name
, result
);
41 return open_system_file ("protocol");
44 /* Wrapper for open_system_file(), fixing the constant name
45 "services". Returns the open file. */
49 return open_system_file ("services");
52 /* Read an entire line up till the next \n character. Memory for the
53 line is dynamically allocated, and the caller must call free() to
54 deallocate it. When the end of file is reached, NULL is returned. */
56 get_entire_line (FILE *fd
)
58 static const int BUFF_SIZE
= 1024;
61 char buffer
[BUFF_SIZE
];
65 line_fragment
*fragment_list_head
= NULL
;
66 line_fragment
*fragment
= NULL
;
67 int fragment_count
= 0;
72 line_fragment
*new_fragment
= (line_fragment
*) malloc (sizeof (line_fragment
));
73 paranoid_printf ("line fragment allocated %p", new_fragment
);
74 if (!fragment_list_head
)
75 fragment_list_head
= new_fragment
;
77 fragment
->next
= new_fragment
;
78 fragment
= new_fragment
;
79 fragment
->next
= NULL
;
80 *fragment
->buffer
= '\0';
81 result
= fgets (fragment
->buffer
, BUFF_SIZE
, fd
);
84 while (result
&& !strchr (fragment
->buffer
, '\n'));
86 if (*fragment_list_head
->buffer
!= '\0')
88 char *concatenated_line
= (char *) calloc (fragment_count
* BUFF_SIZE
, sizeof (char));
89 paranoid_printf ("concatenated line allocated %p", concatenated_line
);
90 *concatenated_line
= '\0';
91 fragment
= fragment_list_head
;
92 while (fragment
!= NULL
)
94 line_fragment
*previous
= fragment
;
95 strcat (concatenated_line
, fragment
->buffer
);
96 fragment
= fragment
->next
;
99 return concatenated_line
;
103 fragment
= fragment_list_head
;
104 while (fragment
!= NULL
)
106 line_fragment
*previous
= fragment
;
107 fragment
= fragment
->next
;
114 /* Characters representing whitespace. Used by parse_* routines to
116 static const char *SPACE
= " \t\n\r\f";
118 /* Parse a list aliases from a network database file. Returns a
119 char** structure terminated by a NULL. */
121 parse_alias_list (char ***aliases
, char **lasts
)
128 alias_t
*alias_list_head
= NULL
, *alias_list_tail
= NULL
;
131 alias
= strtok_r (NULL
, SPACE
, lasts
);
136 alias_t
*new_alias
= (alias_t
*) malloc (sizeof (alias_t
));
137 paranoid_printf ("new alias alloc %p", new_alias
);
138 if (!alias_list_head
)
139 alias_list_head
= new_alias
;
141 alias_list_tail
->next
= new_alias
;
142 new_alias
->next
= NULL
;
143 new_alias
->alias_name
= alias
;
144 alias_list_tail
= new_alias
;
145 alias
= strtok_r (NULL
, SPACE
, lasts
);
148 *aliases
= (char**) calloc (alias_count
+ 1, sizeof (char *));
149 paranoid_printf ("aliases alloc %p", *aliases
);
151 char **current_entry
= *aliases
;
152 while (alias_list_head
)
154 alias_t
*previous
= alias_list_head
;
155 *current_entry
= strdup (alias_list_head
->alias_name
);
156 paranoid_printf ("*current entry strdup %p", *current_entry
);
157 alias_list_head
= alias_list_head
->next
;
162 *current_entry
= NULL
;
165 /* Read the next line from svc_file, and parse it into the structure
166 pointed to by sep. sep can point to stack or static data, but it's
167 members will be overwritten with pointers to dynamically allocated
168 heap data accommodating parsed data. It is the responsibility of the
169 caller to free up the allocated structures. The function returns true
170 to indicate that a line was successfully read and parsed. False is
171 used to indicate that no more lines can be read and parsed. This
172 should also interpreted as end of file. */
174 parse_services_line (FILE *svc_file
, struct servent
*sep
)
177 while ((line
= get_entire_line (svc_file
)))
179 char *name
, *port
, *protocol
, *lasts
;
181 line
[strcspn (line
, "#")] = '\0'; // truncate at comment marker.
182 name
= strtok_r (line
, SPACE
, &lasts
);
188 port
= strtok_r (NULL
, SPACE
, &lasts
);
189 protocol
= strchr (port
, '/');
191 sep
->s_name
= strdup (name
);
192 paranoid_printf ("sep->s_name strdup %p", sep
->s_name
);
193 sep
->s_port
= htons (atoi (port
));
194 sep
->s_proto
= strdup (protocol
);
195 paranoid_printf ("sep->s_proto strdup %p", sep
->s_proto
);
196 /* parse_alias_list relies on side effects. Read the comments
198 parse_alias_list (& sep
->s_aliases
, &lasts
);
205 static FILE *svc_file
= NULL
;
206 static long int svc_read_pos
= 0;
207 static struct servent current_servent
;
209 /* Steps through a struct servent, and frees all of the internal
212 free_servent (struct servent
*sep
)
216 char ** current
= sep
->s_aliases
;
217 while (current
&& *current
)
222 free (sep
->s_aliases
);
226 sep
->s_aliases
= NULL
;
230 cygwin_setservent (int stay_open
)
235 svc_file
= open_services_file ();
236 free_servent (¤t_servent
);
238 syscall_printf ("setservent (%d)", stay_open
);
241 extern "C" struct servent
*
242 cygwin_getservent (void)
249 fd
= open_services_file ();
252 syscall_printf ("%p = getservent()", NULL
);
255 fseek (fd
, svc_read_pos
, SEEK_SET
);
257 free_servent (¤t_servent
);
258 bool found
= parse_services_line (fd
, ¤t_servent
);
261 svc_read_pos
= ftell (fd
);
264 struct servent
*result
;
266 result
= ¤t_servent
;
269 syscall_printf ("%p = getservent()", result
);
274 cygwin_endservent (void)
281 free_servent (¤t_servent
);
283 syscall_printf ("endservent ()");
286 /* Read the next line from proto_file, and parse it into the structure
287 pointed to by pep. pep can point to stack or static data, but it's
288 members will be overwritten with pointers to dynamically allocated
289 heap data accommodating parsed data. It is the responsibility of the
290 caller to free up the allocated structures. The function returns true
291 to indicate that a line was successfully read and parsed. False is
292 used to indicate that no more lines can be read and parsed. This
293 should also interpreted as end of file. */
295 parse_protocol_line (FILE *proto_file
, struct protoent
*pep
)
298 while ((line
= get_entire_line (proto_file
)))
300 char *name
, *protocol
, *lasts
;
302 line
[strcspn (line
, "#")] = '\0'; // truncate at comment marker.
303 name
= strtok_r (line
, SPACE
, &lasts
);
309 protocol
= strtok_r (NULL
, SPACE
, &lasts
);
310 pep
->p_name
= strdup (name
);
311 paranoid_printf ("pep->p_name strdup %p", pep
->p_name
);
312 pep
->p_proto
= atoi (protocol
);
313 /* parse_alias_list relies on side effects. Read the comments
315 parse_alias_list (& pep
->p_aliases
, &lasts
);
322 static FILE *proto_file
= NULL
;
323 static long int proto_read_pos
= 0;
324 static struct protoent current_protoent
;
326 /* Steps through a struct protoent, and frees all the internal
329 free_protoent (struct protoent
*pep
)
332 char ** current
= pep
->p_aliases
;
333 while (current
&& *current
)
338 free (pep
->p_aliases
);
341 pep
->p_aliases
= NULL
;
345 cygwin_setprotoent (int stay_open
)
351 proto_file
= open_protocol_file ();
353 free_protoent (¤t_protoent
);
355 syscall_printf ("setprotoent (%d)", stay_open
);
358 extern "C" struct protoent
*
359 cygwin_getprotoent (void)
367 fd
= open_protocol_file ();
370 syscall_printf ("%p = getprotoent()", NULL
);
373 fseek (fd
, proto_read_pos
, SEEK_SET
);
375 free_protoent (¤t_protoent
);
377 bool found
= parse_protocol_line (fd
, ¤t_protoent
);
380 proto_read_pos
= ftell (fd
);
384 struct protoent
*result
;
386 result
= ¤t_protoent
;
390 syscall_printf ("%p = getprotoent()", result
);
395 cygwin_endprotoent (void)
403 free_protoent (¤t_protoent
);
405 syscall_printf ("endprotoent ()");