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 = MAX(*(size_pointer), 1) * 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 = 26;
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 = 26;
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