Commit | Line | Data |
2986a63f |
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 |
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 |
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 | |
2986a63f |
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 | |
2986a63f |
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 |
66 | nw_abort(void) |
67 | { |
68 | abort(); // Terminate the NLM application abnormally. |
69 | return; |
70 | } |
71 | |
72 | int |
73 | nw_access(const char *path, int mode) |
74 | { |
75 | return access(path, mode); |
76 | } |
77 | |
78 | int |
79 | nw_chmod(const char *path, int mode) |
80 | { |
81 | return chmod(path, mode); |
82 | } |
83 | |
84 | void |
85 | nw_clearerr(FILE *pf) |
86 | { |
87 | if(pf) |
88 | clearerr(pf); |
89 | } |
90 | |
91 | int |
92 | nw_close(int fd) |
93 | { |
94 | return close(fd); |
95 | } |
96 | |
97 | nw_closedir(DIR *dirp) |
98 | { |
99 | return (closedir(dirp)); |
100 | } |
101 | |
102 | void |
103 | nw_setbuf(FILE *pf, char *buf) |
104 | { |
105 | if(pf) |
106 | setbuf(pf, buf); |
107 | } |
108 | |
109 | int |
110 | nw_setmode(FILE *fp, int mode) |
111 | { |
f355267c |
112 | /** |
113 | // Commented since a few abends were happening in fnFpSetMode |
2986a63f |
114 | int *dummy = 0; |
115 | return(fnFpSetMode(fp, mode, dummy)); |
f355267c |
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 |
128 | } |
129 | |
130 | int |
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 |
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 |
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 |
194 | nw_execv(char *cmdname, char **argv) |
195 | { |
196 | return spawnvp(P_WAIT, cmdname, (char **)argv); |
197 | } |
198 | |
199 | |
200 | int |
201 | nw_execvp(char *cmdname, char **argv) |
202 | { |
203 | return nw_spawnvp(P_WAIT, cmdname, (char **)argv); |
204 | } |
205 | |
206 | int |
207 | nw_stat(const char *path, struct stat *sbuf) |
208 | { |
209 | return (stat(path, sbuf)); |
210 | } |
211 | |
212 | FILE * |
213 | nw_stderr(void) |
214 | { |
215 | return (stderr); |
216 | } |
217 | |
218 | FILE * |
219 | nw_stdin(void) |
220 | { |
221 | return (stdin); |
222 | } |
223 | |
224 | FILE * |
225 | nw_stdout() |
226 | { |
227 | return (stdout); |
228 | } |
229 | |
230 | long |
231 | nw_telldir(DIR *dirp) |
232 | { |
acfe0abc |
233 | dTHX; |
4d76e4b4 |
234 | Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n"); |
2986a63f |
235 | return 0l; |
236 | } |
237 | |
238 | int |
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* |
252 | nw_tmpfile(void) |
253 | { |
254 | return tmpfile(); |
255 | } |
256 | |
257 | int |
258 | nw_uname(struct utsname *name) |
259 | { |
260 | return(uname(name)); |
261 | } |
262 | |
263 | int |
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 |
273 | nw_unlink(const char *filename) |
274 | { |
275 | return(unlink(filename)); |
276 | } |
277 | |
278 | int |
279 | nw_utime(const char *filename, struct utimbuf *times) |
280 | { |
281 | return(utime(filename, times)); |
282 | } |
283 | |
284 | int |
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 |
294 | nw_wait(int *status) |
295 | { |
296 | return 0; |
297 | } |
298 | |
299 | int |
300 | nw_waitpid(int pid, int *status, int flags) |
301 | { |
302 | return 0; |
303 | } |
304 | |
305 | int |
306 | nw_write(int fd, const void *buf, unsigned int cnt) |
307 | { |
308 | return write(fd, buf, cnt); |
309 | } |
310 | |
311 | char * |
312 | nw_crypt(const char *txt, const char *salt) |
313 | { |
acfe0abc |
314 | dTHX; |
2986a63f |
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 |
321 | return Nullch; |
322 | #endif |
323 | } |
324 | |
325 | int |
326 | nw_dup(int fd) |
327 | { |
328 | return dup(fd); |
329 | } |
330 | |
331 | int |
332 | nw_dup2(int fd1,int fd2) |
333 | { |
334 | return dup2(fd1,fd2); |
335 | } |
336 | |
337 | void* |
338 | nw_dynaload(const char* filename) |
339 | { |
340 | return NULL; |
341 | } |
342 | |
343 | int |
344 | nw_fclose(FILE *pf) |
345 | { |
346 | if(pf) |
347 | return (fclose(pf)); |
348 | else |
349 | return -1; |
350 | } |
351 | |
352 | FILE * |
353 | nw_fdopen(int handle, const char *mode) |
354 | { |
355 | return(fdopen(handle, mode)); |
356 | } |
357 | |
358 | int |
359 | nw_feof(FILE *fp) |
360 | { |
361 | if(fp) |
362 | return (feof(fp)); |
363 | else |
364 | return -1; |
365 | } |
366 | |
367 | int |
368 | nw_ferror(FILE *fp) |
369 | { |
370 | if(fp) |
371 | return (ferror(fp)); |
372 | else |
373 | return -1; |
374 | } |
375 | |
376 | |
377 | int |
378 | nw_fflush(FILE *pf) |
379 | { |
380 | if(pf) |
381 | return fflush(pf); |
382 | else |
383 | return -1; |
384 | } |
385 | |
386 | int |
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* |
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 |
405 | nw_fileno(FILE *pf) |
406 | { |
407 | if(pf) |
408 | return fileno(pf); |
409 | else |
410 | return -1; |
411 | } |
412 | |
413 | int |
414 | nw_flock(int fd, int oper) |
415 | { |
4d76e4b4 |
416 | dTHX; |
417 | Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n"); |
2986a63f |
418 | return 0; |
419 | } |
420 | |
421 | |
422 | FILE * |
423 | nw_fopen(const char *filename, const char *mode) |
424 | { |
425 | return (fopen(filename, mode)); |
426 | } |
427 | |
428 | int |
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 |
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 |
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 * |
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 |
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 |
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 |
483 | nw_ftell(FILE *pf) |
484 | { |
485 | if(pf) |
486 | return ftell(pf); |
487 | else |
488 | return -1; |
489 | } |
490 | |
491 | size_t |
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 |
501 | nw_get_osfhandle(int fd) |
502 | { |
503 | return 0l; |
504 | } |
505 | |
506 | int |
507 | nw_getc(FILE *pf) |
508 | { |
509 | if(pf) |
510 | return getc(pf); |
511 | else |
512 | return -1; |
513 | } |
514 | |
515 | int |
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 |
525 | nw_fgetc(FILE *pf) |
526 | { |
527 | if(pf) |
528 | return fgetc(pf); |
529 | else |
530 | return -1; |
531 | } |
532 | |
533 | int |
534 | nw_getpid(void) |
535 | { |
536 | return GetThreadGroupID(); |
537 | } |
538 | |
539 | int |
540 | nw_kill(int pid, int sig) |
541 | { |
542 | return 0; |
543 | } |
544 | |
545 | int |
546 | nw_link(const char *oldname, const char *newname) |
547 | { |
548 | return 0; |
549 | } |
550 | |
551 | long |
552 | nw_lseek(int fd, long offset, int origin) |
553 | { |
554 | return lseek(fd, offset, origin); |
555 | } |
556 | |
557 | int |
558 | nw_chdir(const char *dir) |
559 | { |
560 | return chdir(dir); |
561 | } |
562 | |
563 | int |
564 | nw_rmdir(const char *dir) |
565 | { |
566 | return rmdir(dir); |
567 | } |
568 | |
569 | DIR * |
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 |
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 | |
011f1a1a |
603 | if (stricmp(path, "/dev/null")==0) |
2ea608c3 |
604 | path = "NWNUL"; |
2986a63f |
605 | |
606 | return open(path, flag, pmode); |
607 | } |
608 | |
609 | int |
610 | nw_open_osfhandle(long handle, int flags) |
611 | { |
612 | return 0; |
613 | } |
614 | |
615 | unsigned long |
616 | nw_os_id(void) |
617 | { |
618 | return 0l; |
619 | } |
620 | |
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 | |
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 | |
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 |
735 | nw_vprintf(const char *format, va_list args) |
736 | { |
737 | return (vprintf(format, args)); |
738 | } |
739 | |
740 | int |
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 |
751 | nw_read(int fd, void *buf, unsigned int cnt) |
752 | { |
753 | return read(fd, buf, cnt); |
754 | } |
755 | |
756 | struct direct * |
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 |
768 | nw_rename(const char *oname, const char *newname) |
769 | { |
770 | return(rename(oname,newname)); |
771 | } |
772 | |
773 | void |
774 | nw_rewinddir(DIR *dirp) |
775 | { |
acfe0abc |
776 | dTHX; |
4d76e4b4 |
777 | Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n"); |
2986a63f |
778 | } |
779 | |
780 | void |
781 | nw_rewind(FILE *pf) |
782 | { |
783 | if(pf) |
784 | rewind(pf); |
785 | } |
786 | |
787 | void |
788 | nw_seekdir(DIR *dirp, long loc) |
789 | { |
acfe0abc |
790 | dTHX; |
4d76e4b4 |
791 | Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n"); |
2986a63f |
792 | } |
793 | |
794 | int * |
795 | nw_errno(void) |
796 | { |
797 | return (&errno); |
798 | } |
799 | |
800 | char *** |
801 | nw_environ(void) |
802 | { |
803 | return ((char ***)nw_getenviron()); |
804 | } |
805 | |
806 | char * |
807 | nw_strerror(int e) |
808 | { |
809 | return (strerror(e)); |
810 | } |
811 | |
812 | int |
813 | nw_isatty(int fd) |
814 | { |
815 | return(isatty(fd)); |
816 | } |
817 | |
818 | char * |
819 | nw_mktemp(char *Template) |
820 | { |
821 | return (fnMy_MkTemp(Template)); |
822 | } |
823 | |
824 | int |
825 | nw_chsize(int handle, long size) |
826 | { |
827 | return(chsize(handle,size)); |
828 | } |
829 | |
830 | #ifdef HAVE_INTERP_INTERN |
831 | void |
832 | sys_intern_init(pTHX) |
833 | { |
834 | |
835 | } |
836 | |
837 | void |
838 | sys_intern_clear(pTHX) |
839 | { |
840 | |
841 | } |
842 | |
843 | void |
844 | sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst) |
845 | { |
846 | |
847 | } |
848 | #endif /* HAVE_INTERP_INTERN */ |
849 | |
850 | void |
851 | Perl_init_os_extras(void) |
852 | { |
853 | |
854 | } |
855 | |
856 | void |
857 | Perl_nw5_init(int *argcp, char ***argvp) |
858 | { |
859 | MALLOC_INIT; |
860 | } |
861 | |
afbec6b0 |
862 | #ifdef USE_ITHREADS |
863 | PerlInterpreter * |
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 | |
2986a63f |
871 | // Some more functions: |
872 | |
873 | char * |
874 | nw_get_sitelib(const char *pl) |
875 | { |
876 | return (NULL); |
877 | } |
878 | |
879 | int |
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 |
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 |
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}; |
fa03377f |
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 |
1a95e36d |
925 | // New(1306, argv, (sp - mark) + nw_perlshell_items + 3, char*); // In the old code of 5.6.1 |
926 | New(1306, argv, (sp - mark) + nw_perlshell_items + 2, char*); |
fa03377f |
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 |
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 |
958 | status = 255 * 256; |
959 | } |
960 | else |
961 | status *= 256; |
962 | PL_statusvalue = status; |
963 | } |
964 | |
965 | Safefree(argv); |
966 | return (status); |
2986a63f |
967 | } |
968 | |
969 | int |
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}; |
1a95e36d |
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 | New(1301,argv, strlen(cmd) / 2 + 2, char*); |
991 | New(1302,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 | New(1306, 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); |
2986a63f |
1066 | } |
1067 | |
1068 | int |
1069 | do_spawn(char *cmd) |
1070 | { |
1a95e36d |
1071 | return do_spawn2(cmd, EXECF_SPAWN); |
1072 | } |
1073 | |
1074 | // Added to make system() work for NetWare |
1075 | static BOOL |
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; |
2986a63f |
1114 | } |
1115 | |
1116 | int |
1117 | fork(void) |
1118 | { |
1119 | return 0; |
1120 | } |
1121 | |
011f1a1a |
1122 | |
1123 | // added to remove undefied symbol error in CodeWarrior compilation |
1124 | int |
1125 | Perl_Ireentrant_buffer_ptr(aTHX) |
1126 | { |
1127 | return 0; |
1128 | } |