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 dTHXo, 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_ "telldir function is not implemented");
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 unimplemented due to excessive paranoia.");
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)
402 nw_fopen(const char *filename, const char *mode)
404 return (fopen(filename, mode));
408 nw_fputc(int c, FILE *pf)
417 nw_fputs(const char *s, FILE *pf)
426 nw_fread(void *buf, size_t size, size_t count, FILE *fp)
429 return fread(buf, size, count, fp);
435 nw_freopen(const char *path, const char *mode, FILE *stream)
438 return freopen(path, mode, stream);
444 nw_fseek(FILE *pf, long offset, int origin)
447 return (fseek(pf, offset, origin));
453 nw_fsetpos(FILE *pf, const fpos_t *p)
456 return fsetpos(pf, p);
471 nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
474 return fwrite(buf, size, count, fp);
480 nw_get_osfhandle(int fd)
495 nw_putc(int c, FILE *pf)
515 return GetThreadGroupID();
519 nw_kill(int pid, int sig)
525 nw_link(const char *oldname, const char *newname)
531 nw_lseek(int fd, long offset, int origin)
533 return lseek(fd, offset, origin);
537 nw_chdir(const char *dir)
543 nw_rmdir(const char *dir)
549 nw_opendir(char *filename)
555 len = strlen(filename);
556 buff = malloc(len + 5);
558 strcpy(buff, filename);
559 if (buff[len-1]=='/' || buff[len-1]=='\\') {
562 strcpy(buff+len, "/*.*");
573 nw_open(const char *path, int flag, ...)
579 pmode = va_arg(ap, int);
582 if (stricmp(path, "/dev/null")==0)
585 return open(path, flag, pmode);
589 nw_open_osfhandle(long handle, int flags)
600 int nw_Pipe(int* a, int* e)
612 FILE* nw_Popen(char* command, char* mode, int* e)
617 PTEMPPIPEFILE ptpf = NULL;
619 // this callback is supposed to call _popen, which spawns an
620 // asynchronous command and opens a pipe to it. The returned
621 // file handle can be read or written to; if read, it represents
622 // stdout of the called process and will return EOF when the
623 // called process finishes. If written to, it represents stdin
624 // of the called process. Naturally _popen is not available on
625 // NetWare so we must do some fancy stuff to simulate it. We will
626 // redirect to and from temp files; this has the side effect
627 // of having to run the process synchronously rather than
628 // asynchronously. This means that you will only be able to do
629 // this with CLIB NLMs built to run on the calling thread.
633 ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
634 if (!ptpf1[iPopenCount])
637 ptpf = ptpf1[iPopenCount];
639 if(iPopenCount > MAX_PIPE_RECURSION)
640 iPopenCount = MAX_PIPE_RECURSION; // Limit to the max no of pipes to be open recursively.
642 fnTempPipeFile(ptpf);
643 ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
645 File1[iPopenCount-1] = ret; // Store the obtained Pipe file handle.
647 { // Pipe file not obtained. So free the allocated memory.
648 if(ptpf1[iPopenCount-1])
650 free(ptpf1[iPopenCount-1]);
651 ptpf1[iPopenCount-1] = NULL;
663 int nw_Pclose(FILE* file, int* e)
673 for (i=0; i<iPopenCount; i++)
677 // Delete the memory allocated corresponding to the file handle passed-in and
678 // also close the file corresponding to the file handle passed-in!
681 fnPipeFileClose(ptpf1[i]);
694 // Rearrange the file pointer array
695 for(j=i; j<(iPopenCount-1); j++)
697 File1[j] = File1[j+1];
698 ptpf1[j] = ptpf1[j+1];
714 nw_vprintf(const char *format, va_list args)
716 return (vprintf(format, args));
720 nw_printf(const char *format, ...)
724 va_start(marker, format); /* Initialize variable arguments. */
726 return (vprintf(format, marker));
730 nw_read(int fd, void *buf, unsigned int cnt)
732 return read(fd, buf, cnt);
736 nw_readdir(DIR *dirp)
742 return((struct direct *)ret);
747 nw_rename(const char *oname, const char *newname)
749 return(rename(oname,newname));
753 nw_rewinddir(DIR *dirp)
756 Perl_croak(aTHX_ "rewinddir function is not implemented");
767 nw_seekdir(DIR *dirp, long loc)
770 Perl_croak(aTHX_ "seekdir function is not implemented");
782 return ((char ***)nw_getenviron());
788 return (strerror(e));
798 nw_mktemp(char *Template)
800 return (fnMy_MkTemp(Template));
804 nw_chsize(int handle, long size)
806 return(chsize(handle,size));
809 #ifdef HAVE_INTERP_INTERN
811 sys_intern_init(pTHX)
817 sys_intern_clear(pTHX)
823 sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
827 #endif /* HAVE_INTERP_INTERN */
830 Perl_init_os_extras(void)
836 Perl_nw5_init(int *argcp, char ***argvp)
843 perl_clone_host(PerlInterpreter* proto_perl, UV flags)
845 // Perl Clone is not implemented on NetWare.
850 // Some more functions:
853 nw_get_sitelib(const char *pl)
859 execv(char *cmdname, char **argv)
861 // This feature needs to be implemented.
862 // _asm is commented out since it goes into the internal debugger.
868 execvp(char *cmdname, char **argv)
870 // This feature needs to be implemented.
871 // _asm is commented out since it goes into the internal debugger.
877 do_aspawn(void *vreally, void **vmark, void **vsp)
879 // This feature needs to be implemented.
880 // _asm is commented out since it goes into the internal debugger.
886 do_spawn2(char *cmd, int exectype)
888 // This feature needs to be implemented.
889 // _asm is commented out since it goes into the internal debugger.
897 return do_spawn2(cmd, 2);