This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update ExtUtils::ParseXS to 2.20_01
[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");
4e205ed6 321 return NULL;
2986a63f
JH
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{
7918f24d 846 PERL_ARGS_ASSERT_SYS_INTERN_DUP;
2986a63f
JH
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
2986a63f
JH
873int
874execv(char *cmdname, char **argv)
875{
876 // This feature needs to be implemented.
877 // _asm is commented out since it goes into the internal debugger.
878// _asm {int 3};
879 return(0);
880}
881
882int
883execvp(char *cmdname, char **argv)
884{
885 // This feature needs to be implemented.
886 // _asm is commented out since it goes into the internal debugger.
887// _asm {int 3};
888 return(0);
889}
890
891int
892do_aspawn(void *vreally, void **vmark, void **vsp)
893{
894 // This feature needs to be implemented.
895 // _asm is commented out since it goes into the internal debugger.
896// _asm {int 3};
fa03377f
JH
897//// return(0);
898
899
900 // This below code is required for system() call.
901 // Otherwise system() does not work on NetWare.
902 // Ananth, 3 Sept 2001
903
904 dTHX;
905 SV *really = (SV*)vreally;
906 SV **mark = (SV**)vmark;
907 SV **sp = (SV**)vsp;
908 char **argv;
909 char *str;
910 int status;
911 int flag = P_WAIT;
912 int index = 0;
913
914
915 if (sp <= mark)
916 return -1;
917
918 nw_perlshell_items = 0; // No Shell
a02a5408
JC
919// Newx(argv, (sp - mark) + nw_perlshell_items + 3, char*); // In the old code of 5.6.1
920 Newx(argv, (sp - mark) + nw_perlshell_items + 2, char*);
fa03377f
JH
921
922 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
923 ++mark;
924 flag = SvIVx(*mark);
925 }
926
927 while (++mark <= sp) {
928 if (*mark && (str = (char *)SvPV_nolen(*mark)))
929 {
930 argv[index] = str;
931 index++;
932 }
933 else
934 {
935 argv[index] = "";
936// argv[index] = '\0';
937 index++;
938 }
939 }
940 argv[index] = '\0';
941 index++;
942
943 status = nw_spawnvp(flag,
944 (char*)(really ? SvPV_nolen(really) : argv[0]),
945 (char**)argv);
946
fa03377f
JH
947 if (flag != P_NOWAIT) {
948 if (status < 0) {
1a95e36d 949// dTHR; // Only in old code of 5.6.1
fa03377f 950 if (ckWARN(WARN_EXEC))
f98bc0c6 951 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
fa03377f
JH
952 status = 255 * 256;
953 }
954 else
955 status *= 256;
956 PL_statusvalue = status;
957 }
958
959 Safefree(argv);
960 return (status);
2986a63f
JH
961}
962
963int
964do_spawn2(char *cmd, int exectype)
965{
966 // This feature needs to be implemented.
967 // _asm is commented out since it goes into the internal debugger.
968// _asm {int 3};
1a95e36d
JH
969//// return(0);
970
971 // Below added to make system() work for NetWare
972
973 dTHX;
974 char **a;
975 char *s;
976 char **argv;
977 int status = -1;
978 BOOL needToTry = TRUE;
979 char *cmd2;
980
981 /* Save an extra exec if possible. See if there are shell
982 * metacharacters in it */
983 if (!has_shell_metachars(cmd)) {
a02a5408
JC
984 Newx(argv, strlen(cmd) / 2 + 2, char*);
985 Newx(cmd2, strlen(cmd) + 1, char);
1a95e36d
JH
986 strcpy(cmd2, cmd);
987 a = argv;
988 for (s = cmd2; *s;) {
989 while (*s && isSPACE(*s))
990 s++;
991 if (*s)
992 *(a++) = s;
993 while (*s && !isSPACE(*s))
994 s++;
995 if (*s)
996 *s++ = '\0';
997 }
4e205ed6 998 *a = NULL;
1a95e36d
JH
999 if (argv[0]) {
1000 switch (exectype) {
1001 case EXECF_SPAWN:
1002 status = nw_spawnvp(P_WAIT, argv[0], (char **)argv);
1003 break;
1004
1005 case EXECF_SPAWN_NOWAIT:
1006 status = nw_spawnvp(P_NOWAIT, argv[0], (char **)argv);
1007 break;
1008
1009 case EXECF_EXEC:
1010 status = nw_execvp(argv[0], (char **)argv);
1011 break;
1012 }
1013 if (status != -1 || errno == 0)
1014 needToTry = FALSE;
1015 }
1016 Safefree(argv);
1017 Safefree(cmd2);
1018 }
1019
1020 if (needToTry) {
1021 char **argv = NULL;
1022 int i = -1;
1023
a02a5408 1024 Newx(argv, nw_perlshell_items + 2, char*);
1a95e36d
JH
1025 while (++i < nw_perlshell_items)
1026 argv[i] = nw_perlshell_vec[i];
1027 argv[i++] = cmd;
4e205ed6 1028 argv[i] = NULL;
1a95e36d
JH
1029 switch (exectype) {
1030 case EXECF_SPAWN:
1031 status = nw_spawnvp(P_WAIT, argv[0], (char **)argv);
1032 break;
1033
1034 case EXECF_SPAWN_NOWAIT:
1035 status = nw_spawnvp(P_NOWAIT, argv[0], (char **)argv);
1036 break;
1037
1038 case EXECF_EXEC:
1039 status = nw_execvp(argv[0], (char **)argv);
1040 break;
1041 }
1042 cmd = argv[0];
1043 Safefree(argv);
1044 }
1045
1046 if (exectype != EXECF_SPAWN_NOWAIT) {
1047 if (status < 0) {
1048 dTHR;
1049 if (ckWARN(WARN_EXEC))
1050 Perl_warner(aTHX_ WARN_EXEC, "Can't %s \"%s\": %s",
1051 (exectype == EXECF_EXEC ? "exec" : "spawn"),
1052 cmd, strerror(errno));
1053 status = 255 * 256;
1054 }
1055 else
1056 status *= 256;
1057 PL_statusvalue = status;
1058 }
1059 return (status);
2986a63f
JH
1060}
1061
1062int
1063do_spawn(char *cmd)
1064{
1a95e36d
JH
1065 return do_spawn2(cmd, EXECF_SPAWN);
1066}
1067
1068// Added to make system() work for NetWare
1069static BOOL
1070has_shell_metachars(char *ptr)
1071{
1072 int inquote = 0;
1073 char quote = '\0';
1074
1075 /*
1076 * Scan string looking for redirection (< or >) or pipe
1077 * characters (|) that are not in a quoted string.
1078 * Shell variable interpolation (%VAR%) can also happen inside strings.
1079 */
1080 while (*ptr) {
1081 switch(*ptr) {
1082 case '%':
1083 return TRUE;
1084 case '\'':
1085 case '\"':
1086 if (inquote) {
1087 if (quote == *ptr) {
1088 inquote = 0;
1089 quote = '\0';
1090 }
1091 }
1092 else {
1093 quote = *ptr;
1094 inquote++;
1095 }
1096 break;
1097 case '>':
1098 case '<':
1099 case '|':
1100 if (!inquote)
1101 return TRUE;
1102 default:
1103 break;
1104 }
1105 ++ptr;
1106 }
1107 return FALSE;
2986a63f
JH
1108}
1109
1110int
1111fork(void)
1112{
1113 return 0;
1114}
1115
011f1a1a
JH
1116
1117// added to remove undefied symbol error in CodeWarrior compilation
1118int
1119Perl_Ireentrant_buffer_ptr(aTHX)
1120{
1121 return 0;
1122}