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