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