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