1 /* -*- buffer-read-only: t -*-
2  *
3  *    reentr.c
4  *
5  *    Copyright (C) 2002, 2003, 2005, 2006, 2007 by Larry Wall and others
6  *
7  *    You may distribute under the terms of either the GNU General Public
8  *    License or the Artistic License, as specified in the README file.
9  *
10  * !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
11  * This file is built by regen/reentr.pl from data in regen/reentr.pl.
12  * Any changes made here will be lost!
13  */
14 
15 /*
16  * "Saruman," I said, standing away from him, "only one hand at a time can
17  *  wield the One, and you know that well, so do not trouble to say we!"
18  *
19  *     [p.260 of _The Lord of the Rings_, II/ii: "The Council of Elrond"]
20  */
21 
22 /*
23  * This file contains a collection of automatically created wrappers
24  * (created by running reentr.pl) for reentrant (thread-safe) versions of
25  * various library calls, such as getpwent_r.  The wrapping is done so
26  * that other files like pp_sys.c calling those library functions need not
27  * care about the differences between various platforms' idiosyncrasies
28  * regarding these reentrant interfaces.
29  */
30 
31 #include "EXTERN.h"
32 #define PERL_IN_REENTR_C
33 #include "perl.h"
34 #include "reentr.h"
35 #include "keywords.h"
36 
37 #define RenewDouble(data_pointer, size_pointer, type) \
38     STMT_START { \
39 	const size_t size = *(size_pointer) * 2; \
40 	Renew((data_pointer), (size), type); \
41 	*(size_pointer) = size; \
42     } STMT_END
43 
44 void
Perl_reentrant_size(pTHX)45 Perl_reentrant_size(pTHX) {
46 	PERL_UNUSED_CONTEXT;
47 
48         /* Set the sizes of the reentrant buffers */
49 
50 #ifdef USE_REENTRANT_API
51 #  define REENTRANTSMALLSIZE	 256	/* Make something up. */
52 #  define REENTRANTUSUALSIZE	4096	/* Make something up. */
53 
54 #  ifdef HAS_ASCTIME_R
55 	PL_reentrant_buffer->_asctime_size = REENTRANTSMALLSIZE;
56 #  endif /* HAS_ASCTIME_R */
57 
58 #  ifdef HAS_CRYPT_R
59 #  endif /* HAS_CRYPT_R */
60 
61 #  ifdef HAS_CTIME_R
62 	PL_reentrant_buffer->_ctime_size = REENTRANTSMALLSIZE;
63 #  endif /* HAS_CTIME_R */
64 
65 #  ifdef HAS_GETGRNAM_R
66 #    if defined(HAS_SYSCONF) && defined(_SC_GETGR_R_SIZE_MAX) && !defined(__GLIBC__)
67 	PL_reentrant_buffer->_grent_size = sysconf(_SC_GETGR_R_SIZE_MAX);
68 	if (PL_reentrant_buffer->_grent_size == (size_t) -1)
69 		PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
70 #    elif defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
71 	PL_reentrant_buffer->_grent_size = SIABUFSIZ;
72 #    elif defined(__sgi)
73 	PL_reentrant_buffer->_grent_size = BUFSIZ;
74 #    else
75 	PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
76 #    endif
77 #  endif /* HAS_GETGRNAM_R */
78 
79 #  ifdef HAS_GETHOSTBYNAME_R
80 #  if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
81 	PL_reentrant_buffer->_hostent_size = REENTRANTUSUALSIZE;
82 #  endif
83 #  endif /* HAS_GETHOSTBYNAME_R */
84 
85 #  ifdef HAS_GETLOGIN_R
86 	PL_reentrant_buffer->_getlogin_size = REENTRANTSMALLSIZE;
87 #  endif /* HAS_GETLOGIN_R */
88 
89 #  ifdef HAS_GETNETBYNAME_R
90 #  if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
91 	PL_reentrant_buffer->_netent_size = REENTRANTUSUALSIZE;
92 #  endif
93 #  endif /* HAS_GETNETBYNAME_R */
94 
95 #  ifdef HAS_GETPROTOBYNAME_R
96 #  if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
97 	PL_reentrant_buffer->_protoent_size = REENTRANTUSUALSIZE;
98 #  endif
99 #  endif /* HAS_GETPROTOBYNAME_R */
100 
101 #  ifdef HAS_GETPWNAM_R
102 #    if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
103 	PL_reentrant_buffer->_pwent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
104 	if (PL_reentrant_buffer->_pwent_size == (size_t) -1)
105 		PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
106 #    elif defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
107 	PL_reentrant_buffer->_pwent_size = SIABUFSIZ;
108 #    elif defined(__sgi)
109 	PL_reentrant_buffer->_pwent_size = BUFSIZ;
110 #    else
111 	PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
112 #    endif
113 #  endif /* HAS_GETPWNAM_R */
114 
115 #  ifdef HAS_GETSERVBYNAME_R
116 #  if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
117 	PL_reentrant_buffer->_servent_size = REENTRANTUSUALSIZE;
118 #  endif
119 #  endif /* HAS_GETSERVBYNAME_R */
120 
121 #  ifdef HAS_GETSPNAM_R
122 #    if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
123 	PL_reentrant_buffer->_spent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
124 	if (PL_reentrant_buffer->_spent_size == (size_t) -1)
125 		PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
126 #    elif defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
127 	PL_reentrant_buffer->_spent_size = SIABUFSIZ;
128 #    elif defined(__sgi)
129 	PL_reentrant_buffer->_spent_size = BUFSIZ;
130 #    else
131 	PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
132 #    endif
133 #  endif /* HAS_GETSPNAM_R */
134 
135 #  ifdef HAS_GMTIME_R
136 #  endif /* HAS_GMTIME_R */
137 
138 #  ifdef HAS_LOCALTIME_R
139 #  endif /* HAS_LOCALTIME_R */
140 
141 #  ifdef HAS_READDIR_R
142 	/* This is the size Solaris recommends.
143 	 * (though we go static, should use pathconf() instead) */
144 	PL_reentrant_buffer->_readdir_size = sizeof(struct dirent) + MAXPATHLEN + 1;
145 #  endif /* HAS_READDIR_R */
146 
147 #  ifdef HAS_READDIR64_R
148 	/* This is the size Solaris recommends.
149 	 * (though we go static, should use pathconf() instead) */
150 	PL_reentrant_buffer->_readdir64_size = sizeof(struct dirent64) + MAXPATHLEN + 1;
151 #  endif /* HAS_READDIR64_R */
152 
153 #  ifdef HAS_SETLOCALE_R
154 	PL_reentrant_buffer->_setlocale_size = REENTRANTSMALLSIZE;
155 #  endif /* HAS_SETLOCALE_R */
156 
157 #  ifdef HAS_STRERROR_R
158 	PL_reentrant_buffer->_strerror_size = REENTRANTSMALLSIZE;
159 #  endif /* HAS_STRERROR_R */
160 
161 #  ifdef HAS_TTYNAME_R
162 	PL_reentrant_buffer->_ttyname_size = REENTRANTSMALLSIZE;
163 #  endif /* HAS_TTYNAME_R */
164 
165 
166 #endif /* USE_REENTRANT_API */
167 
168 }
169 
170 void
Perl_reentrant_init(pTHX)171 Perl_reentrant_init(pTHX) {
172 	PERL_UNUSED_CONTEXT;
173 
174         /* Initialize the whole thing */
175 
176 #ifdef USE_REENTRANT_API
177 
178 	Newx(PL_reentrant_buffer, 1, REENTR);
179 	Perl_reentrant_size(aTHX);
180 
181 #  ifdef HAS_ASCTIME_R
182 	Newx(PL_reentrant_buffer->_asctime_buffer, PL_reentrant_buffer->_asctime_size, char);
183 #  endif /* HAS_ASCTIME_R */
184 
185 #  ifdef HAS_CRYPT_R
186 #  if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
187 	PL_reentrant_buffer->_crypt_struct_buffer = 0;
188 #  endif
189 #  endif /* HAS_CRYPT_R */
190 
191 #  ifdef HAS_CTIME_R
192 	Newx(PL_reentrant_buffer->_ctime_buffer, PL_reentrant_buffer->_ctime_size, char);
193 #  endif /* HAS_CTIME_R */
194 
195 #  ifdef HAS_GETGRNAM_R
196 #   ifdef USE_GRENT_FPTR
197 	PL_reentrant_buffer->_grent_fptr = NULL;
198 #   endif
199 	Newx(PL_reentrant_buffer->_grent_buffer, PL_reentrant_buffer->_grent_size, char);
200 #  endif /* HAS_GETGRNAM_R */
201 
202 #  ifdef HAS_GETHOSTBYNAME_R
203 #  if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
204 	Newx(PL_reentrant_buffer->_hostent_buffer, PL_reentrant_buffer->_hostent_size, char);
205 #  endif
206 #  endif /* HAS_GETHOSTBYNAME_R */
207 
208 #  ifdef HAS_GETLOGIN_R
209 	Newx(PL_reentrant_buffer->_getlogin_buffer, PL_reentrant_buffer->_getlogin_size, char);
210 #  endif /* HAS_GETLOGIN_R */
211 
212 #  ifdef HAS_GETNETBYNAME_R
213 #  if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
214 	Newx(PL_reentrant_buffer->_netent_buffer, PL_reentrant_buffer->_netent_size, char);
215 #  endif
216 #  endif /* HAS_GETNETBYNAME_R */
217 
218 #  ifdef HAS_GETPROTOBYNAME_R
219 #  if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
220 	Newx(PL_reentrant_buffer->_protoent_buffer, PL_reentrant_buffer->_protoent_size, char);
221 #  endif
222 #  endif /* HAS_GETPROTOBYNAME_R */
223 
224 #  ifdef HAS_GETPWNAM_R
225 #   ifdef USE_PWENT_FPTR
226 	PL_reentrant_buffer->_pwent_fptr = NULL;
227 #   endif
228 	Newx(PL_reentrant_buffer->_pwent_buffer, PL_reentrant_buffer->_pwent_size, char);
229 #  endif /* HAS_GETPWNAM_R */
230 
231 #  ifdef HAS_GETSERVBYNAME_R
232 #  if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
233 	Newx(PL_reentrant_buffer->_servent_buffer, PL_reentrant_buffer->_servent_size, char);
234 #  endif
235 #  endif /* HAS_GETSERVBYNAME_R */
236 
237 #  ifdef HAS_GETSPNAM_R
238 #   ifdef USE_SPENT_FPTR
239 	PL_reentrant_buffer->_spent_fptr = NULL;
240 #   endif
241 	Newx(PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char);
242 #  endif /* HAS_GETSPNAM_R */
243 
244 #  ifdef HAS_GMTIME_R
245 #  endif /* HAS_GMTIME_R */
246 
247 #  ifdef HAS_LOCALTIME_R
248 #  endif /* HAS_LOCALTIME_R */
249 
250 #  ifdef HAS_READDIR_R
251 	PL_reentrant_buffer->_readdir_struct = (struct dirent*)safemalloc(PL_reentrant_buffer->_readdir_size);
252 #  endif /* HAS_READDIR_R */
253 
254 #  ifdef HAS_READDIR64_R
255 	PL_reentrant_buffer->_readdir64_struct = (struct dirent64*)safemalloc(PL_reentrant_buffer->_readdir64_size);
256 #  endif /* HAS_READDIR64_R */
257 
258 #  ifdef HAS_SETLOCALE_R
259 	Newx(PL_reentrant_buffer->_setlocale_buffer, PL_reentrant_buffer->_setlocale_size, char);
260 #  endif /* HAS_SETLOCALE_R */
261 
262 #  ifdef HAS_STRERROR_R
263 	Newx(PL_reentrant_buffer->_strerror_buffer, PL_reentrant_buffer->_strerror_size, char);
264 #  endif /* HAS_STRERROR_R */
265 
266 #  ifdef HAS_TTYNAME_R
267 	Newx(PL_reentrant_buffer->_ttyname_buffer, PL_reentrant_buffer->_ttyname_size, char);
268 #  endif /* HAS_TTYNAME_R */
269 
270 
271 #endif /* USE_REENTRANT_API */
272 
273 }
274 
275 void
Perl_reentrant_free(pTHX)276 Perl_reentrant_free(pTHX) {
277 	PERL_UNUSED_CONTEXT;
278 
279         /* Tear down */
280 
281 #ifdef USE_REENTRANT_API
282 
283 #  ifdef HAS_ASCTIME_R
284 	Safefree(PL_reentrant_buffer->_asctime_buffer);
285 #  endif /* HAS_ASCTIME_R */
286 
287 #  ifdef HAS_CRYPT_R
288 #  if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
289 	Safefree(PL_reentrant_buffer->_crypt_struct_buffer);
290 #  endif
291 #  endif /* HAS_CRYPT_R */
292 
293 #  ifdef HAS_CTIME_R
294 	Safefree(PL_reentrant_buffer->_ctime_buffer);
295 #  endif /* HAS_CTIME_R */
296 
297 #  ifdef HAS_GETGRNAM_R
298 	Safefree(PL_reentrant_buffer->_grent_buffer);
299 #  endif /* HAS_GETGRNAM_R */
300 
301 #  ifdef HAS_GETHOSTBYNAME_R
302 #  if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
303 	Safefree(PL_reentrant_buffer->_hostent_buffer);
304 #  endif
305 #  endif /* HAS_GETHOSTBYNAME_R */
306 
307 #  ifdef HAS_GETLOGIN_R
308 	Safefree(PL_reentrant_buffer->_getlogin_buffer);
309 #  endif /* HAS_GETLOGIN_R */
310 
311 #  ifdef HAS_GETNETBYNAME_R
312 #  if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
313 	Safefree(PL_reentrant_buffer->_netent_buffer);
314 #  endif
315 #  endif /* HAS_GETNETBYNAME_R */
316 
317 #  ifdef HAS_GETPROTOBYNAME_R
318 #  if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
319 	Safefree(PL_reentrant_buffer->_protoent_buffer);
320 #  endif
321 #  endif /* HAS_GETPROTOBYNAME_R */
322 
323 #  ifdef HAS_GETPWNAM_R
324 	Safefree(PL_reentrant_buffer->_pwent_buffer);
325 #  endif /* HAS_GETPWNAM_R */
326 
327 #  ifdef HAS_GETSERVBYNAME_R
328 #  if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
329 	Safefree(PL_reentrant_buffer->_servent_buffer);
330 #  endif
331 #  endif /* HAS_GETSERVBYNAME_R */
332 
333 #  ifdef HAS_GETSPNAM_R
334 	Safefree(PL_reentrant_buffer->_spent_buffer);
335 #  endif /* HAS_GETSPNAM_R */
336 
337 #  ifdef HAS_GMTIME_R
338 #  endif /* HAS_GMTIME_R */
339 
340 #  ifdef HAS_LOCALTIME_R
341 #  endif /* HAS_LOCALTIME_R */
342 
343 #  ifdef HAS_READDIR_R
344 	Safefree(PL_reentrant_buffer->_readdir_struct);
345 #  endif /* HAS_READDIR_R */
346 
347 #  ifdef HAS_READDIR64_R
348 	Safefree(PL_reentrant_buffer->_readdir64_struct);
349 #  endif /* HAS_READDIR64_R */
350 
351 #  ifdef HAS_SETLOCALE_R
352 	Safefree(PL_reentrant_buffer->_setlocale_buffer);
353 #  endif /* HAS_SETLOCALE_R */
354 
355 #  ifdef HAS_STRERROR_R
356 	Safefree(PL_reentrant_buffer->_strerror_buffer);
357 #  endif /* HAS_STRERROR_R */
358 
359 #  ifdef HAS_TTYNAME_R
360 	Safefree(PL_reentrant_buffer->_ttyname_buffer);
361 #  endif /* HAS_TTYNAME_R */
362 
363 
364 	Safefree(PL_reentrant_buffer);
365 
366 #endif /* USE_REENTRANT_API */
367 }
368 
369 void*
Perl_reentrant_retry(const char * f,...)370 Perl_reentrant_retry(const char *f, ...)
371 {
372     /* This function is set up to be called if the normal function returns
373      * failure with errno ERANGE, which indicates the buffer is too small.
374      * This function calls the failing one again with a larger buffer.
375      *
376      * What has happened is that, due to the magic of C preprocessor macro
377      * expansion, when the original code called function 'foo(args)', it was
378      * instead compiled into something like a call of 'foo_r(args, buffer)'
379      * Below we retry with 'foo', but the preprocessor has changed that into
380      * 'foo_r', so this function will end up calling itself recursively, each
381      * time with a larger buffer.  If PERL_REENTRANT_MAXSIZE is defined, it
382      * won't increase beyond that, instead failing. */
383 
384     void *retptr = NULL;
385     va_list ap;
386 
387     I32 key = 0;
388 
389 #ifdef USE_REENTRANT_API
390 
391     dTHX;
392 
393     key = Perl_keyword (aTHX_ f, strlen(f), FALSE /* not feature enabled */);
394 
395     /* Easier to special case this here than in embed.pl. (Look at what it
396        generates for proto.h) */
397     PERL_ARGS_ASSERT_REENTRANT_RETRY;
398 
399 #endif
400 
401     if (key == 0) {
402 
403 #ifdef HAS_GETSPNAM_R
404 
405 	/* This is a #define as has no corresponding keyword */
406         if (strEQ(f, "getspnam")) {
407             key = KEY_getspnam;
408         }
409 
410 #endif
411 
412     }
413     else if (key < 0) {
414         key = -key;
415     }
416 
417     va_start(ap, f);
418 
419 #ifdef USE_REENTRANT_API
420 
421     switch (key) {
422 
423 #  ifdef USE_HOSTENT_BUFFER
424 
425     case KEY_gethostbyaddr:
426     case KEY_gethostbyname:
427     case KEY_endhostent:
428 	{
429             char * host_addr;
430             Size_t asize;
431             char * host_name;
432             int anint;
433 
434 #    ifdef PERL_REENTRANT_MAXSIZE
435 	    if (PL_reentrant_buffer->_hostent_size <=
436 		PERL_REENTRANT_MAXSIZE / 2)
437 #    endif
438             RenewDouble(PL_reentrant_buffer->_hostent_buffer,
439                     &PL_reentrant_buffer->_hostent_size, char);
440             switch (key) {
441 	        case KEY_gethostbyaddr:
442 		    host_addr = va_arg(ap, char *);
443 		    asize = va_arg(ap, Size_t);
444 		    anint  = va_arg(ap, int);
445                     /* socklen_t is what Posix 2001 says this should be */
446 		    retptr = gethostbyaddr(host_addr, (socklen_t) asize, anint); break;
447 	        case KEY_gethostbyname:
448 		    host_name = va_arg(ap, char *);
449 		    retptr = gethostbyname(host_name); break;
450 	        case KEY_endhostent:
451 		    retptr = gethostent(); break;
452 	        default:
453 		    SETERRNO(ERANGE, LIB_INVARG);
454 		    break;
455 	    }
456 	}
457 	break;
458 
459 #  endif
460 #  ifdef USE_GRENT_BUFFER
461 
462     case KEY_getgrent:
463     case KEY_getgrgid:
464     case KEY_getgrnam:
465 	{
466             char * name;
467             Gid_t gid;
468 
469 #    ifdef PERL_REENTRANT_MAXSIZE
470 	    if (PL_reentrant_buffer->_grent_size <=
471 		PERL_REENTRANT_MAXSIZE / 2)
472 #    endif
473             RenewDouble(PL_reentrant_buffer->_grent_buffer,
474                     &PL_reentrant_buffer->_grent_size, char);
475             switch (key) {
476 	        case KEY_getgrnam:
477 		    name = va_arg(ap, char *);
478 		    retptr = getgrnam(name); break;
479 	        case KEY_getgrgid:
480 #    if Gid_t_size < INTSIZE
481                     gid = (Gid_t)va_arg(ap, int);
482 #    else
483 		    gid = va_arg(ap, Gid_t);
484 #    endif
485 		    retptr = getgrgid(gid); break;
486 	        case KEY_getgrent:
487 		    retptr = getgrent(); break;
488 	        default:
489 		    SETERRNO(ERANGE, LIB_INVARG);
490 		    break;
491 	    }
492 	}
493 	break;
494 
495 #  endif
496 #  ifdef USE_NETENT_BUFFER
497 
498     case KEY_getnetbyaddr:
499     case KEY_getnetbyname:
500     case KEY_getnetent:
501 	{
502             char * name;
503             Netdb_net_t net;
504             int anint;
505 
506 #    ifdef PERL_REENTRANT_MAXSIZE
507 	    if (PL_reentrant_buffer->_netent_size <=
508 		PERL_REENTRANT_MAXSIZE / 2)
509 #    endif
510             RenewDouble(PL_reentrant_buffer->_netent_buffer,
511                     &PL_reentrant_buffer->_netent_size, char);
512             switch (key) {
513                 case KEY_getnetbyaddr:
514                     net = va_arg(ap, Netdb_net_t);
515                     anint = va_arg(ap, int);
516                     retptr = getnetbyaddr(net, anint); break;
517                 case KEY_getnetbyname:
518                     name = va_arg(ap, char *);
519                     retptr = getnetbyname(name); break;
520                 case KEY_getnetent:
521                     retptr = getnetent(); break;
522                 default:
523                     SETERRNO(ERANGE, LIB_INVARG);
524                     break;
525 	    }
526 	}
527 	break;
528 
529 #  endif
530 #  ifdef USE_PWENT_BUFFER
531 
532     case  KEY_getpwnam:
533     case  KEY_getpwuid:
534     case  KEY_getpwent:
535 	{
536             Uid_t uid;
537             char * name;
538 
539 #    ifdef PERL_REENTRANT_MAXSIZE
540 	    if (PL_reentrant_buffer->_pwent_size <=
541 		PERL_REENTRANT_MAXSIZE / 2)
542 
543 #    endif
544             RenewDouble(PL_reentrant_buffer->_pwent_buffer,
545                     &PL_reentrant_buffer->_pwent_size, char);
546             switch (key) {
547 	        case KEY_getpwnam:
548 		    name = va_arg(ap, char *);
549 		    retptr = getpwnam(name); break;
550 	        case KEY_getpwuid:
551 
552 #    if Uid_t_size < INTSIZE
553 		    uid = (Uid_t)va_arg(ap, int);
554 #    else
555 		    uid = va_arg(ap, Uid_t);
556 #    endif
557 		    retptr = getpwuid(uid); break;
558 
559 #  if defined(HAS_GETPWENT) || defined(HAS_GETPWENT_R)
560 
561 	        case KEY_getpwent:
562 		    retptr = getpwent(); break;
563 #  endif
564 	        default:
565 		    SETERRNO(ERANGE, LIB_INVARG);
566 		    break;
567             }
568 	}
569 	break;
570 
571 #  endif
572 #  ifdef USE_SPENT_BUFFER
573 
574     case KEY_getspnam:
575 	{
576             char * name;
577 
578 #    ifdef PERL_REENTRANT_MAXSIZE
579 	    if (PL_reentrant_buffer->_spent_size <=
580 		PERL_REENTRANT_MAXSIZE / 2)
581 
582 #    endif
583             RenewDouble(PL_reentrant_buffer->_spent_buffer,
584                     &PL_reentrant_buffer->_spent_size, char);
585             switch (key) {
586 	        case KEY_getspnam:
587 		    name = va_arg(ap, char *);
588 		    retptr = getspnam(name); break;
589 	        default:
590 		    SETERRNO(ERANGE, LIB_INVARG);
591 		    break;
592             }
593 	}
594 	break;
595 
596 #  endif
597 #  ifdef USE_PROTOENT_BUFFER
598 
599     case KEY_getprotobyname:
600     case KEY_getprotobynumber:
601     case KEY_getprotoent:
602 	{
603             char * name;
604             int anint;
605 
606 #    ifdef PERL_REENTRANT_MAXSIZE
607 	    if (PL_reentrant_buffer->_protoent_size <=
608 		PERL_REENTRANT_MAXSIZE / 2)
609 #    endif
610             RenewDouble(PL_reentrant_buffer->_protoent_buffer,
611                     &PL_reentrant_buffer->_protoent_size, char);
612             switch (key) {
613 	        case KEY_getprotobyname:
614 		    name = va_arg(ap, char *);
615 		    retptr = getprotobyname(name); break;
616 	        case KEY_getprotobynumber:
617 		    anint = va_arg(ap, int);
618 		    retptr = getprotobynumber(anint); break;
619 	        case KEY_getprotoent:
620 		    retptr = getprotoent(); break;
621 	        default:
622 		    SETERRNO(ERANGE, LIB_INVARG);
623 		    break;
624 	    }
625 	}
626 	break;
627 
628 #  endif
629 #  ifdef USE_SERVENT_BUFFER
630 
631     case KEY_getservbyname:
632     case KEY_getservbyport:
633     case KEY_getservent:
634 	{
635             char * name;
636             char * proto;
637             int anint;
638 
639 #    ifdef PERL_REENTRANT_MAXSIZE
640 	    if (PL_reentrant_buffer->_servent_size <=
641 		PERL_REENTRANT_MAXSIZE / 2)
642 #    endif
643             RenewDouble(PL_reentrant_buffer->_servent_buffer,
644                     &PL_reentrant_buffer->_servent_size, char);
645             switch (key) {
646 	        case KEY_getservbyname:
647 		    name = va_arg(ap, char *);
648 		    proto = va_arg(ap, char *);
649 		    retptr = getservbyname(name, proto); break;
650 	        case KEY_getservbyport:
651 		    anint = va_arg(ap, int);
652 		    name = va_arg(ap, char *);
653 		    retptr = getservbyport(anint, name); break;
654 	        case KEY_getservent:
655 		    retptr = getservent(); break;
656 	        default:
657 		    SETERRNO(ERANGE, LIB_INVARG);
658 		    break;
659 	    }
660 	}
661 	break;
662 
663 #  endif
664 
665     default:
666 	/* Not known how to retry, so just fail. */
667 	break;
668     }
669 
670 #else
671 
672     PERL_UNUSED_ARG(f);
673 
674 #endif
675 
676     va_end(ap);
677     return retptr;
678 }
679 
680 /* ex: set ro: */
681