1/* -*- mode: C; 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
44void
45Perl_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
170void
171Perl_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
275void
276Perl_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
369void*
370Perl_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 ft=c: */
681