Constant.t for EBCDIC platforms
[p5sagit/p5-mst-13.2.git] / NetWare / nw5.c
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 // 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!
43 PTEMPPIPEFILE ptpf1[MAX_PIPE_RECURSION] = {'\0'};
44 int iPopenCount = 0;
45 FILE* File1[MAX_PIPE_RECURSION] = {'\0'};
46
47
48 /**
49 General:
50
51 In this code, wherever there is a  FILE *, the error condition is checked; and only if the FILE * is TRUE,
52 then the corresponding operation is done. Otherwise the error value is returned.
53 This is done because the file operations like "open" in the Perl code returns the FILE *,
54 returning a valid value if the file is found or NULL when the particular file is not found.
55 Now, if the return value is NULL, then an operation say "fgets", "fopen" etc. using this this NULL value
56 for FILE * will abend the server. If the check is made then an operation on a non existing file
57 does not abend the server.
58 **/
59
60 void
61 nw_abort(void)
62 {
63         abort();        // Terminate the NLM application abnormally.
64         return;
65 }
66
67 int
68 nw_access(const char *path, int mode) 
69 {
70     return access(path, mode);
71 }
72
73 int
74 nw_chmod(const char *path, int mode)
75 {
76     return chmod(path, mode);
77 }
78
79 void
80 nw_clearerr(FILE *pf)
81 {
82         if(pf)
83             clearerr(pf);
84 }
85
86 int
87 nw_close(int fd)
88 {
89     return close(fd);
90 }
91
92 nw_closedir(DIR *dirp)
93 {
94         return (closedir(dirp));
95 }
96
97 void
98 nw_setbuf(FILE *pf, char *buf)
99 {
100         if(pf)
101             setbuf(pf, buf);
102 }
103
104 int
105 nw_setmode(FILE *fp, int mode)
106 {
107 /**
108         // Commented since a few abends were happening in fnFpSetMode
109         int *dummy = 0;
110         return(fnFpSetMode(fp, mode, dummy));
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);
123 }
124
125 int
126 nw_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
135 unsigned int
136 nw_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
142 int
143 nw_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
188 int
189 nw_execv(char *cmdname, char **argv)
190 {
191         return spawnvp(P_WAIT, cmdname, (char **)argv);
192 }
193
194
195 int
196 nw_execvp(char *cmdname, char **argv)
197 {
198         return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
199 }
200
201 int
202 nw_stat(const char *path, struct stat *sbuf)
203 {
204         return (stat(path, sbuf));
205 }
206
207 FILE *
208 nw_stderr(void)
209 {
210         return (stderr);
211 }
212
213 FILE *
214 nw_stdin(void)
215 {
216         return (stdin);
217 }
218
219 FILE *
220 nw_stdout()
221 {
222         return (stdout);
223 }
224
225 long
226 nw_telldir(DIR *dirp)
227 {
228         dTHX;
229         Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
230         return 0l;
231 }
232
233 int
234 nw_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
246 FILE*
247 nw_tmpfile(void)
248 {
249     return tmpfile();
250 }
251
252 int
253 nw_uname(struct utsname *name)
254 {
255         return(uname(name));
256 }
257
258 int
259 nw_ungetc(int c, FILE *pf)
260 {
261         if(pf)
262             return ungetc(c, pf);
263         else
264             return -1;
265 }
266
267 int
268 nw_unlink(const char *filename)
269 {
270         return(unlink(filename));
271 }
272
273 int
274 nw_utime(const char *filename, struct utimbuf *times)
275 {
276          return(utime(filename, times));
277 }
278
279 int
280 nw_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
288 int
289 nw_wait(int *status)
290 {
291     return 0;   
292 }
293
294 int
295 nw_waitpid(int pid, int *status, int flags)
296 {
297     return 0;   
298 }
299
300 int
301 nw_write(int fd, const void *buf, unsigned int cnt)
302 {
303     return write(fd, buf, cnt);
304 }
305
306 char *
307 nw_crypt(const char *txt, const char *salt)
308 {
309          dTHX;
310
311 #ifdef HAVE_DES_FCRYPT
312     dTHR;
313     return des_fcrypt(txt, salt, w32_crypt_buffer);
314 #else
315     Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
316     return Nullch;
317 #endif
318 }
319
320 int
321 nw_dup(int fd)
322 {
323     return dup(fd);
324 }
325
326 int
327 nw_dup2(int fd1,int fd2)
328 {
329         return dup2(fd1,fd2);
330 }
331
332 void*
333 nw_dynaload(const char* filename)
334 {
335         return NULL;
336 }
337
338 int
339 nw_fclose(FILE *pf)
340 {
341         if(pf)
342             return (fclose(pf));
343         else
344             return -1;
345 }
346
347 FILE *
348 nw_fdopen(int handle, const char *mode)
349 {
350         return(fdopen(handle, mode));
351 }
352
353 int
354 nw_feof(FILE *fp)
355 {
356         if(fp)
357             return (feof(fp));
358         else
359             return -1;
360 }
361
362 int
363 nw_ferror(FILE *fp)
364 {
365         if(fp)
366             return (ferror(fp));
367         else
368             return -1;
369 }
370
371
372 int
373 nw_fflush(FILE *pf)
374 {
375         if(pf)
376             return fflush(pf);
377         else
378             return -1;
379 }
380
381 int
382 nw_fgetpos(FILE *pf, fpos_t *p)
383 {
384         if(pf)
385             return fgetpos(pf, p);
386         else
387             return -1;
388 }
389
390 char*
391 nw_fgets(char *s, int n, FILE *pf)
392 {
393         if(pf)
394             return(fgets(s, n, pf));
395         else
396             return NULL;
397 }
398
399 int
400 nw_fileno(FILE *pf)
401 {
402         if(pf)
403             return fileno(pf);
404         else
405             return -1;
406 }
407
408 int
409 nw_flock(int fd, int oper)
410 {
411         dTHX;
412         Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
413         return 0;
414 }
415
416
417 FILE *
418 nw_fopen(const char *filename, const char *mode)
419 {
420         return (fopen(filename, mode));
421 }
422
423 int
424 nw_fputc(int c, FILE *pf)
425 {
426         if(pf)
427             return fputc(c,pf);
428         else
429             return -1;
430 }
431
432 int
433 nw_fputs(const char *s, FILE *pf)
434 {
435         if(pf)
436             return fputs(s, pf);
437         else
438             return -1;
439 }
440
441 size_t
442 nw_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
450 FILE *
451 nw_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
459 int
460 nw_fseek(FILE *pf, long offset, int origin)
461 {
462         if(pf)
463             return (fseek(pf, offset, origin));
464         else
465             return -1;
466 }
467
468 int
469 nw_fsetpos(FILE *pf, const fpos_t *p)
470 {
471         if(pf)
472             return fsetpos(pf, p);
473         else
474             return -1;
475 }
476
477 long
478 nw_ftell(FILE *pf)
479 {
480         if(pf)
481             return ftell(pf);
482         else
483             return -1;
484 }
485
486 size_t
487 nw_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
495 long
496 nw_get_osfhandle(int fd)
497 {
498         return 0l;
499 }
500
501 int
502 nw_getc(FILE *pf)
503 {
504         if(pf)
505             return getc(pf);
506         else
507             return -1;
508 }
509
510 int
511 nw_putc(int c, FILE *pf)
512 {
513         if(pf)
514             return putc(c,pf);
515         else
516             return -1;
517 }
518
519 int
520 nw_fgetc(FILE *pf)
521 {
522         if(pf)
523             return fgetc(pf);
524         else
525             return -1;
526 }
527
528 int
529 nw_getpid(void)
530 {
531         return GetThreadGroupID();
532 }
533
534 int
535 nw_kill(int pid, int sig)
536 {
537         return 0;
538 }
539
540 int
541 nw_link(const char *oldname, const char *newname)
542 {
543         return 0;
544 }
545
546 long
547 nw_lseek(int fd, long offset, int origin)
548 {
549     return lseek(fd, offset, origin);
550 }
551
552 int
553 nw_chdir(const char *dir)
554 {
555     return chdir(dir);
556 }
557
558 int
559 nw_rmdir(const char *dir)
560 {
561     return rmdir(dir);
562 }
563
564 DIR *
565 nw_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
588 int
589 nw_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
598         if (stricmp(path, "/dev/null")==0)
599         path = "NWNUL";
600
601         return open(path, flag, pmode);
602 }
603
604 int
605 nw_open_osfhandle(long handle, int flags)
606 {
607         return 0;
608 }
609
610 unsigned long
611 nw_os_id(void)
612 {
613         return 0l;
614 }
615
616 int 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
628 FILE* 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
679 int 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
729 int
730 nw_vprintf(const char *format, va_list args)
731 {
732     return (vprintf(format, args));
733 }
734
735 int
736 nw_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
745 int
746 nw_read(int fd, void *buf, unsigned int cnt)
747 {
748         return read(fd, buf, cnt);
749 }
750
751 struct direct *
752 nw_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
762 int
763 nw_rename(const char *oname, const char *newname)
764 {
765         return(rename(oname,newname));
766 }
767
768 void
769 nw_rewinddir(DIR *dirp)
770 {
771         dTHX;
772         Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
773 }
774
775 void
776 nw_rewind(FILE *pf)
777 {
778         if(pf)
779             rewind(pf);
780 }
781
782 void
783 nw_seekdir(DIR *dirp, long loc)
784 {
785         dTHX;
786         Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
787 }
788
789 int *
790 nw_errno(void)
791 {
792     return (&errno);
793 }
794
795 char ***
796 nw_environ(void)
797 {
798         return ((char ***)nw_getenviron());
799 }
800
801 char *
802 nw_strerror(int e)
803 {
804         return (strerror(e));
805 }
806
807 int
808 nw_isatty(int fd)
809 {
810         return(isatty(fd));
811 }
812
813 char *
814 nw_mktemp(char *Template)
815 {
816         return (fnMy_MkTemp(Template));
817 }
818
819 int
820 nw_chsize(int handle, long size)
821 {
822         return(chsize(handle,size));
823 }
824
825 #ifdef HAVE_INTERP_INTERN
826 void
827 sys_intern_init(pTHX)
828 {
829
830 }
831
832 void
833 sys_intern_clear(pTHX)
834 {
835
836 }
837
838 void
839 sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
840 {
841
842 }
843 #endif  /* HAVE_INTERP_INTERN */
844
845 void
846 Perl_init_os_extras(void)
847 {
848     
849 }
850
851 void
852 Perl_nw5_init(int *argcp, char ***argvp)
853 {
854     MALLOC_INIT;
855 }
856
857 #ifdef USE_ITHREADS
858 PerlInterpreter *
859 perl_clone_host(PerlInterpreter* proto_perl, UV flags)
860 {
861         // Perl Clone is not implemented on NetWare.
862     return NULL;
863 }
864 #endif
865
866 // Some more functions:
867
868 char *
869 nw_get_sitelib(const char *pl)
870 {
871     return (NULL);
872 }
873
874 int
875 execv(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
883 int
884 execvp(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
892 int
893 do_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};
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))
952                 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
953             status = 255 * 256;
954         }
955         else
956             status *= 256;
957         PL_statusvalue = status;
958     }
959
960     Safefree(argv);
961     return (status);
962 }
963
964 int
965 do_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
973 int
974 do_spawn(char *cmd)
975 {
976     return do_spawn2(cmd, 2);
977 }
978
979 int
980 fork(void)
981 {
982         return 0;
983 }
984
985
986 // added to remove undefied symbol error in CodeWarrior compilation
987 int
988 Perl_Ireentrant_buffer_ptr(aTHX)
989 {
990         return 0;
991 }