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