This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perluniintro: Add note
[perl5.git] / reentr.c
1 /* -*- buffer-read-only: t -*-
2  *
3  *    reentr.c
4  *
5  *    Copyright (C) 2002, 2003, 2005, 2006, 2007 by Larry Wall and others
6  *
7  *    You may distribute under the terms of either the GNU General Public
8  *    License or the Artistic License, as specified in the README file.
9  *
10  * !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
11  * This file is built by regen/reentr.pl from data in regen/reentr.pl.
12  * Any changes made here will be lost!
13  *
14  * "Saruman," I said, standing away from him, "only one hand at a time can
15  *  wield the One, and you know that well, so do not trouble to say we!"
16  *
17  * This file contains a collection of automatically created wrappers
18  * (created by running reentr.pl) for reentrant (thread-safe) versions of
19  * various library calls, such as getpwent_r.  The wrapping is done so
20  * that other files like pp_sys.c calling those library functions need not
21  * care about the differences between various platforms' idiosyncrasies
22  * regarding these reentrant interfaces.  
23  */
24
25 #include "EXTERN.h"
26 #define PERL_IN_REENTR_C
27 #include "perl.h"
28 #include "reentr.h"
29
30 void
31 Perl_reentrant_size(pTHX) {
32         PERL_UNUSED_CONTEXT;
33 #ifdef USE_REENTRANT_API
34 #define REENTRANTSMALLSIZE       256    /* Make something up. */
35 #define REENTRANTUSUALSIZE      4096    /* Make something up. */
36 #ifdef HAS_ASCTIME_R
37         PL_reentrant_buffer->_asctime_size = REENTRANTSMALLSIZE;
38 #endif /* HAS_ASCTIME_R */
39 #ifdef HAS_CRYPT_R
40 #endif /* HAS_CRYPT_R */
41 #ifdef HAS_CTIME_R
42         PL_reentrant_buffer->_ctime_size = REENTRANTSMALLSIZE;
43 #endif /* HAS_CTIME_R */
44 #ifdef HAS_GETGRNAM_R
45 #   if defined(HAS_SYSCONF) && defined(_SC_GETGR_R_SIZE_MAX) && !defined(__GLIBC__)
46         PL_reentrant_buffer->_grent_size = sysconf(_SC_GETGR_R_SIZE_MAX);
47         if (PL_reentrant_buffer->_grent_size == (size_t) -1)
48                 PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
49 #   else
50 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
51         PL_reentrant_buffer->_grent_size = SIABUFSIZ;
52 #       else
53 #           ifdef __sgi
54         PL_reentrant_buffer->_grent_size = BUFSIZ;
55 #           else
56         PL_reentrant_buffer->_grent_size = REENTRANTUSUALSIZE;
57 #           endif
58 #       endif
59 #   endif 
60 #endif /* HAS_GETGRNAM_R */
61 #ifdef HAS_GETHOSTBYNAME_R
62 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
63         PL_reentrant_buffer->_hostent_size = REENTRANTUSUALSIZE;
64 #endif
65 #endif /* HAS_GETHOSTBYNAME_R */
66 #ifdef HAS_GETLOGIN_R
67         PL_reentrant_buffer->_getlogin_size = REENTRANTSMALLSIZE;
68 #endif /* HAS_GETLOGIN_R */
69 #ifdef HAS_GETNETBYNAME_R
70 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
71         PL_reentrant_buffer->_netent_size = REENTRANTUSUALSIZE;
72 #endif
73 #endif /* HAS_GETNETBYNAME_R */
74 #ifdef HAS_GETPROTOBYNAME_R
75 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
76         PL_reentrant_buffer->_protoent_size = REENTRANTUSUALSIZE;
77 #endif
78 #endif /* HAS_GETPROTOBYNAME_R */
79 #ifdef HAS_GETPWNAM_R
80 #   if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
81         PL_reentrant_buffer->_pwent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
82         if (PL_reentrant_buffer->_pwent_size == (size_t) -1)
83                 PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
84 #   else
85 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
86         PL_reentrant_buffer->_pwent_size = SIABUFSIZ;
87 #       else
88 #           ifdef __sgi
89         PL_reentrant_buffer->_pwent_size = BUFSIZ;
90 #           else
91         PL_reentrant_buffer->_pwent_size = REENTRANTUSUALSIZE;
92 #           endif
93 #       endif
94 #   endif 
95 #endif /* HAS_GETPWNAM_R */
96 #ifdef HAS_GETSERVBYNAME_R
97 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
98         PL_reentrant_buffer->_servent_size = REENTRANTUSUALSIZE;
99 #endif
100 #endif /* HAS_GETSERVBYNAME_R */
101 #ifdef HAS_GETSPNAM_R
102 #   if defined(HAS_SYSCONF) && defined(_SC_GETPW_R_SIZE_MAX) && !defined(__GLIBC__)
103         PL_reentrant_buffer->_spent_size = sysconf(_SC_GETPW_R_SIZE_MAX);
104         if (PL_reentrant_buffer->_spent_size == (size_t) -1)
105                 PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
106 #   else
107 #       if defined(__osf__) && defined(__alpha) && defined(SIABUFSIZ)
108         PL_reentrant_buffer->_spent_size = SIABUFSIZ;
109 #       else
110 #           ifdef __sgi
111         PL_reentrant_buffer->_spent_size = BUFSIZ;
112 #           else
113         PL_reentrant_buffer->_spent_size = REENTRANTUSUALSIZE;
114 #           endif
115 #       endif
116 #   endif 
117 #endif /* HAS_GETSPNAM_R */
118 #ifdef HAS_READDIR_R
119         /* This is the size Solaris recommends.
120          * (though we go static, should use pathconf() instead) */
121         PL_reentrant_buffer->_readdir_size = sizeof(struct dirent) + MAXPATHLEN + 1;
122 #endif /* HAS_READDIR_R */
123 #ifdef HAS_READDIR64_R
124         /* This is the size Solaris recommends.
125          * (though we go static, should use pathconf() instead) */
126         PL_reentrant_buffer->_readdir64_size = sizeof(struct dirent64) + MAXPATHLEN + 1;
127 #endif /* HAS_READDIR64_R */
128 #ifdef HAS_SETLOCALE_R
129         PL_reentrant_buffer->_setlocale_size = REENTRANTSMALLSIZE;
130 #endif /* HAS_SETLOCALE_R */
131 #ifdef HAS_STRERROR_R
132         PL_reentrant_buffer->_strerror_size = REENTRANTSMALLSIZE;
133 #endif /* HAS_STRERROR_R */
134 #ifdef HAS_TTYNAME_R
135         PL_reentrant_buffer->_ttyname_size = REENTRANTSMALLSIZE;
136 #endif /* HAS_TTYNAME_R */
137
138 #endif /* USE_REENTRANT_API */
139 }
140
141 void
142 Perl_reentrant_init(pTHX) {
143         PERL_UNUSED_CONTEXT;
144 #ifdef USE_REENTRANT_API
145         Newx(PL_reentrant_buffer, 1, REENTR);
146         Perl_reentrant_size(aTHX);
147 #ifdef HAS_ASCTIME_R
148         Newx(PL_reentrant_buffer->_asctime_buffer, PL_reentrant_buffer->_asctime_size, char);
149 #endif /* HAS_ASCTIME_R */
150 #ifdef HAS_CRYPT_R
151 #if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
152         PL_reentrant_buffer->_crypt_struct_buffer = 0;
153 #endif
154 #endif /* HAS_CRYPT_R */
155 #ifdef HAS_CTIME_R
156         Newx(PL_reentrant_buffer->_ctime_buffer, PL_reentrant_buffer->_ctime_size, char);
157 #endif /* HAS_CTIME_R */
158 #ifdef HAS_GETGRNAM_R
159 #   ifdef USE_GRENT_FPTR
160         PL_reentrant_buffer->_grent_fptr = NULL;
161 #   endif
162         Newx(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         Newx(PL_reentrant_buffer->_hostent_buffer, PL_reentrant_buffer->_hostent_size, char);
167 #endif
168 #endif /* HAS_GETHOSTBYNAME_R */
169 #ifdef HAS_GETLOGIN_R
170         Newx(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         Newx(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         Newx(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         Newx(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         Newx(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         Newx(PL_reentrant_buffer->_spent_buffer, PL_reentrant_buffer->_spent_size, char);
198 #endif /* HAS_GETSPNAM_R */
199 #ifdef HAS_READDIR_R
200         PL_reentrant_buffer->_readdir_struct = (struct dirent*)safemalloc(PL_reentrant_buffer->_readdir_size);
201 #endif /* HAS_READDIR_R */
202 #ifdef HAS_READDIR64_R
203         PL_reentrant_buffer->_readdir64_struct = (struct dirent64*)safemalloc(PL_reentrant_buffer->_readdir64_size);
204 #endif /* HAS_READDIR64_R */
205 #ifdef HAS_SETLOCALE_R
206         Newx(PL_reentrant_buffer->_setlocale_buffer, PL_reentrant_buffer->_setlocale_size, char);
207 #endif /* HAS_SETLOCALE_R */
208 #ifdef HAS_STRERROR_R
209         Newx(PL_reentrant_buffer->_strerror_buffer, PL_reentrant_buffer->_strerror_size, char);
210 #endif /* HAS_STRERROR_R */
211 #ifdef HAS_TTYNAME_R
212         Newx(PL_reentrant_buffer->_ttyname_buffer, PL_reentrant_buffer->_ttyname_size, char);
213 #endif /* HAS_TTYNAME_R */
214
215 #endif /* USE_REENTRANT_API */
216 }
217
218 void
219 Perl_reentrant_free(pTHX) {
220         PERL_UNUSED_CONTEXT;
221 #ifdef USE_REENTRANT_API
222 #ifdef HAS_ASCTIME_R
223         Safefree(PL_reentrant_buffer->_asctime_buffer);
224 #endif /* HAS_ASCTIME_R */
225 #ifdef HAS_CRYPT_R
226 #if CRYPT_R_PROTO != REENTRANT_PROTO_B_CCD
227         Safefree(PL_reentrant_buffer->_crypt_struct_buffer);
228 #endif
229 #endif /* HAS_CRYPT_R */
230 #ifdef HAS_CTIME_R
231         Safefree(PL_reentrant_buffer->_ctime_buffer);
232 #endif /* HAS_CTIME_R */
233 #ifdef HAS_GETGRNAM_R
234         Safefree(PL_reentrant_buffer->_grent_buffer);
235 #endif /* HAS_GETGRNAM_R */
236 #ifdef HAS_GETHOSTBYNAME_R
237 #if   !(GETHOSTBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
238         Safefree(PL_reentrant_buffer->_hostent_buffer);
239 #endif
240 #endif /* HAS_GETHOSTBYNAME_R */
241 #ifdef HAS_GETLOGIN_R
242         Safefree(PL_reentrant_buffer->_getlogin_buffer);
243 #endif /* HAS_GETLOGIN_R */
244 #ifdef HAS_GETNETBYNAME_R
245 #if   !(GETNETBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
246         Safefree(PL_reentrant_buffer->_netent_buffer);
247 #endif
248 #endif /* HAS_GETNETBYNAME_R */
249 #ifdef HAS_GETPROTOBYNAME_R
250 #if   !(GETPROTOBYNAME_R_PROTO == REENTRANT_PROTO_I_CSD)
251         Safefree(PL_reentrant_buffer->_protoent_buffer);
252 #endif
253 #endif /* HAS_GETPROTOBYNAME_R */
254 #ifdef HAS_GETPWNAM_R
255         Safefree(PL_reentrant_buffer->_pwent_buffer);
256 #endif /* HAS_GETPWNAM_R */
257 #ifdef HAS_GETSERVBYNAME_R
258 #if   !(GETSERVBYNAME_R_PROTO == REENTRANT_PROTO_I_CCSD)
259         Safefree(PL_reentrant_buffer->_servent_buffer);
260 #endif
261 #endif /* HAS_GETSERVBYNAME_R */
262 #ifdef HAS_GETSPNAM_R
263         Safefree(PL_reentrant_buffer->_spent_buffer);
264 #endif /* HAS_GETSPNAM_R */
265 #ifdef HAS_READDIR_R
266         Safefree(PL_reentrant_buffer->_readdir_struct);
267 #endif /* HAS_READDIR_R */
268 #ifdef HAS_READDIR64_R
269         Safefree(PL_reentrant_buffer->_readdir64_struct);
270 #endif /* HAS_READDIR64_R */
271 #ifdef HAS_SETLOCALE_R
272         Safefree(PL_reentrant_buffer->_setlocale_buffer);
273 #endif /* HAS_SETLOCALE_R */
274 #ifdef HAS_STRERROR_R
275         Safefree(PL_reentrant_buffer->_strerror_buffer);
276 #endif /* HAS_STRERROR_R */
277 #ifdef HAS_TTYNAME_R
278         Safefree(PL_reentrant_buffer->_ttyname_buffer);
279 #endif /* HAS_TTYNAME_R */
280
281         Safefree(PL_reentrant_buffer);
282 #endif /* USE_REENTRANT_API */
283 }
284
285 void*
286 Perl_reentrant_retry(const char *f, ...)
287 {
288     void *retptr = NULL;
289     va_list ap;
290 #ifdef USE_REENTRANT_API
291     dTHX;
292     /* Easier to special case this here than in embed.pl. (Look at what it
293        generates for proto.h) */
294     PERL_ARGS_ASSERT_REENTRANT_RETRY;
295 #endif
296     va_start(ap, f);
297     {
298 #ifdef USE_REENTRANT_API
299 #  if defined(USE_HOSTENT_BUFFER) || defined(USE_GRENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PWENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
300     void *p0;
301 #  endif
302 #  if defined(USE_SERVENT_BUFFER)
303     void *p1;
304 #  endif
305 #  if defined(USE_HOSTENT_BUFFER)
306     size_t asize;
307 #  endif
308 #  if defined(USE_HOSTENT_BUFFER) || defined(USE_NETENT_BUFFER) || defined(USE_PROTOENT_BUFFER) || defined(USE_SERVENT_BUFFER)
309     int anint;
310 #  endif
311
312     switch (PL_op->op_type) {
313 #ifdef USE_HOSTENT_BUFFER
314     case OP_GHBYADDR:
315     case OP_GHBYNAME:
316     case OP_GHOSTENT:
317         {
318 #ifdef PERL_REENTRANT_MAXSIZE
319             if (PL_reentrant_buffer->_hostent_size <=
320                 PERL_REENTRANT_MAXSIZE / 2)
321 #endif
322             {
323                 PL_reentrant_buffer->_hostent_size *= 2;
324                 Renew(PL_reentrant_buffer->_hostent_buffer,
325                       PL_reentrant_buffer->_hostent_size, char);
326                 switch (PL_op->op_type) {
327                 case OP_GHBYADDR:
328                     p0    = va_arg(ap, void *);
329                     asize = va_arg(ap, size_t);
330                     anint  = va_arg(ap, int);
331                     retptr = gethostbyaddr(p0, asize, anint); break;
332                 case OP_GHBYNAME:
333                     p0 = va_arg(ap, void *);
334                     retptr = gethostbyname((char *)p0); break;
335                 case OP_GHOSTENT:
336                     retptr = gethostent(); break;
337                 default:
338                     SETERRNO(ERANGE, LIB_INVARG);
339                     break;
340                 }
341             }
342         }
343         break;
344 #endif
345 #ifdef USE_GRENT_BUFFER
346     case OP_GGRNAM:
347     case OP_GGRGID:
348     case OP_GGRENT:
349         {
350 #ifdef PERL_REENTRANT_MAXSIZE
351             if (PL_reentrant_buffer->_grent_size <=
352                 PERL_REENTRANT_MAXSIZE / 2)
353 #endif
354             {
355                 Gid_t gid;
356                 PL_reentrant_buffer->_grent_size *= 2;
357                 Renew(PL_reentrant_buffer->_grent_buffer,
358                       PL_reentrant_buffer->_grent_size, char);
359                 switch (PL_op->op_type) {
360                 case OP_GGRNAM:
361                     p0 = va_arg(ap, void *);
362                     retptr = getgrnam((char *)p0); break;
363                 case OP_GGRGID:
364 #if Gid_t_size < INTSIZE
365                     gid = (Gid_t)va_arg(ap, int);
366 #else
367                     gid = va_arg(ap, Gid_t);
368 #endif
369                     retptr = getgrgid(gid); break;
370                 case OP_GGRENT:
371                     retptr = getgrent(); break;
372                 default:
373                     SETERRNO(ERANGE, LIB_INVARG);
374                     break;
375                 }
376             }
377         }
378         break;
379 #endif
380 #ifdef USE_NETENT_BUFFER
381     case OP_GNBYADDR:
382     case OP_GNBYNAME:
383     case OP_GNETENT:
384         {
385 #ifdef PERL_REENTRANT_MAXSIZE
386             if (PL_reentrant_buffer->_netent_size <=
387                 PERL_REENTRANT_MAXSIZE / 2)
388 #endif
389             {
390                 Netdb_net_t net;
391                 PL_reentrant_buffer->_netent_size *= 2;
392                 Renew(PL_reentrant_buffer->_netent_buffer,
393                       PL_reentrant_buffer->_netent_size, char);
394                 switch (PL_op->op_type) {
395                 case OP_GNBYADDR:
396                     net = va_arg(ap, Netdb_net_t);
397                     anint = va_arg(ap, int);
398                     retptr = getnetbyaddr(net, anint); break;
399                 case OP_GNBYNAME:
400                     p0 = va_arg(ap, void *);
401                     retptr = getnetbyname((char *)p0); break;
402                 case OP_GNETENT:
403                     retptr = getnetent(); break;
404                 default:
405                     SETERRNO(ERANGE, LIB_INVARG);
406                     break;
407                 }
408             }
409         }
410         break;
411 #endif
412 #ifdef USE_PWENT_BUFFER
413     case OP_GPWNAM:
414     case OP_GPWUID:
415     case OP_GPWENT:
416         {
417 #ifdef PERL_REENTRANT_MAXSIZE
418             if (PL_reentrant_buffer->_pwent_size <=
419                 PERL_REENTRANT_MAXSIZE / 2)
420 #endif
421             {
422                 Uid_t uid;
423                 PL_reentrant_buffer->_pwent_size *= 2;
424                 Renew(PL_reentrant_buffer->_pwent_buffer,
425                       PL_reentrant_buffer->_pwent_size, char);
426                 switch (PL_op->op_type) {
427                 case OP_GPWNAM:
428                     p0 = va_arg(ap, void *);
429                     retptr = getpwnam((char *)p0); break;
430                 case OP_GPWUID:
431 #if Uid_t_size < INTSIZE
432                     uid = (Uid_t)va_arg(ap, int);
433 #else
434                     uid = va_arg(ap, Uid_t);
435 #endif
436                     retptr = getpwuid(uid); break;
437 #if defined(HAS_GETPWENT) || defined(HAS_GETPWENT_R)
438                 case OP_GPWENT:
439                     retptr = getpwent(); break;
440 #endif
441                 default:
442                     SETERRNO(ERANGE, LIB_INVARG);
443                     break;
444                 }
445             }
446         }
447         break;
448 #endif
449 #ifdef USE_PROTOENT_BUFFER
450     case OP_GPBYNAME:
451     case OP_GPBYNUMBER:
452     case OP_GPROTOENT:
453         {
454 #ifdef PERL_REENTRANT_MAXSIZE
455             if (PL_reentrant_buffer->_protoent_size <=
456                 PERL_REENTRANT_MAXSIZE / 2)
457 #endif
458             {
459                 PL_reentrant_buffer->_protoent_size *= 2;
460                 Renew(PL_reentrant_buffer->_protoent_buffer,
461                       PL_reentrant_buffer->_protoent_size, char);
462                 switch (PL_op->op_type) {
463                 case OP_GPBYNAME:
464                     p0 = va_arg(ap, void *);
465                     retptr = getprotobyname((char *)p0); break;
466                 case OP_GPBYNUMBER:
467                     anint = va_arg(ap, int);
468                     retptr = getprotobynumber(anint); break;
469                 case OP_GPROTOENT:
470                     retptr = getprotoent(); break;
471                 default:
472                     SETERRNO(ERANGE, LIB_INVARG);
473                     break;
474                 }
475             }
476         }
477         break;
478 #endif
479 #ifdef USE_SERVENT_BUFFER
480     case OP_GSBYNAME:
481     case OP_GSBYPORT:
482     case OP_GSERVENT:
483         {
484 #ifdef PERL_REENTRANT_MAXSIZE
485             if (PL_reentrant_buffer->_servent_size <=
486                 PERL_REENTRANT_MAXSIZE / 2)
487 #endif
488             {
489                 PL_reentrant_buffer->_servent_size *= 2;
490                 Renew(PL_reentrant_buffer->_servent_buffer,
491                       PL_reentrant_buffer->_servent_size, char);
492                 switch (PL_op->op_type) {
493                 case OP_GSBYNAME:
494                     p0 = va_arg(ap, void *);
495                     p1 = va_arg(ap, void *);
496                     retptr = getservbyname((char *)p0, (char *)p1); break;
497                 case OP_GSBYPORT:
498                     anint = va_arg(ap, int);
499                     p0 = va_arg(ap, void *);
500                     retptr = getservbyport(anint, (char *)p0); break;
501                 case OP_GSERVENT:
502                     retptr = getservent(); break;
503                 default:
504                     SETERRNO(ERANGE, LIB_INVARG);
505                     break;
506                 }
507             }
508         }
509         break;
510 #endif
511     default:
512         /* Not known how to retry, so just fail. */
513         break;
514     }
515 #else
516     PERL_UNUSED_ARG(f);
517 #endif
518     }
519     va_end(ap);
520     return retptr;
521 }
522
523 /* ex: set ro: */