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