#ifdef __hpux
# undef HAS_CRYPT_R
# undef HAS_DRAND48_R
+# undef HAS_ENDGRENT_R
+# undef HAS_ENDPWENT_R
# undef HAS_GETGRENT_R
# undef HAS_GETPWENT_R
# undef HAS_SETLOCALE_R
if ($opts{U} && open(U, ">d_${f}_r.U")) {
select U;
}
- my $prereqh = $h eq 'stdio' ? '' : "i_$h"; # There's no i_stdio.
- print <<EOF if $opts{U};
+ my $prereqs = '';
+ my $prereqh = '';
+ my $prereqsh = '';
+ if ($h ne 'stdio') { # There's no i_stdio.
+ $prereqs = "i_$h";
+ $prereqh = "$h.h";
+ $prereqsh = "\$$prereqs $prereqh";
+ }
+ if ($opts{U}) {
+ print <<EOF;
?RCS: \$Id: d_${f}_r.U,v $
?RCS:
?RCS: Copyright (c) 2002 Jarkko Hietaniemi
?RCS:
?RCS: Generated by the reentr.pl from the Perl 5.8 distribution.
?RCS:
-?MAKE:d_${f}_r ${f}_r_proto: Inlibc Protochk i_systypes $prereqh
+?MAKE:d_${f}_r ${f}_r_proto: Inlibc Protochk Hasproto i_systypes i_systime $prereqs usethreads i_pthread
?MAKE: -pick add \$@ %<
?S:d_${f}_r:
?S: This variable conditionally defines the HAS_${F}_R symbol,
?H:#\$d_${f}_r HAS_${F}_R /**/
?H:#define ${F}_R_PROTO \$${f}_r_proto /**/
?H:.
-?T:try hdrs
+?T:try hdrs d_${f}_r_proto
?LINT:set d_${f}_r
?LINT:set ${f}_r_proto
: see if ${f}_r exists
eval \$inlibc
case "\$d_${f}_r" in
"\$define")
- hdrs="\$i_systypes sys/types.h define stdio.h \$i_${h} $h.h"
EOF
- for my $p (@p) {
- my ($r, $a) = ($p =~ /^(.)_(.+)/);
- my $v = join(", ", map { $m{$_} } split '', $a);
- if ($opts{U}) {
- print <<EOF ;
+ my $hdrs = "\$i_systypes sys/types.h define stdio.h $prereqsh";
+ if ($h eq 'time') {
+ $hdrs .= " \$i_systime sys/time.h";
+ }
+ print <<EOF;
+ hdrs="$hdrs"
+ case "\$d_${f}_r_proto:\$usethreads" in
+ ":define") d_${f}_r_proto=define
+ set d_${f}_r_proto ${f}_r \$hdrs
+ eval \$hasproto ;;
+ *) ;;
+ esac
+ case "\$d_${f}_r_proto" in
+ define)
+EOF
+ }
+ for my $p (@p) {
+ my ($r, $a) = ($p =~ /^(.)_(.+)/);
+ my $v = join(", ", map { $m{$_} } split '', $a);
+ if ($opts{U}) {
+ print <<EOF ;
case "\$${f}_r_proto" in
''|0) try='$m{$r} ${f}_r($v);'
./protochk "extern \$try" \$hdrs && ${f}_r_proto=$p ;;
esac
EOF
- }
- $seenh{$f}->{$p}++;
- push @{$seena{$f}}, $p;
- $seenp{$p}++;
- $seent{$f} = $t;
- $seens{$f} = $m{S};
- $seend{$f} = $m{D};
- }
- if ($opts{U}) {
- print <<EOF;
+ }
+ $seenh{$f}->{$p}++;
+ push @{$seena{$f}}, $p;
+ $seenp{$p}++;
+ $seent{$f} = $t;
+ $seens{$f} = $m{S};
+ $seend{$f} = $m{D};
+ }
+ if ($opts{U}) {
+ print <<EOF;
case "\$${f}_r_proto" in
- '') d_${f}_r=undef
+ ''|0) d_${f}_r=undef
${f}_r_proto=0
- echo "Disabling ${f}_r, cannot determine prototype." ;;
+ echo "Disabling ${f}_r, cannot determine prototype." >&4 ;;
* ) case "\$${f}_r_proto" in
REENTRANT_PROTO*) ;;
*) ${f}_r_proto="REENTRANT_PROTO_\$${f}_r_proto" ;;
echo "Prototype: \$try" ;;
esac
;;
+ *) case "\$usethreads" in
+ define) echo "${f}_r has no prototype, not using it." >&4 ;;
+ esac
+ d_${f}_r=undef
+ ${f}_r_proto=0
+ ;;
+ esac
+ ;;
*) ${f}_r_proto=0
;;
esac
/* The @F using \L$n? */
EOF
+ my $G;
for my $f (@F) {
my $F = uc $f;
my $h = "${F}_R_HAS_$n";
push @H, $h;
my @h = grep { /$p/ } @{$seena{$f}};
+ unless (defined $G) {
+ $G = $F;
+ $G =~ s/^GET//;
+ }
if (@h) {
push @define, "#if defined(HAS_${F}_R) && (" . join(" || ", map { "${F}_R_PROTO == REENTRANT_PROTO_$_" } @h) . ")\n";
EOF
push @define, "#if (" . join(" || ", map { "defined($_)" } @H) . ")\n";
push @define, <<EOF;
-# define USE_${H}_$n
+# define USE_${G}_$n
#else
-# undef USE_${H}_$n
+# undef USE_${G}_$n
#endif
EOF
}
+define('BUFFER', 'B',
+ qw(getgrent getgrgid getgrnam));
+
define('PTR', 'R',
qw(getgrent getgrgid getgrnam));
define('PTR', 'R',
qw(getspent getspnam));
define('FPTR', 'H',
- qw(getgrent getgrgid getgrnam));
+ qw(getgrent getgrgid getgrnam setgrent endgrent));
define('FPTR', 'H',
- qw(getpwent getpwnam getpwuid));
+ qw(getpwent getpwnam getpwuid setpwent endpwent));
+
+define('BUFFER', 'B',
+ qw(getpwent getpwgid getpwnam));
define('PTR', 'R',
qw(gethostent gethostbyaddr gethostbyname));
define('PTR', 'R',
qw(getservent getservbyname getservbyport));
+define('BUFFER', 'B',
+ qw(gethostent gethostbyaddr gethostbyname));
+define('BUFFER', 'B',
+ qw(getnetent getnetbyaddr getnetbyname));
+define('BUFFER', 'B',
+ qw(getprotoent getprotobyname getprotobynumber));
+define('BUFFER', 'B',
+ qw(getservent getservbyname getservbyport));
+
define('ERRNO', 'E',
qw(gethostent gethostbyaddr gethostbyname));
define('ERRNO', 'E',
size_t _${f}_size;
EOF
push @size, <<EOF;
- PL_reentrant_buffer->_${f}_size = 256; /* Make something up. */
+ PL_reentrant_buffer->_${f}_size = REENTRANTSMALLSIZE;
EOF
pushinitfree $f;
pushssif $endif;
}
- elsif ($f =~ /^(crypt|drand48|gmtime|localtime|random)$/) {
+ elsif ($f =~ /^(crypt)$/) {
pushssif $ifdef;
push @struct, <<EOF;
+#if CRYPT_R_PROTO == REENTRANT_PROTO_B_CCD
+ $seend{$f} _${f}_data;
+#else
$seent{$f} _${f}_struct;
+#endif
EOF
- if ($f eq 'crypt') {
- push @init, <<EOF;
+ push @init, <<EOF;
#ifdef __GLIBC__
PL_reentrant_buffer->_${f}_struct.initialized = 0;
#endif
EOF
- }
+ pushssif $endif;
+ }
+ elsif ($f =~ /^(drand48|gmtime|localtime|random)$/) {
+ pushssif $ifdef;
+ push @struct, <<EOF;
+ $seent{$f} _${f}_struct;
+EOF
if ($1 eq 'drand48') {
push @struct, <<EOF;
double _${f}_double;
pushssif $ifdef;
my $g = $f;
$g =~ s/nam/ent/g;
+ $g =~ s/^get//;
my $G = uc $g;
push @struct, <<EOF;
$seent{$f} _${g}_struct;
EOF
my $sc = $g eq 'getgrent' ?
'_SC_GETGR_R_SIZE_MAX' : '_SC_GETPW_R_SIZE_MAX';
+ my $sz = $g eq 'getgrent' ?
+ '_grent_size' : '_pwent_size';
push @size, <<EOF;
# if defined(HAS_SYSCONF) && defined($sc) && !defined(__GLIBC__)
PL_reentrant_buffer->_${g}_size = sysconf($sc);
+ if (PL_reentrant_buffer->$sz == -1)
+ PL_reentrant_buffer->$sz = REENTRANTUSUALSIZE;
# else
# if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
PL_reentrant_buffer->_${g}_size = SIABUFSIZ;
# ifdef __sgi
PL_reentrant_buffer->_${g}_size = BUFSIZ;
# else
- PL_reentrant_buffer->_${g}_size = 2048;
+ PL_reentrant_buffer->_${g}_size = REENTRANTUSUALSIZE;
# endif
# endif
# endif
pushssif $ifdef;
my $g = $f;
$g =~ s/byname/ent/;
+ $g =~ s/^get//;
my $G = uc $g;
my $D = ifprotomatch($F, grep {/D/} @p);
my $d = $seend{$f};
+ $d =~ s/\*$//; # snip: we need need the base type.
push @struct, <<EOF;
$seent{$f} _${g}_struct;
# if $D
EOF
push @size, <<EOF;
#if !($D)
- PL_reentrant_buffer->_${g}_size = 2048; /* Any better ideas? */
+ PL_reentrant_buffer->_${g}_size = REENTRANTUSUALSIZE;
#endif
EOF
push @init, <<EOF;
push @wrap, $ifdef;
-# Doesn't implement the buffer growth loop for glibc gethostby*().
push @wrap, <<EOF;
# undef $f
EOF
my ($r, $a) = split '_', $p;
my $test = $r eq 'I' ? ' == 0' : '';
my $true = 1;
- my $false = 0;
my $g = $f;
if ($g =~ /^(?:get|set|end)(pw|gr|host|net|proto|serv|sp)/) {
- $g = "get$1ent";
+ $g = "$1ent";
} elsif ($g eq 'srand48') {
$g = "drand48";
}
# define $f($v) $call
EOF
} else {
- push @wrap, <<EOF;
-# define $f($v) ($call$test ? $true : $false)
+ if ($f =~ /^get/) {
+ my $rv = $v ? ", $v" : "";
+ push @wrap, <<EOF;
+# define $f($v) ($call$test ? $true : (errno == ERANGE ? Perl_reentrant_retry("$f"$rv) : 0))
EOF
+ } else {
+ push @wrap, <<EOF;
+# define $f($v) ($call$test ? $true : 0)
+EOF
+ }
}
push @wrap, <<EOF;
# endif
void
Perl_reentrant_size(pTHX) {
#ifdef USE_REENTRANT_API
+#define REENTRANTSMALLSIZE 256 /* Make something up. */
+#define REENTRANTUSUALSIZE 4096 /* Make something up. */
@size
#endif /* USE_REENTRANT_API */
}
#endif /* USE_REENTRANT_API */
}
+void*
+Perl_reentrant_retry(const char *f, ...)
+{
+ dTHX;
+ void *retptr = NULL;
+#ifdef USE_REENTRANT_API
+# if defined(USE_HOSTENT_BUFFER) || defined(USE_GRENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PWENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SRVENT_BUFFER)
+ void *p0;
+# endif
+# if defined(USE_SERVENT_BUFFER)
+ void *p1;
+# endif
+# if defined(USE_HOSTENT_BUFFER)
+ size_t asize;
+# endif
+# if defined(USE_HOSTENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
+ int anint;
+# endif
+ va_list ap;
+
+ va_start(ap, f);
+
+#define REENTRANTHALFMAXSIZE 32768 /* The maximum may end up twice this. */
+
+ switch (PL_op->op_type) {
+#ifdef USE_HOSTENT_BUFFER
+ case OP_GHBYADDR:
+ case OP_GHBYNAME:
+ case OP_GHOSTENT:
+ {
+ if (PL_reentrant_buffer->_hostent_size <= REENTRANTHALFMAXSIZE) {
+ PL_reentrant_buffer->_hostent_size *= 2;
+ Renew(PL_reentrant_buffer->_hostent_buffer,
+ PL_reentrant_buffer->_hostent_size, char);
+ switch (PL_op->op_type) {
+ case OP_GHBYADDR:
+ p0 = va_arg(ap, void *);
+ asize = va_arg(ap, size_t);
+ anint = va_arg(ap, int);
+ retptr = gethostbyaddr(p0, asize, anint); break;
+ case OP_GHBYNAME:
+ p0 = va_arg(ap, void *);
+ retptr = gethostbyname(p0); break;
+ case OP_GHOSTENT:
+ retptr = gethostent(); break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+#endif
+#ifdef USE_GRENT_BUFFER
+ case OP_GGRNAM:
+ case OP_GGRGID:
+ case OP_GGRENT:
+ {
+ if (PL_reentrant_buffer->_grent_size <= REENTRANTHALFMAXSIZE) {
+ Gid_t gid;
+ PL_reentrant_buffer->_grent_size *= 2;
+ Renew(PL_reentrant_buffer->_grent_buffer,
+ PL_reentrant_buffer->_grent_size, char);
+ switch (PL_op->op_type) {
+ case OP_GGRNAM:
+ p0 = va_arg(ap, void *);
+ retptr = getgrnam(p0); break;
+ case OP_GGRGID:
+ gid = va_arg(ap, Gid_t);
+ retptr = getgrgid(gid); break;
+ case OP_GGRENT:
+ retptr = getgrent(); break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+#endif
+#ifdef USE_NETENT_BUFFER
+ case OP_GNBYADDR:
+ case OP_GNBYNAME:
+ case OP_GNETENT:
+ {
+ if (PL_reentrant_buffer->_netent_size <= REENTRANTHALFMAXSIZE) {
+ Netdb_net_t net;
+ PL_reentrant_buffer->_netent_size *= 2;
+ Renew(PL_reentrant_buffer->_netent_buffer,
+ PL_reentrant_buffer->_netent_size, char);
+ switch (PL_op->op_type) {
+ case OP_GNBYADDR:
+ net = va_arg(ap, Netdb_net_t);
+ anint = va_arg(ap, int);
+ retptr = getnetbyaddr(net, anint); break;
+ case OP_GNBYNAME:
+ p0 = va_arg(ap, void *);
+ retptr = getnetbyname(p0); break;
+ case OP_GNETENT:
+ retptr = getnetent(); break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+#endif
+#ifdef USE_PWENT_BUFFER
+ case OP_GPWNAM:
+ case OP_GPWUID:
+ case OP_GPWENT:
+ {
+ if (PL_reentrant_buffer->_pwent_size <= REENTRANTHALFMAXSIZE) {
+ Uid_t uid;
+ PL_reentrant_buffer->_pwent_size *= 2;
+ Renew(PL_reentrant_buffer->_pwent_buffer,
+ PL_reentrant_buffer->_pwent_size, char);
+ switch (PL_op->op_type) {
+ case OP_GPWNAM:
+ p0 = va_arg(ap, void *);
+ retptr = getpwnam(p0); break;
+ case OP_GPWUID:
+ uid = va_arg(ap, Uid_t);
+ retptr = getpwuid(uid); break;
+ case OP_GPWENT:
+ retptr = getpwent(); break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+#endif
+#ifdef USE_PROTOENT_BUFFER
+ case OP_GPBYNAME:
+ case OP_GPBYNUMBER:
+ case OP_GPROTOENT:
+ {
+ if (PL_reentrant_buffer->_protoent_size <= REENTRANTHALFMAXSIZE) {
+ PL_reentrant_buffer->_protoent_size *= 2;
+ Renew(PL_reentrant_buffer->_protoent_buffer,
+ PL_reentrant_buffer->_protoent_size, char);
+ switch (PL_op->op_type) {
+ case OP_GPBYNAME:
+ p0 = va_arg(ap, void *);
+ retptr = getprotobyname(p0); break;
+ case OP_GPBYNUMBER:
+ anint = va_arg(ap, int);
+ retptr = getprotobynumber(anint); break;
+ case OP_GPROTOENT:
+ retptr = getprotoent(); break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+#endif
+#ifdef USE_SERVENT_BUFFER
+ case OP_GSBYNAME:
+ case OP_GSBYPORT:
+ case OP_GSERVENT:
+ {
+ if (PL_reentrant_buffer->_servent_size <= REENTRANTHALFMAXSIZE) {
+ PL_reentrant_buffer->_servent_size *= 2;
+ Renew(PL_reentrant_buffer->_servent_buffer,
+ PL_reentrant_buffer->_servent_size, char);
+ switch (PL_op->op_type) {
+ case OP_GSBYNAME:
+ p0 = va_arg(ap, void *);
+ p1 = va_arg(ap, void *);
+ retptr = getservbyname(p0, p1); break;
+ case OP_GSBYPORT:
+ anint = va_arg(ap, int);
+ p0 = va_arg(ap, void *);
+ retptr = getservbyport(anint, p0); break;
+ case OP_GSERVENT:
+ retptr = getservent(); break;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ /* Not known how to retry, so just fail. */
+ break;
+ }
+
+ va_end(ap);
+#endif
+ return retptr;
+}
+
EOF
__DATA__
asctime S |time |const struct tm|B_SB|B_SBI|I_SB|I_SBI
-crypt CC |crypt |struct crypt_data|B_CCS
+crypt CC |crypt |struct crypt_data|B_CCS|B_CCD|D=CRYPTD*
ctermid B |stdio | |B_B
ctime S |time |const time_t |B_SB|B_SBI|I_SB|I_SBI
drand48 |stdlib |struct drand48_data |I_ST|T=double*
endgrent |grp | |I_H|V_H
-endhostent |netdb |struct hostent_data |I_S|V_S
-endnetent |netdb |struct netent_data |I_S|V_S
-endprotoent |netdb |struct protoent_data |I_S|V_S
+endhostent |netdb | |I_D|V_D|D=struct hostent_data*
+endnetent |netdb | |I_D|V_D|D=struct netent_data*
+endprotoent |netdb | |I_D|V_D|D=struct protoent_data*
endpwent |pwd | |I_H|V_H
-endservent |netdb |struct servent_data |I_S|V_S
+endservent |netdb | |I_D|V_D|D=struct servent_data*
getgrent |grp |struct group |I_SBWR|I_SBIR|S_SBW|S_SBI|I_SBI|I_SBIH
getgrgid T |grp |struct group |I_TSBWR|I_TSBIR|I_TSBI|S_TSBI|T=gid_t
getgrnam C |grp |struct group |I_CSBWR|I_CSBIR|S_CBI|I_CSBI|S_CSBI