This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
HP-UX has also endgrent_r/endpwent_r marked obsolete.
[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;
4d76e4b4 215 Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
2986a63f
JH
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
4d76e4b4 301 Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
2986a63f
JH
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{
4d76e4b4
JH
397 dTHX;
398 Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
2986a63f
JH
399 return 0;
400}
401
402
403FILE *
404nw_fopen(const char *filename, const char *mode)
405{
406 return (fopen(filename, mode));
407}
408
409int
410nw_fputc(int c, FILE *pf)
411{
412 if(pf)
413 return fputc(c,pf);
414 else
415 return -1;
416}
417
418int
419nw_fputs(const char *s, FILE *pf)
420{
421 if(pf)
422 return fputs(s, pf);
423 else
424 return -1;
425}
426
427size_t
428nw_fread(void *buf, size_t size, size_t count, FILE *fp)
429{
430 if(fp)
431 return fread(buf, size, count, fp);
432 else
433 return -1;
434}
435
436FILE *
437nw_freopen(const char *path, const char *mode, FILE *stream)
438{
439 if(stream)
440 return freopen(path, mode, stream);
441 else
442 return NULL;
443}
444
445int
446nw_fseek(FILE *pf, long offset, int origin)
447{
448 if(pf)
449 return (fseek(pf, offset, origin));
450 else
451 return -1;
452}
453
454int
455nw_fsetpos(FILE *pf, const fpos_t *p)
456{
457 if(pf)
458 return fsetpos(pf, p);
459 else
460 return -1;
461}
462
463long
464nw_ftell(FILE *pf)
465{
466 if(pf)
467 return ftell(pf);
468 else
469 return -1;
470}
471
472size_t
473nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
474{
475 if(fp)
476 return fwrite(buf, size, count, fp);
477 else
478 return -1;
479}
480
481long
482nw_get_osfhandle(int fd)
483{
484 return 0l;
485}
486
487int
488nw_getc(FILE *pf)
489{
490 if(pf)
491 return getc(pf);
492 else
493 return -1;
494}
495
496int
497nw_putc(int c, FILE *pf)
498{
499 if(pf)
500 return putc(c,pf);
501 else
502 return -1;
503}
504
505int
506nw_fgetc(FILE *pf)
507{
508 if(pf)
509 return fgetc(pf);
510 else
511 return -1;
512}
513
514int
515nw_getpid(void)
516{
517 return GetThreadGroupID();
518}
519
520int
521nw_kill(int pid, int sig)
522{
523 return 0;
524}
525
526int
527nw_link(const char *oldname, const char *newname)
528{
529 return 0;
530}
531
532long
533nw_lseek(int fd, long offset, int origin)
534{
535 return lseek(fd, offset, origin);
536}
537
538int
539nw_chdir(const char *dir)
540{
541 return chdir(dir);
542}
543
544int
545nw_rmdir(const char *dir)
546{
547 return rmdir(dir);
548}
549
550DIR *
551nw_opendir(char *filename)
552{
553 char *buff = NULL;
554 int len = 0;
555 DIR *ret = NULL;
556
557 len = strlen(filename);
558 buff = malloc(len + 5);
559 if (buff) {
560 strcpy(buff, filename);
561 if (buff[len-1]=='/' || buff[len-1]=='\\') {
562 buff[--len] = 0;
563 }
564 strcpy(buff+len, "/*.*");
565 ret = opendir(buff);
566 free (buff);
567 buff = NULL;
568 return ret;
569 } else {
570 return NULL;
571 }
572}
573
574int
575nw_open(const char *path, int flag, ...)
576{
577 va_list ap;
578 int pmode = -1;
579
580 va_start(ap, flag);
581 pmode = va_arg(ap, int);
582 va_end(ap);
583
584 if (stricmp(path, "/dev/null")==0)
585 path = "NUL";
586
587 return open(path, flag, pmode);
588}
589
590int
591nw_open_osfhandle(long handle, int flags)
592{
593 return 0;
594}
595
596unsigned long
597nw_os_id(void)
598{
599 return 0l;
600}
601
602int nw_Pipe(int* a, int* e)
603{
604 int ret = 0;
605
606 errno = 0;
607 ret = pipe(a);
608 if(errno)
609 e = &errno;
610
611 return ret;
612}
613
614FILE* nw_Popen(char* command, char* mode, int* e)
615{
616 int i = -1;
617
618 FILE* ret = NULL;
619 PTEMPPIPEFILE ptpf = NULL;
620
621 // this callback is supposed to call _popen, which spawns an
622 // asynchronous command and opens a pipe to it. The returned
623 // file handle can be read or written to; if read, it represents
624 // stdout of the called process and will return EOF when the
625 // called process finishes. If written to, it represents stdin
626 // of the called process. Naturally _popen is not available on
627 // NetWare so we must do some fancy stuff to simulate it. We will
628 // redirect to and from temp files; this has the side effect
629 // of having to run the process synchronously rather than
630 // asynchronously. This means that you will only be able to do
631 // this with CLIB NLMs built to run on the calling thread.
632
633 errno = 0;
634
635 ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
636 if (!ptpf1[iPopenCount])
637 return NULL;
638
639 ptpf = ptpf1[iPopenCount];
640 iPopenCount ++;
641 if(iPopenCount > MAX_PIPE_RECURSION)
642 iPopenCount = MAX_PIPE_RECURSION; // Limit to the max no of pipes to be open recursively.
643
644 fnTempPipeFile(ptpf);
645 ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
646 if (ret)
647 File1[iPopenCount-1] = ret; // Store the obtained Pipe file handle.
648 else
649 { // Pipe file not obtained. So free the allocated memory.
650 if(ptpf1[iPopenCount-1])
651 {
652 free(ptpf1[iPopenCount-1]);
653 ptpf1[iPopenCount-1] = NULL;
654 ptpf = NULL;
655 iPopenCount --;
656 }
657 }
658
659 if (errno)
660 e = &errno;
661
662 return ret;
663}
664
665int nw_Pclose(FILE* file, int* e)
666{
667 int i=0, j=0;
668
669 errno = 0;
670
671 if(file)
672 {
673 if(iPopenCount > 0)
674 {
675 for (i=0; i<iPopenCount; i++)
676 {
677 if(File1[i] == file)
678 {
679 // Delete the memory allocated corresponding to the file handle passed-in and
680 // also close the file corresponding to the file handle passed-in!
681 if(ptpf1[i])
682 {
683 fnPipeFileClose(ptpf1[i]);
684
685 free(ptpf1[i]);
686 ptpf1[i] = NULL;
687 }
688
689 fclose(File1[i]);
690 File1[i] = NULL;
691
692 break;
693 }
694 }
695
696 // Rearrange the file pointer array
697 for(j=i; j<(iPopenCount-1); j++)
698 {
699 File1[j] = File1[j+1];
700 ptpf1[j] = ptpf1[j+1];
701 }
702 iPopenCount--;
703 }
704 }
705 else
706 return -1;
707
708 if (errno)
709 e = &errno;
710
711 return 0;
712}
713
714
715int
716nw_vprintf(const char *format, va_list args)
717{
718 return (vprintf(format, args));
719}
720
721int
722nw_printf(const char *format, ...)
723{
724
725 va_list marker;
726 va_start(marker, format); /* Initialize variable arguments. */
727
728 return (vprintf(format, marker));
729}
730
731int
732nw_read(int fd, void *buf, unsigned int cnt)
733{
734 return read(fd, buf, cnt);
735}
736
737struct direct *
738nw_readdir(DIR *dirp)
739{
740 DIR* ret=NULL;
741
742 ret = readdir(dirp);
743 if(ret)
744 return((struct direct *)ret);
745 return NULL;
746}
747
748int
749nw_rename(const char *oname, const char *newname)
750{
751 return(rename(oname,newname));
752}
753
754void
755nw_rewinddir(DIR *dirp)
756{
acfe0abc 757 dTHX;
4d76e4b4 758 Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
2986a63f
JH
759}
760
761void
762nw_rewind(FILE *pf)
763{
764 if(pf)
765 rewind(pf);
766}
767
768void
769nw_seekdir(DIR *dirp, long loc)
770{
acfe0abc 771 dTHX;
4d76e4b4 772 Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
2986a63f
JH
773}
774
775int *
776nw_errno(void)
777{
778 return (&errno);
779}
780
781char ***
782nw_environ(void)
783{
784 return ((char ***)nw_getenviron());
785}
786
787char *
788nw_strerror(int e)
789{
790 return (strerror(e));
791}
792
793int
794nw_isatty(int fd)
795{
796 return(isatty(fd));
797}
798
799char *
800nw_mktemp(char *Template)
801{
802 return (fnMy_MkTemp(Template));
803}
804
805int
806nw_chsize(int handle, long size)
807{
808 return(chsize(handle,size));
809}
810
811#ifdef HAVE_INTERP_INTERN
812void
813sys_intern_init(pTHX)
814{
815
816}
817
818void
819sys_intern_clear(pTHX)
820{
821
822}
823
824void
825sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
826{
827
828}
829#endif /* HAVE_INTERP_INTERN */
830
831void
832Perl_init_os_extras(void)
833{
834
835}
836
837void
838Perl_nw5_init(int *argcp, char ***argvp)
839{
840 MALLOC_INIT;
841}
842
afbec6b0
JH
843#ifdef USE_ITHREADS
844PerlInterpreter *
845perl_clone_host(PerlInterpreter* proto_perl, UV flags)
846{
847 // Perl Clone is not implemented on NetWare.
848 return NULL;
849}
850#endif
851
2986a63f
JH
852// Some more functions:
853
854char *
855nw_get_sitelib(const char *pl)
856{
857 return (NULL);
858}
859
860int
861execv(char *cmdname, char **argv)
862{
863 // This feature needs to be implemented.
864 // _asm is commented out since it goes into the internal debugger.
865// _asm {int 3};
866 return(0);
867}
868
869int
870execvp(char *cmdname, char **argv)
871{
872 // This feature needs to be implemented.
873 // _asm is commented out since it goes into the internal debugger.
874// _asm {int 3};
875 return(0);
876}
877
878int
879do_aspawn(void *vreally, void **vmark, void **vsp)
880{
881 // This feature needs to be implemented.
882 // _asm is commented out since it goes into the internal debugger.
883// _asm {int 3};
fa03377f
JH
884//// return(0);
885
886
887 // This below code is required for system() call.
888 // Otherwise system() does not work on NetWare.
889 // Ananth, 3 Sept 2001
890
891 dTHX;
892 SV *really = (SV*)vreally;
893 SV **mark = (SV**)vmark;
894 SV **sp = (SV**)vsp;
895 char **argv;
896 char *str;
897 int status;
898 int flag = P_WAIT;
899 int index = 0;
900
901
902 if (sp <= mark)
903 return -1;
904
905 nw_perlshell_items = 0; // No Shell
906 New(1306, argv, (sp - mark) + nw_perlshell_items + 3, char*);
907
908 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
909 ++mark;
910 flag = SvIVx(*mark);
911 }
912
913 while (++mark <= sp) {
914 if (*mark && (str = (char *)SvPV_nolen(*mark)))
915 {
916 argv[index] = str;
917 index++;
918 }
919 else
920 {
921 argv[index] = "";
922// argv[index] = '\0';
923 index++;
924 }
925 }
926 argv[index] = '\0';
927 index++;
928
929 status = nw_spawnvp(flag,
930 (char*)(really ? SvPV_nolen(really) : argv[0]),
931 (char**)argv);
932
933
934 if (flag != P_NOWAIT) {
935 if (status < 0) {
936 dTHR;
937 if (ckWARN(WARN_EXEC))
938 Perl_warner(aTHX_ WARN_EXEC, "Can't spawn \"%s\": %s", argv[0], strerror(errno));
939 status = 255 * 256;
940 }
941 else
942 status *= 256;
943 PL_statusvalue = status;
944 }
945
946 Safefree(argv);
947 return (status);
2986a63f
JH
948}
949
950int
951do_spawn2(char *cmd, int exectype)
952{
953 // This feature needs to be implemented.
954 // _asm is commented out since it goes into the internal debugger.
955// _asm {int 3};
956 return(0);
957}
958
959int
960do_spawn(char *cmd)
961{
962 return do_spawn2(cmd, 2);
963}
964
965int
966fork(void)
967{
968 return 0;
969}
970