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