1 
2 /*
3  * Copyright � 2001 Novell, Inc. All Rights Reserved.
4  *
5  * You may distribute under the terms of either the GNU General Public
6  * License or the Artistic License, as specified in the README file.
7  *
8  */
9 
10 /*
11  * FILENAME		:	nw5.c
12  * DESCRIPTION	:	Definitions for the redefined functions for NetWare.
13  * Author		:	SGP, HYAK
14  * Date			:	January 2001.
15  *
16  */
17 
18 
19 
20 #include <perl.h>	// For dTHX, etc.
21 #include "nwpipe.h"
22 
23 
24 // This was added since the compile failed saying "undefined P_WAIT"
25 // when USE_ITHREADS was commented in the makefile
26 #ifndef P_WAIT
27 #define	P_WAIT		0
28 #endif
29 
30 #ifndef P_NOWAIT
31 #define	P_NOWAIT	1
32 #endif
33 
34 #define EXECF_EXEC 1
35 #define EXECF_SPAWN 2
36 #define EXECF_SPAWN_NOWAIT 3
37 
38 static BOOL has_shell_metachars(char *ptr);
39 
40 // The array is used to store pointer to the memory allocated to the TempPipeFile structure everytime
41 // a call to the function, nw_Popen. If a simple variable is used, everytime the memory is allocated before
42 // the previously allocated memory is freed, the pointer will get overwritten and the previous memory allocations
43 // are lost! Only the most recent one will get freed when calls are made to nw_Pclose.
44 // By using the array and the iPopenCount to index the array, all memory are freed!
45 
46 // The size of the array indicates the limit on the no of times the nw_Popen function can be called (and
47 // memory allocted) from within a script through backtick operators!
48 // This is arbitrarily set to MAX_PIPE_RECURSION=256 which indicates there can be 256 nested backtick operators possible!
49 PTEMPPIPEFILE ptpf1[MAX_PIPE_RECURSION] = {'\0'};
50 int iPopenCount = 0;
51 FILE* File1[MAX_PIPE_RECURSION] = {'\0'};
52 
53 /**
54 General:
55 
56 In this code, wherever there is a  FILE *, the error condition is checked; and only if the FILE * is TRUE,
57 then the corresponding operation is done. Otherwise the error value is returned.
58 This is done because the file operations like "open" in the Perl code returns the FILE *,
59 returning a valid value if the file is found or NULL when the particular file is not found.
60 Now, if the return value is NULL, then an operation say "fgets", "fopen" etc. using this this NULL value
61 for FILE * will abend the server. If the check is made then an operation on a non existing file
62 does not abend the server.
63 **/
64 
65 void
nw_abort(void)66 nw_abort(void)
67 {
68 	abort();	// Terminate the NLM application abnormally.
69 	return;
70 }
71 
72 int
nw_access(const char * path,int mode)73 nw_access(const char *path, int mode)
74 {
75     return access(path, mode);
76 }
77 
78 int
nw_chmod(const char * path,int mode)79 nw_chmod(const char *path, int mode)
80 {
81     return chmod(path, mode);
82 }
83 
84 void
nw_clearerr(FILE * pf)85 nw_clearerr(FILE *pf)
86 {
87 	if(pf)
88 	    clearerr(pf);
89 }
90 
91 int
nw_close(int fd)92 nw_close(int fd)
93 {
94     return close(fd);
95 }
96 
nw_closedir(DIR * dirp)97 nw_closedir(DIR *dirp)
98 {
99 	return (closedir(dirp));
100 }
101 
102 void
nw_setbuf(FILE * pf,char * buf)103 nw_setbuf(FILE *pf, char *buf)
104 {
105 	if(pf)
106 	    setbuf(pf, buf);
107 }
108 
109 int
nw_setmode(FILE * fp,int mode)110 nw_setmode(FILE *fp, int mode)
111 {
112 /**
113 	// Commented since a few abends were happening in fnFpSetMode
114 	int *dummy = 0;
115 	return(fnFpSetMode(fp, mode, dummy));
116 **/
117 
118 	int handle = -1;
119 	errno = 0;
120 
121 	handle = fileno(fp);
122 	if (errno)
123 	{
124 		errno = 0;
125 		return -1;
126 	}
127 	return setmode(handle, mode);
128 }
129 
130 int
nw_setvbuf(FILE * pf,char * buf,int type,size_t size)131 nw_setvbuf(FILE *pf, char *buf, int type, size_t size)
132 {
133 	if(pf)
134 	    return setvbuf(pf, buf, type, size);
135 	else
136 	    return -1;
137 }
138 
139 
140 unsigned int
nw_sleep(unsigned int t)141 nw_sleep(unsigned int t)
142 {
143 	delay(t*1000);	// Put the thread to sleep for 't' seconds.  Initially 't' is passed in milliseconds.
144     return 0;
145 }
146 
147 int
nw_spawnvp(int mode,char * cmdname,char ** argv)148 nw_spawnvp(int mode, char *cmdname, char **argv)
149 {
150 	// There is no pass-around environment on NetWare so we throw that
151 	// argument away for now.
152 
153 	//  The function "spawnvp" does not work in all situations. Loading
154 	// edit.nlm seems to work, for example, but the name of the file
155 	// to edit does not appear to get passed correctly. Another problem
156 	// is that on Netware, P_WAIT does not really work reliably. It only
157 	// works with NLMs built to use CLIB (according to Nile Thayne).
158 	// NLMs such as EDIT that are written directly to the system have no
159 	// way of running synchronously from another process. The whole
160 	// architecture on NetWare seems pretty busted, so we just support it
161 	// as best we can.
162 	//
163 	// The spawnvp function only launches NLMs, it will not execute a command;
164 	// the NetWare "system" function is used for that purpose. Unfortunately, "system"
165 	// always returns success whether the command is successful or not or even
166 	// if the command was not found! To avoid ambiguity--you can have both an
167 	// NLM named "perl" and a system command named "perl"--we need to
168 	// force perl scripts to carry the word "load" when loading an NLM. This
169 	// might be clearer anyway.
170 
171 	int ret = 0;
172 	int argc = 0;
173 
174 
175 	if (stricmp(cmdname, LOAD_COMMAND) == 0)
176 	{
177 		if (argv[1] != NULL)
178 			ret = spawnvp(mode, argv[1], &argv[1]);
179 	}
180 	else
181 	{
182 		int i=0;
183 		while (argv[i] != '\0')
184 			i++;
185 		argc = i;
186 
187 		fnSystemCommand(argv, argc);
188 	}
189 
190 	return ret;
191 }
192 
193 int
nw_execv(char * cmdname,char ** argv)194 nw_execv(char *cmdname, char **argv)
195 {
196 	return spawnvp(P_WAIT, cmdname, (char **)argv);
197 }
198 
199 
200 int
nw_execvp(char * cmdname,char ** argv)201 nw_execvp(char *cmdname, char **argv)
202 {
203 	return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
204 }
205 
206 int
nw_stat(const char * path,struct stat * sbuf)207 nw_stat(const char *path, struct stat *sbuf)
208 {
209 	return (stat(path, sbuf));
210 }
211 
212 FILE *
nw_stderr(void)213 nw_stderr(void)
214 {
215 	return (stderr);
216 }
217 
218 FILE *
nw_stdin(void)219 nw_stdin(void)
220 {
221 	return (stdin);
222 }
223 
224 FILE *
nw_stdout()225 nw_stdout()
226 {
227 	return (stdout);
228 }
229 
230 long
nw_telldir(DIR * dirp)231 nw_telldir(DIR *dirp)
232 {
233 	dTHX;
234 	Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
235 	return 0l;
236 }
237 
238 int
nw_times(struct tms * timebuf)239 nw_times(struct tms *timebuf)
240 {
241 	clock_t now = clock();
242 
243 	timebuf->tms_utime = now;
244 	timebuf->tms_stime = 0;
245 	timebuf->tms_cutime = 0;
246 	timebuf->tms_cstime = 0;
247 
248 	return 0;
249 }
250 
251 FILE*
nw_tmpfile(void)252 nw_tmpfile(void)
253 {
254     return tmpfile();
255 }
256 
257 int
nw_uname(struct utsname * name)258 nw_uname(struct utsname *name)
259 {
260 	return(uname(name));
261 }
262 
263 int
nw_ungetc(int c,FILE * pf)264 nw_ungetc(int c, FILE *pf)
265 {
266 	if(pf)
267 	    return ungetc(c, pf);
268 	else
269 	    return -1;
270 }
271 
272 int
nw_unlink(const char * filename)273 nw_unlink(const char *filename)
274 {
275 	return(unlink(filename));
276 }
277 
278 int
nw_utime(const char * filename,struct utimbuf * times)279 nw_utime(const char *filename, struct utimbuf *times)
280 {
281  	 return(utime(filename, times));
282 }
283 
284 int
nw_vfprintf(FILE * fp,const char * format,va_list args)285 nw_vfprintf(FILE *fp, const char *format, va_list args)
286 {
287 	if(fp)
288 	    return (vfprintf(fp, format, args));
289 	else
290 	    return -1;
291 }
292 
293 int
nw_wait(int * status)294 nw_wait(int *status)
295 {
296     return 0;
297 }
298 
299 int
nw_waitpid(int pid,int * status,int flags)300 nw_waitpid(int pid, int *status, int flags)
301 {
302     return 0;
303 }
304 
305 int
nw_write(int fd,const void * buf,unsigned int cnt)306 nw_write(int fd, const void *buf, unsigned int cnt)
307 {
308     return write(fd, buf, cnt);
309 }
310 
311 char *
nw_crypt(const char * txt,const char * salt)312 nw_crypt(const char *txt, const char *salt)
313 {
314 	 dTHX;
315 
316 #ifdef HAVE_DES_FCRYPT
317     dTHR;
318     return des_fcrypt(txt, salt, w32_crypt_buffer);
319 #else
320     Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
321     return Nullch;
322 #endif
323 }
324 
325 int
nw_dup(int fd)326 nw_dup(int fd)
327 {
328     return dup(fd);
329 }
330 
331 int
nw_dup2(int fd1,int fd2)332 nw_dup2(int fd1,int fd2)
333 {
334 	return dup2(fd1,fd2);
335 }
336 
337 void*
nw_dynaload(const char * filename)338 nw_dynaload(const char* filename)
339 {
340 	return NULL;
341 }
342 
343 int
nw_fclose(FILE * pf)344 nw_fclose(FILE *pf)
345 {
346 	if(pf)
347 	    return (fclose(pf));
348 	else
349 	    return -1;
350 }
351 
352 FILE *
nw_fdopen(int handle,const char * mode)353 nw_fdopen(int handle, const char *mode)
354 {
355 	return(fdopen(handle, mode));
356 }
357 
358 int
nw_feof(FILE * fp)359 nw_feof(FILE *fp)
360 {
361 	if(fp)
362 	    return (feof(fp));
363 	else
364 	    return -1;
365 }
366 
367 int
nw_ferror(FILE * fp)368 nw_ferror(FILE *fp)
369 {
370 	if(fp)
371 	    return (ferror(fp));
372 	else
373 	    return -1;
374 }
375 
376 
377 int
nw_fflush(FILE * pf)378 nw_fflush(FILE *pf)
379 {
380 	if(pf)
381 	    return fflush(pf);
382 	else
383 	    return -1;
384 }
385 
386 int
nw_fgetpos(FILE * pf,fpos_t * p)387 nw_fgetpos(FILE *pf, fpos_t *p)
388 {
389 	if(pf)
390 	    return fgetpos(pf, p);
391 	else
392 	    return -1;
393 }
394 
395 char*
nw_fgets(char * s,int n,FILE * pf)396 nw_fgets(char *s, int n, FILE *pf)
397 {
398 	if(pf)
399 	    return(fgets(s, n, pf));
400 	else
401 	    return NULL;
402 }
403 
404 int
nw_fileno(FILE * pf)405 nw_fileno(FILE *pf)
406 {
407 	if(pf)
408 	    return fileno(pf);
409 	else
410 	    return -1;
411 }
412 
413 int
nw_flock(int fd,int oper)414 nw_flock(int fd, int oper)
415 {
416 	dTHX;
417 	Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
418 	return 0;
419 }
420 
421 
422 FILE *
nw_fopen(const char * filename,const char * mode)423 nw_fopen(const char *filename, const char *mode)
424 {
425 	return (fopen(filename, mode));
426 }
427 
428 int
nw_fputc(int c,FILE * pf)429 nw_fputc(int c, FILE *pf)
430 {
431 	if(pf)
432 	    return fputc(c,pf);
433 	else
434 	    return -1;
435 }
436 
437 int
nw_fputs(const char * s,FILE * pf)438 nw_fputs(const char *s, FILE *pf)
439 {
440 	if(pf)
441 	    return fputs(s, pf);
442 	else
443 	    return -1;
444 }
445 
446 size_t
nw_fread(void * buf,size_t size,size_t count,FILE * fp)447 nw_fread(void *buf, size_t size, size_t count, FILE *fp)
448 {
449 	if(fp)
450 	    return fread(buf, size, count, fp);
451 	else
452 	    return -1;
453 }
454 
455 FILE *
nw_freopen(const char * path,const char * mode,FILE * stream)456 nw_freopen(const char *path, const char *mode, FILE *stream)
457 {
458 	if(stream)
459 	    return freopen(path, mode, stream);
460 	else
461 	    return NULL;
462 }
463 
464 int
nw_fseek(FILE * pf,long offset,int origin)465 nw_fseek(FILE *pf, long offset, int origin)
466 {
467 	if(pf)
468 	    return (fseek(pf, offset, origin));
469 	else
470 	    return -1;
471 }
472 
473 int
nw_fsetpos(FILE * pf,const fpos_t * p)474 nw_fsetpos(FILE *pf, const fpos_t *p)
475 {
476 	if(pf)
477 	    return fsetpos(pf, p);
478 	else
479 	    return -1;
480 }
481 
482 long
nw_ftell(FILE * pf)483 nw_ftell(FILE *pf)
484 {
485 	if(pf)
486 	    return ftell(pf);
487 	else
488 	    return -1;
489 }
490 
491 size_t
nw_fwrite(const void * buf,size_t size,size_t count,FILE * fp)492 nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
493 {
494 	if(fp)
495 	    return fwrite(buf, size, count, fp);
496 	else
497 	    return -1;
498 }
499 
500 long
nw_get_osfhandle(int fd)501 nw_get_osfhandle(int fd)
502 {
503 	return 0l;
504 }
505 
506 int
nw_getc(FILE * pf)507 nw_getc(FILE *pf)
508 {
509 	if(pf)
510 	    return getc(pf);
511 	else
512 	    return -1;
513 }
514 
515 int
nw_putc(int c,FILE * pf)516 nw_putc(int c, FILE *pf)
517 {
518 	if(pf)
519 	    return putc(c,pf);
520 	else
521 	    return -1;
522 }
523 
524 int
nw_fgetc(FILE * pf)525 nw_fgetc(FILE *pf)
526 {
527 	if(pf)
528 	    return fgetc(pf);
529 	else
530 	    return -1;
531 }
532 
533 int
nw_getpid(void)534 nw_getpid(void)
535 {
536 	return GetThreadGroupID();
537 }
538 
539 int
nw_kill(int pid,int sig)540 nw_kill(int pid, int sig)
541 {
542 	return 0;
543 }
544 
545 int
nw_link(const char * oldname,const char * newname)546 nw_link(const char *oldname, const char *newname)
547 {
548 	return 0;
549 }
550 
551 long
nw_lseek(int fd,long offset,int origin)552 nw_lseek(int fd, long offset, int origin)
553 {
554     return lseek(fd, offset, origin);
555 }
556 
557 int
nw_chdir(const char * dir)558 nw_chdir(const char *dir)
559 {
560     return chdir(dir);
561 }
562 
563 int
nw_rmdir(const char * dir)564 nw_rmdir(const char *dir)
565 {
566     return rmdir(dir);
567 }
568 
569 DIR *
nw_opendir(char * filename)570 nw_opendir(char *filename)
571 {
572 	char	*buff = NULL;
573 	int		len = 0;
574 	DIR		*ret = NULL;
575 
576 	len = strlen(filename);
577 	buff = malloc(len + 5);
578 	if (buff) {
579 		strcpy(buff, filename);
580 		if (buff[len-1]=='/' || buff[len-1]=='\\') {
581 			buff[--len] = 0;
582 		}
583 		strcpy(buff+len, "/*.*");
584 		ret = opendir(buff);
585 		free (buff);
586 		buff = NULL;
587 		return ret;
588 	} else {
589 		return NULL;
590 	}
591 }
592 
593 int
nw_open(const char * path,int flag,...)594 nw_open(const char *path, int flag, ...)
595 {
596 	va_list ap;
597 	int pmode = -1;
598 
599 	va_start(ap, flag);
600     pmode = va_arg(ap, int);
601     va_end(ap);
602 
603 	if (stricmp(path, "/dev/null")==0)
604 	path = "NWNUL";
605 
606 	return open(path, flag, pmode);
607 }
608 
609 int
nw_open_osfhandle(long handle,int flags)610 nw_open_osfhandle(long handle, int flags)
611 {
612 	return 0;
613 }
614 
615 unsigned long
nw_os_id(void)616 nw_os_id(void)
617 {
618 	return 0l;
619 }
620 
nw_Pipe(int * a,int * e)621 int nw_Pipe(int* a, int* e)
622 {
623 	int ret = 0;
624 
625 	errno = 0;
626 	ret = pipe(a);
627 	if(errno)
628 		e = &errno;
629 
630 	return ret;
631 }
632 
nw_Popen(char * command,char * mode,int * e)633 FILE* nw_Popen(char* command, char* mode, int* e)
634 {
635 	int i = -1;
636 
637 	FILE* ret = NULL;
638 	PTEMPPIPEFILE ptpf = NULL;
639 
640 	// this callback is supposed to call _popen, which spawns an
641 	// asynchronous command and opens a pipe to it. The returned
642 	// file handle can be read or written to; if read, it represents
643 	// stdout of the called process and will return EOF when the
644 	// called process finishes. If written to, it represents stdin
645 	// of the called process. Naturally _popen is not available on
646 	// NetWare so we must do some fancy stuff to simulate it. We will
647 	// redirect to and from temp files; this has the side effect
648 	// of having to run the process synchronously rather than
649 	// asynchronously. This means that you will only be able to do
650 	// this with CLIB NLMs built to run on the calling thread.
651 
652 	errno = 0;
653 
654 	ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
655 	if (!ptpf1[iPopenCount])
656 		return NULL;
657 
658 	ptpf = ptpf1[iPopenCount];
659 	iPopenCount ++;
660 	if(iPopenCount > MAX_PIPE_RECURSION)
661 		iPopenCount = MAX_PIPE_RECURSION;	// Limit to the max no of pipes to be open recursively.
662 
663 	fnTempPipeFile(ptpf);
664 	ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
665 	if (ret)
666 		File1[iPopenCount-1] = ret;	// Store the obtained Pipe file handle.
667 	else
668 	{	// Pipe file not obtained. So free the allocated memory.
669 		if(ptpf1[iPopenCount-1])
670 		{
671 			free(ptpf1[iPopenCount-1]);
672 			ptpf1[iPopenCount-1] = NULL;
673 			ptpf = NULL;
674 			iPopenCount --;
675 		}
676 	}
677 
678 	if (errno)
679 		e = &errno;
680 
681 	return ret;
682 }
683 
nw_Pclose(FILE * file,int * e)684 int nw_Pclose(FILE* file, int* e)
685 {
686 	int i=0, j=0;
687 
688 	errno = 0;
689 
690 	if(file)
691 	{
692 		if(iPopenCount > 0)
693 		{
694 			for (i=0; i<iPopenCount; i++)
695 			{
696 				if(File1[i] == file)
697 				{
698 					// Delete the memory allocated corresponding to the file handle passed-in and
699 					// also close the file corresponding to the file handle passed-in!
700 					if(ptpf1[i])
701 					{
702 						fnPipeFileClose(ptpf1[i]);
703 
704 						free(ptpf1[i]);
705 						ptpf1[i] = NULL;
706 					}
707 
708 					fclose(File1[i]);
709 					File1[i] = NULL;
710 
711 					break;
712 				}
713 			}
714 
715 			// Rearrange the file pointer array
716 			for(j=i; j<(iPopenCount-1); j++)
717 			{
718 				File1[j] = File1[j+1];
719 				ptpf1[j] = ptpf1[j+1];
720 			}
721 			iPopenCount--;
722 		}
723 	}
724 	else
725 	    return -1;
726 
727 	if (errno)
728 		e = &errno;
729 
730 	return 0;
731 }
732 
733 
734 int
nw_vprintf(const char * format,va_list args)735 nw_vprintf(const char *format, va_list args)
736 {
737     return (vprintf(format, args));
738 }
739 
740 int
nw_printf(const char * format,...)741 nw_printf(const char *format, ...)
742 {
743 
744 	va_list marker;
745     va_start(marker, format);     /* Initialize variable arguments. */
746 
747     return (vprintf(format, marker));
748 }
749 
750 int
nw_read(int fd,void * buf,unsigned int cnt)751 nw_read(int fd, void *buf, unsigned int cnt)
752 {
753 	return read(fd, buf, cnt);
754 }
755 
756 struct direct *
nw_readdir(DIR * dirp)757 nw_readdir(DIR *dirp)
758 {
759 	DIR* ret=NULL;
760 
761 	ret = readdir(dirp);
762 	if(ret)
763 		return((struct direct *)ret);
764 	return NULL;
765 }
766 
767 int
nw_rename(const char * oname,const char * newname)768 nw_rename(const char *oname, const char *newname)
769 {
770 	return(rename(oname,newname));
771 }
772 
773 void
nw_rewinddir(DIR * dirp)774 nw_rewinddir(DIR *dirp)
775 {
776 	dTHX;
777 	Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
778 }
779 
780 void
nw_rewind(FILE * pf)781 nw_rewind(FILE *pf)
782 {
783 	if(pf)
784 	    rewind(pf);
785 }
786 
787 void
nw_seekdir(DIR * dirp,long loc)788 nw_seekdir(DIR *dirp, long loc)
789 {
790 	dTHX;
791 	Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
792 }
793 
794 int *
nw_errno(void)795 nw_errno(void)
796 {
797     return (&errno);
798 }
799 
800 char ***
nw_environ(void)801 nw_environ(void)
802 {
803 	return ((char ***)nw_getenviron());
804 }
805 
806 char *
nw_strerror(int e)807 nw_strerror(int e)
808 {
809 	return (strerror(e));
810 }
811 
812 int
nw_isatty(int fd)813 nw_isatty(int fd)
814 {
815 	return(isatty(fd));
816 }
817 
818 char *
nw_mktemp(char * Template)819 nw_mktemp(char *Template)
820 {
821 	return (fnMy_MkTemp(Template));
822 }
823 
824 int
nw_chsize(int handle,long size)825 nw_chsize(int handle, long size)
826 {
827 	return(chsize(handle,size));
828 }
829 
830 #ifdef HAVE_INTERP_INTERN
831 void
sys_intern_init(pTHX)832 sys_intern_init(pTHX)
833 {
834 
835 }
836 
837 void
sys_intern_clear(pTHX)838 sys_intern_clear(pTHX)
839 {
840 
841 }
842 
843 void
sys_intern_dup(pTHX_ struct interp_intern * src,struct interp_intern * dst)844 sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
845 {
846 
847 }
848 #endif	/* HAVE_INTERP_INTERN */
849 
850 void
Perl_init_os_extras(void)851 Perl_init_os_extras(void)
852 {
853 
854 }
855 
856 void
Perl_nw5_init(int * argcp,char *** argvp)857 Perl_nw5_init(int *argcp, char ***argvp)
858 {
859     MALLOC_INIT;
860 }
861 
862 #ifdef USE_ITHREADS
863 PerlInterpreter *
perl_clone_host(PerlInterpreter * proto_perl,UV flags)864 perl_clone_host(PerlInterpreter* proto_perl, UV flags)
865 {
866 	// Perl Clone is not implemented on NetWare.
867     return NULL;
868 }
869 #endif
870 
871 // Some more functions:
872 
873 char *
nw_get_sitelib(const char * pl)874 nw_get_sitelib(const char *pl)
875 {
876     return (NULL);
877 }
878 
879 int
execv(char * cmdname,char ** argv)880 execv(char *cmdname, char **argv)
881 {
882 	// This feature needs to be implemented.
883 	// _asm is commented out since it goes into the internal debugger.
884 //	_asm {int 3};
885 	return(0);
886 }
887 
888 int
execvp(char * cmdname,char ** argv)889 execvp(char *cmdname, char **argv)
890 {
891 	// This feature needs to be implemented.
892 	// _asm is commented out since it goes into the internal debugger.
893 //	_asm {int 3};
894 	return(0);
895 }
896 
897 int
do_aspawn(void * vreally,void ** vmark,void ** vsp)898 do_aspawn(void *vreally, void **vmark, void **vsp)
899 {
900 	// This feature needs to be implemented.
901 	// _asm is commented out since it goes into the internal debugger.
902 //	_asm {int 3};
903 ////	return(0);
904 
905 
906 	// This below code is required for system() call.
907 	// Otherwise system() does not work on NetWare.
908 	// Ananth, 3 Sept 2001
909 
910     dTHX;
911     SV *really = (SV*)vreally;
912     SV **mark = (SV**)vmark;
913     SV **sp = (SV**)vsp;
914     char **argv;
915     char *str;
916     int status;
917     int flag = P_WAIT;
918     int index = 0;
919 
920 
921     if (sp <= mark)
922 	return -1;
923 
924 	nw_perlshell_items = 0;	// No Shell
925 //    Newx(argv, (sp - mark) + nw_perlshell_items + 3, char*);	// In the old code of 5.6.1
926     Newx(argv, (sp - mark) + nw_perlshell_items + 2, char*);
927 
928     if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
929 	++mark;
930 	flag = SvIVx(*mark);
931     }
932 
933     while (++mark <= sp) {
934 	if (*mark && (str = (char *)SvPV_nolen(*mark)))
935 	{
936 	    argv[index] = str;
937 		index++;
938 	}
939 	else
940 	{
941 		argv[index] = "";
942 //		argv[index] = '\0';
943 		index++;
944     }
945 	}
946     argv[index] = '\0';
947 	index++;
948 
949     status = nw_spawnvp(flag,
950 			   (char*)(really ? SvPV_nolen(really) : argv[0]),
951 			   (char**)argv);
952 
953     if (flag != P_NOWAIT) {
954 	if (status < 0) {
955 //   	    dTHR;	// Only in old code of 5.6.1
956 	    if (ckWARN(WARN_EXEC))
957 		Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
958 	    status = 255 * 256;
959 	}
960 	else
961 	    status *= 256;
962 	PL_statusvalue = status;
963     }
964 
965     Safefree(argv);
966     return (status);
967 }
968 
969 int
do_spawn2(char * cmd,int exectype)970 do_spawn2(char *cmd, int exectype)
971 {
972 	// This feature needs to be implemented.
973 	// _asm is commented out since it goes into the internal debugger.
974 //	_asm {int 3};
975 ////	return(0);
976 
977 	// Below added to make system() work for NetWare
978 
979     dTHX;
980     char **a;
981     char *s;
982     char **argv;
983     int status = -1;
984     BOOL needToTry = TRUE;
985     char *cmd2;
986 
987     /* Save an extra exec if possible. See if there are shell
988      * metacharacters in it */
989     if (!has_shell_metachars(cmd)) {
990 	Newx(argv, strlen(cmd) / 2 + 2, char*);
991 	Newx(cmd2, strlen(cmd) + 1, char);
992 	strcpy(cmd2, cmd);
993 	a = argv;
994 	for (s = cmd2; *s;) {
995 	    while (*s && isSPACE(*s))
996 		s++;
997 	    if (*s)
998 		*(a++) = s;
999 	    while (*s && !isSPACE(*s))
1000 		s++;
1001 	    if (*s)
1002 		*s++ = '\0';
1003 	}
1004 	*a = Nullch;
1005 	if (argv[0]) {
1006 	    switch (exectype) {
1007 			case EXECF_SPAWN:
1008 				status = nw_spawnvp(P_WAIT, argv[0], (char **)argv);
1009 				break;
1010 
1011 			case EXECF_SPAWN_NOWAIT:
1012 				status = nw_spawnvp(P_NOWAIT, argv[0], (char **)argv);
1013 				break;
1014 
1015 			case EXECF_EXEC:
1016 				status = nw_execvp(argv[0], (char **)argv);
1017 				break;
1018 	    }
1019 	    if (status != -1 || errno == 0)
1020 		needToTry = FALSE;
1021 	}
1022 	Safefree(argv);
1023 	Safefree(cmd2);
1024     }
1025 
1026     if (needToTry) {
1027 	char **argv = NULL;
1028 	int i = -1;
1029 
1030 	Newx(argv, nw_perlshell_items + 2, char*);
1031 	while (++i < nw_perlshell_items)
1032 	    argv[i] = nw_perlshell_vec[i];
1033 	argv[i++] = cmd;
1034 	argv[i] = Nullch;
1035 	switch (exectype) {
1036 		case EXECF_SPAWN:
1037 			status = nw_spawnvp(P_WAIT, argv[0], (char **)argv);
1038 			break;
1039 
1040 		case EXECF_SPAWN_NOWAIT:
1041 			status = nw_spawnvp(P_NOWAIT, argv[0], (char **)argv);
1042 			break;
1043 
1044 		case EXECF_EXEC:
1045 			status = nw_execvp(argv[0], (char **)argv);
1046 			break;
1047 	}
1048 	cmd = argv[0];
1049 	Safefree(argv);
1050     }
1051 
1052     if (exectype != EXECF_SPAWN_NOWAIT) {
1053 	if (status < 0) {
1054     	    dTHR;
1055 	    if (ckWARN(WARN_EXEC))
1056 		Perl_warner(aTHX_ WARN_EXEC, "Can't %s \"%s\": %s",
1057 		     (exectype == EXECF_EXEC ? "exec" : "spawn"),
1058 		     cmd, strerror(errno));
1059 	    status = 255 * 256;
1060 	}
1061 	else
1062 	    status *= 256;
1063 	PL_statusvalue = status;
1064     }
1065     return (status);
1066 }
1067 
1068 int
do_spawn(char * cmd)1069 do_spawn(char *cmd)
1070 {
1071     return do_spawn2(cmd, EXECF_SPAWN);
1072 }
1073 
1074 // Added to make system() work for NetWare
1075 static BOOL
has_shell_metachars(char * ptr)1076 has_shell_metachars(char *ptr)
1077 {
1078     int inquote = 0;
1079     char quote = '\0';
1080 
1081     /*
1082      * Scan string looking for redirection (< or >) or pipe
1083      * characters (|) that are not in a quoted string.
1084      * Shell variable interpolation (%VAR%) can also happen inside strings.
1085      */
1086     while (*ptr) {
1087 	switch(*ptr) {
1088 	case '%':
1089 	    return TRUE;
1090 	case '\'':
1091 	case '\"':
1092 	    if (inquote) {
1093 		if (quote == *ptr) {
1094 		    inquote = 0;
1095 		    quote = '\0';
1096 		}
1097 	    }
1098 	    else {
1099 		quote = *ptr;
1100 		inquote++;
1101 	    }
1102 	    break;
1103 	case '>':
1104 	case '<':
1105 	case '|':
1106 	    if (!inquote)
1107 		return TRUE;
1108 	default:
1109 	    break;
1110 	}
1111 	++ptr;
1112     }
1113     return FALSE;
1114 }
1115 
1116 int
fork(void)1117 fork(void)
1118 {
1119 	return 0;
1120 }
1121 
1122 
1123 // added to remove undefied symbol error in CodeWarrior compilation
1124 int
Perl_Ireentrant_buffer_ptr(aTHX)1125 Perl_Ireentrant_buffer_ptr(aTHX)
1126 {
1127 	return 0;
1128 }
1129