summaryrefslogtreecommitdiff
path: root/NetWare/nw5.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>2001-06-16 19:46:38 +0000
committerJarkko Hietaniemi <jhi@iki.fi>2001-06-16 19:46:38 +0000
commit2986a63f7e513cf37f46db9f211b77071260031f (patch)
tree9a6e62602396938ea5a612420f53ebf267e8d941 /NetWare/nw5.c
parent87b11a197a59fac210fc9265bde0ef1ffe36de89 (diff)
downloadperl-2986a63f7e513cf37f46db9f211b77071260031f.tar.gz
NetWare port from Guruprasad S <SGURUPRASAD@novell.com>.
p4raw-id: //depot/perl@10643
Diffstat (limited to 'NetWare/nw5.c')
-rw-r--r--NetWare/nw5.c896
1 files changed, 896 insertions, 0 deletions
diff --git a/NetWare/nw5.c b/NetWare/nw5.c
new file mode 100644
index 0000000000..e32fdb6b2f
--- /dev/null
+++ b/NetWare/nw5.c
@@ -0,0 +1,896 @@
+
+/*
+ * Copyright © 2001 Novell, Inc. All Rights Reserved.
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the README file.
+ *
+ */
+
+/*
+ * FILENAME : nw5.c
+ * DESCRIPTION : Definitions for the redefined functions for NetWare.
+ * Author : SGP, HYAK
+ * Date : January 2001.
+ *
+ */
+
+
+
+#include <perl.h> // For dTHXo, etc.
+#include "nwpipe.h"
+
+
+// This was added since the compile failed saying "undefined P_WAIT"
+// when USE_ITHREADS was commented in the makefile
+#ifndef P_WAIT
+#define P_WAIT 0
+#endif
+
+#ifndef P_NOWAIT
+#define P_NOWAIT 1
+#endif
+
+// The array is used to store pointer to the memory allocated to the TempPipeFile structure everytime
+// a call to the function, nw_Popen. If a simple variable is used, everytime the memory is allocated before
+// the previously allocated memory is freed, the pointer will get overwritten and the previous memory allocations
+// are lost! Only the most recent one will get freed when calls are made to nw_Pclose.
+// By using the array and the iPopenCount to index the array, all memory are freed!
+
+// The size of the array indicates the limit on the no of times the nw_Popen function can be called (and
+// memory allocted) from within a script through backtick operators!
+// This is arbitrarily set to MAX_PIPE_RECURSION=256 which indicates there can be 256 nested backtick operators possible!
+PTEMPPIPEFILE ptpf1[MAX_PIPE_RECURSION] = {'\0'};
+int iPopenCount = 0;
+FILE* File1[MAX_PIPE_RECURSION] = {'\0'};
+
+
+/**
+General:
+
+In this code, wherever there is a FILE *, the error condition is checked; and only if the FILE * is TRUE,
+then the corresponding operation is done. Otherwise the error value is returned.
+This is done because the file operations like "open" in the Perl code returns the FILE *,
+returning a valid value if the file is found or NULL when the particular file is not found.
+Now, if the return value is NULL, then an operation say "fgets", "fopen" etc. using this this NULL value
+for FILE * will abend the server. If the check is made then an operation on a non existing file
+does not abend the server.
+**/
+
+void
+nw_abort(void)
+{
+ abort(); // Terminate the NLM application abnormally.
+ return;
+}
+
+int
+nw_access(const char *path, int mode)
+{
+ return access(path, mode);
+}
+
+int
+nw_chmod(const char *path, int mode)
+{
+ return chmod(path, mode);
+}
+
+void
+nw_clearerr(FILE *pf)
+{
+ if(pf)
+ clearerr(pf);
+}
+
+int
+nw_close(int fd)
+{
+ return close(fd);
+}
+
+nw_closedir(DIR *dirp)
+{
+ return (closedir(dirp));
+}
+
+void
+nw_setbuf(FILE *pf, char *buf)
+{
+ if(pf)
+ setbuf(pf, buf);
+}
+
+int
+nw_setmode(FILE *fp, int mode)
+{
+ int *dummy = 0;
+ return(fnFpSetMode(fp, mode, dummy));
+}
+
+int
+nw_setvbuf(FILE *pf, char *buf, int type, size_t size)
+{
+ if(pf)
+ return setvbuf(pf, buf, type, size);
+ else
+ return -1;
+}
+
+
+unsigned int
+nw_sleep(unsigned int t)
+{
+ delay(t*1000); // Put the thread to sleep for 't' seconds. Initially 't' is passed in milliseconds.
+ return 0;
+}
+
+int
+nw_spawnvp(int mode, char *cmdname, char **argv)
+{
+ // There is no pass-around environment on NetWare so we throw that
+ // argument away for now.
+
+ // The function "spawnvp" does not work in all situations. Loading
+ // edit.nlm seems to work, for example, but the name of the file
+ // to edit does not appear to get passed correctly. Another problem
+ // is that on Netware, P_WAIT does not really work reliably. It only
+ // works with NLMs built to use CLIB (according to Nile Thayne).
+ // NLMs such as EDIT that are written directly to the system have no
+ // way of running synchronously from another process. The whole
+ // architecture on NetWare seems pretty busted, so we just support it
+ // as best we can.
+ //
+ // The spawnvp function only launches NLMs, it will not execute a command;
+ // the NetWare "system" function is used for that purpose. Unfortunately, "system"
+ // always returns success whether the command is successful or not or even
+ // if the command was not found! To avoid ambiguity--you can have both an
+ // NLM named "perl" and a system command named "perl"--we need to
+ // force perl scripts to carry the word "load" when loading an NLM. This
+ // might be clearer anyway.
+
+ int ret = 0;
+ int argc = 0;
+
+
+ if (stricmp(cmdname, LOAD_COMMAND) == 0)
+ {
+ if (argv[1] != NULL)
+ ret = spawnvp(mode, argv[1], &argv[1]);
+ }
+ else
+ {
+ int i=0;
+ while (argv[i] != '\0')
+ i++;
+ argc = i;
+
+ fnSystemCommand(argv, argc);
+ }
+
+ return ret;
+}
+
+int
+nw_execv(char *cmdname, char **argv)
+{
+ return spawnvp(P_WAIT, cmdname, (char **)argv);
+}
+
+
+int
+nw_execvp(char *cmdname, char **argv)
+{
+ return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
+}
+
+int
+nw_stat(const char *path, struct stat *sbuf)
+{
+ return (stat(path, sbuf));
+}
+
+FILE *
+nw_stderr(void)
+{
+ return (stderr);
+}
+
+FILE *
+nw_stdin(void)
+{
+ return (stdin);
+}
+
+FILE *
+nw_stdout()
+{
+ return (stdout);
+}
+
+long
+nw_telldir(DIR *dirp)
+{
+ dTHXo;
+ Perl_croak(aTHX_ "telldir function is not implemented");
+ return 0l;
+}
+
+int
+nw_times(struct tms *timebuf)
+{
+ clock_t now = clock();
+
+ timebuf->tms_utime = now;
+ timebuf->tms_stime = 0;
+ timebuf->tms_cutime = 0;
+ timebuf->tms_cstime = 0;
+
+ return 0;
+}
+
+FILE*
+nw_tmpfile(void)
+{
+ return tmpfile();
+}
+
+int
+nw_uname(struct utsname *name)
+{
+ return(uname(name));
+}
+
+int
+nw_ungetc(int c, FILE *pf)
+{
+ if(pf)
+ return ungetc(c, pf);
+ else
+ return -1;
+}
+
+int
+nw_unlink(const char *filename)
+{
+ return(unlink(filename));
+}
+
+int
+nw_utime(const char *filename, struct utimbuf *times)
+{
+ return(utime(filename, times));
+}
+
+int
+nw_vfprintf(FILE *fp, const char *format, va_list args)
+{
+ if(fp)
+ return (vfprintf(fp, format, args));
+ else
+ return -1;
+}
+
+int
+nw_wait(int *status)
+{
+ return 0;
+}
+
+int
+nw_waitpid(int pid, int *status, int flags)
+{
+ return 0;
+}
+
+int
+nw_write(int fd, const void *buf, unsigned int cnt)
+{
+ return write(fd, buf, cnt);
+}
+
+char *
+nw_crypt(const char *txt, const char *salt)
+{
+ dTHXo;
+
+#ifdef HAVE_DES_FCRYPT
+ dTHR;
+ return des_fcrypt(txt, salt, w32_crypt_buffer);
+#else
+ Perl_croak(aTHX_ "The crypt() function is unimplemented due to excessive paranoia.");
+ return Nullch;
+#endif
+}
+
+int
+nw_dup(int fd)
+{
+ return dup(fd);
+}
+
+int
+nw_dup2(int fd1,int fd2)
+{
+ return dup2(fd1,fd2);
+}
+
+void*
+nw_dynaload(const char* filename)
+{
+ return NULL;
+}
+
+int
+nw_fclose(FILE *pf)
+{
+ if(pf)
+ return (fclose(pf));
+ else
+ return -1;
+}
+
+FILE *
+nw_fdopen(int handle, const char *mode)
+{
+ return(fdopen(handle, mode));
+}
+
+int
+nw_feof(FILE *fp)
+{
+ if(fp)
+ return (feof(fp));
+ else
+ return -1;
+}
+
+int
+nw_ferror(FILE *fp)
+{
+ if(fp)
+ return (ferror(fp));
+ else
+ return -1;
+}
+
+
+int
+nw_fflush(FILE *pf)
+{
+ if(pf)
+ return fflush(pf);
+ else
+ return -1;
+}
+
+int
+nw_fgetpos(FILE *pf, fpos_t *p)
+{
+ if(pf)
+ return fgetpos(pf, p);
+ else
+ return -1;
+}
+
+char*
+nw_fgets(char *s, int n, FILE *pf)
+{
+ if(pf)
+ return(fgets(s, n, pf));
+ else
+ return NULL;
+}
+
+int
+nw_fileno(FILE *pf)
+{
+ if(pf)
+ return fileno(pf);
+ else
+ return -1;
+}
+
+int
+nw_flock(int fd, int oper)
+{
+ return 0;
+}
+
+
+FILE *
+nw_fopen(const char *filename, const char *mode)
+{
+ return (fopen(filename, mode));
+}
+
+int
+nw_fputc(int c, FILE *pf)
+{
+ if(pf)
+ return fputc(c,pf);
+ else
+ return -1;
+}
+
+int
+nw_fputs(const char *s, FILE *pf)
+{
+ if(pf)
+ return fputs(s, pf);
+ else
+ return -1;
+}
+
+size_t
+nw_fread(void *buf, size_t size, size_t count, FILE *fp)
+{
+ if(fp)
+ return fread(buf, size, count, fp);
+ else
+ return -1;
+}
+
+FILE *
+nw_freopen(const char *path, const char *mode, FILE *stream)
+{
+ if(stream)
+ return freopen(path, mode, stream);
+ else
+ return NULL;
+}
+
+int
+nw_fseek(FILE *pf, long offset, int origin)
+{
+ if(pf)
+ return (fseek(pf, offset, origin));
+ else
+ return -1;
+}
+
+int
+nw_fsetpos(FILE *pf, const fpos_t *p)
+{
+ if(pf)
+ return fsetpos(pf, p);
+ else
+ return -1;
+}
+
+long
+nw_ftell(FILE *pf)
+{
+ if(pf)
+ return ftell(pf);
+ else
+ return -1;
+}
+
+size_t
+nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
+{
+ if(fp)
+ return fwrite(buf, size, count, fp);
+ else
+ return -1;
+}
+
+long
+nw_get_osfhandle(int fd)
+{
+ return 0l;
+}
+
+int
+nw_getc(FILE *pf)
+{
+ if(pf)
+ return getc(pf);
+ else
+ return -1;
+}
+
+int
+nw_putc(int c, FILE *pf)
+{
+ if(pf)
+ return putc(c,pf);
+ else
+ return -1;
+}
+
+int
+nw_fgetc(FILE *pf)
+{
+ if(pf)
+ return fgetc(pf);
+ else
+ return -1;
+}
+
+int
+nw_getpid(void)
+{
+ return GetThreadGroupID();
+}
+
+int
+nw_kill(int pid, int sig)
+{
+ return 0;
+}
+
+int
+nw_link(const char *oldname, const char *newname)
+{
+ return 0;
+}
+
+long
+nw_lseek(int fd, long offset, int origin)
+{
+ return lseek(fd, offset, origin);
+}
+
+int
+nw_chdir(const char *dir)
+{
+ return chdir(dir);
+}
+
+int
+nw_rmdir(const char *dir)
+{
+ return rmdir(dir);
+}
+
+DIR *
+nw_opendir(char *filename)
+{
+ char *buff = NULL;
+ int len = 0;
+ DIR *ret = NULL;
+
+ len = strlen(filename);
+ buff = malloc(len + 5);
+ if (buff) {
+ strcpy(buff, filename);
+ if (buff[len-1]=='/' || buff[len-1]=='\\') {
+ buff[--len] = 0;
+ }
+ strcpy(buff+len, "/*.*");
+ ret = opendir(buff);
+ free (buff);
+ buff = NULL;
+ return ret;
+ } else {
+ return NULL;
+ }
+}
+
+int
+nw_open(const char *path, int flag, ...)
+{
+ va_list ap;
+ int pmode = -1;
+
+ va_start(ap, flag);
+ pmode = va_arg(ap, int);
+ va_end(ap);
+
+ if (stricmp(path, "/dev/null")==0)
+ path = "NUL";
+
+ return open(path, flag, pmode);
+}
+
+int
+nw_open_osfhandle(long handle, int flags)
+{
+ return 0;
+}
+
+unsigned long
+nw_os_id(void)
+{
+ return 0l;
+}
+
+int nw_Pipe(int* a, int* e)
+{
+ int ret = 0;
+
+ errno = 0;
+ ret = pipe(a);
+ if(errno)
+ e = &errno;
+
+ return ret;
+}
+
+FILE* nw_Popen(char* command, char* mode, int* e)
+{
+ int i = -1;
+
+ FILE* ret = NULL;
+ PTEMPPIPEFILE ptpf = NULL;
+
+ // this callback is supposed to call _popen, which spawns an
+ // asynchronous command and opens a pipe to it. The returned
+ // file handle can be read or written to; if read, it represents
+ // stdout of the called process and will return EOF when the
+ // called process finishes. If written to, it represents stdin
+ // of the called process. Naturally _popen is not available on
+ // NetWare so we must do some fancy stuff to simulate it. We will
+ // redirect to and from temp files; this has the side effect
+ // of having to run the process synchronously rather than
+ // asynchronously. This means that you will only be able to do
+ // this with CLIB NLMs built to run on the calling thread.
+
+ errno = 0;
+
+ ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
+ if (!ptpf1[iPopenCount])
+ return NULL;
+
+ ptpf = ptpf1[iPopenCount];
+ iPopenCount ++;
+ if(iPopenCount > MAX_PIPE_RECURSION)
+ iPopenCount = MAX_PIPE_RECURSION; // Limit to the max no of pipes to be open recursively.
+
+ fnTempPipeFile(ptpf);
+ ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
+ if (ret)
+ File1[iPopenCount-1] = ret; // Store the obtained Pipe file handle.
+ else
+ { // Pipe file not obtained. So free the allocated memory.
+ if(ptpf1[iPopenCount-1])
+ {
+ free(ptpf1[iPopenCount-1]);
+ ptpf1[iPopenCount-1] = NULL;
+ ptpf = NULL;
+ iPopenCount --;
+ }
+ }
+
+ if (errno)
+ e = &errno;
+
+ return ret;
+}
+
+int nw_Pclose(FILE* file, int* e)
+{
+ int i=0, j=0;
+
+ errno = 0;
+
+ if(file)
+ {
+ if(iPopenCount > 0)
+ {
+ for (i=0; i<iPopenCount; i++)
+ {
+ if(File1[i] == file)
+ {
+ // Delete the memory allocated corresponding to the file handle passed-in and
+ // also close the file corresponding to the file handle passed-in!
+ if(ptpf1[i])
+ {
+ fnPipeFileClose(ptpf1[i]);
+
+ free(ptpf1[i]);
+ ptpf1[i] = NULL;
+ }
+
+ fclose(File1[i]);
+ File1[i] = NULL;
+
+ break;
+ }
+ }
+
+ // Rearrange the file pointer array
+ for(j=i; j<(iPopenCount-1); j++)
+ {
+ File1[j] = File1[j+1];
+ ptpf1[j] = ptpf1[j+1];
+ }
+ iPopenCount--;
+ }
+ }
+ else
+ return -1;
+
+ if (errno)
+ e = &errno;
+
+ return 0;
+}
+
+
+int
+nw_vprintf(const char *format, va_list args)
+{
+ return (vprintf(format, args));
+}
+
+int
+nw_printf(const char *format, ...)
+{
+
+ va_list marker;
+ va_start(marker, format); /* Initialize variable arguments. */
+
+ return (vprintf(format, marker));
+}
+
+int
+nw_read(int fd, void *buf, unsigned int cnt)
+{
+ return read(fd, buf, cnt);
+}
+
+struct direct *
+nw_readdir(DIR *dirp)
+{
+ DIR* ret=NULL;
+
+ ret = readdir(dirp);
+ if(ret)
+ return((struct direct *)ret);
+ return NULL;
+}
+
+int
+nw_rename(const char *oname, const char *newname)
+{
+ return(rename(oname,newname));
+}
+
+void
+nw_rewinddir(DIR *dirp)
+{
+ dTHXo;
+ Perl_croak(aTHX_ "rewinddir function is not implemented");
+}
+
+void
+nw_rewind(FILE *pf)
+{
+ if(pf)
+ rewind(pf);
+}
+
+void
+nw_seekdir(DIR *dirp, long loc)
+{
+ dTHXo;
+ Perl_croak(aTHX_ "seekdir function is not implemented");
+}
+
+int *
+nw_errno(void)
+{
+ return (&errno);
+}
+
+char ***
+nw_environ(void)
+{
+ return ((char ***)nw_getenviron());
+}
+
+char *
+nw_strerror(int e)
+{
+ return (strerror(e));
+}
+
+int
+nw_isatty(int fd)
+{
+ return(isatty(fd));
+}
+
+char *
+nw_mktemp(char *Template)
+{
+ return (fnMy_MkTemp(Template));
+}
+
+int
+nw_chsize(int handle, long size)
+{
+ return(chsize(handle,size));
+}
+
+#ifdef HAVE_INTERP_INTERN
+void
+sys_intern_init(pTHX)
+{
+
+}
+
+void
+sys_intern_clear(pTHX)
+{
+
+}
+
+void
+sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
+{
+
+}
+#endif /* HAVE_INTERP_INTERN */
+
+void
+Perl_init_os_extras(void)
+{
+
+}
+
+void
+Perl_nw5_init(int *argcp, char ***argvp)
+{
+ MALLOC_INIT;
+}
+
+// Some more functions:
+
+char *
+nw_get_sitelib(const char *pl)
+{
+ return (NULL);
+}
+
+int
+execv(char *cmdname, char **argv)
+{
+ // This feature needs to be implemented.
+ // _asm is commented out since it goes into the internal debugger.
+// _asm {int 3};
+ return(0);
+}
+
+int
+execvp(char *cmdname, char **argv)
+{
+ // This feature needs to be implemented.
+ // _asm is commented out since it goes into the internal debugger.
+// _asm {int 3};
+ return(0);
+}
+
+int
+do_aspawn(void *vreally, void **vmark, void **vsp)
+{
+ // This feature needs to be implemented.
+ // _asm is commented out since it goes into the internal debugger.
+// _asm {int 3};
+ return(0);
+}
+
+int
+do_spawn2(char *cmd, int exectype)
+{
+ // This feature needs to be implemented.
+ // _asm is commented out since it goes into the internal debugger.
+// _asm {int 3};
+ return(0);
+}
+
+int
+do_spawn(char *cmd)
+{
+ return do_spawn2(cmd, 2);
+}
+
+int
+fork(void)
+{
+ return 0;
+}
+