xref: /openbsd-src/gnu/usr.bin/perl/win32/perlhost.h (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1 /* perlhost.h
2  *
3  * (c) 1999 Microsoft Corporation. All rights reserved.
4  * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/
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 
10 #define CHECK_HOST_INTERP
11 
12 #ifndef ___PerlHost_H___
13 #define ___PerlHost_H___
14 
15 #include <signal.h>
16 #include <wchar.h>
17 #include "iperlsys.h"
18 #include "vmem.h"
19 #include "vdir.h"
20 
21 #ifndef WC_NO_BEST_FIT_CHARS
22 #  define WC_NO_BEST_FIT_CHARS 0x00000400
23 #endif
24 
25 START_EXTERN_C
26 extern char *	g_getlogin(void);
27 END_EXTERN_C
28 
29 class CPerlHost
30 {
31 public:
32     /* Constructors */
33     CPerlHost(void);
34     CPerlHost(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared,
35 		 struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv,
36 		 struct IPerlStdIO** ppStdIO, struct IPerlLIO** ppLIO,
37 		 struct IPerlDir** ppDir, struct IPerlSock** ppSock,
38 		 struct IPerlProc** ppProc);
39     CPerlHost(CPerlHost& host);
40     ~CPerlHost(void);
41 
42     static CPerlHost* IPerlMem2Host(struct IPerlMem* piPerl);
43     static CPerlHost* IPerlMemShared2Host(struct IPerlMem* piPerl);
44     static CPerlHost* IPerlMemParse2Host(struct IPerlMem* piPerl);
45     static CPerlHost* IPerlEnv2Host(struct IPerlEnv* piPerl);
46     static CPerlHost* IPerlStdIO2Host(struct IPerlStdIO* piPerl);
47     static CPerlHost* IPerlLIO2Host(struct IPerlLIO* piPerl);
48     static CPerlHost* IPerlDir2Host(struct IPerlDir* piPerl);
49     static CPerlHost* IPerlSock2Host(struct IPerlSock* piPerl);
50     static CPerlHost* IPerlProc2Host(struct IPerlProc* piPerl);
51 
52     BOOL PerlCreate(void);
53     int PerlParse(int argc, char** argv, char** env);
54     int PerlRun(void);
55     void PerlDestroy(void);
56 
57 /* IPerlMem */
58     /* Locks provided but should be unnecessary as this is private pool */
59     inline void* Malloc(size_t size) { return m_pVMem->Malloc(size); };
60     inline void* Realloc(void* ptr, size_t size) { return m_pVMem->Realloc(ptr, size); };
61     inline void Free(void* ptr) { m_pVMem->Free(ptr); };
62     inline void* Calloc(size_t num, size_t size)
63     {
64 	size_t count = num*size;
65 	void* lpVoid = Malloc(count);
66 	if (lpVoid)
67 	    ZeroMemory(lpVoid, count);
68 	return lpVoid;
69     };
70     inline void GetLock(void) { m_pVMem->GetLock(); };
71     inline void FreeLock(void) { m_pVMem->FreeLock(); };
72     inline int IsLocked(void) { return m_pVMem->IsLocked(); };
73 
74 /* IPerlMemShared */
75     /* Locks used to serialize access to the pool */
76     inline void GetLockShared(void) { m_pVMemShared->GetLock(); };
77     inline void FreeLockShared(void) { m_pVMemShared->FreeLock(); };
78     inline int IsLockedShared(void) { return m_pVMemShared->IsLocked(); };
79     inline void* MallocShared(size_t size)
80     {
81 	void *result;
82 	GetLockShared();
83 	result = m_pVMemShared->Malloc(size);
84 	FreeLockShared();
85 	return result;
86     };
87     inline void* ReallocShared(void* ptr, size_t size)
88     {
89 	void *result;
90 	GetLockShared();
91 	result = m_pVMemShared->Realloc(ptr, size);
92 	FreeLockShared();
93 	return result;
94     };
95     inline void FreeShared(void* ptr)
96     {
97 	GetLockShared();
98 	m_pVMemShared->Free(ptr);
99 	FreeLockShared();
100     };
101     inline void* CallocShared(size_t num, size_t size)
102     {
103 	size_t count = num*size;
104 	void* lpVoid = MallocShared(count);
105 	if (lpVoid)
106 	    ZeroMemory(lpVoid, count);
107 	return lpVoid;
108     };
109 
110 /* IPerlMemParse */
111     /* Assume something else is using locks to mangaging serialize
112        on a batch basis
113      */
114     inline void GetLockParse(void) { m_pVMemParse->GetLock(); };
115     inline void FreeLockParse(void) { m_pVMemParse->FreeLock(); };
116     inline int IsLockedParse(void) { return m_pVMemParse->IsLocked(); };
117     inline void* MallocParse(size_t size) { return m_pVMemParse->Malloc(size); };
118     inline void* ReallocParse(void* ptr, size_t size) { return m_pVMemParse->Realloc(ptr, size); };
119     inline void FreeParse(void* ptr) { m_pVMemParse->Free(ptr); };
120     inline void* CallocParse(size_t num, size_t size)
121     {
122 	size_t count = num*size;
123 	void* lpVoid = MallocParse(count);
124 	if (lpVoid)
125 	    ZeroMemory(lpVoid, count);
126 	return lpVoid;
127     };
128 
129 /* IPerlEnv */
130     char *Getenv(const char *varname);
131     int Putenv(const char *envstring);
132     inline char *Getenv(const char *varname, unsigned long *len)
133     {
134 	*len = 0;
135 	char *e = Getenv(varname);
136 	if (e)
137 	    *len = strlen(e);
138 	return e;
139     }
140     void* CreateChildEnv(void) { return CreateLocalEnvironmentStrings(*m_pvDir); };
141     void FreeChildEnv(void* pStr) { FreeLocalEnvironmentStrings((char*)pStr); };
142     char* GetChildDir(void);
143     void FreeChildDir(char* pStr);
144     void Reset(void);
145     void Clearenv(void);
146 
147     inline LPSTR GetIndex(DWORD &dwIndex)
148     {
149 	if(dwIndex < m_dwEnvCount)
150 	{
151 	    ++dwIndex;
152 	    return m_lppEnvList[dwIndex-1];
153 	}
154 	return NULL;
155     };
156 
157 protected:
158     LPSTR Find(LPCSTR lpStr);
159     void Add(LPCSTR lpStr);
160 
161     LPSTR CreateLocalEnvironmentStrings(VDir &vDir);
162     void FreeLocalEnvironmentStrings(LPSTR lpStr);
163     LPSTR* Lookup(LPCSTR lpStr);
164     DWORD CalculateEnvironmentSpace(void);
165 
166 public:
167 
168 /* IPerlDIR */
169     virtual int Chdir(const char *dirname);
170 
171 /* IPerllProc */
172     void Abort(void);
173     void Exit(int status);
174     void _Exit(int status);
175     int Execl(const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3);
176     int Execv(const char *cmdname, const char *const *argv);
177     int Execvp(const char *cmdname, const char *const *argv);
178 
179     inline VMem* GetMemShared(void) { m_pVMemShared->AddRef(); return m_pVMemShared; };
180     inline VMem* GetMemParse(void) { m_pVMemParse->AddRef(); return m_pVMemParse; };
181     inline VDir* GetDir(void) { return m_pvDir; };
182 
183 public:
184 
185     struct IPerlMem	    m_hostperlMem;
186     struct IPerlMem	    m_hostperlMemShared;
187     struct IPerlMem	    m_hostperlMemParse;
188     struct IPerlEnv	    m_hostperlEnv;
189     struct IPerlStdIO	    m_hostperlStdIO;
190     struct IPerlLIO	    m_hostperlLIO;
191     struct IPerlDir	    m_hostperlDir;
192     struct IPerlSock	    m_hostperlSock;
193     struct IPerlProc	    m_hostperlProc;
194 
195     struct IPerlMem*	    m_pHostperlMem;
196     struct IPerlMem*	    m_pHostperlMemShared;
197     struct IPerlMem*	    m_pHostperlMemParse;
198     struct IPerlEnv*	    m_pHostperlEnv;
199     struct IPerlStdIO*	    m_pHostperlStdIO;
200     struct IPerlLIO*	    m_pHostperlLIO;
201     struct IPerlDir*	    m_pHostperlDir;
202     struct IPerlSock*	    m_pHostperlSock;
203     struct IPerlProc*	    m_pHostperlProc;
204 
205     inline char* MapPathA(const char *pInName) { return m_pvDir->MapPathA(pInName); };
206     inline WCHAR* MapPathW(const WCHAR *pInName) { return m_pvDir->MapPathW(pInName); };
207 protected:
208 
209     VDir*   m_pvDir;
210     VMem*   m_pVMem;
211     VMem*   m_pVMemShared;
212     VMem*   m_pVMemParse;
213 
214     DWORD   m_dwEnvCount;
215     LPSTR*  m_lppEnvList;
216     BOOL    m_bTopLevel;	// is this a toplevel host?
217     static long num_hosts;
218 public:
219     inline  int LastHost(void) { return num_hosts == 1L; };
220     struct interpreter *host_perl;
221 };
222 
223 long CPerlHost::num_hosts = 0L;
224 
225 extern "C" void win32_checkTLS(struct interpreter *host_perl);
226 
227 #define STRUCT2RAWPTR(x, y) (CPerlHost*)(((LPBYTE)x)-offsetof(CPerlHost, y))
228 #ifdef CHECK_HOST_INTERP
229 inline CPerlHost* CheckInterp(CPerlHost *host)
230 {
231  win32_checkTLS(host->host_perl);
232  return host;
233 }
234 #define STRUCT2PTR(x, y) CheckInterp(STRUCT2RAWPTR(x, y))
235 #else
236 #define STRUCT2PTR(x, y) STRUCT2RAWPTR(x, y)
237 #endif
238 
239 inline CPerlHost* IPerlMem2Host(struct IPerlMem* piPerl)
240 {
241     return STRUCT2RAWPTR(piPerl, m_hostperlMem);
242 }
243 
244 inline CPerlHost* IPerlMemShared2Host(struct IPerlMem* piPerl)
245 {
246     return STRUCT2RAWPTR(piPerl, m_hostperlMemShared);
247 }
248 
249 inline CPerlHost* IPerlMemParse2Host(struct IPerlMem* piPerl)
250 {
251     return STRUCT2RAWPTR(piPerl, m_hostperlMemParse);
252 }
253 
254 inline CPerlHost* IPerlEnv2Host(struct IPerlEnv* piPerl)
255 {
256     return STRUCT2PTR(piPerl, m_hostperlEnv);
257 }
258 
259 inline CPerlHost* IPerlStdIO2Host(struct IPerlStdIO* piPerl)
260 {
261     return STRUCT2PTR(piPerl, m_hostperlStdIO);
262 }
263 
264 inline CPerlHost* IPerlLIO2Host(struct IPerlLIO* piPerl)
265 {
266     return STRUCT2PTR(piPerl, m_hostperlLIO);
267 }
268 
269 inline CPerlHost* IPerlDir2Host(struct IPerlDir* piPerl)
270 {
271     return STRUCT2PTR(piPerl, m_hostperlDir);
272 }
273 
274 inline CPerlHost* IPerlSock2Host(struct IPerlSock* piPerl)
275 {
276     return STRUCT2PTR(piPerl, m_hostperlSock);
277 }
278 
279 inline CPerlHost* IPerlProc2Host(struct IPerlProc* piPerl)
280 {
281     return STRUCT2PTR(piPerl, m_hostperlProc);
282 }
283 
284 
285 
286 #undef IPERL2HOST
287 #define IPERL2HOST(x) IPerlMem2Host(x)
288 
289 /* IPerlMem */
290 void*
291 PerlMemMalloc(struct IPerlMem* piPerl, size_t size)
292 {
293     return IPERL2HOST(piPerl)->Malloc(size);
294 }
295 void*
296 PerlMemRealloc(struct IPerlMem* piPerl, void* ptr, size_t size)
297 {
298     return IPERL2HOST(piPerl)->Realloc(ptr, size);
299 }
300 void
301 PerlMemFree(struct IPerlMem* piPerl, void* ptr)
302 {
303     IPERL2HOST(piPerl)->Free(ptr);
304 }
305 void*
306 PerlMemCalloc(struct IPerlMem* piPerl, size_t num, size_t size)
307 {
308     return IPERL2HOST(piPerl)->Calloc(num, size);
309 }
310 
311 void
312 PerlMemGetLock(struct IPerlMem* piPerl)
313 {
314     IPERL2HOST(piPerl)->GetLock();
315 }
316 
317 void
318 PerlMemFreeLock(struct IPerlMem* piPerl)
319 {
320     IPERL2HOST(piPerl)->FreeLock();
321 }
322 
323 int
324 PerlMemIsLocked(struct IPerlMem* piPerl)
325 {
326     return IPERL2HOST(piPerl)->IsLocked();
327 }
328 
329 const struct IPerlMem perlMem =
330 {
331     PerlMemMalloc,
332     PerlMemRealloc,
333     PerlMemFree,
334     PerlMemCalloc,
335     PerlMemGetLock,
336     PerlMemFreeLock,
337     PerlMemIsLocked,
338 };
339 
340 #undef IPERL2HOST
341 #define IPERL2HOST(x) IPerlMemShared2Host(x)
342 
343 /* IPerlMemShared */
344 void*
345 PerlMemSharedMalloc(struct IPerlMem* piPerl, size_t size)
346 {
347     return IPERL2HOST(piPerl)->MallocShared(size);
348 }
349 void*
350 PerlMemSharedRealloc(struct IPerlMem* piPerl, void* ptr, size_t size)
351 {
352     return IPERL2HOST(piPerl)->ReallocShared(ptr, size);
353 }
354 void
355 PerlMemSharedFree(struct IPerlMem* piPerl, void* ptr)
356 {
357     IPERL2HOST(piPerl)->FreeShared(ptr);
358 }
359 void*
360 PerlMemSharedCalloc(struct IPerlMem* piPerl, size_t num, size_t size)
361 {
362     return IPERL2HOST(piPerl)->CallocShared(num, size);
363 }
364 
365 void
366 PerlMemSharedGetLock(struct IPerlMem* piPerl)
367 {
368     IPERL2HOST(piPerl)->GetLockShared();
369 }
370 
371 void
372 PerlMemSharedFreeLock(struct IPerlMem* piPerl)
373 {
374     IPERL2HOST(piPerl)->FreeLockShared();
375 }
376 
377 int
378 PerlMemSharedIsLocked(struct IPerlMem* piPerl)
379 {
380     return IPERL2HOST(piPerl)->IsLockedShared();
381 }
382 
383 const struct IPerlMem perlMemShared =
384 {
385     PerlMemSharedMalloc,
386     PerlMemSharedRealloc,
387     PerlMemSharedFree,
388     PerlMemSharedCalloc,
389     PerlMemSharedGetLock,
390     PerlMemSharedFreeLock,
391     PerlMemSharedIsLocked,
392 };
393 
394 #undef IPERL2HOST
395 #define IPERL2HOST(x) IPerlMemParse2Host(x)
396 
397 /* IPerlMemParse */
398 void*
399 PerlMemParseMalloc(struct IPerlMem* piPerl, size_t size)
400 {
401     return IPERL2HOST(piPerl)->MallocParse(size);
402 }
403 void*
404 PerlMemParseRealloc(struct IPerlMem* piPerl, void* ptr, size_t size)
405 {
406     return IPERL2HOST(piPerl)->ReallocParse(ptr, size);
407 }
408 void
409 PerlMemParseFree(struct IPerlMem* piPerl, void* ptr)
410 {
411     IPERL2HOST(piPerl)->FreeParse(ptr);
412 }
413 void*
414 PerlMemParseCalloc(struct IPerlMem* piPerl, size_t num, size_t size)
415 {
416     return IPERL2HOST(piPerl)->CallocParse(num, size);
417 }
418 
419 void
420 PerlMemParseGetLock(struct IPerlMem* piPerl)
421 {
422     IPERL2HOST(piPerl)->GetLockParse();
423 }
424 
425 void
426 PerlMemParseFreeLock(struct IPerlMem* piPerl)
427 {
428     IPERL2HOST(piPerl)->FreeLockParse();
429 }
430 
431 int
432 PerlMemParseIsLocked(struct IPerlMem* piPerl)
433 {
434     return IPERL2HOST(piPerl)->IsLockedParse();
435 }
436 
437 const struct IPerlMem perlMemParse =
438 {
439     PerlMemParseMalloc,
440     PerlMemParseRealloc,
441     PerlMemParseFree,
442     PerlMemParseCalloc,
443     PerlMemParseGetLock,
444     PerlMemParseFreeLock,
445     PerlMemParseIsLocked,
446 };
447 
448 
449 #undef IPERL2HOST
450 #define IPERL2HOST(x) IPerlEnv2Host(x)
451 
452 /* IPerlEnv */
453 char*
454 PerlEnvGetenv(struct IPerlEnv* piPerl, const char *varname)
455 {
456     return IPERL2HOST(piPerl)->Getenv(varname);
457 };
458 
459 int
460 PerlEnvPutenv(struct IPerlEnv* piPerl, const char *envstring)
461 {
462     return IPERL2HOST(piPerl)->Putenv(envstring);
463 };
464 
465 char*
466 PerlEnvGetenv_len(struct IPerlEnv* piPerl, const char* varname, unsigned long* len)
467 {
468     return IPERL2HOST(piPerl)->Getenv(varname, len);
469 }
470 
471 int
472 PerlEnvUname(struct IPerlEnv* piPerl, struct utsname *name)
473 {
474     return win32_uname(name);
475 }
476 
477 void
478 PerlEnvClearenv(struct IPerlEnv* piPerl)
479 {
480     IPERL2HOST(piPerl)->Clearenv();
481 }
482 
483 void*
484 PerlEnvGetChildenv(struct IPerlEnv* piPerl)
485 {
486     return IPERL2HOST(piPerl)->CreateChildEnv();
487 }
488 
489 void
490 PerlEnvFreeChildenv(struct IPerlEnv* piPerl, void* childEnv)
491 {
492     IPERL2HOST(piPerl)->FreeChildEnv(childEnv);
493 }
494 
495 char*
496 PerlEnvGetChilddir(struct IPerlEnv* piPerl)
497 {
498     return IPERL2HOST(piPerl)->GetChildDir();
499 }
500 
501 void
502 PerlEnvFreeChilddir(struct IPerlEnv* piPerl, char* childDir)
503 {
504     IPERL2HOST(piPerl)->FreeChildDir(childDir);
505 }
506 
507 unsigned long
508 PerlEnvOsId(struct IPerlEnv* piPerl)
509 {
510     return win32_os_id();
511 }
512 
513 char*
514 PerlEnvLibPath(struct IPerlEnv* piPerl, WIN32_NO_REGISTRY_M_(const char *pl) STRLEN *const len)
515 {
516     return win32_get_privlib(WIN32_NO_REGISTRY_M_(pl) len);
517 }
518 
519 char*
520 PerlEnvSiteLibPath(struct IPerlEnv* piPerl, const char *pl, STRLEN *const len)
521 {
522     return win32_get_sitelib(pl, len);
523 }
524 
525 char*
526 PerlEnvVendorLibPath(struct IPerlEnv* piPerl, const char *pl,
527 		     STRLEN *const len)
528 {
529     return win32_get_vendorlib(pl, len);
530 }
531 
532 void
533 PerlEnvGetChildIO(struct IPerlEnv* piPerl, child_IO_table* ptr)
534 {
535     win32_get_child_IO(ptr);
536 }
537 
538 const struct IPerlEnv perlEnv =
539 {
540     PerlEnvGetenv,
541     PerlEnvPutenv,
542     PerlEnvGetenv_len,
543     PerlEnvUname,
544     PerlEnvClearenv,
545     PerlEnvGetChildenv,
546     PerlEnvFreeChildenv,
547     PerlEnvGetChilddir,
548     PerlEnvFreeChilddir,
549     PerlEnvOsId,
550     PerlEnvLibPath,
551     PerlEnvSiteLibPath,
552     PerlEnvVendorLibPath,
553     PerlEnvGetChildIO,
554 };
555 
556 #undef IPERL2HOST
557 #define IPERL2HOST(x) IPerlStdIO2Host(x)
558 
559 /* PerlStdIO */
560 FILE*
561 PerlStdIOStdin(struct IPerlStdIO* piPerl)
562 {
563     return win32_stdin();
564 }
565 
566 FILE*
567 PerlStdIOStdout(struct IPerlStdIO* piPerl)
568 {
569     return win32_stdout();
570 }
571 
572 FILE*
573 PerlStdIOStderr(struct IPerlStdIO* piPerl)
574 {
575     return win32_stderr();
576 }
577 
578 FILE*
579 PerlStdIOOpen(struct IPerlStdIO* piPerl, const char *path, const char *mode)
580 {
581     return win32_fopen(path, mode);
582 }
583 
584 int
585 PerlStdIOClose(struct IPerlStdIO* piPerl, FILE* pf)
586 {
587     return win32_fclose((pf));
588 }
589 
590 int
591 PerlStdIOEof(struct IPerlStdIO* piPerl, FILE* pf)
592 {
593     return win32_feof(pf);
594 }
595 
596 int
597 PerlStdIOError(struct IPerlStdIO* piPerl, FILE* pf)
598 {
599     return win32_ferror(pf);
600 }
601 
602 void
603 PerlStdIOClearerr(struct IPerlStdIO* piPerl, FILE* pf)
604 {
605     win32_clearerr(pf);
606 }
607 
608 int
609 PerlStdIOGetc(struct IPerlStdIO* piPerl, FILE* pf)
610 {
611     return win32_getc(pf);
612 }
613 
614 STDCHAR*
615 PerlStdIOGetBase(struct IPerlStdIO* piPerl, FILE* pf)
616 {
617 #ifdef FILE_base
618     FILE *f = pf;
619     return FILE_base(f);
620 #else
621     return NULL;
622 #endif
623 }
624 
625 int
626 PerlStdIOGetBufsiz(struct IPerlStdIO* piPerl, FILE* pf)
627 {
628 #ifdef FILE_bufsiz
629     FILE *f = pf;
630     return FILE_bufsiz(f);
631 #else
632     return (-1);
633 #endif
634 }
635 
636 int
637 PerlStdIOGetCnt(struct IPerlStdIO* piPerl, FILE* pf)
638 {
639 #ifdef USE_STDIO_PTR
640     FILE *f = pf;
641     return FILE_cnt(f);
642 #else
643     return (-1);
644 #endif
645 }
646 
647 STDCHAR*
648 PerlStdIOGetPtr(struct IPerlStdIO* piPerl, FILE* pf)
649 {
650 #ifdef USE_STDIO_PTR
651     FILE *f = pf;
652     return FILE_ptr(f);
653 #else
654     return NULL;
655 #endif
656 }
657 
658 char*
659 PerlStdIOGets(struct IPerlStdIO* piPerl, char* s, int n, FILE* pf)
660 {
661     return win32_fgets(s, n, pf);
662 }
663 
664 int
665 PerlStdIOPutc(struct IPerlStdIO* piPerl, int c, FILE* pf)
666 {
667     return win32_fputc(c, pf);
668 }
669 
670 int
671 PerlStdIOPuts(struct IPerlStdIO* piPerl, const char *s, FILE* pf)
672 {
673     return win32_fputs(s, pf);
674 }
675 
676 int
677 PerlStdIOFlush(struct IPerlStdIO* piPerl, FILE* pf)
678 {
679     return win32_fflush(pf);
680 }
681 
682 int
683 PerlStdIOUngetc(struct IPerlStdIO* piPerl,int c, FILE* pf)
684 {
685     return win32_ungetc(c, pf);
686 }
687 
688 int
689 PerlStdIOFileno(struct IPerlStdIO* piPerl, FILE* pf)
690 {
691     return win32_fileno(pf);
692 }
693 
694 FILE*
695 PerlStdIOFdopen(struct IPerlStdIO* piPerl, int fd, const char *mode)
696 {
697     return win32_fdopen(fd, mode);
698 }
699 
700 FILE*
701 PerlStdIOReopen(struct IPerlStdIO* piPerl, const char*path, const char*mode, FILE* pf)
702 {
703     return win32_freopen(path, mode, (FILE*)pf);
704 }
705 
706 SSize_t
707 PerlStdIORead(struct IPerlStdIO* piPerl, void *buffer, Size_t size, Size_t count, FILE* pf)
708 {
709     return win32_fread(buffer, size, count, pf);
710 }
711 
712 SSize_t
713 PerlStdIOWrite(struct IPerlStdIO* piPerl, const void *buffer, Size_t size, Size_t count, FILE* pf)
714 {
715     return win32_fwrite(buffer, size, count, pf);
716 }
717 
718 void
719 PerlStdIOSetBuf(struct IPerlStdIO* piPerl, FILE* pf, char* buffer)
720 {
721     win32_setbuf(pf, buffer);
722 }
723 
724 int
725 PerlStdIOSetVBuf(struct IPerlStdIO* piPerl, FILE* pf, char* buffer, int type, Size_t size)
726 {
727     return win32_setvbuf(pf, buffer, type, size);
728 }
729 
730 void
731 PerlStdIOSetCnt(struct IPerlStdIO* piPerl, FILE* pf, int n)
732 {
733 #ifdef STDIO_CNT_LVALUE
734     FILE *f = pf;
735     FILE_cnt(f) = n;
736 #endif
737 }
738 
739 void
740 PerlStdIOSetPtr(struct IPerlStdIO* piPerl, FILE* pf, STDCHAR * ptr)
741 {
742 #ifdef STDIO_PTR_LVALUE
743     FILE *f = pf;
744     FILE_ptr(f) = ptr;
745 #endif
746 }
747 
748 void
749 PerlStdIOSetlinebuf(struct IPerlStdIO* piPerl, FILE* pf)
750 {
751     win32_setvbuf(pf, NULL, _IOLBF, 0);
752 }
753 
754 int
755 PerlStdIOPrintf(struct IPerlStdIO* piPerl, FILE* pf, const char *format,...)
756 {
757     va_list(arglist);
758     va_start(arglist, format);
759     return win32_vfprintf(pf, format, arglist);
760 }
761 
762 int
763 PerlStdIOVprintf(struct IPerlStdIO* piPerl, FILE* pf, const char *format, va_list arglist)
764 {
765     return win32_vfprintf(pf, format, arglist);
766 }
767 
768 Off_t
769 PerlStdIOTell(struct IPerlStdIO* piPerl, FILE* pf)
770 {
771     return win32_ftell(pf);
772 }
773 
774 int
775 PerlStdIOSeek(struct IPerlStdIO* piPerl, FILE* pf, Off_t offset, int origin)
776 {
777     return win32_fseek(pf, offset, origin);
778 }
779 
780 void
781 PerlStdIORewind(struct IPerlStdIO* piPerl, FILE* pf)
782 {
783     win32_rewind(pf);
784 }
785 
786 FILE*
787 PerlStdIOTmpfile(struct IPerlStdIO* piPerl)
788 {
789     return win32_tmpfile();
790 }
791 
792 int
793 PerlStdIOGetpos(struct IPerlStdIO* piPerl, FILE* pf, Fpos_t *p)
794 {
795     return win32_fgetpos(pf, p);
796 }
797 
798 int
799 PerlStdIOSetpos(struct IPerlStdIO* piPerl, FILE* pf, const Fpos_t *p)
800 {
801     return win32_fsetpos(pf, p);
802 }
803 void
804 PerlStdIOInit(struct IPerlStdIO* piPerl)
805 {
806 }
807 
808 void
809 PerlStdIOInitOSExtras(struct IPerlStdIO* piPerl)
810 {
811     Perl_init_os_extras();
812 }
813 
814 int
815 PerlStdIOOpenOSfhandle(struct IPerlStdIO* piPerl, intptr_t osfhandle, int flags)
816 {
817     return win32_open_osfhandle(osfhandle, flags);
818 }
819 
820 intptr_t
821 PerlStdIOGetOSfhandle(struct IPerlStdIO* piPerl, int filenum)
822 {
823     return win32_get_osfhandle(filenum);
824 }
825 
826 FILE*
827 PerlStdIOFdupopen(struct IPerlStdIO* piPerl, FILE* pf)
828 {
829     FILE* pfdup;
830     fpos_t pos;
831     char mode[3];
832     int fileno = win32_dup(win32_fileno(pf));
833 
834     /* open the file in the same mode */
835     if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RD) {
836 	mode[0] = 'r';
837 	mode[1] = 0;
838     }
839     else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_WR) {
840 	mode[0] = 'a';
841 	mode[1] = 0;
842     }
843     else if (PERLIO_FILE_flag(pf) & PERLIO_FILE_flag_RW) {
844 	mode[0] = 'r';
845 	mode[1] = '+';
846 	mode[2] = 0;
847     }
848 
849     /* it appears that the binmode is attached to the
850      * file descriptor so binmode files will be handled
851      * correctly
852      */
853     pfdup = win32_fdopen(fileno, mode);
854 
855     /* move the file pointer to the same position */
856     if (!fgetpos(pf, &pos)) {
857 	fsetpos(pfdup, &pos);
858     }
859     return pfdup;
860 }
861 
862 const struct IPerlStdIO perlStdIO =
863 {
864     PerlStdIOStdin,
865     PerlStdIOStdout,
866     PerlStdIOStderr,
867     PerlStdIOOpen,
868     PerlStdIOClose,
869     PerlStdIOEof,
870     PerlStdIOError,
871     PerlStdIOClearerr,
872     PerlStdIOGetc,
873     PerlStdIOGetBase,
874     PerlStdIOGetBufsiz,
875     PerlStdIOGetCnt,
876     PerlStdIOGetPtr,
877     PerlStdIOGets,
878     PerlStdIOPutc,
879     PerlStdIOPuts,
880     PerlStdIOFlush,
881     PerlStdIOUngetc,
882     PerlStdIOFileno,
883     PerlStdIOFdopen,
884     PerlStdIOReopen,
885     PerlStdIORead,
886     PerlStdIOWrite,
887     PerlStdIOSetBuf,
888     PerlStdIOSetVBuf,
889     PerlStdIOSetCnt,
890     PerlStdIOSetPtr,
891     PerlStdIOSetlinebuf,
892     PerlStdIOPrintf,
893     PerlStdIOVprintf,
894     PerlStdIOTell,
895     PerlStdIOSeek,
896     PerlStdIORewind,
897     PerlStdIOTmpfile,
898     PerlStdIOGetpos,
899     PerlStdIOSetpos,
900     PerlStdIOInit,
901     PerlStdIOInitOSExtras,
902     PerlStdIOFdupopen,
903 };
904 
905 
906 #undef IPERL2HOST
907 #define IPERL2HOST(x) IPerlLIO2Host(x)
908 
909 /* IPerlLIO */
910 int
911 PerlLIOAccess(struct IPerlLIO* piPerl, const char *path, int mode)
912 {
913     return win32_access(path, mode);
914 }
915 
916 int
917 PerlLIOChmod(struct IPerlLIO* piPerl, const char *filename, int pmode)
918 {
919     return win32_chmod(filename, pmode);
920 }
921 
922 int
923 PerlLIOChown(struct IPerlLIO* piPerl, const char *filename, uid_t owner, gid_t group)
924 {
925     return chown(filename, owner, group);
926 }
927 
928 int
929 PerlLIOChsize(struct IPerlLIO* piPerl, int handle, Off_t size)
930 {
931     return win32_chsize(handle, size);
932 }
933 
934 int
935 PerlLIOClose(struct IPerlLIO* piPerl, int handle)
936 {
937     return win32_close(handle);
938 }
939 
940 int
941 PerlLIODup(struct IPerlLIO* piPerl, int handle)
942 {
943     return win32_dup(handle);
944 }
945 
946 int
947 PerlLIODup2(struct IPerlLIO* piPerl, int handle1, int handle2)
948 {
949     return win32_dup2(handle1, handle2);
950 }
951 
952 int
953 PerlLIOFlock(struct IPerlLIO* piPerl, int fd, int oper)
954 {
955     return win32_flock(fd, oper);
956 }
957 
958 int
959 PerlLIOFileStat(struct IPerlLIO* piPerl, int handle, Stat_t *buffer)
960 {
961     return win32_fstat(handle, buffer);
962 }
963 
964 int
965 PerlLIOIOCtl(struct IPerlLIO* piPerl, int i, unsigned int u, char *data)
966 {
967     u_long u_long_arg;
968     int retval;
969 
970     /* mauke says using memcpy avoids alignment issues */
971     memcpy(&u_long_arg, data, sizeof u_long_arg);
972     retval = win32_ioctlsocket((SOCKET)i, (long)u, &u_long_arg);
973     memcpy(data, &u_long_arg, sizeof u_long_arg);
974     return retval;
975 }
976 
977 int
978 PerlLIOIsatty(struct IPerlLIO* piPerl, int fd)
979 {
980     return win32_isatty(fd);
981 }
982 
983 int
984 PerlLIOLink(struct IPerlLIO* piPerl, const char*oldname, const char *newname)
985 {
986     return win32_link(oldname, newname);
987 }
988 
989 Off_t
990 PerlLIOLseek(struct IPerlLIO* piPerl, int handle, Off_t offset, int origin)
991 {
992     return win32_lseek(handle, offset, origin);
993 }
994 
995 int
996 PerlLIOLstat(struct IPerlLIO* piPerl, const char *path, Stat_t *buffer)
997 {
998     return win32_stat(path, buffer);
999 }
1000 
1001 char*
1002 PerlLIOMktemp(struct IPerlLIO* piPerl, char *Template)
1003 {
1004     return mktemp(Template);
1005 }
1006 
1007 int
1008 PerlLIOOpen(struct IPerlLIO* piPerl, const char *filename, int oflag)
1009 {
1010     return win32_open(filename, oflag);
1011 }
1012 
1013 int
1014 PerlLIOOpen3(struct IPerlLIO* piPerl, const char *filename, int oflag, int pmode)
1015 {
1016     return win32_open(filename, oflag, pmode);
1017 }
1018 
1019 int
1020 PerlLIORead(struct IPerlLIO* piPerl, int handle, void *buffer, unsigned int count)
1021 {
1022     return win32_read(handle, buffer, count);
1023 }
1024 
1025 int
1026 PerlLIORename(struct IPerlLIO* piPerl, const char *OldFileName, const char *newname)
1027 {
1028     return win32_rename(OldFileName, newname);
1029 }
1030 
1031 int
1032 PerlLIOSetmode(struct IPerlLIO* piPerl, int handle, int mode)
1033 {
1034     return win32_setmode(handle, mode);
1035 }
1036 
1037 int
1038 PerlLIONameStat(struct IPerlLIO* piPerl, const char *path, Stat_t *buffer)
1039 {
1040     return win32_stat(path, buffer);
1041 }
1042 
1043 char*
1044 PerlLIOTmpnam(struct IPerlLIO* piPerl, char *string)
1045 {
1046     return tmpnam(string);
1047 }
1048 
1049 int
1050 PerlLIOUmask(struct IPerlLIO* piPerl, int pmode)
1051 {
1052     return umask(pmode);
1053 }
1054 
1055 int
1056 PerlLIOUnlink(struct IPerlLIO* piPerl, const char *filename)
1057 {
1058     return win32_unlink(filename);
1059 }
1060 
1061 int
1062 PerlLIOUtime(struct IPerlLIO* piPerl, const char *filename, struct utimbuf *times)
1063 {
1064     return win32_utime(filename, times);
1065 }
1066 
1067 int
1068 PerlLIOWrite(struct IPerlLIO* piPerl, int handle, const void *buffer, unsigned int count)
1069 {
1070     return win32_write(handle, buffer, count);
1071 }
1072 
1073 const struct IPerlLIO perlLIO =
1074 {
1075     PerlLIOAccess,
1076     PerlLIOChmod,
1077     PerlLIOChown,
1078     PerlLIOChsize,
1079     PerlLIOClose,
1080     PerlLIODup,
1081     PerlLIODup2,
1082     PerlLIOFlock,
1083     PerlLIOFileStat,
1084     PerlLIOIOCtl,
1085     PerlLIOIsatty,
1086     PerlLIOLink,
1087     PerlLIOLseek,
1088     PerlLIOLstat,
1089     PerlLIOMktemp,
1090     PerlLIOOpen,
1091     PerlLIOOpen3,
1092     PerlLIORead,
1093     PerlLIORename,
1094     PerlLIOSetmode,
1095     PerlLIONameStat,
1096     PerlLIOTmpnam,
1097     PerlLIOUmask,
1098     PerlLIOUnlink,
1099     PerlLIOUtime,
1100     PerlLIOWrite,
1101 };
1102 
1103 
1104 #undef IPERL2HOST
1105 #define IPERL2HOST(x) IPerlDir2Host(x)
1106 
1107 /* IPerlDIR */
1108 int
1109 PerlDirMakedir(struct IPerlDir* piPerl, const char *dirname, int mode)
1110 {
1111     return win32_mkdir(dirname, mode);
1112 }
1113 
1114 int
1115 PerlDirChdir(struct IPerlDir* piPerl, const char *dirname)
1116 {
1117     return IPERL2HOST(piPerl)->Chdir(dirname);
1118 }
1119 
1120 int
1121 PerlDirRmdir(struct IPerlDir* piPerl, const char *dirname)
1122 {
1123     return win32_rmdir(dirname);
1124 }
1125 
1126 int
1127 PerlDirClose(struct IPerlDir* piPerl, DIR *dirp)
1128 {
1129     return win32_closedir(dirp);
1130 }
1131 
1132 DIR*
1133 PerlDirOpen(struct IPerlDir* piPerl, const char *filename)
1134 {
1135     return win32_opendir(filename);
1136 }
1137 
1138 struct direct *
1139 PerlDirRead(struct IPerlDir* piPerl, DIR *dirp)
1140 {
1141     return win32_readdir(dirp);
1142 }
1143 
1144 void
1145 PerlDirRewind(struct IPerlDir* piPerl, DIR *dirp)
1146 {
1147     win32_rewinddir(dirp);
1148 }
1149 
1150 void
1151 PerlDirSeek(struct IPerlDir* piPerl, DIR *dirp, long loc)
1152 {
1153     win32_seekdir(dirp, loc);
1154 }
1155 
1156 long
1157 PerlDirTell(struct IPerlDir* piPerl, DIR *dirp)
1158 {
1159     return win32_telldir(dirp);
1160 }
1161 
1162 char*
1163 PerlDirMapPathA(struct IPerlDir* piPerl, const char* path)
1164 {
1165     return IPERL2HOST(piPerl)->MapPathA(path);
1166 }
1167 
1168 WCHAR*
1169 PerlDirMapPathW(struct IPerlDir* piPerl, const WCHAR* path)
1170 {
1171     return IPERL2HOST(piPerl)->MapPathW(path);
1172 }
1173 
1174 const struct IPerlDir perlDir =
1175 {
1176     PerlDirMakedir,
1177     PerlDirChdir,
1178     PerlDirRmdir,
1179     PerlDirClose,
1180     PerlDirOpen,
1181     PerlDirRead,
1182     PerlDirRewind,
1183     PerlDirSeek,
1184     PerlDirTell,
1185     PerlDirMapPathA,
1186     PerlDirMapPathW,
1187 };
1188 
1189 
1190 /* IPerlSock */
1191 u_long
1192 PerlSockHtonl(struct IPerlSock* piPerl, u_long hostlong)
1193 {
1194     return win32_htonl(hostlong);
1195 }
1196 
1197 u_short
1198 PerlSockHtons(struct IPerlSock* piPerl, u_short hostshort)
1199 {
1200     return win32_htons(hostshort);
1201 }
1202 
1203 u_long
1204 PerlSockNtohl(struct IPerlSock* piPerl, u_long netlong)
1205 {
1206     return win32_ntohl(netlong);
1207 }
1208 
1209 u_short
1210 PerlSockNtohs(struct IPerlSock* piPerl, u_short netshort)
1211 {
1212     return win32_ntohs(netshort);
1213 }
1214 
1215 SOCKET PerlSockAccept(struct IPerlSock* piPerl, SOCKET s, struct sockaddr* addr, int* addrlen)
1216 {
1217     return win32_accept(s, addr, addrlen);
1218 }
1219 
1220 int
1221 PerlSockBind(struct IPerlSock* piPerl, SOCKET s, const struct sockaddr* name, int namelen)
1222 {
1223     return win32_bind(s, name, namelen);
1224 }
1225 
1226 int
1227 PerlSockConnect(struct IPerlSock* piPerl, SOCKET s, const struct sockaddr* name, int namelen)
1228 {
1229     return win32_connect(s, name, namelen);
1230 }
1231 
1232 void
1233 PerlSockEndhostent(struct IPerlSock* piPerl)
1234 {
1235     win32_endhostent();
1236 }
1237 
1238 void
1239 PerlSockEndnetent(struct IPerlSock* piPerl)
1240 {
1241     win32_endnetent();
1242 }
1243 
1244 void
1245 PerlSockEndprotoent(struct IPerlSock* piPerl)
1246 {
1247     win32_endprotoent();
1248 }
1249 
1250 void
1251 PerlSockEndservent(struct IPerlSock* piPerl)
1252 {
1253     win32_endservent();
1254 }
1255 
1256 struct hostent*
1257 PerlSockGethostbyaddr(struct IPerlSock* piPerl, const char* addr, int len, int type)
1258 {
1259     return win32_gethostbyaddr(addr, len, type);
1260 }
1261 
1262 struct hostent*
1263 PerlSockGethostbyname(struct IPerlSock* piPerl, const char* name)
1264 {
1265     return win32_gethostbyname(name);
1266 }
1267 
1268 struct hostent*
1269 PerlSockGethostent(struct IPerlSock* piPerl)
1270 {
1271     win32_croak_not_implemented("gethostent");
1272     return NULL;
1273 }
1274 
1275 int
1276 PerlSockGethostname(struct IPerlSock* piPerl, char* name, int namelen)
1277 {
1278     return win32_gethostname(name, namelen);
1279 }
1280 
1281 struct netent *
1282 PerlSockGetnetbyaddr(struct IPerlSock* piPerl, long net, int type)
1283 {
1284     return win32_getnetbyaddr(net, type);
1285 }
1286 
1287 struct netent *
1288 PerlSockGetnetbyname(struct IPerlSock* piPerl, const char *name)
1289 {
1290     return win32_getnetbyname((char*)name);
1291 }
1292 
1293 struct netent *
1294 PerlSockGetnetent(struct IPerlSock* piPerl)
1295 {
1296     return win32_getnetent();
1297 }
1298 
1299 int PerlSockGetpeername(struct IPerlSock* piPerl, SOCKET s, struct sockaddr* name, int* namelen)
1300 {
1301     return win32_getpeername(s, name, namelen);
1302 }
1303 
1304 struct protoent*
1305 PerlSockGetprotobyname(struct IPerlSock* piPerl, const char* name)
1306 {
1307     return win32_getprotobyname(name);
1308 }
1309 
1310 struct protoent*
1311 PerlSockGetprotobynumber(struct IPerlSock* piPerl, int number)
1312 {
1313     return win32_getprotobynumber(number);
1314 }
1315 
1316 struct protoent*
1317 PerlSockGetprotoent(struct IPerlSock* piPerl)
1318 {
1319     return win32_getprotoent();
1320 }
1321 
1322 struct servent*
1323 PerlSockGetservbyname(struct IPerlSock* piPerl, const char* name, const char* proto)
1324 {
1325     return win32_getservbyname(name, proto);
1326 }
1327 
1328 struct servent*
1329 PerlSockGetservbyport(struct IPerlSock* piPerl, int port, const char* proto)
1330 {
1331     return win32_getservbyport(port, proto);
1332 }
1333 
1334 struct servent*
1335 PerlSockGetservent(struct IPerlSock* piPerl)
1336 {
1337     return win32_getservent();
1338 }
1339 
1340 int
1341 PerlSockGetsockname(struct IPerlSock* piPerl, SOCKET s, struct sockaddr* name, int* namelen)
1342 {
1343     return win32_getsockname(s, name, namelen);
1344 }
1345 
1346 int
1347 PerlSockGetsockopt(struct IPerlSock* piPerl, SOCKET s, int level, int optname, char* optval, int* optlen)
1348 {
1349     return win32_getsockopt(s, level, optname, optval, optlen);
1350 }
1351 
1352 unsigned long
1353 PerlSockInetAddr(struct IPerlSock* piPerl, const char* cp)
1354 {
1355     return win32_inet_addr(cp);
1356 }
1357 
1358 char*
1359 PerlSockInetNtoa(struct IPerlSock* piPerl, struct in_addr in)
1360 {
1361     return win32_inet_ntoa(in);
1362 }
1363 
1364 int
1365 PerlSockListen(struct IPerlSock* piPerl, SOCKET s, int backlog)
1366 {
1367     return win32_listen(s, backlog);
1368 }
1369 
1370 int
1371 PerlSockRecv(struct IPerlSock* piPerl, SOCKET s, char* buffer, int len, int flags)
1372 {
1373     return win32_recv(s, buffer, len, flags);
1374 }
1375 
1376 int
1377 PerlSockRecvfrom(struct IPerlSock* piPerl, SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen)
1378 {
1379     return win32_recvfrom(s, buffer, len, flags, from, fromlen);
1380 }
1381 
1382 int
1383 PerlSockSelect(struct IPerlSock* piPerl, int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout)
1384 {
1385     return win32_select(nfds, (Perl_fd_set*)readfds, (Perl_fd_set*)writefds, (Perl_fd_set*)exceptfds, timeout);
1386 }
1387 
1388 int
1389 PerlSockSend(struct IPerlSock* piPerl, SOCKET s, const char* buffer, int len, int flags)
1390 {
1391     return win32_send(s, buffer, len, flags);
1392 }
1393 
1394 int
1395 PerlSockSendto(struct IPerlSock* piPerl, SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen)
1396 {
1397     return win32_sendto(s, buffer, len, flags, to, tolen);
1398 }
1399 
1400 void
1401 PerlSockSethostent(struct IPerlSock* piPerl, int stayopen)
1402 {
1403     win32_sethostent(stayopen);
1404 }
1405 
1406 void
1407 PerlSockSetnetent(struct IPerlSock* piPerl, int stayopen)
1408 {
1409     win32_setnetent(stayopen);
1410 }
1411 
1412 void
1413 PerlSockSetprotoent(struct IPerlSock* piPerl, int stayopen)
1414 {
1415     win32_setprotoent(stayopen);
1416 }
1417 
1418 void
1419 PerlSockSetservent(struct IPerlSock* piPerl, int stayopen)
1420 {
1421     win32_setservent(stayopen);
1422 }
1423 
1424 int
1425 PerlSockSetsockopt(struct IPerlSock* piPerl, SOCKET s, int level, int optname, const char* optval, int optlen)
1426 {
1427     return win32_setsockopt(s, level, optname, optval, optlen);
1428 }
1429 
1430 int
1431 PerlSockShutdown(struct IPerlSock* piPerl, SOCKET s, int how)
1432 {
1433     return win32_shutdown(s, how);
1434 }
1435 
1436 SOCKET
1437 PerlSockSocket(struct IPerlSock* piPerl, int af, int type, int protocol)
1438 {
1439     return win32_socket(af, type, protocol);
1440 }
1441 
1442 int
1443 PerlSockSocketpair(struct IPerlSock* piPerl, int domain, int type, int protocol, int* fds)
1444 {
1445     return Perl_my_socketpair(domain, type, protocol, fds);
1446 }
1447 
1448 int
1449 PerlSockClosesocket(struct IPerlSock* piPerl, SOCKET s)
1450 {
1451     return win32_closesocket(s);
1452 }
1453 
1454 int
1455 PerlSockIoctlsocket(struct IPerlSock* piPerl, SOCKET s, long cmd, u_long *argp)
1456 {
1457     return win32_ioctlsocket(s, cmd, argp);
1458 }
1459 
1460 const struct IPerlSock perlSock =
1461 {
1462     PerlSockHtonl,
1463     PerlSockHtons,
1464     PerlSockNtohl,
1465     PerlSockNtohs,
1466     PerlSockAccept,
1467     PerlSockBind,
1468     PerlSockConnect,
1469     PerlSockEndhostent,
1470     PerlSockEndnetent,
1471     PerlSockEndprotoent,
1472     PerlSockEndservent,
1473     PerlSockGethostname,
1474     PerlSockGetpeername,
1475     PerlSockGethostbyaddr,
1476     PerlSockGethostbyname,
1477     PerlSockGethostent,
1478     PerlSockGetnetbyaddr,
1479     PerlSockGetnetbyname,
1480     PerlSockGetnetent,
1481     PerlSockGetprotobyname,
1482     PerlSockGetprotobynumber,
1483     PerlSockGetprotoent,
1484     PerlSockGetservbyname,
1485     PerlSockGetservbyport,
1486     PerlSockGetservent,
1487     PerlSockGetsockname,
1488     PerlSockGetsockopt,
1489     PerlSockInetAddr,
1490     PerlSockInetNtoa,
1491     PerlSockListen,
1492     PerlSockRecv,
1493     PerlSockRecvfrom,
1494     PerlSockSelect,
1495     PerlSockSend,
1496     PerlSockSendto,
1497     PerlSockSethostent,
1498     PerlSockSetnetent,
1499     PerlSockSetprotoent,
1500     PerlSockSetservent,
1501     PerlSockSetsockopt,
1502     PerlSockShutdown,
1503     PerlSockSocket,
1504     PerlSockSocketpair,
1505     PerlSockClosesocket,
1506 };
1507 
1508 
1509 /* IPerlProc */
1510 
1511 #define EXECF_EXEC 1
1512 #define EXECF_SPAWN 2
1513 
1514 void
1515 PerlProcAbort(struct IPerlProc* piPerl)
1516 {
1517     win32_abort();
1518 }
1519 
1520 char *
1521 PerlProcCrypt(struct IPerlProc* piPerl, const char* clear, const char* salt)
1522 {
1523     return win32_crypt(clear, salt);
1524 }
1525 
1526 PERL_CALLCONV_NO_RET void
1527 PerlProcExit(struct IPerlProc* piPerl, int status)
1528 {
1529     exit(status);
1530 }
1531 
1532 PERL_CALLCONV_NO_RET void
1533 PerlProc_Exit(struct IPerlProc* piPerl, int status)
1534 {
1535     _exit(status);
1536 }
1537 
1538 int
1539 PerlProcExecl(struct IPerlProc* piPerl, const char *cmdname, const char *arg0, const char *arg1, const char *arg2, const char *arg3)
1540 {
1541     return execl(cmdname, arg0, arg1, arg2, arg3);
1542 }
1543 
1544 int
1545 PerlProcExecv(struct IPerlProc* piPerl, const char *cmdname, const char *const *argv)
1546 {
1547     return win32_execvp(cmdname, argv);
1548 }
1549 
1550 int
1551 PerlProcExecvp(struct IPerlProc* piPerl, const char *cmdname, const char *const *argv)
1552 {
1553     return win32_execvp(cmdname, argv);
1554 }
1555 
1556 uid_t
1557 PerlProcGetuid(struct IPerlProc* piPerl)
1558 {
1559     return getuid();
1560 }
1561 
1562 uid_t
1563 PerlProcGeteuid(struct IPerlProc* piPerl)
1564 {
1565     return geteuid();
1566 }
1567 
1568 gid_t
1569 PerlProcGetgid(struct IPerlProc* piPerl)
1570 {
1571     return getgid();
1572 }
1573 
1574 gid_t
1575 PerlProcGetegid(struct IPerlProc* piPerl)
1576 {
1577     return getegid();
1578 }
1579 
1580 char *
1581 PerlProcGetlogin(struct IPerlProc* piPerl)
1582 {
1583     return g_getlogin();
1584 }
1585 
1586 int
1587 PerlProcKill(struct IPerlProc* piPerl, int pid, int sig)
1588 {
1589     return win32_kill(pid, sig);
1590 }
1591 
1592 int
1593 PerlProcKillpg(struct IPerlProc* piPerl, int pid, int sig)
1594 {
1595     return win32_kill(pid, -sig);
1596 }
1597 
1598 int
1599 PerlProcPauseProc(struct IPerlProc* piPerl)
1600 {
1601     return win32_pause();
1602 }
1603 
1604 PerlIO*
1605 PerlProcPopen(struct IPerlProc* piPerl, const char *command, const char *mode)
1606 {
1607     dTHX;
1608     PERL_FLUSHALL_FOR_CHILD;
1609     return win32_popen(command, mode);
1610 }
1611 
1612 PerlIO*
1613 PerlProcPopenList(struct IPerlProc* piPerl, const char *mode, IV narg, SV **args)
1614 {
1615     dTHX;
1616     PERL_FLUSHALL_FOR_CHILD;
1617     return win32_popenlist(mode, narg, args);
1618 }
1619 
1620 int
1621 PerlProcPclose(struct IPerlProc* piPerl, PerlIO *stream)
1622 {
1623     return win32_pclose(stream);
1624 }
1625 
1626 int
1627 PerlProcPipe(struct IPerlProc* piPerl, int *phandles)
1628 {
1629     return win32_pipe(phandles, 512, O_BINARY);
1630 }
1631 
1632 int
1633 PerlProcSetuid(struct IPerlProc* piPerl, uid_t u)
1634 {
1635     return setuid(u);
1636 }
1637 
1638 int
1639 PerlProcSetgid(struct IPerlProc* piPerl, gid_t g)
1640 {
1641     return setgid(g);
1642 }
1643 
1644 int
1645 PerlProcSleep(struct IPerlProc* piPerl, unsigned int s)
1646 {
1647     return win32_sleep(s);
1648 }
1649 
1650 int
1651 PerlProcTimes(struct IPerlProc* piPerl, struct tms *timebuf)
1652 {
1653     return win32_times(timebuf);
1654 }
1655 
1656 int
1657 PerlProcWait(struct IPerlProc* piPerl, int *status)
1658 {
1659     return win32_wait(status);
1660 }
1661 
1662 int
1663 PerlProcWaitpid(struct IPerlProc* piPerl, int pid, int *status, int flags)
1664 {
1665     return win32_waitpid(pid, status, flags);
1666 }
1667 
1668 Sighandler_t
1669 PerlProcSignal(struct IPerlProc* piPerl, int sig, Sighandler_t subcode)
1670 {
1671     return win32_signal(sig, subcode);
1672 }
1673 
1674 int
1675 PerlProcGetTimeOfDay(struct IPerlProc* piPerl, struct timeval *t, void *z)
1676 {
1677     return win32_gettimeofday(t, z);
1678 }
1679 
1680 #ifdef USE_ITHREADS
1681 static THREAD_RET_TYPE
1682 win32_start_child(LPVOID arg)
1683 {
1684     PerlInterpreter *my_perl = (PerlInterpreter*)arg;
1685     int status;
1686     HWND parent_message_hwnd;
1687 #ifdef PERL_SYNC_FORK
1688     static long sync_fork_id = 0;
1689     long id = ++sync_fork_id;
1690 #endif
1691 
1692 
1693     PERL_SET_THX(my_perl);
1694     win32_checkTLS(my_perl);
1695 
1696 #ifdef PERL_SYNC_FORK
1697     w32_pseudo_id = id;
1698 #else
1699     w32_pseudo_id = GetCurrentThreadId();
1700 #endif
1701 #ifdef PERL_USES_PL_PIDSTATUS
1702     hv_clear(PL_pidstatus);
1703 #endif
1704 
1705     /* create message window and tell parent about it */
1706     parent_message_hwnd = w32_message_hwnd;
1707     w32_message_hwnd = win32_create_message_window();
1708     if (parent_message_hwnd != NULL)
1709         PostMessage(parent_message_hwnd, WM_USER_MESSAGE, w32_pseudo_id, (LPARAM)w32_message_hwnd);
1710 
1711     /* push a zero on the stack (we are the child) */
1712     {
1713 	dSP;
1714 	dTARGET;
1715 	PUSHi(0);
1716 	PUTBACK;
1717     }
1718 
1719     /* continue from next op */
1720     PL_op = PL_op->op_next;
1721 
1722     {
1723 	dJMPENV;
1724 	volatile int oldscope = 1; /* We are responsible for all scopes */
1725 
1726 restart:
1727 	JMPENV_PUSH(status);
1728 	switch (status) {
1729 	case 0:
1730 	    CALLRUNOPS(aTHX);
1731             /* We may have additional unclosed scopes if fork() was called
1732              * from within a BEGIN block.  See perlfork.pod for more details.
1733              * We cannot clean up these other scopes because they belong to a
1734              * different interpreter, but we also cannot leave PL_scopestack_ix
1735              * dangling because that can trigger an assertion in perl_destruct().
1736              */
1737             if (PL_scopestack_ix > oldscope) {
1738                 PL_scopestack[oldscope-1] = PL_scopestack[PL_scopestack_ix-1];
1739                 PL_scopestack_ix = oldscope;
1740             }
1741 	    status = 0;
1742 	    break;
1743 	case 2:
1744 	    while (PL_scopestack_ix > oldscope)
1745 		LEAVE;
1746 	    FREETMPS;
1747 	    PL_curstash = PL_defstash;
1748 	    if (PL_curstash != PL_defstash) {
1749 		SvREFCNT_dec(PL_curstash);
1750 		PL_curstash = (HV *)SvREFCNT_inc(PL_defstash);
1751 	    }
1752 	    if (PL_endav && !PL_minus_c) {
1753 		PERL_SET_PHASE(PERL_PHASE_END);
1754 		call_list(oldscope, PL_endav);
1755 	    }
1756 	    status = STATUS_EXIT;
1757 	    break;
1758 	case 3:
1759 	    if (PL_restartop) {
1760 		POPSTACK_TO(PL_mainstack);
1761 		PL_op = PL_restartop;
1762 		PL_restartop = (OP*)NULL;
1763 		goto restart;
1764 	    }
1765 	    PerlIO_printf(Perl_error_log, "panic: restartop\n");
1766 	    FREETMPS;
1767 	    status = 1;
1768 	    break;
1769 	}
1770 	JMPENV_POP;
1771 
1772 	/* XXX hack to avoid perl_destruct() freeing optree */
1773         win32_checkTLS(my_perl);
1774 	PL_main_root = (OP*)NULL;
1775     }
1776 
1777     win32_checkTLS(my_perl);
1778     /* close the std handles to avoid fd leaks */
1779     {
1780 	do_close(PL_stdingv, FALSE);
1781 	do_close(gv_fetchpv("STDOUT", TRUE, SVt_PVIO), FALSE); /* PL_stdoutgv - ISAGN */
1782 	do_close(PL_stderrgv, FALSE);
1783     }
1784 
1785     /* destroy everything (waits for any pseudo-forked children) */
1786     win32_checkTLS(my_perl);
1787     perl_destruct(my_perl);
1788     win32_checkTLS(my_perl);
1789     perl_free(my_perl);
1790 
1791 #ifdef PERL_SYNC_FORK
1792     return id;
1793 #else
1794     return (DWORD)status;
1795 #endif
1796 }
1797 #endif /* USE_ITHREADS */
1798 
1799 int
1800 PerlProcFork(struct IPerlProc* piPerl)
1801 {
1802 #ifdef USE_ITHREADS
1803     dTHX;
1804     DWORD id;
1805     HANDLE handle;
1806     CPerlHost *h;
1807 
1808     if (w32_num_pseudo_children >= MAXIMUM_WAIT_OBJECTS) {
1809 	errno = EAGAIN;
1810 	return -1;
1811     }
1812     h = new CPerlHost(*(CPerlHost*)w32_internal_host);
1813     PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTHX,
1814 						 CLONEf_COPY_STACKS,
1815 						 h->m_pHostperlMem,
1816 						 h->m_pHostperlMemShared,
1817 						 h->m_pHostperlMemParse,
1818 						 h->m_pHostperlEnv,
1819 						 h->m_pHostperlStdIO,
1820 						 h->m_pHostperlLIO,
1821 						 h->m_pHostperlDir,
1822 						 h->m_pHostperlSock,
1823 						 h->m_pHostperlProc
1824 						 );
1825     new_perl->Isys_intern.internal_host = h;
1826     h->host_perl = new_perl;
1827 #  ifdef PERL_SYNC_FORK
1828     id = win32_start_child((LPVOID)new_perl);
1829     PERL_SET_THX(aTHX);
1830 #  else
1831     if (w32_message_hwnd == INVALID_HANDLE_VALUE)
1832         w32_message_hwnd = win32_create_message_window();
1833     new_perl->Isys_intern.message_hwnd = w32_message_hwnd;
1834     w32_pseudo_child_message_hwnds[w32_num_pseudo_children] =
1835         (w32_message_hwnd == NULL) ? (HWND)NULL : (HWND)INVALID_HANDLE_VALUE;
1836 #    ifdef USE_RTL_THREAD_API
1837     handle = (HANDLE)_beginthreadex((void*)NULL, 0, win32_start_child,
1838 				    (void*)new_perl, 0, (unsigned*)&id);
1839 #    else
1840     handle = CreateThread(NULL, 0, win32_start_child,
1841 			  (LPVOID)new_perl, 0, &id);
1842 #    endif
1843     PERL_SET_THX(aTHX);	/* XXX perl_clone*() set TLS */
1844     if (!handle) {
1845 	errno = EAGAIN;
1846 	return -1;
1847     }
1848     w32_pseudo_child_handles[w32_num_pseudo_children] = handle;
1849     w32_pseudo_child_pids[w32_num_pseudo_children] = id;
1850     w32_pseudo_child_sigterm[w32_num_pseudo_children] = 0;
1851     ++w32_num_pseudo_children;
1852 #  endif
1853     return -(int)id;
1854 #else
1855     win32_croak_not_implemented("fork()");
1856     return -1;
1857 #endif /* USE_ITHREADS */
1858 }
1859 
1860 int
1861 PerlProcGetpid(struct IPerlProc* piPerl)
1862 {
1863     return win32_getpid();
1864 }
1865 
1866 void*
1867 PerlProcDynaLoader(struct IPerlProc* piPerl, const char* filename)
1868 {
1869     return win32_dynaload(filename);
1870 }
1871 
1872 void
1873 PerlProcGetOSError(struct IPerlProc* piPerl, SV* sv, DWORD dwErr)
1874 {
1875     win32_str_os_error(sv, dwErr);
1876 }
1877 
1878 int
1879 PerlProcSpawnvp(struct IPerlProc* piPerl, int mode, const char *cmdname, const char *const *argv)
1880 {
1881     return win32_spawnvp(mode, cmdname, argv);
1882 }
1883 
1884 int
1885 PerlProcLastHost(struct IPerlProc* piPerl)
1886 {
1887  /* this dTHX is unused in an optimized build since CPerlHost::num_hosts
1888     is a static */
1889  dTHX;
1890  CPerlHost *h = (CPerlHost*)w32_internal_host;
1891  return h->LastHost();
1892 }
1893 
1894 const struct IPerlProc perlProc =
1895 {
1896     PerlProcAbort,
1897     PerlProcCrypt,
1898     PerlProcExit,
1899     PerlProc_Exit,
1900     PerlProcExecl,
1901     PerlProcExecv,
1902     PerlProcExecvp,
1903     PerlProcGetuid,
1904     PerlProcGeteuid,
1905     PerlProcGetgid,
1906     PerlProcGetegid,
1907     PerlProcGetlogin,
1908     PerlProcKill,
1909     PerlProcKillpg,
1910     PerlProcPauseProc,
1911     PerlProcPopen,
1912     PerlProcPclose,
1913     PerlProcPipe,
1914     PerlProcSetuid,
1915     PerlProcSetgid,
1916     PerlProcSleep,
1917     PerlProcTimes,
1918     PerlProcWait,
1919     PerlProcWaitpid,
1920     PerlProcSignal,
1921     PerlProcFork,
1922     PerlProcGetpid,
1923     PerlProcDynaLoader,
1924     PerlProcGetOSError,
1925     PerlProcSpawnvp,
1926     PerlProcLastHost,
1927     PerlProcPopenList,
1928     PerlProcGetTimeOfDay
1929 };
1930 
1931 
1932 /*
1933  * CPerlHost
1934  */
1935 
1936 CPerlHost::CPerlHost(void)
1937 {
1938     /* Construct a host from scratch */
1939     InterlockedIncrement(&num_hosts);
1940     m_pvDir = new VDir();
1941     m_pVMem = new VMem();
1942     m_pVMemShared = new VMem();
1943     m_pVMemParse =  new VMem();
1944 
1945     m_pvDir->Init(NULL, m_pVMem);
1946 
1947     m_dwEnvCount = 0;
1948     m_lppEnvList = NULL;
1949     m_bTopLevel = TRUE;
1950 
1951     CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem));
1952     CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared));
1953     CopyMemory(&m_hostperlMemParse, &perlMemParse, sizeof(perlMemParse));
1954     CopyMemory(&m_hostperlEnv, &perlEnv, sizeof(perlEnv));
1955     CopyMemory(&m_hostperlStdIO, &perlStdIO, sizeof(perlStdIO));
1956     CopyMemory(&m_hostperlLIO, &perlLIO, sizeof(perlLIO));
1957     CopyMemory(&m_hostperlDir, &perlDir, sizeof(perlDir));
1958     CopyMemory(&m_hostperlSock, &perlSock, sizeof(perlSock));
1959     CopyMemory(&m_hostperlProc, &perlProc, sizeof(perlProc));
1960 
1961     m_pHostperlMem	    = &m_hostperlMem;
1962     m_pHostperlMemShared    = &m_hostperlMemShared;
1963     m_pHostperlMemParse	    = &m_hostperlMemParse;
1964     m_pHostperlEnv	    = &m_hostperlEnv;
1965     m_pHostperlStdIO	    = &m_hostperlStdIO;
1966     m_pHostperlLIO	    = &m_hostperlLIO;
1967     m_pHostperlDir	    = &m_hostperlDir;
1968     m_pHostperlSock	    = &m_hostperlSock;
1969     m_pHostperlProc	    = &m_hostperlProc;
1970 }
1971 
1972 #define SETUPEXCHANGE(xptr, iptr, table) \
1973     STMT_START {				\
1974 	if (xptr) {				\
1975 	    iptr = *xptr;			\
1976 	    *xptr = &table;			\
1977 	}					\
1978 	else {					\
1979 	    iptr = &table;			\
1980 	}					\
1981     } STMT_END
1982 
1983 CPerlHost::CPerlHost(struct IPerlMem** ppMem, struct IPerlMem** ppMemShared,
1984 		 struct IPerlMem** ppMemParse, struct IPerlEnv** ppEnv,
1985 		 struct IPerlStdIO** ppStdIO, struct IPerlLIO** ppLIO,
1986 		 struct IPerlDir** ppDir, struct IPerlSock** ppSock,
1987 		 struct IPerlProc** ppProc)
1988 {
1989     InterlockedIncrement(&num_hosts);
1990     m_pvDir = new VDir(0);
1991     m_pVMem = new VMem();
1992     m_pVMemShared = new VMem();
1993     m_pVMemParse =  new VMem();
1994 
1995     m_pvDir->Init(NULL, m_pVMem);
1996 
1997     m_dwEnvCount = 0;
1998     m_lppEnvList = NULL;
1999     m_bTopLevel = FALSE;
2000 
2001     CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem));
2002     CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared));
2003     CopyMemory(&m_hostperlMemParse, &perlMemParse, sizeof(perlMemParse));
2004     CopyMemory(&m_hostperlEnv, &perlEnv, sizeof(perlEnv));
2005     CopyMemory(&m_hostperlStdIO, &perlStdIO, sizeof(perlStdIO));
2006     CopyMemory(&m_hostperlLIO, &perlLIO, sizeof(perlLIO));
2007     CopyMemory(&m_hostperlDir, &perlDir, sizeof(perlDir));
2008     CopyMemory(&m_hostperlSock, &perlSock, sizeof(perlSock));
2009     CopyMemory(&m_hostperlProc, &perlProc, sizeof(perlProc));
2010 
2011     SETUPEXCHANGE(ppMem,	m_pHostperlMem,		m_hostperlMem);
2012     SETUPEXCHANGE(ppMemShared,	m_pHostperlMemShared,	m_hostperlMemShared);
2013     SETUPEXCHANGE(ppMemParse,	m_pHostperlMemParse,	m_hostperlMemParse);
2014     SETUPEXCHANGE(ppEnv,	m_pHostperlEnv,		m_hostperlEnv);
2015     SETUPEXCHANGE(ppStdIO,	m_pHostperlStdIO,	m_hostperlStdIO);
2016     SETUPEXCHANGE(ppLIO,	m_pHostperlLIO,		m_hostperlLIO);
2017     SETUPEXCHANGE(ppDir,	m_pHostperlDir,		m_hostperlDir);
2018     SETUPEXCHANGE(ppSock,	m_pHostperlSock,	m_hostperlSock);
2019     SETUPEXCHANGE(ppProc,	m_pHostperlProc,	m_hostperlProc);
2020 }
2021 #undef SETUPEXCHANGE
2022 
2023 CPerlHost::CPerlHost(CPerlHost& host)
2024 {
2025     /* Construct a host from another host */
2026     InterlockedIncrement(&num_hosts);
2027     m_pVMem = new VMem();
2028     m_pVMemShared = host.GetMemShared();
2029     m_pVMemParse =  host.GetMemParse();
2030 
2031     /* duplicate directory info */
2032     m_pvDir = new VDir(0);
2033     m_pvDir->Init(host.GetDir(), m_pVMem);
2034 
2035     CopyMemory(&m_hostperlMem, &perlMem, sizeof(perlMem));
2036     CopyMemory(&m_hostperlMemShared, &perlMemShared, sizeof(perlMemShared));
2037     CopyMemory(&m_hostperlMemParse, &perlMemParse, sizeof(perlMemParse));
2038     CopyMemory(&m_hostperlEnv, &perlEnv, sizeof(perlEnv));
2039     CopyMemory(&m_hostperlStdIO, &perlStdIO, sizeof(perlStdIO));
2040     CopyMemory(&m_hostperlLIO, &perlLIO, sizeof(perlLIO));
2041     CopyMemory(&m_hostperlDir, &perlDir, sizeof(perlDir));
2042     CopyMemory(&m_hostperlSock, &perlSock, sizeof(perlSock));
2043     CopyMemory(&m_hostperlProc, &perlProc, sizeof(perlProc));
2044     m_pHostperlMem	    = &m_hostperlMem;
2045     m_pHostperlMemShared    = &m_hostperlMemShared;
2046     m_pHostperlMemParse	    = &m_hostperlMemParse;
2047     m_pHostperlEnv	    = &m_hostperlEnv;
2048     m_pHostperlStdIO	    = &m_hostperlStdIO;
2049     m_pHostperlLIO	    = &m_hostperlLIO;
2050     m_pHostperlDir	    = &m_hostperlDir;
2051     m_pHostperlSock	    = &m_hostperlSock;
2052     m_pHostperlProc	    = &m_hostperlProc;
2053 
2054     m_dwEnvCount = 0;
2055     m_lppEnvList = NULL;
2056     m_bTopLevel = FALSE;
2057 
2058     /* duplicate environment info */
2059     LPSTR lpPtr;
2060     DWORD dwIndex = 0;
2061     while(lpPtr = host.GetIndex(dwIndex))
2062 	Add(lpPtr);
2063 }
2064 
2065 CPerlHost::~CPerlHost(void)
2066 {
2067     Reset();
2068     InterlockedDecrement(&num_hosts);
2069     delete m_pvDir;
2070     m_pVMemParse->Release();
2071     m_pVMemShared->Release();
2072     m_pVMem->Release();
2073 }
2074 
2075 LPSTR
2076 CPerlHost::Find(LPCSTR lpStr)
2077 {
2078     LPSTR lpPtr;
2079     LPSTR* lppPtr = Lookup(lpStr);
2080     if(lppPtr != NULL) {
2081 	for(lpPtr = *lppPtr; *lpPtr != '\0' && *lpPtr != '='; ++lpPtr)
2082 	    ;
2083 
2084 	if(*lpPtr == '=')
2085 	    ++lpPtr;
2086 
2087 	return lpPtr;
2088     }
2089     return NULL;
2090 }
2091 
2092 int
2093 lookup(const void *arg1, const void *arg2)
2094 {   // Compare strings
2095     char*ptr1, *ptr2;
2096     char c1,c2;
2097 
2098     ptr1 = *(char**)arg1;
2099     ptr2 = *(char**)arg2;
2100     for(;;) {
2101 	c1 = *ptr1++;
2102 	c2 = *ptr2++;
2103 	if(c1 == '\0' || c1 == '=') {
2104 	    if(c2 == '\0' || c2 == '=')
2105 		break;
2106 
2107 	    return -1; // string 1 < string 2
2108 	}
2109 	else if(c2 == '\0' || c2 == '=')
2110 	    return 1; // string 1 > string 2
2111 	else if(c1 != c2) {
2112 	    c1 = toupper(c1);
2113 	    c2 = toupper(c2);
2114 	    if(c1 != c2) {
2115 		if(c1 < c2)
2116 		    return -1; // string 1 < string 2
2117 
2118 		return 1; // string 1 > string 2
2119 	    }
2120 	}
2121     }
2122     return 0;
2123 }
2124 
2125 LPSTR*
2126 CPerlHost::Lookup(LPCSTR lpStr)
2127 {
2128     if (!lpStr)
2129 	return NULL;
2130     return (LPSTR*)bsearch(&lpStr, m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), lookup);
2131 }
2132 
2133 int
2134 compare(const void *arg1, const void *arg2)
2135 {   // Compare strings
2136     char*ptr1, *ptr2;
2137     char c1,c2;
2138 
2139     ptr1 = *(char**)arg1;
2140     ptr2 = *(char**)arg2;
2141     for(;;) {
2142 	c1 = *ptr1++;
2143 	c2 = *ptr2++;
2144 	if(c1 == '\0' || c1 == '=') {
2145 	    if(c1 == c2)
2146 		break;
2147 
2148 	    return -1; // string 1 < string 2
2149 	}
2150 	else if(c2 == '\0' || c2 == '=')
2151 	    return 1; // string 1 > string 2
2152 	else if(c1 != c2) {
2153 	    c1 = toupper(c1);
2154 	    c2 = toupper(c2);
2155 	    if(c1 != c2) {
2156 		if(c1 < c2)
2157 		    return -1; // string 1 < string 2
2158 
2159 		return 1; // string 1 > string 2
2160 	    }
2161 	}
2162     }
2163     return 0;
2164 }
2165 
2166 void
2167 CPerlHost::Add(LPCSTR lpStr)
2168 {
2169     LPSTR *lpPtr;
2170     STRLEN length = strlen(lpStr)+1;
2171 
2172     // replacing ?
2173     lpPtr = Lookup(lpStr);
2174     if (lpPtr != NULL) {
2175 	// must allocate things via host memory allocation functions
2176 	// rather than perl's Renew() et al, as the perl interpreter
2177 	// may either not be initialized enough when we allocate these,
2178 	// or may already be dead when we go to free these
2179 	*lpPtr = (char*)Realloc(*lpPtr, length * sizeof(char));
2180 	strcpy(*lpPtr, lpStr);
2181     }
2182     else {
2183 	m_lppEnvList = (LPSTR*)Realloc(m_lppEnvList, (m_dwEnvCount+1) * sizeof(LPSTR));
2184 	if (m_lppEnvList) {
2185 	    m_lppEnvList[m_dwEnvCount] = (char*)Malloc(length * sizeof(char));
2186 	    if (m_lppEnvList[m_dwEnvCount] != NULL) {
2187 		strcpy(m_lppEnvList[m_dwEnvCount], lpStr);
2188 		++m_dwEnvCount;
2189 		qsort(m_lppEnvList, m_dwEnvCount, sizeof(LPSTR), compare);
2190 	    }
2191 	}
2192     }
2193 }
2194 
2195 DWORD
2196 CPerlHost::CalculateEnvironmentSpace(void)
2197 {
2198     DWORD index;
2199     DWORD dwSize = 0;
2200     for(index = 0; index < m_dwEnvCount; ++index)
2201 	dwSize += strlen(m_lppEnvList[index]) + 1;
2202 
2203     return dwSize;
2204 }
2205 
2206 void
2207 CPerlHost::FreeLocalEnvironmentStrings(LPSTR lpStr)
2208 {
2209     Safefree(lpStr);
2210 }
2211 
2212 char*
2213 CPerlHost::GetChildDir(void)
2214 {
2215     char* ptr;
2216     size_t length;
2217 
2218     Newx(ptr, MAX_PATH+1, char);
2219     m_pvDir->GetCurrentDirectoryA(MAX_PATH+1, ptr);
2220     length = strlen(ptr);
2221     if (length > 3) {
2222         if ((ptr[length-1] == '\\') || (ptr[length-1] == '/'))
2223             ptr[length-1] = 0;
2224     }
2225     return ptr;
2226 }
2227 
2228 void
2229 CPerlHost::FreeChildDir(char* pStr)
2230 {
2231     Safefree(pStr);
2232 }
2233 
2234 LPSTR
2235 CPerlHost::CreateLocalEnvironmentStrings(VDir &vDir)
2236 {
2237     LPSTR lpStr, lpPtr, lpEnvPtr, lpTmp, lpLocalEnv, lpAllocPtr;
2238     DWORD dwSize, dwEnvIndex;
2239     int nLength, compVal;
2240 
2241     // get the process environment strings
2242     lpAllocPtr = lpTmp = (LPSTR)win32_getenvironmentstrings();
2243 
2244     // step over current directory stuff
2245     while(*lpTmp == '=')
2246 	lpTmp += strlen(lpTmp) + 1;
2247 
2248     // save the start of the environment strings
2249     lpEnvPtr = lpTmp;
2250     for(dwSize = 1; *lpTmp != '\0'; lpTmp += strlen(lpTmp) + 1) {
2251 	// calculate the size of the environment strings
2252 	dwSize += strlen(lpTmp) + 1;
2253     }
2254 
2255     // add the size of current directories
2256     dwSize += vDir.CalculateEnvironmentSpace();
2257 
2258     // add the additional space used by changes made to the environment
2259     dwSize += CalculateEnvironmentSpace();
2260 
2261     Newx(lpStr, dwSize, char);
2262     lpPtr = lpStr;
2263     if(lpStr != NULL) {
2264 	// build the local environment
2265 	lpStr = vDir.BuildEnvironmentSpace(lpStr);
2266 
2267 	dwEnvIndex = 0;
2268 	lpLocalEnv = GetIndex(dwEnvIndex);
2269 	while(*lpEnvPtr != '\0') {
2270 	    if(!lpLocalEnv) {
2271 		// all environment overrides have been added
2272 		// so copy string into place
2273 		strcpy(lpStr, lpEnvPtr);
2274 		nLength = strlen(lpEnvPtr) + 1;
2275 		lpStr += nLength;
2276 		lpEnvPtr += nLength;
2277 	    }
2278 	    else {
2279 		// determine which string to copy next
2280 		compVal = compare(&lpEnvPtr, &lpLocalEnv);
2281 		if(compVal < 0) {
2282 		    strcpy(lpStr, lpEnvPtr);
2283 		    nLength = strlen(lpEnvPtr) + 1;
2284 		    lpStr += nLength;
2285 		    lpEnvPtr += nLength;
2286 		}
2287 		else {
2288 		    char *ptr = strchr(lpLocalEnv, '=');
2289 		    if(ptr && ptr[1]) {
2290 			strcpy(lpStr, lpLocalEnv);
2291 			lpStr += strlen(lpLocalEnv) + 1;
2292 		    }
2293 		    lpLocalEnv = GetIndex(dwEnvIndex);
2294 		    if(compVal == 0) {
2295 			// this string was replaced
2296 			lpEnvPtr += strlen(lpEnvPtr) + 1;
2297 		    }
2298 		}
2299 	    }
2300 	}
2301 
2302 	while(lpLocalEnv) {
2303 	    // still have environment overrides to add
2304 	    // so copy the strings into place if not an override
2305 	    char *ptr = strchr(lpLocalEnv, '=');
2306 	    if(ptr && ptr[1]) {
2307 		strcpy(lpStr, lpLocalEnv);
2308 		lpStr += strlen(lpLocalEnv) + 1;
2309 	    }
2310 	    lpLocalEnv = GetIndex(dwEnvIndex);
2311 	}
2312 
2313 	// add final NULL
2314 	*lpStr = '\0';
2315     }
2316 
2317     // release the process environment strings
2318     win32_freeenvironmentstrings(lpAllocPtr);
2319 
2320     return lpPtr;
2321 }
2322 
2323 void
2324 CPerlHost::Reset(void)
2325 {
2326     if(m_lppEnvList != NULL) {
2327 	for(DWORD index = 0; index < m_dwEnvCount; ++index) {
2328 	    Free(m_lppEnvList[index]);
2329 	    m_lppEnvList[index] = NULL;
2330 	}
2331     }
2332     m_dwEnvCount = 0;
2333     Free(m_lppEnvList);
2334     m_lppEnvList = NULL;
2335 }
2336 
2337 void
2338 CPerlHost::Clearenv(void)
2339 {
2340     char ch;
2341     LPSTR lpPtr, lpStr, lpEnvPtr;
2342     if (m_lppEnvList != NULL) {
2343 	/* set every entry to an empty string */
2344 	for(DWORD index = 0; index < m_dwEnvCount; ++index) {
2345 	    char* ptr = strchr(m_lppEnvList[index], '=');
2346 	    if(ptr) {
2347 		*++ptr = 0;
2348 	    }
2349 	}
2350     }
2351 
2352     /* get the process environment strings */
2353     lpStr = lpEnvPtr = (LPSTR)win32_getenvironmentstrings();
2354 
2355     /* step over current directory stuff */
2356     while(*lpStr == '=')
2357 	lpStr += strlen(lpStr) + 1;
2358 
2359     while(*lpStr) {
2360 	lpPtr = strchr(lpStr, '=');
2361 	if(lpPtr) {
2362 	    ch = *++lpPtr;
2363 	    *lpPtr = 0;
2364 	    Add(lpStr);
2365 	    if (m_bTopLevel)
2366 		(void)win32_putenv(lpStr);
2367 	    *lpPtr = ch;
2368 	}
2369 	lpStr += strlen(lpStr) + 1;
2370     }
2371 
2372     win32_freeenvironmentstrings(lpEnvPtr);
2373 }
2374 
2375 
2376 char*
2377 CPerlHost::Getenv(const char *varname)
2378 {
2379     if (!m_bTopLevel) {
2380 	char *pEnv = Find(varname);
2381 	if (pEnv && *pEnv)
2382 	    return pEnv;
2383     }
2384     return win32_getenv(varname);
2385 }
2386 
2387 int
2388 CPerlHost::Putenv(const char *envstring)
2389 {
2390     Add(envstring);
2391     if (m_bTopLevel)
2392 	return win32_putenv(envstring);
2393 
2394     return 0;
2395 }
2396 
2397 int
2398 CPerlHost::Chdir(const char *dirname)
2399 {
2400     int ret;
2401     if (!dirname) {
2402 	errno = ENOENT;
2403 	return -1;
2404     }
2405     ret = m_pvDir->SetCurrentDirectoryA((char*)dirname);
2406     if(ret < 0) {
2407 	errno = ENOENT;
2408     }
2409     return ret;
2410 }
2411 
2412 #endif /* ___PerlHost_H___ */
2413