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
36 #define EXECF_SPAWN_NOWAIT 3
38 static BOOL has_shell_metachars(char *ptr);
40 // The array is used to store pointer to the memory allocated to the TempPipeFile structure everytime
41 // a call to the function, nw_Popen. If a simple variable is used, everytime the memory is allocated before
42 // the previously allocated memory is freed, the pointer will get overwritten and the previous memory allocations
43 // are lost! Only the most recent one will get freed when calls are made to nw_Pclose.
44 // By using the array and the iPopenCount to index the array, all memory are freed!
46 // The size of the array indicates the limit on the no of times the nw_Popen function can be called (and
47 // memory allocted) from within a script through backtick operators!
48 // This is arbitrarily set to MAX_PIPE_RECURSION=256 which indicates there can be 256 nested backtick operators possible!
49 PTEMPPIPEFILE ptpf1[MAX_PIPE_RECURSION] = {'\0'};
51 FILE* File1[MAX_PIPE_RECURSION] = {'\0'};
56 In this code, wherever there is a FILE *, the error condition is checked; and only if the FILE * is TRUE,
57 then the corresponding operation is done. Otherwise the error value is returned.
58 This is done because the file operations like "open" in the Perl code returns the FILE *,
59 returning a valid value if the file is found or NULL when the particular file is not found.
60 Now, if the return value is NULL, then an operation say "fgets", "fopen" etc. using this this NULL value
61 for FILE * will abend the server. If the check is made then an operation on a non existing file
62 does not abend the server.
68 abort(); // Terminate the NLM application abnormally.
73 nw_access(const char *path, int mode)
75 return access(path, mode);
79 nw_chmod(const char *path, int mode)
81 return chmod(path, mode);
97 nw_closedir(DIR *dirp)
99 return (closedir(dirp));
103 nw_setbuf(FILE *pf, char *buf)
110 nw_setmode(FILE *fp, int mode)
113 // Commented since a few abends were happening in fnFpSetMode
115 return(fnFpSetMode(fp, mode, dummy));
127 return setmode(handle, mode);
131 nw_setvbuf(FILE *pf, char *buf, int type, size_t size)
134 return setvbuf(pf, buf, type, size);
141 nw_sleep(unsigned int t)
143 delay(t*1000); // Put the thread to sleep for 't' seconds. Initially 't' is passed in milliseconds.
148 nw_spawnvp(int mode, char *cmdname, char **argv)
150 // There is no pass-around environment on NetWare so we throw that
151 // argument away for now.
153 // The function "spawnvp" does not work in all situations. Loading
154 // edit.nlm seems to work, for example, but the name of the file
155 // to edit does not appear to get passed correctly. Another problem
156 // is that on Netware, P_WAIT does not really work reliably. It only
157 // works with NLMs built to use CLIB (according to Nile Thayne).
158 // NLMs such as EDIT that are written directly to the system have no
159 // way of running synchronously from another process. The whole
160 // architecture on NetWare seems pretty busted, so we just support it
163 // The spawnvp function only launches NLMs, it will not execute a command;
164 // the NetWare "system" function is used for that purpose. Unfortunately, "system"
165 // always returns success whether the command is successful or not or even
166 // if the command was not found! To avoid ambiguity--you can have both an
167 // NLM named "perl" and a system command named "perl"--we need to
168 // force perl scripts to carry the word "load" when loading an NLM. This
169 // might be clearer anyway.
175 if (stricmp(cmdname, LOAD_COMMAND) == 0)
178 ret = spawnvp(mode, argv[1], &argv[1]);
183 while (argv[i] != '\0')
187 fnSystemCommand(argv, argc);
194 nw_execv(char *cmdname, char **argv)
196 return spawnvp(P_WAIT, cmdname, (char **)argv);
201 nw_execvp(char *cmdname, char **argv)
203 return nw_spawnvp(P_WAIT, cmdname, (char **)argv);
207 nw_stat(const char *path, struct stat *sbuf)
209 return (stat(path, sbuf));
231 nw_telldir(DIR *dirp)
234 Perl_croak(aTHX_ "The telldir() function is not implemented on NetWare\n");
239 nw_times(struct tms *timebuf)
241 clock_t now = clock();
243 timebuf->tms_utime = now;
244 timebuf->tms_stime = 0;
245 timebuf->tms_cutime = 0;
246 timebuf->tms_cstime = 0;
258 nw_uname(struct utsname *name)
264 nw_ungetc(int c, FILE *pf)
267 return ungetc(c, pf);
273 nw_unlink(const char *filename)
275 return(unlink(filename));
279 nw_utime(const char *filename, struct utimbuf *times)
281 return(utime(filename, times));
285 nw_vfprintf(FILE *fp, const char *format, va_list args)
288 return (vfprintf(fp, format, args));
300 nw_waitpid(int pid, int *status, int flags)
306 nw_write(int fd, const void *buf, unsigned int cnt)
308 return write(fd, buf, cnt);
312 nw_crypt(const char *txt, const char *salt)
316 #ifdef HAVE_DES_FCRYPT
318 return des_fcrypt(txt, salt, w32_crypt_buffer);
320 Perl_croak(aTHX_ "The crypt() function is not implemented on NetWare\n");
332 nw_dup2(int fd1,int fd2)
334 return dup2(fd1,fd2);
338 nw_dynaload(const char* filename)
353 nw_fdopen(int handle, const char *mode)
355 return(fdopen(handle, mode));
387 nw_fgetpos(FILE *pf, fpos_t *p)
390 return fgetpos(pf, p);
396 nw_fgets(char *s, int n, FILE *pf)
399 return(fgets(s, n, pf));
414 nw_flock(int fd, int oper)
417 Perl_croak(aTHX_ "The flock() function is not implemented on NetWare\n");
423 nw_fopen(const char *filename, const char *mode)
425 return (fopen(filename, mode));
429 nw_fputc(int c, FILE *pf)
438 nw_fputs(const char *s, FILE *pf)
447 nw_fread(void *buf, size_t size, size_t count, FILE *fp)
450 return fread(buf, size, count, fp);
456 nw_freopen(const char *path, const char *mode, FILE *stream)
459 return freopen(path, mode, stream);
465 nw_fseek(FILE *pf, long offset, int origin)
468 return (fseek(pf, offset, origin));
474 nw_fsetpos(FILE *pf, const fpos_t *p)
477 return fsetpos(pf, p);
492 nw_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
495 return fwrite(buf, size, count, fp);
501 nw_get_osfhandle(int fd)
516 nw_putc(int c, FILE *pf)
536 return GetThreadGroupID();
540 nw_kill(int pid, int sig)
546 nw_link(const char *oldname, const char *newname)
552 nw_lseek(int fd, long offset, int origin)
554 return lseek(fd, offset, origin);
558 nw_chdir(const char *dir)
564 nw_rmdir(const char *dir)
570 nw_opendir(char *filename)
576 len = strlen(filename);
577 buff = malloc(len + 5);
579 strcpy(buff, filename);
580 if (buff[len-1]=='/' || buff[len-1]=='\\') {
583 strcpy(buff+len, "/*.*");
594 nw_open(const char *path, int flag, ...)
600 pmode = va_arg(ap, int);
603 if (stricmp(path, "/dev/null")==0)
606 return open(path, flag, pmode);
610 nw_open_osfhandle(long handle, int flags)
621 int nw_Pipe(int* a, int* e)
633 FILE* nw_Popen(char* command, char* mode, int* e)
638 PTEMPPIPEFILE ptpf = NULL;
640 // this callback is supposed to call _popen, which spawns an
641 // asynchronous command and opens a pipe to it. The returned
642 // file handle can be read or written to; if read, it represents
643 // stdout of the called process and will return EOF when the
644 // called process finishes. If written to, it represents stdin
645 // of the called process. Naturally _popen is not available on
646 // NetWare so we must do some fancy stuff to simulate it. We will
647 // redirect to and from temp files; this has the side effect
648 // of having to run the process synchronously rather than
649 // asynchronously. This means that you will only be able to do
650 // this with CLIB NLMs built to run on the calling thread.
654 ptpf1[iPopenCount] = (PTEMPPIPEFILE) malloc(sizeof(TEMPPIPEFILE));
655 if (!ptpf1[iPopenCount])
658 ptpf = ptpf1[iPopenCount];
660 if(iPopenCount > MAX_PIPE_RECURSION)
661 iPopenCount = MAX_PIPE_RECURSION; // Limit to the max no of pipes to be open recursively.
663 fnTempPipeFile(ptpf);
664 ret = fnPipeFileOpen((PTEMPPIPEFILE) ptpf, (char *) command, (char *) mode);
666 File1[iPopenCount-1] = ret; // Store the obtained Pipe file handle.
668 { // Pipe file not obtained. So free the allocated memory.
669 if(ptpf1[iPopenCount-1])
671 free(ptpf1[iPopenCount-1]);
672 ptpf1[iPopenCount-1] = NULL;
684 int nw_Pclose(FILE* file, int* e)
694 for (i=0; i<iPopenCount; i++)
698 // Delete the memory allocated corresponding to the file handle passed-in and
699 // also close the file corresponding to the file handle passed-in!
702 fnPipeFileClose(ptpf1[i]);
715 // Rearrange the file pointer array
716 for(j=i; j<(iPopenCount-1); j++)
718 File1[j] = File1[j+1];
719 ptpf1[j] = ptpf1[j+1];
735 nw_vprintf(const char *format, va_list args)
737 return (vprintf(format, args));
741 nw_printf(const char *format, ...)
745 va_start(marker, format); /* Initialize variable arguments. */
747 return (vprintf(format, marker));
751 nw_read(int fd, void *buf, unsigned int cnt)
753 return read(fd, buf, cnt);
757 nw_readdir(DIR *dirp)
763 return((struct direct *)ret);
768 nw_rename(const char *oname, const char *newname)
770 return(rename(oname,newname));
774 nw_rewinddir(DIR *dirp)
777 Perl_croak(aTHX_ "The rewinddir() function is not implemented on NetWare\n");
788 nw_seekdir(DIR *dirp, long loc)
791 Perl_croak(aTHX_ "The seekdir() function is not implemented on NetWare\n");
803 return ((char ***)nw_getenviron());
809 return (strerror(e));
819 nw_mktemp(char *Template)
821 return (fnMy_MkTemp(Template));
825 nw_chsize(int handle, long size)
827 return(chsize(handle,size));
830 #ifdef HAVE_INTERP_INTERN
832 sys_intern_init(pTHX)
838 sys_intern_clear(pTHX)
844 sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
848 #endif /* HAVE_INTERP_INTERN */
851 Perl_init_os_extras(void)
857 Perl_nw5_init(int *argcp, char ***argvp)
864 perl_clone_host(PerlInterpreter* proto_perl, UV flags)
866 // Perl Clone is not implemented on NetWare.
871 // Some more functions:
874 nw_get_sitelib(const char *pl)
880 execv(char *cmdname, char **argv)
882 // This feature needs to be implemented.
883 // _asm is commented out since it goes into the internal debugger.
889 execvp(char *cmdname, char **argv)
891 // This feature needs to be implemented.
892 // _asm is commented out since it goes into the internal debugger.
898 do_aspawn(void *vreally, void **vmark, void **vsp)
900 // This feature needs to be implemented.
901 // _asm is commented out since it goes into the internal debugger.
906 // This below code is required for system() call.
907 // Otherwise system() does not work on NetWare.
908 // Ananth, 3 Sept 2001
911 SV *really = (SV*)vreally;
912 SV **mark = (SV**)vmark;
924 nw_perlshell_items = 0; // No Shell
925 // New(1306, argv, (sp - mark) + nw_perlshell_items + 3, char*); // In the old code of 5.6.1
926 New(1306, argv, (sp - mark) + nw_perlshell_items + 2, char*);
928 if (SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
933 while (++mark <= sp) {
934 if (*mark && (str = (char *)SvPV_nolen(*mark)))
942 // argv[index] = '\0';
949 status = nw_spawnvp(flag,
950 (char*)(really ? SvPV_nolen(really) : argv[0]),
953 if (flag != P_NOWAIT) {
955 // dTHR; // Only in old code of 5.6.1
956 if (ckWARN(WARN_EXEC))
957 Perl_warner(aTHX_ packWARN(WARN_EXEC), "Can't spawn \"%s\": %s", argv[0], strerror(errno));
962 PL_statusvalue = status;
970 do_spawn2(char *cmd, int exectype)
972 // This feature needs to be implemented.
973 // _asm is commented out since it goes into the internal debugger.
977 // Below added to make system() work for NetWare
984 BOOL needToTry = TRUE;
987 /* Save an extra exec if possible. See if there are shell
988 * metacharacters in it */
989 if (!has_shell_metachars(cmd)) {
990 New(1301,argv, strlen(cmd) / 2 + 2, char*);
991 New(1302,cmd2, strlen(cmd) + 1, char);
994 for (s = cmd2; *s;) {
995 while (*s && isSPACE(*s))
999 while (*s && !isSPACE(*s))
1008 status = nw_spawnvp(P_WAIT, argv[0], (char **)argv);
1011 case EXECF_SPAWN_NOWAIT:
1012 status = nw_spawnvp(P_NOWAIT, argv[0], (char **)argv);
1016 status = nw_execvp(argv[0], (char **)argv);
1019 if (status != -1 || errno == 0)
1030 New(1306, argv, nw_perlshell_items + 2, char*);
1031 while (++i < nw_perlshell_items)
1032 argv[i] = nw_perlshell_vec[i];
1037 status = nw_spawnvp(P_WAIT, argv[0], (char **)argv);
1040 case EXECF_SPAWN_NOWAIT:
1041 status = nw_spawnvp(P_NOWAIT, argv[0], (char **)argv);
1045 status = nw_execvp(argv[0], (char **)argv);
1052 if (exectype != EXECF_SPAWN_NOWAIT) {
1055 if (ckWARN(WARN_EXEC))
1056 Perl_warner(aTHX_ WARN_EXEC, "Can't %s \"%s\": %s",
1057 (exectype == EXECF_EXEC ? "exec" : "spawn"),
1058 cmd, strerror(errno));
1063 PL_statusvalue = status;
1071 return do_spawn2(cmd, EXECF_SPAWN);
1074 // Added to make system() work for NetWare
1076 has_shell_metachars(char *ptr)
1082 * Scan string looking for redirection (< or >) or pipe
1083 * characters (|) that are not in a quoted string.
1084 * Shell variable interpolation (%VAR%) can also happen inside strings.
1093 if (quote == *ptr) {
1123 // added to remove undefied symbol error in CodeWarrior compilation
1125 Perl_Ireentrant_buffer_ptr(aTHX)