3 * Copyright © 2001 Novell, Inc. All Rights Reserved.
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.
12 * DESCRIPTION : Definitions for the redefined functions for NetWare.
14 * Date : January 2001.
20 #include <perl.h> // For dTHX, etc.
24 // This was added since the compile failed saying "undefined P_WAIT"
25 // when USE_ITHREADS was commented in the makefile
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!
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'};
45 FILE* File1[MAX_PIPE_RECURSION] = {'\0'};
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.
63 abort(); // Terminate the NLM application abnormally.
68 nw_access(const char *path, int mode)
70 return access(path, mode);
74 nw_chmod(const char *path, int mode)
76 return chmod(path, mode);
92 nw_closedir(DIR *dirp)
94 return (closedir(dirp));
98 nw_setbuf(FILE *pf, char *buf)
105 nw_setmode(FILE *fp, int mode)
108 // Commented since a few abends were happening in fnFpSetMode
110 return(fnFpSetMode(fp, mode, dummy));
122 return setmode(handle, mode);
126 nw_setvbuf(FILE *pf, char *buf, int type, size_t size)
129 return setvbuf(pf, buf, type, size);
136 nw_sleep(unsigned int t)
138 delay(t*1000); // Put the thread to sleep for 't' seconds. Initially 't' is passed in milliseconds.
143 nw_spawnvp(int mode, char *cmdname, char **argv)
145 // There is no pass-around environment on NetWare so we throw that
146 // argument away for now.
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
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.
170 if (stricmp(cmdname, LOAD_COMMAND) == 0)
173 ret = spawnvp(mode, argv[1], &argv[1]);
178 while (argv[i] != '\0')
182 fnSystemCommand(argv, argc);
189 nw_execv(char *cmdname, char **argv)
191 return spawnvp(P_WAIT, cmdname, (char **)argv);
196 nw_execvp(char *cmdname, char **argv)
198 return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
202 nw_stat(const char *path, struct stat *sbuf)
204 return (stat(path, sbuf));
226 nw_telldir(DIR *dirp)
229 Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
234 nw_times(struct tms *timebuf)
236 clock_t now = clock();
238 timebuf->tms_utime = now;
239 timebuf->tms_stime = 0;
240 timebuf->tms_cutime = 0;
241 timebuf->tms_cstime = 0;
253 nw_uname(struct utsname *name)
259 nw_ungetc(int c, FILE *pf)
262 return ungetc(c, pf);
268 nw_unlink(const char *filename)
270 return(unlink(filename));
274 nw_utime(const char *filename, struct utimbuf *times)
276 return(utime(filename, times));
280 nw_vfprintf(FILE *fp, const char *format, va_list args)
283 return (vfprintf(fp, format, args));
295 nw_waitpid(int pid, int *status, int flags)
301 nw_write(int fd, const void *buf, unsigned int cnt)
303 return write(fd, buf, cnt);
307 nw_crypt(const char *txt, const char *salt)
311 #ifdef HAVE_DES_FCRYPT
313 return des_fcrypt(txt, salt, w32_crypt_buffer);
315 Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
327 nw_dup2(int fd1,int fd2)
329 return dup2(fd1,fd2);
333 nw_dynaload(const char* filename)
348 nw_fdopen(int handle, const char *mode)
350 return(fdopen(handle, mode));
382 nw_fgetpos(FILE *pf, fpos_t *p)
385 return fgetpos(pf, p);
391 nw_fgets(char *s, int n, FILE *pf)
394 return(fgets(s, n, pf));
409 nw_flock(int fd, int oper)
412 Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
418 nw_fopen(const char *filename, const char *mode)
420 return (fopen(filename, mode));
424 nw_fputc(int c, FILE *pf)
433 nw_fputs(const char *s, FILE *pf)
442 nw_fread(void *buf, size_t size, size_t count, FILE *fp)
445 return fread(buf, size, count, fp);
451 nw_freopen(const char *path, const char *mode, FILE *stream)
454 return freopen(path, mode, stream);
460 nw_fseek(FILE *pf, long offset, int origin)
463 return (fseek(pf, offset, origin));
469 nw_fsetpos(FILE *pf, const fpos_t *p)
472 return fsetpos(pf, p);
487 nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
490 return fwrite(buf, size, count, fp);
496 nw_get_osfhandle(int fd)
511 nw_putc(int c, FILE *pf)
531 return GetThreadGroupID();
535 nw_kill(int pid, int sig)
541 nw_link(const char *oldname, const char *newname)
547 nw_lseek(int fd, long offset, int origin)
549 return lseek(fd, offset, origin);
553 nw_chdir(const char *dir)
559 nw_rmdir(const char *dir)
565 nw_opendir(char *filename)
571 len = strlen(filename);
572 buff = malloc(len + 5);
574 strcpy(buff, filename);
575 if (buff[len-1]=='/' || buff[len-1]=='\\') {
578 strcpy(buff+len, "/*.*");
589 nw_open(const char *path, int flag, ...)
595 pmode = va_arg(ap, int);
598 if (stricmp(path, "/dev/null")==0)
601 return open(path, flag, pmode);
605 nw_open_osfhandle(long handle, int flags)
616 int nw_Pipe(int* a, int* e)
628 FILE* nw_Popen(char* command, char* mode, int* e)
633 PTEMPPIPEFILE ptpf = NULL;
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.
649 ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
650 if (!ptpf1[iPopenCount])
653 ptpf = ptpf1[iPopenCount];
655 if(iPopenCount > MAX_PIPE_RECURSION)
656 iPopenCount = MAX_PIPE_RECURSION; // Limit to the max no of pipes to be open recursively.
658 fnTempPipeFile(ptpf);
659 ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
661 File1[iPopenCount-1] = ret; // Store the obtained Pipe file handle.
663 { // Pipe file not obtained. So free the allocated memory.
664 if(ptpf1[iPopenCount-1])
666 free(ptpf1[iPopenCount-1]);
667 ptpf1[iPopenCount-1] = NULL;
679 int nw_Pclose(FILE* file, int* e)
689 for (i=0; i<iPopenCount; i++)
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!
697 fnPipeFileClose(ptpf1[i]);
710 // Rearrange the file pointer array
711 for(j=i; j<(iPopenCount-1); j++)
713 File1[j] = File1[j+1];
714 ptpf1[j] = ptpf1[j+1];
730 nw_vprintf(const char *format, va_list args)
732 return (vprintf(format, args));
736 nw_printf(const char *format, ...)
740 va_start(marker, format); /* Initialize variable arguments. */
742 return (vprintf(format, marker));
746 nw_read(int fd, void *buf, unsigned int cnt)
748 return read(fd, buf, cnt);
752 nw_readdir(DIR *dirp)
758 return((struct direct *)ret);
763 nw_rename(const char *oname, const char *newname)
765 return(rename(oname,newname));
769 nw_rewinddir(DIR *dirp)
772 Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
783 nw_seekdir(DIR *dirp, long loc)
786 Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
798 return ((char ***)nw_getenviron());
804 return (strerror(e));
814 nw_mktemp(char *Template)
816 return (fnMy_MkTemp(Template));
820 nw_chsize(int handle, long size)
822 return(chsize(handle,size));
825 #ifdef HAVE_INTERP_INTERN
827 sys_intern_init(pTHX)
833 sys_intern_clear(pTHX)
839 sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
843 #endif /* HAVE_INTERP_INTERN */
846 Perl_init_os_extras(void)
852 Perl_nw5_init(int *argcp, char ***argvp)
859 perl_clone_host(PerlInterpreter* proto_perl, UV flags)
861 // Perl Clone is not implemented on NetWare.
866 // Some more functions:
869 nw_get_sitelib(const char *pl)
875 execv(char *cmdname, char **argv)
877 // This feature needs to be implemented.
878 // _asm is commented out since it goes into the internal debugger.
884 execvp(char *cmdname, char **argv)
886 // This feature needs to be implemented.
887 // _asm is commented out since it goes into the internal debugger.
893 do_aspawn(void *vreally, void **vmark, void **vsp)
895 // This feature needs to be implemented.
896 // _asm is commented out since it goes into the internal debugger.
901 // This below code is required for system() call.
902 // Otherwise system() does not work on NetWare.
903 // Ananth, 3 Sept 2001
906 SV *really = (SV*)vreally;
907 SV **mark = (SV**)vmark;
919 nw_perlshell_items = 0; // No Shell
920 New(1306, argv, (sp - mark) + nw_perlshell_items + 3, char*);
922 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
927 while (++mark <= sp) {
928 if (*mark && (str = (char *)SvPV_nolen(*mark)))
936 // argv[index] = '\0';
943 status = nw_spawnvp(flag,
944 (char*)(really ? SvPV_nolen(really) : argv[0]),
948 if (flag != P_NOWAIT) {
951 if (ckWARN(WARN_EXEC))
952 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
957 PL_statusvalue = status;
965 do_spawn2(char *cmd, int exectype)
967 // This feature needs to be implemented.
968 // _asm is commented out since it goes into the internal debugger.
976 return do_spawn2(cmd, 2);
986 // added to remove undefied symbol error in CodeWarrior compilation
988 Perl_Ireentrant_buffer_ptr(aTHX)