[ID 20020407.002] Bug (?) and patch for DProf
[perl.git] / reentr.c
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_GETGR_R_SIZE_MAX) && !defined(__GLIBC__)
39         PL_reentrant_buffer->_getgrent_size = sysconf(_SC_GETGR_R_SIZE_MAX);
40         if (PL_reentrant_buffer->_getgrent_size == -1)
41                 PL_reentrant_buffer->_getgrent_size = REENTRANTUSUALSIZE;
42 #   else
43 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
44         PL_reentrant_buffer->_getgrent_size = SIABUFSIZ;
45 #       else
46 #           ifdef __sgi
47         PL_reentrant_buffer->_getgrent_size = BUFSIZ;
48 #           else
49         PL_reentrant_buffer->_getgrent_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->_gethostent_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->_getnetent_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->_getprotoent_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->_getpwent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
75         if (PL_reentrant_buffer->_getpwent_size == -1)
76                 PL_reentrant_buffer->_getpwent_size = REENTRANTUSUALSIZE;
77 #   else
78 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
79         PL_reentrant_buffer->_getpwent_size = SIABUFSIZ;
80 #       else
81 #           ifdef __sgi
82         PL_reentrant_buffer->_getpwent_size = BUFSIZ;
83 #           else
84         PL_reentrant_buffer->_getpwent_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->_getservent_size = REENTRANTUSUALSIZE;
92 #endif
93 #endif /* HAS_GETSERVBYNAME_R */
94 #ifdef HAS_GETSPNAM_R
95         PL_reentrant_buffer->_getspent_size = 1024;
96 #endif /* HAS_GETSPNAM_R */
97 #ifdef HAS_GMTIME_R
98 #endif /* HAS_GMTIME_R */
99 #ifdef HAS_LOCALTIME_R
100 #endif /* HAS_LOCALTIME_R */
101 #ifdef HAS_RANDOM_R
102 #endif /* HAS_RANDOM_R */
103 #ifdef HAS_READDIR_R
104         /* This is the size Solaris recommends.
105          * (though we go static, should use pathconf() instead) */
106         PL_reentrant_buffer->_readdir_size = sizeof(struct dirent) + MAXPATHLEN + 1;
107 #endif /* HAS_READDIR_R */
108 #ifdef HAS_READDIR64_R
109         /* This is the size Solaris recommends.
110          * (though we go static, should use pathconf() instead) */
111         PL_reentrant_buffer->_readdir64_size = sizeof(struct dirent64) + MAXPATHLEN + 1;
112 #endif /* HAS_READDIR64_R */
113 #ifdef HAS_SETLOCALE_R
114         PL_reentrant_buffer->_setlocale_size = REENTRANTSMALLSIZE;
115 #endif /* HAS_SETLOCALE_R */
116 #ifdef HAS_STRERROR_R
117         PL_reentrant_buffer->_strerror_size = REENTRANTSMALLSIZE;
118 #endif /* HAS_STRERROR_R */
119 #ifdef HAS_TTYNAME_R
120         PL_reentrant_buffer->_ttyname_size = REENTRANTSMALLSIZE;
121 #endif /* HAS_TTYNAME_R */
122
123 #endif /* USE_REENTRANT_API */
124 }
125
126 void
127 Perl_reentrant_init(pTHX) {
128 #ifdef USE_REENTRANT_API
129         New(31337, PL_reentrant_buffer, 1, REENTR);
130         Perl_reentrant_size(aTHX);
131 #ifdef HAS_ASCTIME_R
132         New(31338, PL_reentrant_buffer->_asctime_buffer, PL_reentrant_buffer->_asctime_size, char);
133 #endif /* HAS_ASCTIME_R */
134 #ifdef HAS_CRYPT_R
135 #ifdef __GLIBC__
136         PL_reentrant_buffer->_crypt_struct.initialized = 0;
137 #endif
138 #endif /* HAS_CRYPT_R */
139 #ifdef HAS_CTIME_R
140         New(31338, PL_reentrant_buffer->_ctime_buffer, PL_reentrant_buffer->_ctime_size, char);
141 #endif /* HAS_CTIME_R */
142 #ifdef HAS_DRAND48_R
143 #endif /* HAS_DRAND48_R */
144 #ifdef HAS_GETGRNAM_R
145 #   ifdef USE_GETGRENT_FPTR
146         PL_reentrant_buffer->_getgrent_fptr = NULL;
147 #   endif
148         New(31338, PL_reentrant_buffer->_getgrent_buffer, PL_reentrant_buffer->_getgrent_size, char);
149 #endif /* HAS_GETGRNAM_R */
150 #ifdef HAS_GETHOSTBYNAME_R
151 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
152         New(31338, PL_reentrant_buffer->_gethostent_buffer, PL_reentrant_buffer->_gethostent_size, char);
153 #endif
154 #endif /* HAS_GETHOSTBYNAME_R */
155 #ifdef HAS_GETLOGIN_R
156         New(31338, PL_reentrant_buffer->_getlogin_buffer, PL_reentrant_buffer->_getlogin_size, char);
157 #endif /* HAS_GETLOGIN_R */
158 #ifdef HAS_GETNETBYNAME_R
159 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
160         New(31338, PL_reentrant_buffer->_getnetent_buffer, PL_reentrant_buffer->_getnetent_size, char);
161 #endif
162 #endif /* HAS_GETNETBYNAME_R */
163 #ifdef HAS_GETPROTOBYNAME_R
164 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
165         New(31338, PL_reentrant_buffer->_getprotoent_buffer, PL_reentrant_buffer->_getprotoent_size, char);
166 #endif
167 #endif /* HAS_GETPROTOBYNAME_R */
168 #ifdef HAS_GETPWNAM_R
169 #   ifdef USE_GETPWENT_FPTR
170         PL_reentrant_buffer->_getpwent_fptr = NULL;
171 #   endif
172         New(31338, PL_reentrant_buffer->_getpwent_buffer, PL_reentrant_buffer->_getpwent_size, char);
173 #endif /* HAS_GETPWNAM_R */
174 #ifdef HAS_GETSERVBYNAME_R
175 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
176         New(31338, PL_reentrant_buffer->_getservent_buffer, PL_reentrant_buffer->_getservent_size, char);
177 #endif
178 #endif /* HAS_GETSERVBYNAME_R */
179 #ifdef HAS_GETSPNAM_R
180         New(31338, PL_reentrant_buffer->_getspent_buffer, PL_reentrant_buffer->_getspent_size, char);
181 #endif /* HAS_GETSPNAM_R */
182 #ifdef HAS_GMTIME_R
183 #endif /* HAS_GMTIME_R */
184 #ifdef HAS_LOCALTIME_R
185 #endif /* HAS_LOCALTIME_R */
186 #ifdef HAS_RANDOM_R
187 #endif /* HAS_RANDOM_R */
188 #ifdef HAS_READDIR_R
189         PL_reentrant_buffer->_readdir_struct = (struct dirent*)safemalloc(PL_reentrant_buffer->_readdir_size);
190 #endif /* HAS_READDIR_R */
191 #ifdef HAS_READDIR64_R
192         PL_reentrant_buffer->_readdir64_struct = (struct dirent64*)safemalloc(PL_reentrant_buffer->_readdir64_size);
193 #endif /* HAS_READDIR64_R */
194 #ifdef HAS_SETLOCALE_R
195         New(31338, PL_reentrant_buffer->_setlocale_buffer, PL_reentrant_buffer->_setlocale_size, char);
196 #endif /* HAS_SETLOCALE_R */
197 #ifdef HAS_STRERROR_R
198         New(31338, PL_reentrant_buffer->_strerror_buffer, PL_reentrant_buffer->_strerror_size, char);
199 #endif /* HAS_STRERROR_R */
200 #ifdef HAS_TTYNAME_R
201         New(31338, PL_reentrant_buffer->_ttyname_buffer, PL_reentrant_buffer->_ttyname_size, char);
202 #endif /* HAS_TTYNAME_R */
203
204 #endif /* USE_REENTRANT_API */
205 }
206
207 void
208 Perl_reentrant_free(pTHX) {
209 #ifdef USE_REENTRANT_API
210 #ifdef HAS_ASCTIME_R
211         Safefree(PL_reentrant_buffer->_asctime_buffer);
212 #endif /* HAS_ASCTIME_R */
213 #ifdef HAS_CRYPT_R
214 #endif /* HAS_CRYPT_R */
215 #ifdef HAS_CTIME_R
216         Safefree(PL_reentrant_buffer->_ctime_buffer);
217 #endif /* HAS_CTIME_R */
218 #ifdef HAS_DRAND48_R
219 #endif /* HAS_DRAND48_R */
220 #ifdef HAS_GETGRNAM_R
221         Safefree(PL_reentrant_buffer->_getgrent_buffer);
222 #endif /* HAS_GETGRNAM_R */
223 #ifdef HAS_GETHOSTBYNAME_R
224 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
225         Safefree(PL_reentrant_buffer->_gethostent_buffer);
226 #endif
227 #endif /* HAS_GETHOSTBYNAME_R */
228 #ifdef HAS_GETLOGIN_R
229         Safefree(PL_reentrant_buffer->_getlogin_buffer);
230 #endif /* HAS_GETLOGIN_R */
231 #ifdef HAS_GETNETBYNAME_R
232 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
233         Safefree(PL_reentrant_buffer->_getnetent_buffer);
234 #endif
235 #endif /* HAS_GETNETBYNAME_R */
236 #ifdef HAS_GETPROTOBYNAME_R
237 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
238         Safefree(PL_reentrant_buffer->_getprotoent_buffer);
239 #endif
240 #endif /* HAS_GETPROTOBYNAME_R */
241 #ifdef HAS_GETPWNAM_R
242         Safefree(PL_reentrant_buffer->_getpwent_buffer);
243 #endif /* HAS_GETPWNAM_R */
244 #ifdef HAS_GETSERVBYNAME_R
245 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
246         Safefree(PL_reentrant_buffer->_getservent_buffer);
247 #endif
248 #endif /* HAS_GETSERVBYNAME_R */
249 #ifdef HAS_GETSPNAM_R
250         Safefree(PL_reentrant_buffer->_getspent_buffer);
251 #endif /* HAS_GETSPNAM_R */
252 #ifdef HAS_GMTIME_R
253 #endif /* HAS_GMTIME_R */
254 #ifdef HAS_LOCALTIME_R
255 #endif /* HAS_LOCALTIME_R */
256 #ifdef HAS_RANDOM_R
257 #endif /* HAS_RANDOM_R */
258 #ifdef HAS_READDIR_R
259         Safefree(PL_reentrant_buffer->_readdir_struct);
260 #endif /* HAS_READDIR_R */
261 #ifdef HAS_READDIR64_R
262         Safefree(PL_reentrant_buffer->_readdir64_struct);
263 #endif /* HAS_READDIR64_R */
264 #ifdef HAS_SETLOCALE_R
265         Safefree(PL_reentrant_buffer->_setlocale_buffer);
266 #endif /* HAS_SETLOCALE_R */
267 #ifdef HAS_STRERROR_R
268         Safefree(PL_reentrant_buffer->_strerror_buffer);
269 #endif /* HAS_STRERROR_R */
270 #ifdef HAS_TTYNAME_R
271         Safefree(PL_reentrant_buffer->_ttyname_buffer);
272 #endif /* HAS_TTYNAME_R */
273
274         Safefree(PL_reentrant_buffer);
275 #endif /* USE_REENTRANT_API */
276 }
277
278 void*
279 Perl_reentrant_retry(const char *f, ...)
280 {
281     dTHX;
282     void *retptr = NULL;
283 #ifdef USE_REENTRANT_API
284 #  if defined(USE_GETHOSTENT_BUFFER) || defined(USE_GETGRENT_BUFFER) || defined(USE_GETNETENT_BUFFER) || defined(USE_GETPWENT_BUFFER) || defined(USE_GETPROTOENT_BUFFER) || defined(USE_GETSERVENT_BUFFER)
285     void *p0;
286 #  endif
287 #  if defined(USE_GETSERVENT_BUFFER)
288     void *p1;
289 #  endif
290 #  if defined(USE_GETHOSTENT_BUFFER)
291     size_t asize;
292 #  endif
293 #  if defined(USE_GETHOSTENT_BUFFER) || defined(USE_GETNETENT_BUFFER) || defined(USE_GETPROTOENT_BUFFER) || defined(USE_GETSERVENT_BUFFER)
294     int anint;
295 #  endif
296     va_list ap;
297
298     va_start(ap, f);
299
300 #define REENTRANTHALFMAXSIZE 32768 /* The maximum may end up twice this. */
301
302     switch (PL_op->op_type) {
303 #ifdef USE_GETHOSTENT_BUFFER
304     case OP_GHBYADDR:
305     case OP_GHBYNAME:
306     case OP_GHOSTENT:
307         {
308             if (PL_reentrant_buffer->_gethostent_size <= REENTRANTHALFMAXSIZE) {
309                 PL_reentrant_buffer->_gethostent_size *= 2;
310                 Renew(PL_reentrant_buffer->_gethostent_buffer,
311                       PL_reentrant_buffer->_gethostent_size, char);
312                 switch (PL_op->op_type) {
313                 case OP_GHBYADDR:
314                     p0    = va_arg(ap, void *);
315                     asize = va_arg(ap, size_t);
316                     anint  = va_arg(ap, int);
317                     retptr = gethostbyaddr(p0, asize, anint); break;
318                 case OP_GHBYNAME:
319                     p0 = va_arg(ap, void *);
320                     retptr = gethostbyname(p0); break;
321                 case OP_GHOSTENT:
322                     retptr = gethostent(); break;
323                 default:
324                     break;
325                 }
326             }
327         }
328         break;
329 #endif
330 #ifdef USE_GETGRENT_BUFFER
331     case OP_GGRNAM:
332     case OP_GGRGID:
333     case OP_GGRENT:
334         {
335             if (PL_reentrant_buffer->_getgrent_size <= REENTRANTHALFMAXSIZE) {
336                 Gid_t gid;
337                 PL_reentrant_buffer->_getgrent_size *= 2;
338                 Renew(PL_reentrant_buffer->_getgrent_buffer,
339                       PL_reentrant_buffer->_getgrent_size, char);
340                 switch (PL_op->op_type) {
341                 case OP_GGRNAM:
342                     p0 = va_arg(ap, void *);
343                     retptr = getgrnam(p0); break;
344                 case OP_GGRGID:
345                     gid = va_arg(ap, Gid_t);
346                     retptr = getgrgid(gid); break;
347                 case OP_GGRENT:
348                     retptr = getgrent(); break;
349                 default:
350                     break;
351                 }
352             }
353         }
354         break;
355 #endif
356 #ifdef USE_GETNETENT_BUFFER
357     case OP_GNBYADDR:
358     case OP_GNBYNAME:
359     case OP_GNETENT:
360         {
361             if (PL_reentrant_buffer->_getnetent_size <= REENTRANTHALFMAXSIZE) {
362                 Netdb_net_t net;
363                 PL_reentrant_buffer->_getnetent_size *= 2;
364                 Renew(PL_reentrant_buffer->_getnetent_buffer,
365                       PL_reentrant_buffer->_getnetent_size, char);
366                 switch (PL_op->op_type) {
367                 case OP_GNBYADDR:
368                     net = va_arg(ap, Netdb_net_t);
369                     anint = va_arg(ap, int);
370                     retptr = getnetbyaddr(net, anint); break;
371                 case OP_GNBYNAME:
372                     p0 = va_arg(ap, void *);
373                     retptr = getnetbyname(p0); break;
374                 case OP_GNETENT:
375                     retptr = getnetent(); break;
376                 default:
377                     break;
378                 }
379             }
380         }
381         break;
382 #endif
383 #ifdef USE_GETPWENT_BUFFER
384     case OP_GPWNAM:
385     case OP_GPWUID:
386     case OP_GPWENT:
387         {
388             if (PL_reentrant_buffer->_getpwent_size <= REENTRANTHALFMAXSIZE) {
389                 Uid_t uid;
390                 PL_reentrant_buffer->_getpwent_size *= 2;
391                 Renew(PL_reentrant_buffer->_getpwent_buffer,
392                       PL_reentrant_buffer->_getpwent_size, char);
393                 switch (PL_op->op_type) {
394                 case OP_GPWNAM:
395                     p0 = va_arg(ap, void *);
396                     retptr = getpwnam(p0); break;
397                 case OP_GPWUID:
398                     uid = va_arg(ap, Uid_t);
399                     retptr = getpwuid(uid); break;
400                 case OP_GPWENT:
401                     retptr = getpwent(); break;
402                 default:
403                     break;
404                 }
405             }
406         }
407         break;
408 #endif
409 #ifdef USE_GETPROTOENT_BUFFER
410     case OP_GPBYNAME:
411     case OP_GPBYNUMBER:
412     case OP_GPROTOENT:
413         {
414             if (PL_reentrant_buffer->_getprotoent_size <= REENTRANTHALFMAXSIZE) {
415                 PL_reentrant_buffer->_getprotoent_size *= 2;
416                 Renew(PL_reentrant_buffer->_getprotoent_buffer,
417                       PL_reentrant_buffer->_getprotoent_size, char);
418                 switch (PL_op->op_type) {
419                 case OP_GPBYNAME:
420                     p0 = va_arg(ap, void *);
421                     retptr = getprotobyname(p0); break;
422                 case OP_GPBYNUMBER:
423                     anint = va_arg(ap, int);
424                     retptr = getprotobynumber(anint); break;
425                 case OP_GPROTOENT:
426                     retptr = getprotoent(); break;
427                 default:
428                     break;
429                 }
430             }
431         }
432         break;
433 #endif
434 #ifdef USE_GETSERVENT_BUFFER
435     case OP_GSBYNAME:
436     case OP_GSBYPORT:
437     case OP_GSERVENT:
438         {
439             if (PL_reentrant_buffer->_getservent_size <= REENTRANTHALFMAXSIZE) {
440                 PL_reentrant_buffer->_getservent_size *= 2;
441                 Renew(PL_reentrant_buffer->_getservent_buffer,
442                       PL_reentrant_buffer->_getservent_size, char);
443                 switch (PL_op->op_type) {
444                 case OP_GSBYNAME:
445                     p0 = va_arg(ap, void *);
446                     p1 = va_arg(ap, void *);
447                     retptr = getservbyname(p0, p1); break;
448                 case OP_GSBYPORT:
449                     anint = va_arg(ap, int);
450                     p0 = va_arg(ap, void *);
451                     retptr = getservbyport(anint, p0); break;
452                 case OP_GSERVENT:
453                     retptr = getservent(); break;
454                 default:
455                     break;
456                 }
457             }
458         }
459         break;
460 #endif
461     default:
462         /* Not known how to retry, so just fail. */
463         break;
464     }
465
466     va_end(ap);
467 #endif
468     return retptr;
469 }
470