This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Replace sv_catsv_mg and sv_catpvn_mg, and move the obsolete bodies to
[perl5.git] / NetWare / nw5.c
CommitLineData
2986a63f
JH
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
acfe0abc 20#include <perl.h> // For dTHX, etc.
2986a63f
JH
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
1a95e36d
JH
34#define EXECF_EXEC 1
35#define EXECF_SPAWN 2
36#define EXECF_SPAWN_NOWAIT 3
37
38static BOOL has_shell_metachars(char *ptr);
39
2986a63f
JH
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!
49PTEMPPIPEFILE ptpf1[MAX_PIPE_RECURSION] = {'\0'};
50int iPopenCount = 0;
51FILE* File1[MAX_PIPE_RECURSION] = {'\0'};
52
2986a63f
JH
53/**
54General:
55
56In this code, wherever there is a FILE *, the error condition is checked; and only if the FILE * is TRUE,
57then the corresponding operation is done. Otherwise the error value is returned.
58This is done because the file operations like "open" in the Perl code returns the FILE *,
59returning a valid value if the file is found or NULL when the particular file is not found.
60Now, if the return value is NULL, then an operation say "fgets", "fopen" etc. using this this NULL value
61for FILE * will abend the server. If the check is made then an operation on a non existing file
62does not abend the server.
63**/
64
65void
66nw_abort(void)
67{
68 abort(); // Terminate the NLM application abnormally.
69 return;
70}
71
72int
73nw_access(const char *path, int mode)
74{
75 return access(path, mode);
76}
77
78int
79nw_chmod(const char *path, int mode)
80{
81 return chmod(path, mode);
82}
83
84void
85nw_clearerr(FILE *pf)
86{
87 if(pf)
88 clearerr(pf);
89}
90
91int
92nw_close(int fd)
93{
94 return close(fd);
95}
96
97nw_closedir(DIR *dirp)
98{
99 return (closedir(dirp));
100}
101
102void
103nw_setbuf(FILE *pf, char *buf)
104{
105 if(pf)
106 setbuf(pf, buf);
107}
108
109int
110nw_setmode(FILE *fp, int mode)
111{
f355267c
JH
112/**
113 // Commented since a few abends were happening in fnFpSetMode
2986a63f
JH
114 int *dummy = 0;
115 return(fnFpSetMode(fp, mode, dummy));
f355267c
JH
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);
2986a63f
JH
128}
129
130int
131nw_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
140unsigned int
141nw_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
147int
148nw_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
193int
194nw_execv(char *cmdname, char **argv)
195{
196 return spawnvp(P_WAIT, cmdname, (char **)argv);
197}
198
199
200int
201nw_execvp(char *cmdname, char **argv)
202{
203 return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
204}
205
206int
207nw_stat(const char *path, struct stat *sbuf)
208{
209 return (stat(path, sbuf));
210}
211
212FILE *
213nw_stderr(void)
214{
215 return (stderr);
216}
217
218FILE *
219nw_stdin(void)
220{
221 return (stdin);
222}
223
224FILE *
225nw_stdout()
226{
227 return (stdout);
228}
229
230long
231nw_telldir(DIR *dirp)
232{
acfe0abc 233 dTHX;
4d76e4b4 234 Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
2986a63f
JH
235 return 0l;
236}
237
238int
239nw_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
251FILE*
252nw_tmpfile(void)
253{
254 return tmpfile();
255}
256
257int
258nw_uname(struct utsname *name)
259{
260 return(uname(name));
261}
262
263int
264nw_ungetc(int c, FILE *pf)
265{
266 if(pf)
267 return ungetc(c, pf);
268 else
269 return -1;
270}
271
272int
273nw_unlink(const char *filename)
274{
275 return(unlink(filename));
276}
277
278int
279nw_utime(const char *filename, struct utimbuf *times)
280{
281 return(utime(filename, times));
282}
283
284int
285nw_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
293int
294nw_wait(int *status)
295{
296 return 0;
297}
298
299int
300nw_waitpid(int pid, int *status, int flags)
301{
302 return 0;
303}
304
305int
306nw_write(int fd, const void *buf, unsigned int cnt)
307{
308 return write(fd, buf, cnt);
309}
310
311char *
312nw_crypt(const char *txt, const char *salt)
313{
acfe0abc 314 dTHX;
2986a63f
JH
315
316#ifdef HAVE_DES_FCRYPT
317 dTHR;
318 return des_fcrypt(txt, salt, w32_crypt_buffer);
319#else
4d76e4b4 320 Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
2986a63f
JH
321 return Nullch;
322#endif
323}
324
325int
326nw_dup(int fd)
327{
328 return dup(fd);
329}
330
331int
332nw_dup2(int fd1,int fd2)
333{
334 return dup2(fd1,fd2);
335}
336
337void*
338nw_dynaload(const char* filename)
339{
340 return NULL;
341}
342
343int
344nw_fclose(FILE *pf)
345{
346 if(pf)
347 return (fclose(pf));
348 else
349 return -1;
350}
351
352FILE *
353nw_fdopen(int handle, const char *mode)
354{
355 return(fdopen(handle, mode));
356}
357
358int
359nw_feof(FILE *fp)
360{
361 if(fp)
362 return (feof(fp));
363 else
364 return -1;
365}
366
367int
368nw_ferror(FILE *fp)
369{
370 if(fp)
371 return (ferror(fp));
372 else
373 return -1;
374}
375
376
377int
378nw_fflush(FILE *pf)
379{
380 if(pf)
381 return fflush(pf);
382 else
383 return -1;
384}
385
386int
387nw_fgetpos(FILE *pf, fpos_t *p)
388{
389 if(pf)
390 return fgetpos(pf, p);
391 else
392 return -1;
393}
394
395char*
396nw_fgets(char *s, int n, FILE *pf)
397{
398 if(pf)
399 return(fgets(s, n, pf));
400 else
401 return NULL;
402}
403
404int
405nw_fileno(FILE *pf)
406{
407 if(pf)
408 return fileno(pf);
409 else
410 return -1;
411}
412
413int
414nw_flock(int fd, int oper)
415{
4d76e4b4
JH
416 dTHX;
417 Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
2986a63f
JH
418 return 0;
419}
420
421
422FILE *
423nw_fopen(const char *filename, const char *mode)
424{
425 return (fopen(filename, mode));
426}
427
428int
429nw_fputc(int c, FILE *pf)
430{
431 if(pf)
432 return fputc(c,pf);
433 else
434 return -1;
435}
436
437int
438nw_fputs(const char *s, FILE *pf)
439{
440 if(pf)
441 return fputs(s, pf);
442 else
443 return -1;
444}
445
446size_t
447nw_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
455FILE *
456nw_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
464int
465nw_fseek(FILE *pf, long offset, int origin)
466{
467 if(pf)
468 return (fseek(pf, offset, origin));
469 else
470 return -1;
471}
472
473int
474nw_fsetpos(FILE *pf, const fpos_t *p)
475{
476 if(pf)
477 return fsetpos(pf, p);
478 else
479 return -1;
480}
481
482long
483nw_ftell(FILE *pf)
484{
485 if(pf)
486 return ftell(pf);
487 else
488 return -1;
489}
490
491size_t
492nw_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
500long
501nw_get_osfhandle(int fd)
502{
503 return 0l;
504}
505
506int
507nw_getc(FILE *pf)
508{
509 if(pf)
510 return getc(pf);
511 else
512 return -1;
513}
514
515int
516nw_putc(int c, FILE *pf)
517{
518 if(pf)
519 return putc(c,pf);
520 else
521 return -1;
522}
523
524int
525nw_fgetc(FILE *pf)
526{
527 if(pf)
528 return fgetc(pf);
529 else
530 return -1;
531}
532
533int
534nw_getpid(void)
535{
536 return GetThreadGroupID();
537}
538
539int
540nw_kill(int pid, int sig)
541{
542 return 0;
543}
544
545int
546nw_link(const char *oldname, const char *newname)
547{
548 return 0;
549}
550
551long
552nw_lseek(int fd, long offset, int origin)
553{
554 return lseek(fd, offset, origin);
555}
556
557int
558nw_chdir(const char *dir)
559{
560 return chdir(dir);
561}
562
563int
564nw_rmdir(const char *dir)
565{
566 return rmdir(dir);
567}
568
569DIR *
0e06f75d 570nw_opendir(const char *filename)
2986a63f
JH
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
593int
594nw_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
011f1a1a 603 if (stricmp(path, "/dev/null")==0)
2ea608c3 604 path = "NWNUL";
2986a63f
JH
605
606 return open(path, flag, pmode);
607}
608
609int
610nw_open_osfhandle(long handle, int flags)
611{
612 return 0;
613}
614
615unsigned long
616nw_os_id(void)
617{
618 return 0l;
619}
620
621int 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
633FILE* 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
684int 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
734int
735nw_vprintf(const char *format, va_list args)
736{
737 return (vprintf(format, args));
738}
739
740int
741nw_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
750int
751nw_read(int fd, void *buf, unsigned int cnt)
752{
753 return read(fd, buf, cnt);
754}
755
756struct direct *
757nw_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
767int
768nw_rename(const char *oname, const char *newname)
769{
770 return(rename(oname,newname));
771}
772
773void
774nw_rewinddir(DIR *dirp)
775{
acfe0abc 776 dTHX;
4d76e4b4 777 Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
2986a63f
JH
778}
779
780void
781nw_rewind(FILE *pf)
782{
783 if(pf)
784 rewind(pf);
785}
786
787void
788nw_seekdir(DIR *dirp, long loc)
789{
acfe0abc 790 dTHX;
4d76e4b4 791 Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
2986a63f
JH
792}
793
794int *
795nw_errno(void)
796{
797 return (&errno);
798}
799
800char ***
801nw_environ(void)
802{
803 return ((char ***)nw_getenviron());
804}
805
806char *
807nw_strerror(int e)
808{
809 return (strerror(e));
810}
811
812int
813nw_isatty(int fd)
814{
815 return(isatty(fd));
816}
817
818char *
819nw_mktemp(char *Template)
820{
821 return (fnMy_MkTemp(Template));
822}
823
824int
825nw_chsize(int handle, long size)
826{
827 return(chsize(handle,size));
828}
829
830#ifdef HAVE_INTERP_INTERN
831void
832sys_intern_init(pTHX)
833{
834
835}
836
837void
838sys_intern_clear(pTHX)
839{
840
841}
842
843void
844sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
845{
846
847}
848#endif /* HAVE_INTERP_INTERN */
849
850void
851Perl_init_os_extras(void)
852{
853
854}
855
856void
857Perl_nw5_init(int *argcp, char ***argvp)
858{
859 MALLOC_INIT;
860}
861
afbec6b0
JH
862#ifdef USE_ITHREADS
863PerlInterpreter *
864perl_clone_host(PerlInterpreter* proto_perl, UV flags)
865{
866 // Perl Clone is not implemented on NetWare.
867 return NULL;
868}
869#endif
870
2986a63f
JH
871// Some more functions:
872
873char *
874nw_get_sitelib(const char *pl)
875{
876 return (NULL);
877}
878
879int
880execv(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
888int
889execvp(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
897int
898do_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};
fa03377f
JH
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
a02a5408
JC
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*);
fa03377f
JH
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
fa03377f
JH
953 if (flag != P_NOWAIT) {
954 if (status < 0) {
1a95e36d 955// dTHR; // Only in old code of 5.6.1
fa03377f 956 if (ckWARN(WARN_EXEC))
f98bc0c6 957 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
fa03377f
JH
958 status = 255 * 256;
959 }
960 else
961 status *= 256;
962 PL_statusvalue = status;
963 }
964
965 Safefree(argv);
966 return (status);
2986a63f
JH
967}
968
969int
970do_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};
1a95e36d
JH
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)) {
a02a5408
JC
990 Newx(argv, strlen(cmd) / 2 + 2, char*);
991 Newx(cmd2, strlen(cmd) + 1, char);
1a95e36d
JH
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
a02a5408 1030 Newx(argv, nw_perlshell_items + 2, char*);
1a95e36d
JH
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);
2986a63f
JH
1066}
1067
1068int
1069do_spawn(char *cmd)
1070{
1a95e36d
JH
1071 return do_spawn2(cmd, EXECF_SPAWN);
1072}
1073
1074// Added to make system() work for NetWare
1075static BOOL
1076has_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;
2986a63f
JH
1114}
1115
1116int
1117fork(void)
1118{
1119 return 0;
1120}
1121
011f1a1a
JH
1122
1123// added to remove undefied symbol error in CodeWarrior compilation
1124int
1125Perl_Ireentrant_buffer_ptr(aTHX)
1126{
1127 return 0;
1128}