Purify: Unitialized memory read. Too many code paths
[p5sagit/p5-mst-13.2.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->_getgrent_size == -1)
76                 PL_reentrant_buffer->_getgrent_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     void *p0, *p1;
285     size_t asize;
286     int anint;
287     va_list ap;
288
289     va_start(ap, f);
290
291 #define REENTRANTHALFMAXSIZE 32768 /* The maximum may end up twice this. */
292
293     switch (PL_op->op_type) {
294 #ifdef USE_GETHOSTENT_BUFFER
295     case OP_GHBYADDR:
296     case OP_GHBYNAME:
297     case OP_GHOSTENT:
298         {
299             if (PL_reentrant_buffer->_gethostent_size <= REENTRANTHALFMAXSIZE) {
300                 PL_reentrant_buffer->_gethostent_size *= 2;
301                 Renew(PL_reentrant_buffer->_gethostent_buffer,
302                       PL_reentrant_buffer->_gethostent_size, char);
303                 switch (PL_op->op_type) {
304                 case OP_GHBYADDR:
305                     p0    = va_arg(ap, void *);
306                     asize = va_arg(ap, size_t);
307                     anint  = va_arg(ap, int);
308                     retptr = gethostbyaddr(p0, asize, anint); break;
309                 case OP_GHBYNAME:
310                     p0 = va_arg(ap, void *);
311                     retptr = gethostbyname(p0); break;
312                 case OP_GHOSTENT:
313                     retptr = gethostent(); break;
314                 default:
315                     break;
316                 }
317             }
318         }
319         break;
320 #endif
321 #ifdef USE_GETGRENT_BUFFER
322     case OP_GGRNAM:
323     case OP_GGRGID:
324     case OP_GGRENT:
325         {
326             if (PL_reentrant_buffer->_getgrent_size <= REENTRANTHALFMAXSIZE) {
327                 Gid_t gid;
328                 PL_reentrant_buffer->_getgrent_size *= 2;
329                 Renew(PL_reentrant_buffer->_getgrent_buffer,
330                       PL_reentrant_buffer->_getgrent_size, char);
331                 switch (PL_op->op_type) {
332                 case OP_GGRNAM:
333                     p0 = va_arg(ap, void *);
334                     retptr = getgrnam(p0); break;
335                 case OP_GGRGID:
336                     gid = va_arg(ap, Gid_t);
337                     retptr = getgrgid(gid); break;
338                 case OP_GGRENT:
339                     retptr = getgrent(); break;
340                 default:
341                     break;
342                 }
343             }
344         }
345         break;
346 #endif
347 #ifdef USE_GETNETENT_BUFFER
348     case OP_GNBYADDR:
349     case OP_GNBYNAME:
350     case OP_GNETENT:
351         {
352             if (PL_reentrant_buffer->_getnetent_size <= REENTRANTHALFMAXSIZE) {
353                 Netdb_net_t net;
354                 PL_reentrant_buffer->_getnetent_size *= 2;
355                 Renew(PL_reentrant_buffer->_getnetent_buffer,
356                       PL_reentrant_buffer->_getnetent_size, char);
357                 switch (PL_op->op_type) {
358                 case OP_GNBYADDR:
359                     net = va_arg(ap, Netdb_net_t);
360                     anint = va_arg(ap, int);
361                     retptr = getnetbyaddr(net, anint); break;
362                 case OP_GNBYNAME:
363                     p0 = va_arg(ap, void *);
364                     retptr = getnetbyname(p0); break;
365                 case OP_GNETENT:
366                     retptr = getnetent(); break;
367                 default:
368                     break;
369                 }
370             }
371         }
372         break;
373 #endif
374 #ifdef USE_GETPWENT_BUFFER
375     case OP_GPWNAM:
376     case OP_GPWUID:
377     case OP_GPWENT:
378         {
379             if (PL_reentrant_buffer->_getpwent_size <= REENTRANTHALFMAXSIZE) {
380                 Uid_t uid;
381                 PL_reentrant_buffer->_getpwent_size *= 2;
382                 Renew(PL_reentrant_buffer->_getpwent_buffer,
383                       PL_reentrant_buffer->_getpwent_size, char);
384                 switch (PL_op->op_type) {
385                 case OP_GPWNAM:
386                     p0 = va_arg(ap, void *);
387                     retptr = getpwnam(p0); break;
388                 case OP_GPWUID:
389                     uid = va_arg(ap, Uid_t);
390                     retptr = getpwuid(uid); break;
391                 case OP_GPWENT:
392                     retptr = getpwent(); break;
393                 default:
394                     break;
395                 }
396             }
397         }
398         break;
399 #endif
400 #ifdef USE_GETPROTOENT_BUFFER
401     case OP_GPBYNAME:
402     case OP_GPBYNUMBER:
403     case OP_GPROTOENT:
404         {
405             if (PL_reentrant_buffer->_getprotoent_size <= REENTRANTHALFMAXSIZE) {
406                 PL_reentrant_buffer->_getprotoent_size *= 2;
407                 Renew(PL_reentrant_buffer->_getprotoent_buffer,
408                       PL_reentrant_buffer->_getprotoent_size, char);
409                 switch (PL_op->op_type) {
410                 case OP_GPBYNAME:
411                     p0 = va_arg(ap, void *);
412                     retptr = getprotobyname(p0); break;
413                 case OP_GPBYNUMBER:
414                     anint = va_arg(ap, int);
415                     retptr = getprotobynumber(anint); break;
416                 case OP_GPROTOENT:
417                     retptr = getprotoent(); break;
418                 default:
419                     break;
420                 }
421             }
422         }
423         break;
424 #endif
425 #ifdef USE_GETSERVENT_BUFFER
426     case OP_GSBYNAME:
427     case OP_GSBYPORT:
428     case OP_GSERVENT:
429         {
430             if (PL_reentrant_buffer->_getservent_size <= REENTRANTHALFMAXSIZE) {
431                 PL_reentrant_buffer->_getservent_size *= 2;
432                 Renew(PL_reentrant_buffer->_getservent_buffer,
433                       PL_reentrant_buffer->_getservent_size, char);
434                 switch (PL_op->op_type) {
435                 case OP_GSBYNAME:
436                     p0 = va_arg(ap, void *);
437                     p1 = va_arg(ap, void *);
438                     retptr = getservbyname(p0, p1); break;
439                 case OP_GSBYPORT:
440                     anint = va_arg(ap, int);
441                     p0 = va_arg(ap, void *);
442                     retptr = getservbyport(anint, p0); break;
443                 case OP_GSERVENT:
444                     retptr = getservent(); break;
445                 default:
446                     break;
447                 }
448             }
449         }
450         break;
451 #endif
452     default:
453         /* Not known how to retry, so just fail. */
454         break;
455     }
456
457     va_end(ap);
458 #endif
459     return retptr;
460 }
461