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 return(fnFpSetMode(fp, mode, dummy));
112 nw_setvbuf(FILE *pf, char *buf, int type, size_t size)
115 return setvbuf(pf, buf, type, size);
122 nw_sleep(unsigned int t)
124 delay(t*1000); // Put the thread to sleep for 't' seconds. Initially 't' is passed in milliseconds.
129 nw_spawnvp(int mode, char *cmdname, char **argv)
131 // There is no pass-around environment on NetWare so we throw that
132 // argument away for now.
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
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.
156 if (stricmp(cmdname, LOAD_COMMAND) == 0)
159 ret = spawnvp(mode, argv[1], &argv[1]);
164 while (argv[i] != '\0')
168 fnSystemCommand(argv, argc);
175 nw_execv(char *cmdname, char **argv)
177 return spawnvp(P_WAIT, cmdname, (char **)argv);
182 nw_execvp(char *cmdname, char **argv)
184 return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
188 nw_stat(const char *path, struct stat *sbuf)
190 return (stat(path, sbuf));
212 nw_telldir(DIR *dirp)
215 Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
220 nw_times(struct tms *timebuf)
222 clock_t now = clock();
224 timebuf->tms_utime = now;
225 timebuf->tms_stime = 0;
226 timebuf->tms_cutime = 0;
227 timebuf->tms_cstime = 0;
239 nw_uname(struct utsname *name)
245 nw_ungetc(int c, FILE *pf)
248 return ungetc(c, pf);
254 nw_unlink(const char *filename)
256 return(unlink(filename));
260 nw_utime(const char *filename, struct utimbuf *times)
262 return(utime(filename, times));
266 nw_vfprintf(FILE *fp, const char *format, va_list args)
269 return (vfprintf(fp, format, args));
281 nw_waitpid(int pid, int *status, int flags)
287 nw_write(int fd, const void *buf, unsigned int cnt)
289 return write(fd, buf, cnt);
293 nw_crypt(const char *txt, const char *salt)
297 #ifdef HAVE_DES_FCRYPT
299 return des_fcrypt(txt, salt, w32_crypt_buffer);
301 Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
313 nw_dup2(int fd1,int fd2)
315 return dup2(fd1,fd2);
319 nw_dynaload(const char* filename)
334 nw_fdopen(int handle, const char *mode)
336 return(fdopen(handle, mode));
368 nw_fgetpos(FILE *pf, fpos_t *p)
371 return fgetpos(pf, p);
377 nw_fgets(char *s, int n, FILE *pf)
380 return(fgets(s, n, pf));
395 nw_flock(int fd, int oper)
398 Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
404 nw_fopen(const char *filename, const char *mode)
406 return (fopen(filename, mode));
410 nw_fputc(int c, FILE *pf)
419 nw_fputs(const char *s, FILE *pf)
428 nw_fread(void *buf, size_t size, size_t count, FILE *fp)
431 return fread(buf, size, count, fp);
437 nw_freopen(const char *path, const char *mode, FILE *stream)
440 return freopen(path, mode, stream);
446 nw_fseek(FILE *pf, long offset, int origin)
449 return (fseek(pf, offset, origin));
455 nw_fsetpos(FILE *pf, const fpos_t *p)
458 return fsetpos(pf, p);
473 nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
476 return fwrite(buf, size, count, fp);
482 nw_get_osfhandle(int fd)
497 nw_putc(int c, FILE *pf)
517 return GetThreadGroupID();
521 nw_kill(int pid, int sig)
527 nw_link(const char *oldname, const char *newname)
533 nw_lseek(int fd, long offset, int origin)
535 return lseek(fd, offset, origin);
539 nw_chdir(const char *dir)
545 nw_rmdir(const char *dir)
551 nw_opendir(char *filename)
557 len = strlen(filename);
558 buff = malloc(len + 5);
560 strcpy(buff, filename);
561 if (buff[len-1]=='/' || buff[len-1]=='\\') {
564 strcpy(buff+len, "/*.*");
575 nw_open(const char *path, int flag, ...)
581 pmode = va_arg(ap, int);
584 if (stricmp(path, "/dev/null")==0)
587 return open(path, flag, pmode);
591 nw_open_osfhandle(long handle, int flags)
602 int nw_Pipe(int* a, int* e)
614 FILE* nw_Popen(char* command, char* mode, int* e)
619 PTEMPPIPEFILE ptpf = NULL;
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.
635 ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
636 if (!ptpf1[iPopenCount])
639 ptpf = ptpf1[iPopenCount];
641 if(iPopenCount > MAX_PIPE_RECURSION)
642 iPopenCount = MAX_PIPE_RECURSION; // Limit to the max no of pipes to be open recursively.
644 fnTempPipeFile(ptpf);
645 ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
647 File1[iPopenCount-1] = ret; // Store the obtained Pipe file handle.
649 { // Pipe file not obtained. So free the allocated memory.
650 if(ptpf1[iPopenCount-1])
652 free(ptpf1[iPopenCount-1]);
653 ptpf1[iPopenCount-1] = NULL;
665 int nw_Pclose(FILE* file, int* e)
675 for (i=0; i<iPopenCount; i++)
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!
683 fnPipeFileClose(ptpf1[i]);
696 // Rearrange the file pointer array
697 for(j=i; j<(iPopenCount-1); j++)
699 File1[j] = File1[j+1];
700 ptpf1[j] = ptpf1[j+1];
716 nw_vprintf(const char *format, va_list args)
718 return (vprintf(format, args));
722 nw_printf(const char *format, ...)
726 va_start(marker, format); /* Initialize variable arguments. */
728 return (vprintf(format, marker));
732 nw_read(int fd, void *buf, unsigned int cnt)
734 return read(fd, buf, cnt);
738 nw_readdir(DIR *dirp)
744 return((struct direct *)ret);
749 nw_rename(const char *oname, const char *newname)
751 return(rename(oname,newname));
755 nw_rewinddir(DIR *dirp)
758 Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
769 nw_seekdir(DIR *dirp, long loc)
772 Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
784 return ((char ***)nw_getenviron());
790 return (strerror(e));
800 nw_mktemp(char *Template)
802 return (fnMy_MkTemp(Template));
806 nw_chsize(int handle, long size)
808 return(chsize(handle,size));
811 #ifdef HAVE_INTERP_INTERN
813 sys_intern_init(pTHX)
819 sys_intern_clear(pTHX)
825 sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
829 #endif /* HAVE_INTERP_INTERN */
832 Perl_init_os_extras(void)
838 Perl_nw5_init(int *argcp, char ***argvp)
845 perl_clone_host(PerlInterpreter* proto_perl, UV flags)
847 // Perl Clone is not implemented on NetWare.
852 // Some more functions:
855 nw_get_sitelib(const char *pl)
861 execv(char *cmdname, char **argv)
863 // This feature needs to be implemented.
864 // _asm is commented out since it goes into the internal debugger.
870 execvp(char *cmdname, char **argv)
872 // This feature needs to be implemented.
873 // _asm is commented out since it goes into the internal debugger.
879 do_aspawn(void *vreally, void **vmark, void **vsp)
881 // This feature needs to be implemented.
882 // _asm is commented out since it goes into the internal debugger.
887 // This below code is required for system() call.
888 // Otherwise system() does not work on NetWare.
889 // Ananth, 3 Sept 2001
892 SV *really = (SV*)vreally;
893 SV **mark = (SV**)vmark;
905 nw_perlshell_items = 0; // No Shell
906 New(1306, argv, (sp - mark) + nw_perlshell_items + 3, char*);
908 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
913 while (++mark <= sp) {
914 if (*mark && (str = (char *)SvPV_nolen(*mark)))
922 // argv[index] = '\0';
929 status = nw_spawnvp(flag,
930 (char*)(really ? SvPV_nolen(really) : argv[0]),
934 if (flag != P_NOWAIT) {
937 if (ckWARN(WARN_EXEC))
938 Perl_warner(aTHX_ WARN_EXEC, "Can't spawn \"%s\": %s", argv[0], strerror(errno));
943 PL_statusvalue = status;
951 do_spawn2(char *cmd, int exectype)
953 // This feature needs to be implemented.
954 // _asm is commented out since it goes into the internal debugger.
962 return do_spawn2(cmd, 2);