xref: /openbsd/gnu/usr.bin/perl/reentr.c (revision e0680481)
1*e0680481Safresh1 /* -*- mode: C; buffer-read-only: t -*-
252bd00bfSmillert  *
355745691Smillert  *    reentr.c
455745691Smillert  *
5850e2753Smillert  *    Copyright (C) 2002, 2003, 2005, 2006, 2007 by Larry Wall and others
655745691Smillert  *
755745691Smillert  *    You may distribute under the terms of either the GNU General Public
855745691Smillert  *    License or the Artistic License, as specified in the README file.
955745691Smillert  *
1055745691Smillert  * !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
11898184e3Ssthen  * This file is built by regen/reentr.pl from data in regen/reentr.pl.
12898184e3Ssthen  * Any changes made here will be lost!
13b8851fccSafresh1  */
14b8851fccSafresh1 
15b8851fccSafresh1 /*
1655745691Smillert  * "Saruman," I said, standing away from him, "only one hand at a time can
1755745691Smillert  *  wield the One, and you know that well, so do not trouble to say we!"
1855745691Smillert  *
19b8851fccSafresh1  *     [p.260 of _The Lord of the Rings_, II/ii: "The Council of Elrond"]
20b8851fccSafresh1  */
21b8851fccSafresh1 
22b8851fccSafresh1 /*
235b2d2359Smillert  * This file contains a collection of automatically created wrappers
245b2d2359Smillert  * (created by running reentr.pl) for reentrant (thread-safe) versions of
255b2d2359Smillert  * various library calls, such as getpwent_r.  The wrapping is done so
265b2d2359Smillert  * that other files like pp_sys.c calling those library functions need not
275b2d2359Smillert  * care about the differences between various platforms' idiosyncrasies
285b2d2359Smillert  * regarding these reentrant interfaces.
2955745691Smillert  */
3055745691Smillert 
3155745691Smillert #include "EXTERN.h"
3255745691Smillert #define PERL_IN_REENTR_C
3355745691Smillert #include "perl.h"
3455745691Smillert #include "reentr.h"
3556d68f1eSafresh1 #include "keywords.h"
3655745691Smillert 
379f11ffb7Safresh1 #define RenewDouble(data_pointer, size_pointer, type) \
389f11ffb7Safresh1     STMT_START { \
39eac174f2Safresh1         const size_t size = MAX(*(size_pointer), 1) * 2; \
409f11ffb7Safresh1         Renew((data_pointer), (size), type); \
419f11ffb7Safresh1         *(size_pointer) = size; \
429f11ffb7Safresh1     } STMT_END
439f11ffb7Safresh1 
4455745691Smillert void
Perl_reentrant_size(pTHX)4555745691Smillert Perl_reentrant_size(pTHX) {
46b8851fccSafresh1         PERL_UNUSED_CONTEXT;
4756d68f1eSafresh1 
4856d68f1eSafresh1         /* Set the sizes of the reentrant buffers */
4956d68f1eSafresh1 
5055745691Smillert #ifdef USE_REENTRANT_API
5155745691Smillert #  define REENTRANTSMALLSIZE	 256	/* Make something up. */
5255745691Smillert #  define REENTRANTUSUALSIZE	4096	/* Make something up. */
5356d68f1eSafresh1 
5455745691Smillert #  ifdef HAS_ASCTIME_R
55eac174f2Safresh1         PL_reentrant_buffer->_asctime_size = 26;
5655745691Smillert #  endif /* HAS_ASCTIME_R */
5756d68f1eSafresh1 
5855745691Smillert #  ifdef HAS_CRYPT_R
5955745691Smillert #  endif /* HAS_CRYPT_R */
6056d68f1eSafresh1 
6155745691Smillert #  ifdef HAS_CTIME_R
62eac174f2Safresh1         PL_reentrant_buffer->_ctime_size = 26;
6355745691Smillert #  endif /* HAS_CTIME_R */
6456d68f1eSafresh1 
6555745691Smillert #  ifdef HAS_GETGRNAM_R
6685009909Smillert #    if defined(HAS_SYSCONF) && defined(_SC_GETGR_R_SIZE_MAX) && !defined(__GLIBC__)
6785009909Smillert         PL_reentrant_buffer->_grent_size = sysconf(_SC_GETGR_R_SIZE_MAX);
68850e2753Smillert         if (PL_reentrant_buffer->_grent_size == (size_t) -1)
6985009909Smillert                 PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
709f11ffb7Safresh1 #    elif defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
7155745691Smillert         PL_reentrant_buffer->_grent_size = SIABUFSIZ;
729f11ffb7Safresh1 #    elif defined(__sgi)
7355745691Smillert         PL_reentrant_buffer->_grent_size = BUFSIZ;
7455745691Smillert #    else
7555745691Smillert         PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
7655745691Smillert #    endif
7755745691Smillert #  endif /* HAS_GETGRNAM_R */
7856d68f1eSafresh1 
7955745691Smillert #  ifdef HAS_GETHOSTBYNAME_R
8055745691Smillert #  if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
8155745691Smillert         PL_reentrant_buffer->_hostent_size = REENTRANTUSUALSIZE;
8255745691Smillert #  endif
8355745691Smillert #  endif /* HAS_GETHOSTBYNAME_R */
8456d68f1eSafresh1 
8555745691Smillert #  ifdef HAS_GETLOGIN_R
8655745691Smillert         PL_reentrant_buffer->_getlogin_size = REENTRANTSMALLSIZE;
8755745691Smillert #  endif /* HAS_GETLOGIN_R */
8856d68f1eSafresh1 
8955745691Smillert #  ifdef HAS_GETNETBYNAME_R
9055745691Smillert #  if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
9155745691Smillert         PL_reentrant_buffer->_netent_size = REENTRANTUSUALSIZE;
9255745691Smillert #  endif
9355745691Smillert #  endif /* HAS_GETNETBYNAME_R */
9456d68f1eSafresh1 
9555745691Smillert #  ifdef HAS_GETPROTOBYNAME_R
9655745691Smillert #  if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
9755745691Smillert         PL_reentrant_buffer->_protoent_size = REENTRANTUSUALSIZE;
9855745691Smillert #  endif
9955745691Smillert #  endif /* HAS_GETPROTOBYNAME_R */
10056d68f1eSafresh1 
10155745691Smillert #  ifdef HAS_GETPWNAM_R
10255745691Smillert #    if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
10355745691Smillert         PL_reentrant_buffer->_pwent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
104850e2753Smillert         if (PL_reentrant_buffer->_pwent_size == (size_t) -1)
10555745691Smillert                 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
1069f11ffb7Safresh1 #    elif defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
10755745691Smillert         PL_reentrant_buffer->_pwent_size = SIABUFSIZ;
1089f11ffb7Safresh1 #    elif defined(__sgi)
10955745691Smillert         PL_reentrant_buffer->_pwent_size = BUFSIZ;
11055745691Smillert #    else
11155745691Smillert         PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
11255745691Smillert #    endif
11355745691Smillert #  endif /* HAS_GETPWNAM_R */
11456d68f1eSafresh1 
11555745691Smillert #  ifdef HAS_GETSERVBYNAME_R
11655745691Smillert #  if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
11755745691Smillert         PL_reentrant_buffer->_servent_size = REENTRANTUSUALSIZE;
11855745691Smillert #  endif
11955745691Smillert #  endif /* HAS_GETSERVBYNAME_R */
12056d68f1eSafresh1 
12155745691Smillert #  ifdef HAS_GETSPNAM_R
12255745691Smillert #    if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
12355745691Smillert         PL_reentrant_buffer->_spent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
124850e2753Smillert         if (PL_reentrant_buffer->_spent_size == (size_t) -1)
12585009909Smillert                 PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
1269f11ffb7Safresh1 #    elif defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
12755745691Smillert         PL_reentrant_buffer->_spent_size = SIABUFSIZ;
1289f11ffb7Safresh1 #    elif defined(__sgi)
12955745691Smillert         PL_reentrant_buffer->_spent_size = BUFSIZ;
13055745691Smillert #    else
13155745691Smillert         PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
13255745691Smillert #    endif
13355745691Smillert #  endif /* HAS_GETSPNAM_R */
13456d68f1eSafresh1 
13556d68f1eSafresh1 #  ifdef HAS_GMTIME_R
13656d68f1eSafresh1 #  endif /* HAS_GMTIME_R */
13756d68f1eSafresh1 
13856d68f1eSafresh1 #  ifdef HAS_LOCALTIME_R
13956d68f1eSafresh1 #  endif /* HAS_LOCALTIME_R */
14056d68f1eSafresh1 
14155745691Smillert #  ifdef HAS_READDIR_R
14255745691Smillert         /* This is the size Solaris recommends.
14355745691Smillert          * (though we go static, should use pathconf() instead) */
14455745691Smillert         PL_reentrant_buffer->_readdir_size = sizeof(struct dirent) + MAXPATHLEN + 1;
14555745691Smillert #  endif /* HAS_READDIR_R */
14656d68f1eSafresh1 
14755745691Smillert #  ifdef HAS_READDIR64_R
14855745691Smillert         /* This is the size Solaris recommends.
14955745691Smillert          * (though we go static, should use pathconf() instead) */
15055745691Smillert         PL_reentrant_buffer->_readdir64_size = sizeof(struct dirent64) + MAXPATHLEN + 1;
15155745691Smillert #  endif /* HAS_READDIR64_R */
15256d68f1eSafresh1 
15355745691Smillert #  ifdef HAS_SETLOCALE_R
15455745691Smillert         PL_reentrant_buffer->_setlocale_size = REENTRANTSMALLSIZE;
15555745691Smillert #  endif /* HAS_SETLOCALE_R */
15656d68f1eSafresh1 
15755745691Smillert #  ifdef HAS_STRERROR_R
15855745691Smillert         PL_reentrant_buffer->_strerror_size = REENTRANTSMALLSIZE;
15955745691Smillert #  endif /* HAS_STRERROR_R */
16056d68f1eSafresh1 
16155745691Smillert #  ifdef HAS_TTYNAME_R
16255745691Smillert         PL_reentrant_buffer->_ttyname_size = REENTRANTSMALLSIZE;
16355745691Smillert #  endif /* HAS_TTYNAME_R */
16455745691Smillert 
16556d68f1eSafresh1 
16655745691Smillert #endif /* USE_REENTRANT_API */
16756d68f1eSafresh1 
16855745691Smillert }
16955745691Smillert 
17055745691Smillert void
Perl_reentrant_init(pTHX)17155745691Smillert Perl_reentrant_init(pTHX) {
172b8851fccSafresh1         PERL_UNUSED_CONTEXT;
17356d68f1eSafresh1 
17456d68f1eSafresh1         /* Initialize the whole thing */
17556d68f1eSafresh1 
17655745691Smillert #ifdef USE_REENTRANT_API
17756d68f1eSafresh1 
17852bd00bfSmillert         Newx(PL_reentrant_buffer, 1, REENTR);
17955745691Smillert         Perl_reentrant_size(aTHX);
18056d68f1eSafresh1 
18155745691Smillert #  ifdef HAS_ASCTIME_R
18252bd00bfSmillert         Newx(PL_reentrant_buffer->_asctime_buffer, PL_reentrant_buffer->_asctime_size, char);
18355745691Smillert #  endif /* HAS_ASCTIME_R */
18456d68f1eSafresh1 
18555745691Smillert #  ifdef HAS_CRYPT_R
18685009909Smillert #  if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
18785009909Smillert         PL_reentrant_buffer->_crypt_struct_buffer = 0;
18855745691Smillert #  endif
18955745691Smillert #  endif /* HAS_CRYPT_R */
19056d68f1eSafresh1 
19155745691Smillert #  ifdef HAS_CTIME_R
19252bd00bfSmillert         Newx(PL_reentrant_buffer->_ctime_buffer, PL_reentrant_buffer->_ctime_size, char);
19355745691Smillert #  endif /* HAS_CTIME_R */
19456d68f1eSafresh1 
19555745691Smillert #  ifdef HAS_GETGRNAM_R
19655745691Smillert #   ifdef USE_GRENT_FPTR
19755745691Smillert         PL_reentrant_buffer->_grent_fptr = NULL;
19855745691Smillert #   endif
19952bd00bfSmillert         Newx(PL_reentrant_buffer->_grent_buffer, PL_reentrant_buffer->_grent_size, char);
20055745691Smillert #  endif /* HAS_GETGRNAM_R */
20156d68f1eSafresh1 
20255745691Smillert #  ifdef HAS_GETHOSTBYNAME_R
20355745691Smillert #  if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
20452bd00bfSmillert         Newx(PL_reentrant_buffer->_hostent_buffer, PL_reentrant_buffer->_hostent_size, char);
20555745691Smillert #  endif
20655745691Smillert #  endif /* HAS_GETHOSTBYNAME_R */
20756d68f1eSafresh1 
20855745691Smillert #  ifdef HAS_GETLOGIN_R
20952bd00bfSmillert         Newx(PL_reentrant_buffer->_getlogin_buffer, PL_reentrant_buffer->_getlogin_size, char);
21055745691Smillert #  endif /* HAS_GETLOGIN_R */
21156d68f1eSafresh1 
21255745691Smillert #  ifdef HAS_GETNETBYNAME_R
21355745691Smillert #  if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
21452bd00bfSmillert         Newx(PL_reentrant_buffer->_netent_buffer, PL_reentrant_buffer->_netent_size, char);
21555745691Smillert #  endif
21655745691Smillert #  endif /* HAS_GETNETBYNAME_R */
21756d68f1eSafresh1 
21855745691Smillert #  ifdef HAS_GETPROTOBYNAME_R
21955745691Smillert #  if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
22052bd00bfSmillert         Newx(PL_reentrant_buffer->_protoent_buffer, PL_reentrant_buffer->_protoent_size, char);
22155745691Smillert #  endif
22255745691Smillert #  endif /* HAS_GETPROTOBYNAME_R */
22356d68f1eSafresh1 
22455745691Smillert #  ifdef HAS_GETPWNAM_R
22555745691Smillert #   ifdef USE_PWENT_FPTR
22655745691Smillert         PL_reentrant_buffer->_pwent_fptr = NULL;
22755745691Smillert #   endif
22852bd00bfSmillert         Newx(PL_reentrant_buffer->_pwent_buffer, PL_reentrant_buffer->_pwent_size, char);
22955745691Smillert #  endif /* HAS_GETPWNAM_R */
23056d68f1eSafresh1 
23155745691Smillert #  ifdef HAS_GETSERVBYNAME_R
23255745691Smillert #  if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
23352bd00bfSmillert         Newx(PL_reentrant_buffer->_servent_buffer, PL_reentrant_buffer->_servent_size, char);
23455745691Smillert #  endif
23555745691Smillert #  endif /* HAS_GETSERVBYNAME_R */
23656d68f1eSafresh1 
23755745691Smillert #  ifdef HAS_GETSPNAM_R
23855745691Smillert #   ifdef USE_SPENT_FPTR
23955745691Smillert         PL_reentrant_buffer->_spent_fptr = NULL;
24055745691Smillert #   endif
24152bd00bfSmillert         Newx(PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char);
24255745691Smillert #  endif /* HAS_GETSPNAM_R */
24356d68f1eSafresh1 
24456d68f1eSafresh1 #  ifdef HAS_GMTIME_R
24556d68f1eSafresh1 #  endif /* HAS_GMTIME_R */
24656d68f1eSafresh1 
24756d68f1eSafresh1 #  ifdef HAS_LOCALTIME_R
24856d68f1eSafresh1 #  endif /* HAS_LOCALTIME_R */
24956d68f1eSafresh1 
25055745691Smillert #  ifdef HAS_READDIR_R
25155745691Smillert         PL_reentrant_buffer->_readdir_struct = (struct dirent*)safemalloc(PL_reentrant_buffer->_readdir_size);
25255745691Smillert #  endif /* HAS_READDIR_R */
25356d68f1eSafresh1 
25455745691Smillert #  ifdef HAS_READDIR64_R
25555745691Smillert         PL_reentrant_buffer->_readdir64_struct = (struct dirent64*)safemalloc(PL_reentrant_buffer->_readdir64_size);
25655745691Smillert #  endif /* HAS_READDIR64_R */
25756d68f1eSafresh1 
25855745691Smillert #  ifdef HAS_SETLOCALE_R
25952bd00bfSmillert         Newx(PL_reentrant_buffer->_setlocale_buffer, PL_reentrant_buffer->_setlocale_size, char);
26055745691Smillert #  endif /* HAS_SETLOCALE_R */
26156d68f1eSafresh1 
26255745691Smillert #  ifdef HAS_STRERROR_R
26352bd00bfSmillert         Newx(PL_reentrant_buffer->_strerror_buffer, PL_reentrant_buffer->_strerror_size, char);
26455745691Smillert #  endif /* HAS_STRERROR_R */
26556d68f1eSafresh1 
26655745691Smillert #  ifdef HAS_TTYNAME_R
26752bd00bfSmillert         Newx(PL_reentrant_buffer->_ttyname_buffer, PL_reentrant_buffer->_ttyname_size, char);
26855745691Smillert #  endif /* HAS_TTYNAME_R */
26955745691Smillert 
27056d68f1eSafresh1 
27155745691Smillert #endif /* USE_REENTRANT_API */
27256d68f1eSafresh1 
27355745691Smillert }
27455745691Smillert 
27555745691Smillert void
Perl_reentrant_free(pTHX)27655745691Smillert Perl_reentrant_free(pTHX) {
277b8851fccSafresh1         PERL_UNUSED_CONTEXT;
27856d68f1eSafresh1 
27956d68f1eSafresh1         /* Tear down */
28056d68f1eSafresh1 
28155745691Smillert #ifdef USE_REENTRANT_API
28256d68f1eSafresh1 
28355745691Smillert #  ifdef HAS_ASCTIME_R
28455745691Smillert         Safefree(PL_reentrant_buffer->_asctime_buffer);
28555745691Smillert #  endif /* HAS_ASCTIME_R */
28656d68f1eSafresh1 
28755745691Smillert #  ifdef HAS_CRYPT_R
28885009909Smillert #  if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
28985009909Smillert         Safefree(PL_reentrant_buffer->_crypt_struct_buffer);
29085009909Smillert #  endif
29155745691Smillert #  endif /* HAS_CRYPT_R */
29256d68f1eSafresh1 
29355745691Smillert #  ifdef HAS_CTIME_R
29455745691Smillert         Safefree(PL_reentrant_buffer->_ctime_buffer);
29555745691Smillert #  endif /* HAS_CTIME_R */
29656d68f1eSafresh1 
29755745691Smillert #  ifdef HAS_GETGRNAM_R
29855745691Smillert         Safefree(PL_reentrant_buffer->_grent_buffer);
29955745691Smillert #  endif /* HAS_GETGRNAM_R */
30056d68f1eSafresh1 
30155745691Smillert #  ifdef HAS_GETHOSTBYNAME_R
30255745691Smillert #  if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
30355745691Smillert         Safefree(PL_reentrant_buffer->_hostent_buffer);
30455745691Smillert #  endif
30555745691Smillert #  endif /* HAS_GETHOSTBYNAME_R */
30656d68f1eSafresh1 
30755745691Smillert #  ifdef HAS_GETLOGIN_R
30855745691Smillert         Safefree(PL_reentrant_buffer->_getlogin_buffer);
30955745691Smillert #  endif /* HAS_GETLOGIN_R */
31056d68f1eSafresh1 
31155745691Smillert #  ifdef HAS_GETNETBYNAME_R
31255745691Smillert #  if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
31355745691Smillert         Safefree(PL_reentrant_buffer->_netent_buffer);
31455745691Smillert #  endif
31555745691Smillert #  endif /* HAS_GETNETBYNAME_R */
31656d68f1eSafresh1 
31755745691Smillert #  ifdef HAS_GETPROTOBYNAME_R
31855745691Smillert #  if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
31955745691Smillert         Safefree(PL_reentrant_buffer->_protoent_buffer);
32055745691Smillert #  endif
32155745691Smillert #  endif /* HAS_GETPROTOBYNAME_R */
32256d68f1eSafresh1 
32355745691Smillert #  ifdef HAS_GETPWNAM_R
32455745691Smillert         Safefree(PL_reentrant_buffer->_pwent_buffer);
32555745691Smillert #  endif /* HAS_GETPWNAM_R */
32656d68f1eSafresh1 
32755745691Smillert #  ifdef HAS_GETSERVBYNAME_R
32855745691Smillert #  if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
32955745691Smillert         Safefree(PL_reentrant_buffer->_servent_buffer);
33055745691Smillert #  endif
33155745691Smillert #  endif /* HAS_GETSERVBYNAME_R */
33256d68f1eSafresh1 
33355745691Smillert #  ifdef HAS_GETSPNAM_R
33455745691Smillert         Safefree(PL_reentrant_buffer->_spent_buffer);
33555745691Smillert #  endif /* HAS_GETSPNAM_R */
33656d68f1eSafresh1 
33756d68f1eSafresh1 #  ifdef HAS_GMTIME_R
33856d68f1eSafresh1 #  endif /* HAS_GMTIME_R */
33956d68f1eSafresh1 
34056d68f1eSafresh1 #  ifdef HAS_LOCALTIME_R
34156d68f1eSafresh1 #  endif /* HAS_LOCALTIME_R */
34256d68f1eSafresh1 
34355745691Smillert #  ifdef HAS_READDIR_R
34455745691Smillert         Safefree(PL_reentrant_buffer->_readdir_struct);
34555745691Smillert #  endif /* HAS_READDIR_R */
34656d68f1eSafresh1 
34755745691Smillert #  ifdef HAS_READDIR64_R
34855745691Smillert         Safefree(PL_reentrant_buffer->_readdir64_struct);
34955745691Smillert #  endif /* HAS_READDIR64_R */
35056d68f1eSafresh1 
35155745691Smillert #  ifdef HAS_SETLOCALE_R
35255745691Smillert         Safefree(PL_reentrant_buffer->_setlocale_buffer);
35355745691Smillert #  endif /* HAS_SETLOCALE_R */
35456d68f1eSafresh1 
35555745691Smillert #  ifdef HAS_STRERROR_R
35655745691Smillert         Safefree(PL_reentrant_buffer->_strerror_buffer);
35755745691Smillert #  endif /* HAS_STRERROR_R */
35856d68f1eSafresh1 
35955745691Smillert #  ifdef HAS_TTYNAME_R
36055745691Smillert         Safefree(PL_reentrant_buffer->_ttyname_buffer);
36155745691Smillert #  endif /* HAS_TTYNAME_R */
36255745691Smillert 
36356d68f1eSafresh1 
36455745691Smillert         Safefree(PL_reentrant_buffer);
36556d68f1eSafresh1 
36655745691Smillert #endif /* USE_REENTRANT_API */
36755745691Smillert }
36855745691Smillert 
36955745691Smillert void*
Perl_reentrant_retry(const char * f,...)37055745691Smillert Perl_reentrant_retry(const char *f, ...)
37155745691Smillert {
37256d68f1eSafresh1     /* This function is set up to be called if the normal function returns
37356d68f1eSafresh1      * failure with errno ERANGE, which indicates the buffer is too small.
37456d68f1eSafresh1      * This function calls the failing one again with a larger buffer.
37556d68f1eSafresh1      *
37656d68f1eSafresh1      * What has happened is that, due to the magic of C preprocessor macro
37756d68f1eSafresh1      * expansion, when the original code called function 'foo(args)', it was
37856d68f1eSafresh1      * instead compiled into something like a call of 'foo_r(args, buffer)'
37956d68f1eSafresh1      * Below we retry with 'foo', but the preprocessor has changed that into
38056d68f1eSafresh1      * 'foo_r', so this function will end up calling itself recursively, each
38156d68f1eSafresh1      * time with a larger buffer.  If PERL_REENTRANT_MAXSIZE is defined, it
38256d68f1eSafresh1      * won't increase beyond that, instead failing. */
38356d68f1eSafresh1 
38455745691Smillert     void *retptr = NULL;
385850e2753Smillert     va_list ap;
38656d68f1eSafresh1 
38756d68f1eSafresh1     I32 key = 0;
38856d68f1eSafresh1 
38943003dfeSmillert #ifdef USE_REENTRANT_API
39056d68f1eSafresh1 
39191f110e0Safresh1     dTHX;
39256d68f1eSafresh1 
39356d68f1eSafresh1     key = Perl_keyword (aTHX_ f, strlen(f), FALSE /* not feature enabled */);
39456d68f1eSafresh1 
39543003dfeSmillert     /* Easier to special case this here than in embed.pl. (Look at what it
39643003dfeSmillert        generates for proto.h) */
39743003dfeSmillert     PERL_ARGS_ASSERT_REENTRANT_RETRY;
39856d68f1eSafresh1 
39955745691Smillert #endif
40055745691Smillert 
40156d68f1eSafresh1     if (key == 0) {
40256d68f1eSafresh1 
40356d68f1eSafresh1 #ifdef HAS_GETSPNAM_R
40456d68f1eSafresh1 
40556d68f1eSafresh1         /* This is a #define as has no corresponding keyword */
40656d68f1eSafresh1         if (strEQ(f, "getspnam")) {
40756d68f1eSafresh1             key = KEY_getspnam;
40856d68f1eSafresh1         }
40956d68f1eSafresh1 
41056d68f1eSafresh1 #endif
41156d68f1eSafresh1 
41256d68f1eSafresh1     }
41356d68f1eSafresh1     else if (key < 0) {
41456d68f1eSafresh1         key = -key;
41556d68f1eSafresh1     }
41656d68f1eSafresh1 
41756d68f1eSafresh1     va_start(ap, f);
41856d68f1eSafresh1 
41956d68f1eSafresh1 #ifdef USE_REENTRANT_API
42056d68f1eSafresh1 
42156d68f1eSafresh1     switch (key) {
42256d68f1eSafresh1 
42355745691Smillert #  ifdef USE_HOSTENT_BUFFER
42456d68f1eSafresh1 
42556d68f1eSafresh1     case KEY_gethostbyaddr:
42656d68f1eSafresh1     case KEY_gethostbyname:
42756d68f1eSafresh1     case KEY_endhostent:
42855745691Smillert         {
42956d68f1eSafresh1             char * host_addr;
43056d68f1eSafresh1             Size_t asize;
43156d68f1eSafresh1             char * host_name;
43256d68f1eSafresh1             int anint;
43356d68f1eSafresh1 
43485009909Smillert #    ifdef PERL_REENTRANT_MAXSIZE
43585009909Smillert             if (PL_reentrant_buffer->_hostent_size <=
43685009909Smillert                 PERL_REENTRANT_MAXSIZE / 2)
43785009909Smillert #    endif
4389f11ffb7Safresh1             RenewDouble(PL_reentrant_buffer->_hostent_buffer,
4399f11ffb7Safresh1                     &PL_reentrant_buffer->_hostent_size, char);
44056d68f1eSafresh1             switch (key) {
44156d68f1eSafresh1                 case KEY_gethostbyaddr:
44256d68f1eSafresh1                     host_addr = va_arg(ap, char *);
44356d68f1eSafresh1                     asize = va_arg(ap, Size_t);
44455745691Smillert                     anint  = va_arg(ap, int);
44556d68f1eSafresh1                     /* socklen_t is what Posix 2001 says this should be */
44656d68f1eSafresh1                     retptr = gethostbyaddr(host_addr, (socklen_t) asize, anint); break;
44756d68f1eSafresh1                 case KEY_gethostbyname:
44856d68f1eSafresh1                     host_name = va_arg(ap, char *);
44956d68f1eSafresh1                     retptr = gethostbyname(host_name); break;
45056d68f1eSafresh1                 case KEY_endhostent:
45155745691Smillert                     retptr = gethostent(); break;
45255745691Smillert                 default:
45385009909Smillert                     SETERRNO(ERANGE, LIB_INVARG);
45455745691Smillert                     break;
45555745691Smillert             }
45655745691Smillert         }
45755745691Smillert         break;
45856d68f1eSafresh1 
45955745691Smillert #  endif
46055745691Smillert #  ifdef USE_GRENT_BUFFER
46156d68f1eSafresh1 
46256d68f1eSafresh1     case KEY_getgrent:
46356d68f1eSafresh1     case KEY_getgrgid:
46456d68f1eSafresh1     case KEY_getgrnam:
46555745691Smillert         {
46656d68f1eSafresh1             char * name;
46756d68f1eSafresh1             Gid_t gid;
46856d68f1eSafresh1 
46985009909Smillert #    ifdef PERL_REENTRANT_MAXSIZE
47085009909Smillert             if (PL_reentrant_buffer->_grent_size <=
47185009909Smillert                 PERL_REENTRANT_MAXSIZE / 2)
47285009909Smillert #    endif
4739f11ffb7Safresh1             RenewDouble(PL_reentrant_buffer->_grent_buffer,
4749f11ffb7Safresh1                     &PL_reentrant_buffer->_grent_size, char);
47556d68f1eSafresh1             switch (key) {
47656d68f1eSafresh1                 case KEY_getgrnam:
47756d68f1eSafresh1                     name = va_arg(ap, char *);
47856d68f1eSafresh1                     retptr = getgrnam(name); break;
47956d68f1eSafresh1                 case KEY_getgrgid:
48085009909Smillert #    if Gid_t_size < INTSIZE
48185009909Smillert                     gid = (Gid_t)va_arg(ap, int);
48285009909Smillert #    else
48355745691Smillert                     gid = va_arg(ap, Gid_t);
48485009909Smillert #    endif
48555745691Smillert                     retptr = getgrgid(gid); break;
48656d68f1eSafresh1                 case KEY_getgrent:
48755745691Smillert                     retptr = getgrent(); break;
48855745691Smillert                 default:
48985009909Smillert                     SETERRNO(ERANGE, LIB_INVARG);
49055745691Smillert                     break;
49155745691Smillert             }
49255745691Smillert         }
49355745691Smillert         break;
49456d68f1eSafresh1 
49555745691Smillert #  endif
49655745691Smillert #  ifdef USE_NETENT_BUFFER
49756d68f1eSafresh1 
49856d68f1eSafresh1     case KEY_getnetbyaddr:
49956d68f1eSafresh1     case KEY_getnetbyname:
50056d68f1eSafresh1     case KEY_getnetent:
50155745691Smillert         {
50256d68f1eSafresh1             char * name;
50356d68f1eSafresh1             Netdb_net_t net;
50456d68f1eSafresh1             int anint;
50556d68f1eSafresh1 
50685009909Smillert #    ifdef PERL_REENTRANT_MAXSIZE
50785009909Smillert             if (PL_reentrant_buffer->_netent_size <=
50885009909Smillert                 PERL_REENTRANT_MAXSIZE / 2)
50985009909Smillert #    endif
5109f11ffb7Safresh1             RenewDouble(PL_reentrant_buffer->_netent_buffer,
5119f11ffb7Safresh1                     &PL_reentrant_buffer->_netent_size, char);
51256d68f1eSafresh1             switch (key) {
51356d68f1eSafresh1                 case KEY_getnetbyaddr:
51455745691Smillert                     net = va_arg(ap, Netdb_net_t);
51555745691Smillert                     anint = va_arg(ap, int);
51655745691Smillert                     retptr = getnetbyaddr(net, anint); break;
51756d68f1eSafresh1                 case KEY_getnetbyname:
51856d68f1eSafresh1                     name = va_arg(ap, char *);
51956d68f1eSafresh1                     retptr = getnetbyname(name); break;
52056d68f1eSafresh1                 case KEY_getnetent:
52155745691Smillert                     retptr = getnetent(); break;
52255745691Smillert                 default:
52385009909Smillert                     SETERRNO(ERANGE, LIB_INVARG);
52455745691Smillert                     break;
52555745691Smillert             }
52655745691Smillert         }
52755745691Smillert         break;
52856d68f1eSafresh1 
52955745691Smillert #  endif
53055745691Smillert #  ifdef USE_PWENT_BUFFER
53156d68f1eSafresh1 
53256d68f1eSafresh1     case  KEY_getpwnam:
53356d68f1eSafresh1     case  KEY_getpwuid:
53456d68f1eSafresh1     case  KEY_getpwent:
53555745691Smillert         {
53656d68f1eSafresh1             Uid_t uid;
53756d68f1eSafresh1             char * name;
53856d68f1eSafresh1 
53985009909Smillert #    ifdef PERL_REENTRANT_MAXSIZE
54085009909Smillert             if (PL_reentrant_buffer->_pwent_size <=
54185009909Smillert                 PERL_REENTRANT_MAXSIZE / 2)
54256d68f1eSafresh1 
54385009909Smillert #    endif
5449f11ffb7Safresh1             RenewDouble(PL_reentrant_buffer->_pwent_buffer,
5459f11ffb7Safresh1                     &PL_reentrant_buffer->_pwent_size, char);
54656d68f1eSafresh1             switch (key) {
54756d68f1eSafresh1                 case KEY_getpwnam:
54856d68f1eSafresh1                     name = va_arg(ap, char *);
54956d68f1eSafresh1                     retptr = getpwnam(name); break;
55056d68f1eSafresh1                 case KEY_getpwuid:
55156d68f1eSafresh1 
55285009909Smillert #    if Uid_t_size < INTSIZE
55385009909Smillert                     uid = (Uid_t)va_arg(ap, int);
55485009909Smillert #    else
55555745691Smillert                     uid = va_arg(ap, Uid_t);
55685009909Smillert #    endif
55755745691Smillert                     retptr = getpwuid(uid); break;
55856d68f1eSafresh1 
5596fb12b70Safresh1 #  if defined(HAS_GETPWENT) || defined(HAS_GETPWENT_R)
56056d68f1eSafresh1 
56156d68f1eSafresh1                 case KEY_getpwent:
56255745691Smillert                     retptr = getpwent(); break;
5636fb12b70Safresh1 #  endif
56455745691Smillert                 default:
56585009909Smillert                     SETERRNO(ERANGE, LIB_INVARG);
56655745691Smillert                     break;
56755745691Smillert             }
56855745691Smillert         }
56956d68f1eSafresh1         break;
57056d68f1eSafresh1 
57156d68f1eSafresh1 #  endif
57256d68f1eSafresh1 #  ifdef USE_SPENT_BUFFER
57356d68f1eSafresh1 
57456d68f1eSafresh1     case KEY_getspnam:
57556d68f1eSafresh1         {
57656d68f1eSafresh1             char * name;
57756d68f1eSafresh1 
57856d68f1eSafresh1 #    ifdef PERL_REENTRANT_MAXSIZE
57956d68f1eSafresh1             if (PL_reentrant_buffer->_spent_size <=
58056d68f1eSafresh1                 PERL_REENTRANT_MAXSIZE / 2)
58156d68f1eSafresh1 
58256d68f1eSafresh1 #    endif
58356d68f1eSafresh1             RenewDouble(PL_reentrant_buffer->_spent_buffer,
58456d68f1eSafresh1                     &PL_reentrant_buffer->_spent_size, char);
58556d68f1eSafresh1             switch (key) {
58656d68f1eSafresh1                 case KEY_getspnam:
58756d68f1eSafresh1                     name = va_arg(ap, char *);
58856d68f1eSafresh1                     retptr = getspnam(name); break;
58956d68f1eSafresh1                 default:
59056d68f1eSafresh1                     SETERRNO(ERANGE, LIB_INVARG);
59156d68f1eSafresh1                     break;
59256d68f1eSafresh1             }
59355745691Smillert         }
59455745691Smillert         break;
59556d68f1eSafresh1 
59655745691Smillert #  endif
59755745691Smillert #  ifdef USE_PROTOENT_BUFFER
59856d68f1eSafresh1 
59956d68f1eSafresh1     case KEY_getprotobyname:
60056d68f1eSafresh1     case KEY_getprotobynumber:
60156d68f1eSafresh1     case KEY_getprotoent:
60255745691Smillert         {
60356d68f1eSafresh1             char * name;
60456d68f1eSafresh1             int anint;
60556d68f1eSafresh1 
60685009909Smillert #    ifdef PERL_REENTRANT_MAXSIZE
60785009909Smillert             if (PL_reentrant_buffer->_protoent_size <=
60885009909Smillert                 PERL_REENTRANT_MAXSIZE / 2)
60985009909Smillert #    endif
6109f11ffb7Safresh1             RenewDouble(PL_reentrant_buffer->_protoent_buffer,
6119f11ffb7Safresh1                     &PL_reentrant_buffer->_protoent_size, char);
61256d68f1eSafresh1             switch (key) {
61356d68f1eSafresh1                 case KEY_getprotobyname:
61456d68f1eSafresh1                     name = va_arg(ap, char *);
61556d68f1eSafresh1                     retptr = getprotobyname(name); break;
61656d68f1eSafresh1                 case KEY_getprotobynumber:
61755745691Smillert                     anint = va_arg(ap, int);
61855745691Smillert                     retptr = getprotobynumber(anint); break;
61956d68f1eSafresh1                 case KEY_getprotoent:
62055745691Smillert                     retptr = getprotoent(); break;
62155745691Smillert                 default:
62285009909Smillert                     SETERRNO(ERANGE, LIB_INVARG);
62355745691Smillert                     break;
62455745691Smillert             }
62555745691Smillert         }
62655745691Smillert         break;
62756d68f1eSafresh1 
62855745691Smillert #  endif
62955745691Smillert #  ifdef USE_SERVENT_BUFFER
63056d68f1eSafresh1 
63156d68f1eSafresh1     case KEY_getservbyname:
63256d68f1eSafresh1     case KEY_getservbyport:
63356d68f1eSafresh1     case KEY_getservent:
63455745691Smillert         {
63556d68f1eSafresh1             char * name;
63656d68f1eSafresh1             char * proto;
63756d68f1eSafresh1             int anint;
63856d68f1eSafresh1 
63985009909Smillert #    ifdef PERL_REENTRANT_MAXSIZE
64085009909Smillert             if (PL_reentrant_buffer->_servent_size <=
64185009909Smillert                 PERL_REENTRANT_MAXSIZE / 2)
64285009909Smillert #    endif
6439f11ffb7Safresh1             RenewDouble(PL_reentrant_buffer->_servent_buffer,
6449f11ffb7Safresh1                     &PL_reentrant_buffer->_servent_size, char);
64556d68f1eSafresh1             switch (key) {
64656d68f1eSafresh1                 case KEY_getservbyname:
64756d68f1eSafresh1                     name = va_arg(ap, char *);
64856d68f1eSafresh1                     proto = va_arg(ap, char *);
64956d68f1eSafresh1                     retptr = getservbyname(name, proto); break;
65056d68f1eSafresh1                 case KEY_getservbyport:
65155745691Smillert                     anint = va_arg(ap, int);
65256d68f1eSafresh1                     name = va_arg(ap, char *);
65356d68f1eSafresh1                     retptr = getservbyport(anint, name); break;
65456d68f1eSafresh1                 case KEY_getservent:
65555745691Smillert                     retptr = getservent(); break;
65655745691Smillert                 default:
65785009909Smillert                     SETERRNO(ERANGE, LIB_INVARG);
65855745691Smillert                     break;
65955745691Smillert             }
66055745691Smillert         }
66155745691Smillert         break;
66256d68f1eSafresh1 
66355745691Smillert #  endif
66456d68f1eSafresh1 
66555745691Smillert     default:
66655745691Smillert         /* Not known how to retry, so just fail. */
66755745691Smillert         break;
66855745691Smillert     }
66956d68f1eSafresh1 
670850e2753Smillert #else
67156d68f1eSafresh1 
672850e2753Smillert     PERL_UNUSED_ARG(f);
67356d68f1eSafresh1 
67455745691Smillert #endif
67556d68f1eSafresh1 
676850e2753Smillert     va_end(ap);
67755745691Smillert     return retptr;
67855745691Smillert }
67955745691Smillert 
680*e0680481Safresh1 /* ex: set ro ft=c: */
681