1 /* 2 * reentr.c 3 * 4 * Copyright (c) 1997-2002, Larry Wall 5 * 6 * You may distribute under the terms of either the GNU General Public 7 * License or the Artistic License, as specified in the README file. 8 * 9 * !!!!!!! DO NOT EDIT THIS FILE !!!!!!! 10 * This file is built by reentrl.pl from data in reentr.pl. 11 * 12 * "Saruman," I said, standing away from him, "only one hand at a time can 13 * wield the One, and you know that well, so do not trouble to say we!" 14 * 15 */ 16 17 #include "EXTERN.h" 18 #define PERL_IN_REENTR_C 19 #include "perl.h" 20 #include "reentr.h" 21 22 void 23 Perl_reentrant_size(pTHX) { 24 #ifdef USE_REENTRANT_API 25 #define REENTRANTSMALLSIZE 256 /* Make something up. */ 26 #define REENTRANTUSUALSIZE 4096 /* Make something up. */ 27 #ifdef HAS_ASCTIME_R 28 PL_reentrant_buffer->_asctime_size = REENTRANTSMALLSIZE; 29 #endif /* HAS_ASCTIME_R */ 30 #ifdef HAS_CRYPT_R 31 #endif /* HAS_CRYPT_R */ 32 #ifdef HAS_CTIME_R 33 PL_reentrant_buffer->_ctime_size = REENTRANTSMALLSIZE; 34 #endif /* HAS_CTIME_R */ 35 #ifdef HAS_DRAND48_R 36 #endif /* HAS_DRAND48_R */ 37 #ifdef HAS_GETGRNAM_R 38 # if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__) 39 PL_reentrant_buffer->_grent_size = sysconf(_SC_GETPW_R_SIZE_MAX); 40 if (PL_reentrant_buffer->_pwent_size == -1) 41 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE; 42 # else 43 # if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ) 44 PL_reentrant_buffer->_grent_size = SIABUFSIZ; 45 # else 46 # ifdef __sgi 47 PL_reentrant_buffer->_grent_size = BUFSIZ; 48 # else 49 PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE; 50 # endif 51 # endif 52 # endif 53 #endif /* HAS_GETGRNAM_R */ 54 #ifdef HAS_GETHOSTBYNAME_R 55 #if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 56 PL_reentrant_buffer->_hostent_size = REENTRANTUSUALSIZE; 57 #endif 58 #endif /* HAS_GETHOSTBYNAME_R */ 59 #ifdef HAS_GETLOGIN_R 60 PL_reentrant_buffer->_getlogin_size = REENTRANTSMALLSIZE; 61 #endif /* HAS_GETLOGIN_R */ 62 #ifdef HAS_GETNETBYNAME_R 63 #if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 64 PL_reentrant_buffer->_netent_size = REENTRANTUSUALSIZE; 65 #endif 66 #endif /* HAS_GETNETBYNAME_R */ 67 #ifdef HAS_GETPROTOBYNAME_R 68 #if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 69 PL_reentrant_buffer->_protoent_size = REENTRANTUSUALSIZE; 70 #endif 71 #endif /* HAS_GETPROTOBYNAME_R */ 72 #ifdef HAS_GETPWNAM_R 73 # if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__) 74 PL_reentrant_buffer->_pwent_size = sysconf(_SC_GETPW_R_SIZE_MAX); 75 if (PL_reentrant_buffer->_pwent_size == -1) 76 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE; 77 # else 78 # if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ) 79 PL_reentrant_buffer->_pwent_size = SIABUFSIZ; 80 # else 81 # ifdef __sgi 82 PL_reentrant_buffer->_pwent_size = BUFSIZ; 83 # else 84 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE; 85 # endif 86 # endif 87 # endif 88 #endif /* HAS_GETPWNAM_R */ 89 #ifdef HAS_GETSERVBYNAME_R 90 #if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD) 91 PL_reentrant_buffer->_servent_size = REENTRANTUSUALSIZE; 92 #endif 93 #endif /* HAS_GETSERVBYNAME_R */ 94 #ifdef HAS_GETSPNAM_R 95 # if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__) 96 PL_reentrant_buffer->_spent_size = sysconf(_SC_GETPW_R_SIZE_MAX); 97 if (PL_reentrant_buffer->_pwent_size == -1) 98 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE; 99 # else 100 # if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ) 101 PL_reentrant_buffer->_spent_size = SIABUFSIZ; 102 # else 103 # ifdef __sgi 104 PL_reentrant_buffer->_spent_size = BUFSIZ; 105 # else 106 PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE; 107 # endif 108 # endif 109 # endif 110 #endif /* HAS_GETSPNAM_R */ 111 #ifdef HAS_GMTIME_R 112 #endif /* HAS_GMTIME_R */ 113 #ifdef HAS_LOCALTIME_R 114 #endif /* HAS_LOCALTIME_R */ 115 #ifdef HAS_RANDOM_R 116 #endif /* HAS_RANDOM_R */ 117 #ifdef HAS_READDIR_R 118 /* This is the size Solaris recommends. 119 * (though we go static, should use pathconf() instead) */ 120 PL_reentrant_buffer->_readdir_size = sizeof(struct dirent) + MAXPATHLEN + 1; 121 #endif /* HAS_READDIR_R */ 122 #ifdef HAS_READDIR64_R 123 /* This is the size Solaris recommends. 124 * (though we go static, should use pathconf() instead) */ 125 PL_reentrant_buffer->_readdir64_size = sizeof(struct dirent64) + MAXPATHLEN + 1; 126 #endif /* HAS_READDIR64_R */ 127 #ifdef HAS_SETLOCALE_R 128 PL_reentrant_buffer->_setlocale_size = REENTRANTSMALLSIZE; 129 #endif /* HAS_SETLOCALE_R */ 130 #ifdef HAS_STRERROR_R 131 PL_reentrant_buffer->_strerror_size = REENTRANTSMALLSIZE; 132 #endif /* HAS_STRERROR_R */ 133 #ifdef HAS_TTYNAME_R 134 PL_reentrant_buffer->_ttyname_size = REENTRANTSMALLSIZE; 135 #endif /* HAS_TTYNAME_R */ 136 137 #endif /* USE_REENTRANT_API */ 138 } 139 140 void 141 Perl_reentrant_init(pTHX) { 142 #ifdef USE_REENTRANT_API 143 New(31337, PL_reentrant_buffer, 1, REENTR); 144 Perl_reentrant_size(aTHX); 145 #ifdef HAS_ASCTIME_R 146 New(31338, PL_reentrant_buffer->_asctime_buffer, PL_reentrant_buffer->_asctime_size, char); 147 #endif /* HAS_ASCTIME_R */ 148 #ifdef HAS_CRYPT_R 149 #ifdef __GLIBC__ 150 PL_reentrant_buffer->_crypt_struct.initialized = 0; 151 #endif 152 #endif /* HAS_CRYPT_R */ 153 #ifdef HAS_CTIME_R 154 New(31338, PL_reentrant_buffer->_ctime_buffer, PL_reentrant_buffer->_ctime_size, char); 155 #endif /* HAS_CTIME_R */ 156 #ifdef HAS_DRAND48_R 157 #endif /* HAS_DRAND48_R */ 158 #ifdef HAS_GETGRNAM_R 159 # ifdef USE_GRENT_FPTR 160 PL_reentrant_buffer->_grent_fptr = NULL; 161 # endif 162 New(31338, PL_reentrant_buffer->_grent_buffer, PL_reentrant_buffer->_grent_size, char); 163 #endif /* HAS_GETGRNAM_R */ 164 #ifdef HAS_GETHOSTBYNAME_R 165 #if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 166 New(31338, PL_reentrant_buffer->_hostent_buffer, PL_reentrant_buffer->_hostent_size, char); 167 #endif 168 #endif /* HAS_GETHOSTBYNAME_R */ 169 #ifdef HAS_GETLOGIN_R 170 New(31338, PL_reentrant_buffer->_getlogin_buffer, PL_reentrant_buffer->_getlogin_size, char); 171 #endif /* HAS_GETLOGIN_R */ 172 #ifdef HAS_GETNETBYNAME_R 173 #if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 174 New(31338, PL_reentrant_buffer->_netent_buffer, PL_reentrant_buffer->_netent_size, char); 175 #endif 176 #endif /* HAS_GETNETBYNAME_R */ 177 #ifdef HAS_GETPROTOBYNAME_R 178 #if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 179 New(31338, PL_reentrant_buffer->_protoent_buffer, PL_reentrant_buffer->_protoent_size, char); 180 #endif 181 #endif /* HAS_GETPROTOBYNAME_R */ 182 #ifdef HAS_GETPWNAM_R 183 # ifdef USE_PWENT_FPTR 184 PL_reentrant_buffer->_pwent_fptr = NULL; 185 # endif 186 New(31338, PL_reentrant_buffer->_pwent_buffer, PL_reentrant_buffer->_pwent_size, char); 187 #endif /* HAS_GETPWNAM_R */ 188 #ifdef HAS_GETSERVBYNAME_R 189 #if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD) 190 New(31338, PL_reentrant_buffer->_servent_buffer, PL_reentrant_buffer->_servent_size, char); 191 #endif 192 #endif /* HAS_GETSERVBYNAME_R */ 193 #ifdef HAS_GETSPNAM_R 194 # ifdef USE_SPENT_FPTR 195 PL_reentrant_buffer->_spent_fptr = NULL; 196 # endif 197 New(31338, PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char); 198 #endif /* HAS_GETSPNAM_R */ 199 #ifdef HAS_GMTIME_R 200 #endif /* HAS_GMTIME_R */ 201 #ifdef HAS_LOCALTIME_R 202 #endif /* HAS_LOCALTIME_R */ 203 #ifdef HAS_RANDOM_R 204 #endif /* HAS_RANDOM_R */ 205 #ifdef HAS_READDIR_R 206 PL_reentrant_buffer->_readdir_struct = (struct dirent*)safemalloc(PL_reentrant_buffer->_readdir_size); 207 #endif /* HAS_READDIR_R */ 208 #ifdef HAS_READDIR64_R 209 PL_reentrant_buffer->_readdir64_struct = (struct dirent64*)safemalloc(PL_reentrant_buffer->_readdir64_size); 210 #endif /* HAS_READDIR64_R */ 211 #ifdef HAS_SETLOCALE_R 212 New(31338, PL_reentrant_buffer->_setlocale_buffer, PL_reentrant_buffer->_setlocale_size, char); 213 #endif /* HAS_SETLOCALE_R */ 214 #ifdef HAS_STRERROR_R 215 New(31338, PL_reentrant_buffer->_strerror_buffer, PL_reentrant_buffer->_strerror_size, char); 216 #endif /* HAS_STRERROR_R */ 217 #ifdef HAS_TTYNAME_R 218 New(31338, PL_reentrant_buffer->_ttyname_buffer, PL_reentrant_buffer->_ttyname_size, char); 219 #endif /* HAS_TTYNAME_R */ 220 221 #endif /* USE_REENTRANT_API */ 222 } 223 224 void 225 Perl_reentrant_free(pTHX) { 226 #ifdef USE_REENTRANT_API 227 #ifdef HAS_ASCTIME_R 228 Safefree(PL_reentrant_buffer->_asctime_buffer); 229 #endif /* HAS_ASCTIME_R */ 230 #ifdef HAS_CRYPT_R 231 #endif /* HAS_CRYPT_R */ 232 #ifdef HAS_CTIME_R 233 Safefree(PL_reentrant_buffer->_ctime_buffer); 234 #endif /* HAS_CTIME_R */ 235 #ifdef HAS_DRAND48_R 236 #endif /* HAS_DRAND48_R */ 237 #ifdef HAS_GETGRNAM_R 238 Safefree(PL_reentrant_buffer->_grent_buffer); 239 #endif /* HAS_GETGRNAM_R */ 240 #ifdef HAS_GETHOSTBYNAME_R 241 #if !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 242 Safefree(PL_reentrant_buffer->_hostent_buffer); 243 #endif 244 #endif /* HAS_GETHOSTBYNAME_R */ 245 #ifdef HAS_GETLOGIN_R 246 Safefree(PL_reentrant_buffer->_getlogin_buffer); 247 #endif /* HAS_GETLOGIN_R */ 248 #ifdef HAS_GETNETBYNAME_R 249 #if !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 250 Safefree(PL_reentrant_buffer->_netent_buffer); 251 #endif 252 #endif /* HAS_GETNETBYNAME_R */ 253 #ifdef HAS_GETPROTOBYNAME_R 254 #if !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD) 255 Safefree(PL_reentrant_buffer->_protoent_buffer); 256 #endif 257 #endif /* HAS_GETPROTOBYNAME_R */ 258 #ifdef HAS_GETPWNAM_R 259 Safefree(PL_reentrant_buffer->_pwent_buffer); 260 #endif /* HAS_GETPWNAM_R */ 261 #ifdef HAS_GETSERVBYNAME_R 262 #if !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD) 263 Safefree(PL_reentrant_buffer->_servent_buffer); 264 #endif 265 #endif /* HAS_GETSERVBYNAME_R */ 266 #ifdef HAS_GETSPNAM_R 267 Safefree(PL_reentrant_buffer->_spent_buffer); 268 #endif /* HAS_GETSPNAM_R */ 269 #ifdef HAS_GMTIME_R 270 #endif /* HAS_GMTIME_R */ 271 #ifdef HAS_LOCALTIME_R 272 #endif /* HAS_LOCALTIME_R */ 273 #ifdef HAS_RANDOM_R 274 #endif /* HAS_RANDOM_R */ 275 #ifdef HAS_READDIR_R 276 Safefree(PL_reentrant_buffer->_readdir_struct); 277 #endif /* HAS_READDIR_R */ 278 #ifdef HAS_READDIR64_R 279 Safefree(PL_reentrant_buffer->_readdir64_struct); 280 #endif /* HAS_READDIR64_R */ 281 #ifdef HAS_SETLOCALE_R 282 Safefree(PL_reentrant_buffer->_setlocale_buffer); 283 #endif /* HAS_SETLOCALE_R */ 284 #ifdef HAS_STRERROR_R 285 Safefree(PL_reentrant_buffer->_strerror_buffer); 286 #endif /* HAS_STRERROR_R */ 287 #ifdef HAS_TTYNAME_R 288 Safefree(PL_reentrant_buffer->_ttyname_buffer); 289 #endif /* HAS_TTYNAME_R */ 290 291 Safefree(PL_reentrant_buffer); 292 #endif /* USE_REENTRANT_API */ 293 } 294 295 void* 296 Perl_reentrant_retry(const char *f, ...) 297 { 298 dTHX; 299 void *retptr = NULL; 300 #ifdef USE_REENTRANT_API 301 # 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) 302 void *p0; 303 # endif 304 # if defined(USE_SERVENT_BUFFER) 305 void *p1; 306 # endif 307 # if defined(USE_HOSTENT_BUFFER) 308 size_t asize; 309 # endif 310 # if defined(USE_HOSTENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER) 311 int anint; 312 # endif 313 va_list ap; 314 315 va_start(ap, f); 316 317 #define REENTRANTHALFMAXSIZE 32768 /* The maximum may end up twice this. */ 318 319 switch (PL_op->op_type) { 320 #ifdef USE_HOSTENT_BUFFER 321 case OP_GHBYADDR: 322 case OP_GHBYNAME: 323 case OP_GHOSTENT: 324 { 325 if (PL_reentrant_buffer->_hostent_size <= REENTRANTHALFMAXSIZE) { 326 PL_reentrant_buffer->_hostent_size *= 2; 327 Renew(PL_reentrant_buffer->_hostent_buffer, 328 PL_reentrant_buffer->_hostent_size, char); 329 switch (PL_op->op_type) { 330 case OP_GHBYADDR: 331 p0 = va_arg(ap, void *); 332 asize = va_arg(ap, size_t); 333 anint = va_arg(ap, int); 334 retptr = gethostbyaddr(p0, asize, anint); break; 335 case OP_GHBYNAME: 336 p0 = va_arg(ap, void *); 337 retptr = gethostbyname(p0); break; 338 case OP_GHOSTENT: 339 retptr = gethostent(); break; 340 default: 341 break; 342 } 343 } 344 } 345 break; 346 #endif 347 #ifdef USE_GRENT_BUFFER 348 case OP_GGRNAM: 349 case OP_GGRGID: 350 case OP_GGRENT: 351 { 352 if (PL_reentrant_buffer->_grent_size <= REENTRANTHALFMAXSIZE) { 353 Gid_t gid; 354 PL_reentrant_buffer->_grent_size *= 2; 355 Renew(PL_reentrant_buffer->_grent_buffer, 356 PL_reentrant_buffer->_grent_size, char); 357 switch (PL_op->op_type) { 358 case OP_GGRNAM: 359 p0 = va_arg(ap, void *); 360 retptr = getgrnam(p0); break; 361 case OP_GGRGID: 362 gid = va_arg(ap, Gid_t); 363 retptr = getgrgid(gid); break; 364 case OP_GGRENT: 365 retptr = getgrent(); break; 366 default: 367 break; 368 } 369 } 370 } 371 break; 372 #endif 373 #ifdef USE_NETENT_BUFFER 374 case OP_GNBYADDR: 375 case OP_GNBYNAME: 376 case OP_GNETENT: 377 { 378 if (PL_reentrant_buffer->_netent_size <= REENTRANTHALFMAXSIZE) { 379 Netdb_net_t net; 380 PL_reentrant_buffer->_netent_size *= 2; 381 Renew(PL_reentrant_buffer->_netent_buffer, 382 PL_reentrant_buffer->_netent_size, char); 383 switch (PL_op->op_type) { 384 case OP_GNBYADDR: 385 net = va_arg(ap, Netdb_net_t); 386 anint = va_arg(ap, int); 387 retptr = getnetbyaddr(net, anint); break; 388 case OP_GNBYNAME: 389 p0 = va_arg(ap, void *); 390 retptr = getnetbyname(p0); break; 391 case OP_GNETENT: 392 retptr = getnetent(); break; 393 default: 394 break; 395 } 396 } 397 } 398 break; 399 #endif 400 #ifdef USE_PWENT_BUFFER 401 case OP_GPWNAM: 402 case OP_GPWUID: 403 case OP_GPWENT: 404 { 405 if (PL_reentrant_buffer->_pwent_size <= REENTRANTHALFMAXSIZE) { 406 Uid_t uid; 407 PL_reentrant_buffer->_pwent_size *= 2; 408 Renew(PL_reentrant_buffer->_pwent_buffer, 409 PL_reentrant_buffer->_pwent_size, char); 410 switch (PL_op->op_type) { 411 case OP_GPWNAM: 412 p0 = va_arg(ap, void *); 413 retptr = getpwnam(p0); break; 414 case OP_GPWUID: 415 uid = va_arg(ap, Uid_t); 416 retptr = getpwuid(uid); break; 417 case OP_GPWENT: 418 retptr = getpwent(); break; 419 default: 420 break; 421 } 422 } 423 } 424 break; 425 #endif 426 #ifdef USE_PROTOENT_BUFFER 427 case OP_GPBYNAME: 428 case OP_GPBYNUMBER: 429 case OP_GPROTOENT: 430 { 431 if (PL_reentrant_buffer->_protoent_size <= REENTRANTHALFMAXSIZE) { 432 PL_reentrant_buffer->_protoent_size *= 2; 433 Renew(PL_reentrant_buffer->_protoent_buffer, 434 PL_reentrant_buffer->_protoent_size, char); 435 switch (PL_op->op_type) { 436 case OP_GPBYNAME: 437 p0 = va_arg(ap, void *); 438 retptr = getprotobyname(p0); break; 439 case OP_GPBYNUMBER: 440 anint = va_arg(ap, int); 441 retptr = getprotobynumber(anint); break; 442 case OP_GPROTOENT: 443 retptr = getprotoent(); break; 444 default: 445 break; 446 } 447 } 448 } 449 break; 450 #endif 451 #ifdef USE_SERVENT_BUFFER 452 case OP_GSBYNAME: 453 case OP_GSBYPORT: 454 case OP_GSERVENT: 455 { 456 if (PL_reentrant_buffer->_servent_size <= REENTRANTHALFMAXSIZE) { 457 PL_reentrant_buffer->_servent_size *= 2; 458 Renew(PL_reentrant_buffer->_servent_buffer, 459 PL_reentrant_buffer->_servent_size, char); 460 switch (PL_op->op_type) { 461 case OP_GSBYNAME: 462 p0 = va_arg(ap, void *); 463 p1 = va_arg(ap, void *); 464 retptr = getservbyname(p0, p1); break; 465 case OP_GSBYPORT: 466 anint = va_arg(ap, int); 467 p0 = va_arg(ap, void *); 468 retptr = getservbyport(anint, p0); break; 469 case OP_GSERVENT: 470 retptr = getservent(); break; 471 default: 472 break; 473 } 474 } 475 } 476 break; 477 #endif 478 default: 479 /* Not known how to retry, so just fail. */ 480 break; 481 } 482 483 va_end(ap); 484 #endif 485 return retptr; 486 } 487 488