X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=vms%2Fvms.c;h=f1f62bd6eb6903b8c3fb64619b470463d13ccd68;hb=c93fa8177be816b728baa070d16f5574403845f6;hp=031f1c6b35aabd3d56bb2961878eb0eccfae7113;hpb=644a288060ff8d01051c5c7e2f4f9f49a69a8eab;p=p5sagit%2Fp5-mst-13.2.git diff --git a/vms/vms.c b/vms/vms.c index 031f1c6..f1f62bd 100644 --- a/vms/vms.c +++ b/vms/vms.c @@ -2,8 +2,8 @@ * * VMS-specific routines for perl5 * - * Last revised: 24-Apr-1999 by Charles Bailey bailey@newman.upenn.edu - * Version: 5.5.58 + * Last revised: 20-Aug-1999 by Charles Bailey bailey@newman.upenn.edu + * Version: 5.5.60 */ #include @@ -91,6 +91,13 @@ static struct dsc$descriptor_s *defenv[] = { &fildevdsc, &crtlenvdsc, NULL }; static struct dsc$descriptor_s **env_tables = defenv; static bool will_taint = FALSE; /* tainting active, but no PL_curinterp yet */ +/* True if we shouldn't treat barewords as logicals during directory */ +/* munching */ +static int no_translate_barewords; + +/* Temp for subprocess commands */ +static struct dsc$descriptor_s VMScmd = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,Nullch}; + /*{{{int vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, struct dsc$descriptor_s **tabvec, unsigned long int flags) */ int vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, @@ -109,7 +116,7 @@ vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, #if defined(USE_THREADS) /* We jump through these hoops because we can be called at */ /* platform-specific initialization time, which is before anything is */ - /* set up--we can't even do a plain dTHR since that relies on the */ + /* set up--we can't even do a plain dTHX since that relies on the */ /* interpreter structure to be initialized */ struct perl_thread *thr; if (PL_curinterp) { @@ -142,7 +149,7 @@ vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, int i; if (!environ) { ivenv = 1; - warn("Can't read CRTL environ\n"); + Perl_warn(aTHX_ "Can't read CRTL environ\n"); continue; } retsts = SS$_NOLOGNAM; @@ -179,11 +186,11 @@ vmstrnenv(const char *lnm, char *eqv, unsigned long int idx, if (thr && PL_curcop) { #endif if (ckWARN(WARN_MISC)) { - warner(WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm); + Perl_warner(aTHX_ WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm); } #if defined(USE_THREADS) } else { - warner(WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm); + Perl_warner(aTHX_ WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm); } #endif @@ -238,7 +245,7 @@ int my_trnlnm(const char *lnm, char *eqv, unsigned long int idx) */ /*{{{ char *my_getenv(const char *lnm, bool sys)*/ char * -my_getenv(const char *lnm, bool sys) +Perl_my_getenv(pTHX_ const char *lnm, bool sys) { static char __my_getenv_eqv[LNM$C_NAMLENGTH+1]; char uplnm[LNM$C_NAMLENGTH+1], *cp1, *cp2, *eqv; @@ -266,6 +273,8 @@ my_getenv(const char *lnm, bool sys) idx = strtoul(cp2+1,NULL,0); lnm = uplnm; } + /* Impose security constraints only if tainting */ + if (sys) sys = PL_curinterp ? PL_tainting : will_taint; if (vmstrnenv(lnm,eqv,idx, sys ? fildev : NULL, #ifdef SECURE_INTERNAL_GETENV @@ -285,6 +294,7 @@ my_getenv(const char *lnm, bool sys) char * my_getenv_len(const char *lnm, unsigned long *len, bool sys) { + dTHX; char *buf, *cp1, *cp2; unsigned long idx = 0; static char __my_getenv_len_eqv[LNM$C_NAMLENGTH+1]; @@ -311,6 +321,8 @@ my_getenv_len(const char *lnm, unsigned long *len, bool sys) idx = strtoul(cp2+1,NULL,0); lnm = buf; } + /* Impose security constraints only if tainting */ + if (sys) sys = PL_curinterp ? PL_tainting : will_taint; if ((*len = vmstrnenv(lnm,buf,idx, sys ? fildev : NULL, #ifdef SECURE_INTERNAL_GETENV @@ -338,7 +350,7 @@ prime_env_iter(void) * find, in preparation for iterating over it. */ { - dTHR; + dTHX; static int primed = 0; HV *seenhv = NULL, *envhv; char cmd[LNM$C_NAMLENGTH+24], mbxnam[LNM$C_NAMLENGTH], *buf = Nullch; @@ -387,7 +399,7 @@ prime_env_iter(void) for (j = 0; environ[j]; j++) { if (!(start = strchr(environ[j],'='))) { if (ckWARN(WARN_INTERNAL)) - warner(WARN_INTERNAL,"Ill-formed CRTL environ value \"%s\"\n",environ[j]); + Perl_warner(aTHX_ WARN_INTERNAL,"Ill-formed CRTL environ value \"%s\"\n",environ[j]); } else { start++; @@ -451,12 +463,12 @@ prime_env_iter(void) buf[retlen] = '\0'; if (iosb[1] != subpid) { if (iosb[1]) { - croak("Unknown process %x sent message to prime_env_iter: %s",buf); + Perl_croak(aTHX_ "Unknown process %x sent message to prime_env_iter: %s",buf); } continue; } if (sts == SS$_BUFFEROVF && ckWARN(WARN_INTERNAL)) - warner(WARN_INTERNAL,"Buffer overflow in prime_env_iter: %s",buf); + Perl_warner(aTHX_ WARN_INTERNAL,"Buffer overflow in prime_env_iter: %s",buf); for (cp1 = buf; *cp1 && isspace(*cp1); cp1++) ; if (*cp1 == '(' || /* Logical name table name */ @@ -477,7 +489,7 @@ prime_env_iter(void) cp1--; /* stop on last non-space char */ } if ((!keylen || (cp1 - cp2 < -1)) && ckWARN(WARN_INTERNAL)) { - warner(WARN_INTERNAL,"Ill-formed message in prime_env_iter: |%s|",buf); + Perl_warner(aTHX_ WARN_INTERNAL,"Ill-formed message in prime_env_iter: |%s|",buf); continue; } PERL_HASH(hash,key,keylen); @@ -524,6 +536,7 @@ vmssetenv(char *lnm, char *eqv, struct dsc$descriptor_s **tabvec) tmpdsc = {6,DSC$K_DTYPE_T,DSC$K_CLASS_S,0}; $DESCRIPTOR(crtlenv,"CRTL_ENV"); $DESCRIPTOR(clisym,"CLISYM"); $DESCRIPTOR(local,"_LOCAL"); + dTHX; for (cp1 = lnm, cp2 = uplnm; *cp1; cp1++, cp2++) { *cp2 = _toupper(*cp1); @@ -549,7 +562,7 @@ vmssetenv(char *lnm, char *eqv, struct dsc$descriptor_s **tabvec) ivenv = 1; retsts = SS$_NOLOGNAM; #else if (ckWARN(WARN_INTERNAL)) - warner(WARN_INTERNAL,"This Perl can't reset CRTL environ elements (%s)",lnm); + Perl_warner(aTHX_ WARN_INTERNAL,"This Perl can't reset CRTL environ elements (%s)",lnm); ivenv = 1; retsts = SS$_NOSUCHPGM; break; } @@ -584,7 +597,7 @@ vmssetenv(char *lnm, char *eqv, struct dsc$descriptor_s **tabvec) return setenv(lnm,eqv,1) ? vaxc$errno : 0; #else if (ckWARN(WARN_INTERNAL)) - warner(WARN_INTERNAL,"This Perl can't set CRTL environ elements (%s=%s)",lnm,eqv); + Perl_warner(aTHX_ WARN_INTERNAL,"This Perl can't set CRTL environ elements (%s=%s)",lnm,eqv); retsts = SS$_NOSUCHPGM; #endif } @@ -603,6 +616,12 @@ vmssetenv(char *lnm, char *eqv, struct dsc$descriptor_s **tabvec) } else { if (!*eqv) eqvdsc.dsc$w_length = 1; + if (eqvdsc.dsc$w_length > LNM$C_NAMLENGTH) { + eqvdsc.dsc$w_length = LNM$C_NAMLENGTH; + if (ckWARN(WARN_MISC)) { + Perl_warner(aTHX_ WARN_MISC,"Value of logical \"%s\" too long. Truncating to %i bytes",lnm, LNM$C_NAMLENGTH); + } + } retsts = lib$set_logical(&lnmdsc,&eqvdsc,tabvec[0],0,0); } } @@ -643,7 +662,7 @@ vmssetenv(char *lnm, char *eqv, struct dsc$descriptor_s **tabvec) /*{{{ void my_setenv(char *lnm, char *eqv)*/ /* This has to be a function since there's a prototype for it in proto.h */ void -my_setenv(char *lnm,char *eqv) +Perl_my_setenv(pTHX_ char *lnm,char *eqv) { if (lnm && *lnm && strlen(lnm) == 7) { char uplnm[8]; @@ -757,6 +776,7 @@ kill_file(char *name) char vmsname[NAM$C_MAXRSS+1], rspec[NAM$C_MAXRSS+1]; unsigned long int jpicode = JPI$_UIC, type = ACL$C_FILE; unsigned long int cxt = 0, aclsts, fndsts, rmsts = -1; + dTHX; struct dsc$descriptor_s fildsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; struct myacedef { unsigned char myace$b_length; @@ -858,6 +878,7 @@ int my_mkdir(char *dir, Mode_t mode) { STRLEN dirlen = strlen(dir); + dTHX; /* CRTL mkdir() doesn't tolerate trailing /, since that implies * null file name/type. However, it's commonplace under Unix, @@ -879,6 +900,7 @@ create_mbx(unsigned short int *chan, struct dsc$descriptor_s *namdsc) { static unsigned long int mbxbufsiz; long int syiitm = SYI$_MAXBUF, dviitm = DVI$_DEVNAM; + dTHX; if (!mbxbufsiz) { /* @@ -929,6 +951,7 @@ pipe_eof(FILE *fp, int immediate) char devnam[NAM$C_MAXRSS+1], *cp; unsigned long int chan, iosb[2], retsts, retsts2; struct dsc$descriptor devdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, devnam}; + dTHX; if (fgetname(fp,devnam,1)) { /* It oughta be a mailbox, so fgetname should give just the device @@ -954,6 +977,7 @@ pipe_exit_routine() struct pipe_details *info; unsigned long int retsts = SS$_NORMAL, abort = SS$_TIMEOUT; int sts, did_stuff; + dTHX; /* first we try sending an EOF...ignore if doesn't work, make sure we @@ -963,7 +987,11 @@ pipe_exit_routine() info = open_pipes; while (info) { - if (info->mode != 'r' && !info->done) { + int need_eof; + _ckvmssts(SYS$SETAST(0)); + need_eof = info->mode != 'r' && !info->done; + _ckvmssts(SYS$SETAST(1)); + if (need_eof) { if (pipe_eof(info->fp, 1) & 1) did_stuff = 1; } info = info->next; @@ -973,22 +1001,26 @@ pipe_exit_routine() did_stuff = 0; info = open_pipes; while (info) { + _ckvmssts(SYS$SETAST(0)); if (!info->done) { /* Tap them gently on the shoulder . . .*/ sts = sys$forcex(&info->pid,0,&abort); if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts(sts); did_stuff = 1; } + _ckvmssts(SYS$SETAST(1)); info = info->next; } if (did_stuff) sleep(1); /* wait for them to respond */ info = open_pipes; while (info) { + _ckvmssts(SYS$SETAST(0)); if (!info->done) { /* We tried to be nice . . . */ sts = sys$delprc(&info->pid,0); if (!(sts&1) && sts != SS$_NONEXPR) _ckvmssts(sts); info->done = 1; /* so my_pclose doesn't try to write EOF */ } + _ckvmssts(SYS$SETAST(1)); info = info->next; } @@ -1014,13 +1046,17 @@ popen_completion_ast(struct pipe_details *thispipe) } } +static unsigned long int setup_cmddsc(char *cmd, int check_img); +static void vms_execfree(); + static PerlIO * safe_popen(char *cmd, char *mode) { static int handler_set_up = FALSE; char mbxname[64]; unsigned short int chan; - unsigned long int flags=1; /* nowait - gnu c doesn't allow &1 */ + unsigned long int sts, flags=1; /* nowait - gnu c doesn't allow &1 */ + dTHX; struct pipe_details *info; struct dsc$descriptor_s namdsc = {sizeof mbxname, DSC$K_DTYPE_T, DSC$K_CLASS_S, mbxname}, @@ -1028,13 +1064,7 @@ safe_popen(char *cmd, char *mode) DSC$K_CLASS_S, 0}; - cmddsc.dsc$w_length=strlen(cmd); - cmddsc.dsc$a_pointer=cmd; - if (cmddsc.dsc$w_length > 255) { - set_errno(E2BIG); set_vaxc_errno(CLI$_BUFOVF); - return Nullfp; - } - + if (!(setup_cmddsc(cmd,0) & 1)) { set_errno(EINVAL); return Nullfp; } New(1301,info,1,struct pipe_details); /* create mailbox */ @@ -1054,16 +1084,17 @@ safe_popen(char *cmd, char *mode) info->completion=0; if (*mode == 'r') { - _ckvmssts(lib$spawn(&cmddsc, &nl_desc, &namdsc, &flags, + _ckvmssts(lib$spawn(&VMScmd, &nl_desc, &namdsc, &flags, 0 /* name */, &info->pid, &info->completion, 0, popen_completion_ast,info,0,0,0)); } else { - _ckvmssts(lib$spawn(&cmddsc, &namdsc, 0 /* sys$output */, &flags, + _ckvmssts(lib$spawn(&VMScmd, &namdsc, 0 /* sys$output */, &flags, 0 /* name */, &info->pid, &info->completion, 0, popen_completion_ast,info,0,0,0)); } + vms_execfree(); if (!handler_set_up) { _ckvmssts(sys$dclexh(&pipe_exitblock)); handler_set_up = TRUE; @@ -1078,7 +1109,7 @@ safe_popen(char *cmd, char *mode) /*{{{ FILE *my_popen(char *cmd, char *mode)*/ FILE * -my_popen(char *cmd, char *mode) +Perl_my_popen(pTHX_ char *cmd, char *mode) { TAINT_ENV(); TAINT_PROPER("popen"); @@ -1089,10 +1120,11 @@ my_popen(char *cmd, char *mode) /*}}}*/ /*{{{ I32 my_pclose(FILE *fp)*/ -I32 my_pclose(FILE *fp) +I32 Perl_my_pclose(pTHX_ FILE *fp) { struct pipe_details *info, *last = NULL; unsigned long int retsts; + int need_eof; for (info = open_pipes; info != NULL; last = info, info = info->next) if (info->fp == fp) break; @@ -1106,15 +1138,20 @@ I32 my_pclose(FILE *fp) /* If we were writing to a subprocess, insure that someone reading from * the mailbox gets an EOF. It looks like a simple fclose() doesn't * produce an EOF record in the mailbox. */ - if (info->mode != 'r' && !info->done) pipe_eof(info->fp,0); + _ckvmssts(SYS$SETAST(0)); + need_eof = info->mode != 'r' && !info->done; + _ckvmssts(SYS$SETAST(1)); + if (need_eof) pipe_eof(info->fp,0); PerlIO_close(info->fp); if (info->done) retsts = info->completion; else waitpid(info->pid,(int *) &retsts,0); /* remove from list of open pipes */ + _ckvmssts(SYS$SETAST(0)); if (last) last->next = info->next; else open_pipes = info->next; + _ckvmssts(SYS$SETAST(1)); Safefree(info); return retsts; @@ -1127,7 +1164,7 @@ Pid_t my_waitpid(Pid_t pid, int *statusp, int flags) { struct pipe_details *info; - dTHR; + dTHX; for (info = open_pipes; info != NULL; info = info->next) if (info->pid == pid) break; @@ -1150,7 +1187,7 @@ my_waitpid(Pid_t pid, int *statusp, int flags) _ckvmssts(lib$getjpi(&ownercode,&pid,0,&ownerpid,0,0)); _ckvmssts(lib$getjpi(&ownercode,0,0,&mypid,0,0)); if (ownerpid != mypid) - warner(WARN_EXEC,"pid %x not a child",pid); + Perl_warner(aTHX_ WARN_EXEC,"pid %x not a child",pid); } _ckvmssts(sys$bintim(&intdsc,interval)); @@ -1579,13 +1616,14 @@ static char *do_fileify_dirspec(char *dir,char *buf,int ts) /* Yes; fake the fnb bits so we'll check type below */ dirnam.nam$l_fnb |= NAM$M_EXP_TYPE | NAM$M_EXP_VER; } - else { - if (dirfab.fab$l_sts != RMS$_FNF) { - set_errno(EVMSERR); - set_vaxc_errno(dirfab.fab$l_sts); + else { /* No; just work with potential name */ + if (dirfab.fab$l_sts == RMS$_FNF) dirnam = savnam; + else { + set_errno(EVMSERR); set_vaxc_errno(dirfab.fab$l_sts); + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); return NULL; } - dirnam = savnam; /* No; just work with potential name */ } } if (!(dirnam.nam$l_fnb & (NAM$M_EXP_DEV | NAM$M_EXP_DIR))) { @@ -1601,6 +1639,8 @@ static char *do_fileify_dirspec(char *dir,char *buf,int ts) cmplen = (dirnam.nam$l_fnb & NAM$M_EXP_VER) ? 6 : 4; if (strncmp(dirnam.nam$l_type,".DIR;1",cmplen)) { /* Something other than .DIR[;1]. Bzzt. */ + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); set_errno(ENOTDIR); set_vaxc_errno(RMS$_DIR); return NULL; @@ -1613,6 +1653,8 @@ static char *do_fileify_dirspec(char *dir,char *buf,int ts) else if (ts) New(1311,retspec,dirnam.nam$b_esl+1,char); else retspec = __fileify_retbuf; strcpy(retspec,esa); + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); return retspec; } if ((cp1 = strstr(esa,".][000000]")) != NULL) { @@ -1621,7 +1663,11 @@ static char *do_fileify_dirspec(char *dir,char *buf,int ts) dirnam.nam$b_esl -= 9; } if ((cp1 = strrchr(esa,']')) == NULL) cp1 = strrchr(esa,'>'); - if (cp1 == NULL) return NULL; /* should never happen */ + if (cp1 == NULL) { /* should never happen */ + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); + return NULL; + } term = *cp1; *cp1 = '\0'; retlen = strlen(esa); @@ -1638,6 +1684,8 @@ static char *do_fileify_dirspec(char *dir,char *buf,int ts) /* Go back and expand rooted logical name */ dirnam.nam$b_nop = NAM$M_SYNCHK | NAM$M_NOCONCEAL; if (!(sys$parse(&dirfab) & 1)) { + dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); set_errno(EVMSERR); set_vaxc_errno(dirfab.fab$l_sts); return NULL; @@ -1682,6 +1730,8 @@ static char *do_fileify_dirspec(char *dir,char *buf,int ts) strcpy(cp2+9,cp1); } } + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); /* We've set up the string up through the filename. Add the type and version, and we're done. */ strcat(retspec,".DIR;1"); @@ -1713,7 +1763,8 @@ static char *do_pathify_dirspec(char *dir,char *buf, int ts) if (*dir) strcpy(trndir,dir); else getcwd(trndir,sizeof trndir - 1); - while (!strpbrk(trndir,"/]:>") && my_trnlnm(trndir,trndir,0)) { + while (!strpbrk(trndir,"/]:>") && !no_translate_barewords + && my_trnlnm(trndir,trndir,0)) { STRLEN trnlen = strlen(trndir); /* Trap simple rooted lnms, and return lnm:[000000] */ @@ -1833,6 +1884,8 @@ static char *do_pathify_dirspec(char *dir,char *buf, int ts) savnam = dirnam; if (!(sys$search(&dirfab)&1)) { /* Does the file really exist? */ if (dirfab.fab$l_sts != RMS$_FNF) { + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); set_errno(EVMSERR); set_vaxc_errno(dirfab.fab$l_sts); return NULL; @@ -1845,6 +1898,8 @@ static char *do_pathify_dirspec(char *dir,char *buf, int ts) cmplen = (dirnam.nam$l_fnb & NAM$M_EXP_VER) ? 6 : 4; if (strncmp(dirnam.nam$l_type,".DIR;1",cmplen)) { /* Something other than .DIR[;1]. Bzzt. */ + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); set_errno(ENOTDIR); set_vaxc_errno(RMS$_DIR); return NULL; @@ -1864,6 +1919,8 @@ static char *do_pathify_dirspec(char *dir,char *buf, int ts) else if (ts) New(1314,retpath,retlen,char); else retpath = __pathify_retbuf; strcpy(retpath,esa); + dirnam.nam$b_nop |= NAM$M_SYNCHK; dirnam.nam$l_rlf = NULL; + dirfab.fab$b_dns = 0; (void) sys$parse(&dirfab,0,0); /* $PARSE may have upcased filespec, so convert output to lower * case if input contained any lowercase characters. */ if (haslower) __mystrtolower(retpath); @@ -2103,16 +2160,12 @@ static char *do_tovmsspec(char *path, char *buf, int ts) { else if (!infront && *cp2 == '.') { if (cp2+1 == dirend || *(cp2+1) == '\0') { cp2++; break; } else if (*(cp2+1) == '/') cp2++; /* skip over "./" - it's redundant */ - else if (*(cp2+1) == '.' && (*(cp2+2) == '/' || *(cp2+2) == '\0')) { - if (*(cp1-1) == '-' || *(cp1-1) == '[') *(cp1++) = '-'; /* handle "../" */ + else if (*(cp2+1) == '.' && (*(cp2+2) == '/' || *(cp2+2) == '\0')) { /* handle "../" */ + if (*(cp1-1) == '-' || *(cp1-1) == '[') *(cp1++) = '-'; else if (*(cp1-2) == '[') *(cp1-1) = '-'; - else { /* back up over previous directory name */ - cp1--; - while (*(cp1-1) != '.' && *(cp1-1) != '[') cp1--; - if (*(cp1-1) == '[') { - memcpy(cp1,"000000.",7); - cp1 += 7; - } + else { +/* if (*(cp1-1) != '.') *(cp1++) = '.'; */ + *(cp1++) = '-'; } cp2 += 2; if (cp2 == dirend) break; @@ -2466,6 +2519,9 @@ getredirection(int *ac, char ***av) exit(vaxc$errno); } if (err != NULL) { + if (strcmp(err,"&1") == 0) { + dup2(fileno(stdout), fileno(Perl_debug_log)); + } else { FILE *tmperr; if (NULL == (tmperr = fopen(err, errmode, "mbc=32", "mbf=2"))) { @@ -2478,6 +2534,7 @@ getredirection(int *ac, char ***av) exit(vaxc$errno); } } + } #ifdef ARGPROC_DEBUG PerlIO_printf(Perl_debug_log, "Arglist:\n"); for (j = 0; j < *ac; ++j) @@ -2746,6 +2803,7 @@ vms_image_init(int *argcp, char ***argvp) unsigned long int iprv[(sizeof(union prvdef) + sizeof(unsigned long int) - 1) / sizeof(unsigned long int)]; unsigned short int dummy, rlen; struct dsc$descriptor_s **tabvec; + dTHX; struct itmlst_3 jpilist[4] = { {sizeof iprv, JPI$_IMAGPRIV, iprv, &dummy}, {sizeof rlst, JPI$_RIGHTSLIST, rlst, &rlen}, { sizeof rsz, JPI$_RIGHTS_SIZE, &rsz, &dummy}, @@ -3093,6 +3151,7 @@ collectversions(dd) char *p, *text, buff[sizeof dd->entry.d_name]; int i; unsigned long context, tmpsts; + dTHX; /* Convenient shorthand. */ e = &dd->entry; @@ -3208,6 +3267,7 @@ void seekdir(DIR *dd, long count) { int vms_wantversions; + dTHX; /* If we haven't done anything yet... */ if (dd->count == 0) @@ -3270,12 +3330,10 @@ my_vfork() /*}}}*/ -static struct dsc$descriptor_s VMScmd = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,Nullch}; - static void vms_execfree() { if (PL_Cmd) { - Safefree(PL_Cmd); + if (PL_Cmd != VMScmd.dsc$a_pointer) Safefree(PL_Cmd); PL_Cmd = Nullch; } if (VMScmd.dsc$a_pointer) { @@ -3288,7 +3346,7 @@ vms_execfree() { static char * setup_argstr(SV *really, SV **mark, SV **sp) { - dTHR; + dTHX; char *junk, *tmps = Nullch; register size_t cmdlen = 0; size_t rlen; @@ -3333,43 +3391,102 @@ setup_argstr(SV *really, SV **mark, SV **sp) static unsigned long int setup_cmddsc(char *cmd, int check_img) { - char resspec[NAM$C_MAXRSS+1]; + char vmsspec[NAM$C_MAXRSS+1], resspec[NAM$C_MAXRSS+1]; $DESCRIPTOR(defdsc,".EXE"); + $DESCRIPTOR(defdsc2,"."); $DESCRIPTOR(resdsc,resspec); struct dsc$descriptor_s imgdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; unsigned long int cxt = 0, flags = 1, retsts = SS$_NORMAL; - register char *s, *rest, *cp; - register int isdcl = 0; + register char *s, *rest, *cp, *wordbreak; + register int isdcl; + dTHX; + if (strlen(cmd) > + (sizeof(vmsspec) > sizeof(resspec) ? sizeof(resspec) : sizeof(vmsspec))) + return LIB$_INVARG; s = cmd; while (*s && isspace(*s)) s++; - if (check_img) { - if (*s == '$') { /* Check whether this is a DCL command: leading $ and */ - isdcl = 1; /* no dev/dir separators (i.e. not a foreign command) */ - for (cp = s; *cp && *cp != '/' && !isspace(*cp); cp++) { - if (*cp == ':' || *cp == '[' || *cp == '<') { - isdcl = 0; - break; - } + + if (*s == '@' || *s == '$') { + vmsspec[0] = *s; rest = s + 1; + for (cp = &vmsspec[1]; *rest && isspace(*rest); rest++,cp++) *cp = *rest; + } + else { cp = vmsspec; rest = s; } + if (*rest == '.' || *rest == '/') { + char *cp2; + for (cp2 = resspec; + *rest && !isspace(*rest) && cp2 - resspec < sizeof resspec; + rest++, cp2++) *cp2 = *rest; + *cp2 = '\0'; + if (do_tovmsspec(resspec,cp,0)) { + s = vmsspec; + if (*rest) { + for (cp2 = vmsspec + strlen(vmsspec); + *rest && cp2 - vmsspec < sizeof vmsspec; + rest++, cp2++) *cp2 = *rest; + *cp2 = '\0'; } } } - else isdcl = 1; + /* Intuit whether verb (first word of cmd) is a DCL command: + * - if first nonspace char is '@', it's a DCL indirection + * otherwise + * - if verb contains a filespec separator, it's not a DCL command + * - if it doesn't, caller tells us whether to default to a DCL + * command, or to a local image unless told it's DCL (by leading '$') + */ + if (*s == '@') isdcl = 1; + else { + register char *filespec = strpbrk(s,":<[.;"); + rest = wordbreak = strpbrk(s," \"\t/"); + if (!wordbreak) wordbreak = s + strlen(s); + if (*s == '$') check_img = 0; + if (filespec && (filespec < wordbreak)) isdcl = 0; + else isdcl = !check_img; + } + if (!isdcl) { - cmd = s; - while (*s && !isspace(*s)) s++; - rest = *s ? s : 0; - imgdsc.dsc$a_pointer = cmd; - imgdsc.dsc$w_length = s - cmd; + imgdsc.dsc$a_pointer = s; + imgdsc.dsc$w_length = wordbreak - s; retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc,0,0,&flags); - if (retsts & 1) { + if (!(retsts&1)) { + _ckvmssts(lib$find_file_end(&cxt)); + retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc2,0,0,&flags); + if (!(retsts & 1) && *s == '$') { + _ckvmssts(lib$find_file_end(&cxt)); + imgdsc.dsc$a_pointer++; imgdsc.dsc$w_length--; + retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc,0,0,&flags); + if (!(retsts&1)) { _ckvmssts(lib$find_file_end(&cxt)); + retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc2,0,0,&flags); + } + } + } + _ckvmssts(lib$find_file_end(&cxt)); + + if (retsts & 1) { + FILE *fp; s = resspec; while (*s && !isspace(*s)) s++; *s = '\0'; + + /* check that it's really not DCL with no file extension */ + fp = fopen(resspec,"r","ctx=bin,shr=get"); + if (fp) { + char b[4] = {0,0,0,0}; + read(fileno(fp),b,4); + isdcl = isprint(b[0]) && isprint(b[1]) && isprint(b[2]) && isprint(b[3]); + fclose(fp); + } + if (check_img && isdcl) return RMS$_FNF; + if (cando_by_name(S_IXUSR,0,resspec)) { New(402,VMScmd.dsc$a_pointer,7 + s - resspec + (rest ? strlen(rest) : 0),char); + if (!isdcl) { strcpy(VMScmd.dsc$a_pointer,"$ MCR "); + } else { + strcpy(VMScmd.dsc$a_pointer,"@"); + } strcat(VMScmd.dsc$a_pointer,resspec); if (rest) strcat(VMScmd.dsc$a_pointer,rest); VMScmd.dsc$w_length = strlen(VMScmd.dsc$a_pointer); @@ -3380,10 +3497,7 @@ setup_cmddsc(char *cmd, int check_img) } /* It's either a DCL command or we couldn't find a suitable image */ VMScmd.dsc$w_length = strlen(cmd); - if (cmd == PL_Cmd) { - VMScmd.dsc$a_pointer = PL_Cmd; - PL_Cmd = Nullch; /* Don't try to free twice in vms_execfree() */ - } + if (cmd == PL_Cmd) VMScmd.dsc$a_pointer = PL_Cmd; else VMScmd.dsc$a_pointer = savepvn(cmd,VMScmd.dsc$w_length); if (!(retsts & 1)) { /* just hand off status values likely to be due to user error */ @@ -3402,12 +3516,12 @@ setup_cmddsc(char *cmd, int check_img) bool vms_do_aexec(SV *really,SV **mark,SV **sp) { - dTHR; + dTHX; if (sp > mark) { if (vfork_called) { /* this follows a vfork - act Unixish */ vfork_called--; if (vfork_called < 0) { - warn("Internal inconsistency in tracking vforks"); + Perl_warn(aTHX_ "Internal inconsistency in tracking vforks"); vfork_called = 0; } else return do_aexec(really,mark,sp); @@ -3426,11 +3540,11 @@ bool vms_do_exec(char *cmd) { - dTHR; + dTHX; if (vfork_called) { /* this follows a vfork - act Unixish */ vfork_called--; if (vfork_called < 0) { - warn("Internal inconsistency in tracking vforks"); + Perl_warn(aTHX_ "Internal inconsistency in tracking vforks"); vfork_called = 0; } else return do_exec(cmd); @@ -3462,7 +3576,7 @@ vms_do_exec(char *cmd) } set_vaxc_errno(retsts); if (ckWARN(WARN_EXEC)) { - warner(WARN_EXEC,"Can't exec \"%*s\": %s", + Perl_warner(aTHX_ WARN_EXEC,"Can't exec \"%*s\": %s", VMScmd.dsc$w_length, VMScmd.dsc$a_pointer, Strerror(errno)); } vms_execfree(); @@ -3479,7 +3593,7 @@ unsigned long int do_spawn(char *); unsigned long int do_aspawn(void *really,void **mark,void **sp) { - dTHR; + dTHX; if (sp > mark) return do_spawn(setup_argstr((SV *)really,(SV **)mark,(SV **)sp)); return SS$_ABORT; @@ -3491,7 +3605,7 @@ unsigned long int do_spawn(char *cmd) { unsigned long int sts, substs, hadcmd = 1; - dTHR; + dTHX; TAINT_ENV(); TAINT_PROPER("spawn"); @@ -3522,7 +3636,7 @@ do_spawn(char *cmd) } set_vaxc_errno(sts); if (ckWARN(WARN_EXEC)) { - warner(WARN_EXEC,"Can't spawn \"%*s\": %s", + Perl_warner(aTHX_ WARN_EXEC,"Can't spawn \"%*s\": %s", hadcmd ? VMScmd.dsc$w_length : 0, hadcmd ? VMScmd.dsc$a_pointer : "", Strerror(errno)); @@ -3564,7 +3678,7 @@ int my_flush(FILE *fp) { int res; - if ((res = fflush(fp)) == 0) { + if ((res = fflush(fp)) == 0 && fp) { #ifdef VMS_DO_SOCKETS Stat_t s; if (Fstat(fileno(fp), &s) == 0 && !S_ISSOCK(s.st_mode)) @@ -3637,6 +3751,7 @@ static char __pw_namecache[UAI$S_IDENT+1]; */ static int fillpasswd (const char *name, struct passwd *pwd) { + dTHX; static struct { unsigned char length; char pw_gecos[UAI$S_OWNER+1]; @@ -3695,7 +3810,7 @@ static int fillpasswd (const char *name, struct passwd *pwd) pwd->pw_gid= uic.uic$v_group; } else - warn("getpwnam returned invalid UIC %#o for user \"%s\""); + Perl_warn(aTHX_ "getpwnam returned invalid UIC %#o for user \"%s\""); pwd->pw_passwd= pw_passwd; pwd->pw_gecos= owner.pw_gecos; pwd->pw_dir= defdev.pw_dir; @@ -3721,6 +3836,7 @@ struct passwd *my_getpwnam(char *name) struct dsc$descriptor_s name_desc; union uicdef uic; unsigned long int status, sts; + dTHX; __pwdcache = __passwd_empty; if (!fillpasswd(name, &__pwdcache)) { @@ -3760,6 +3876,7 @@ struct passwd *my_getpwuid(Uid_t uid) unsigned short lname; union uicdef uic; unsigned long int status; + dTHX; if (uid == (unsigned int) -1) { do { @@ -3821,6 +3938,7 @@ struct passwd *my_getpwent() /*{{{void my_endpwent()*/ void my_endpwent() { + dTHX; if (contxt) { _ckvmssts(sys$finish_rdb(&contxt)); contxt= 0; @@ -3950,6 +4068,27 @@ static long int utc_offset_secs; # define RTL_USES_UTC 1 #endif +/* + * DEC C previous to 6.0 corrupts the behavior of the /prefix + * qualifier with the extern prefix pragma. This provisional + * hack circumvents this prefix pragma problem in previous + * precompilers. + */ +#if defined(__VMS_VER) && __VMS_VER >= 70000000 +# if defined(VMS_WE_ARE_CASE_SENSITIVE) && (__DECC_VER < 60000000) +# pragma __extern_prefix save +# pragma __extern_prefix "" /* set to empty to prevent prefixing */ +# define gmtime decc$__utctz_gmtime +# define localtime decc$__utctz_localtime +# define time decc$__utc_time +# pragma __extern_prefix restore + + struct tm *gmtime(), *localtime(); + +# endif +#endif + + static time_t toutc_dst(time_t loc) { struct tm *rsltmp; @@ -3958,7 +4097,7 @@ static time_t toutc_dst(time_t loc) { if (rsltmp->tm_isdst) loc -= 3600; return loc; } -#define _toutc(secs) ((secs) == -1 ? -1 : \ +#define _toutc(secs) ((secs) == (time_t) -1 ? (time_t) -1 : \ ((gmtime_emulation_type || my_time(NULL)), \ (gmtime_emulation_type == 1 ? toutc_dst(secs) : \ ((secs) - utc_offset_secs)))) @@ -3971,7 +4110,7 @@ static time_t toloc_dst(time_t utc) { if (rsltmp->tm_isdst) utc += 3600; return utc; } -#define _toloc(secs) ((secs) == -1 ? -1 : \ +#define _toloc(secs) ((secs) == (time_t) -1 ? (time_t) -1 : \ ((gmtime_emulation_type || my_time(NULL)), \ (gmtime_emulation_type == 1 ? toloc_dst(secs) : \ ((secs) + utc_offset_secs)))) @@ -3990,7 +4129,7 @@ static time_t toloc_dst(time_t utc) { /*{{{time_t my_time(time_t *timep)*/ time_t my_time(time_t *timep) { - dTHR; + dTHX; time_t when; struct tm *tm_p; @@ -4007,7 +4146,7 @@ time_t my_time(time_t *timep) gmtime_emulation_type++; if (!vmstrnenv("SYS$TIMEZONE_DIFFERENTIAL",off,0,fildev,0)) { gmtime_emulation_type++; - warn("no UTC offset information; assuming local time is UTC"); + Perl_warn(aTHX_ "no UTC offset information; assuming local time is UTC"); } else { utc_offset_secs = atol(off); } } @@ -4043,7 +4182,7 @@ time_t my_time(time_t *timep) struct tm * my_gmtime(const time_t *timep) { - dTHR; + dTHX; char *p; time_t when; struct tm *rsltmp; @@ -4074,7 +4213,7 @@ my_gmtime(const time_t *timep) struct tm * my_localtime(const time_t *timep) { - dTHR; + dTHX; time_t when; struct tm *rsltmp; @@ -4131,7 +4270,7 @@ static const long int utime_baseadjust[2] = { 0x4beb4000, 0x7c9567 }; /*{{{int my_utime(char *path, struct utimbuf *utimes)*/ int my_utime(char *file, struct utimbuf *utimes) { - dTHR; + dTHX; register int i; long int bintime[2], len = 2, lowbit, unixtime, secscale = 10000000; /* seconds --> 100 ns intervals */ @@ -4178,7 +4317,7 @@ int my_utime(char *file, struct utimbuf *utimes) /* If input was UTC; convert to local for sys svc */ if (!VMSISH_TIME) unixtime = _toloc(unixtime); # endif - unixtime >> 1; secscale << 1; + unixtime >>= 1; secscale <<= 1; retsts = lib$emul(&secscale, &unixtime, &lowbit, bintime); if (!(retsts & 1)) { set_errno(EVMSERR); @@ -4224,6 +4363,8 @@ int my_utime(char *file, struct utimbuf *utimes) } retsts = sys$search(&myfab,0,0); if (!(retsts & 1)) { + mynam.nam$b_nop |= NAM$M_SYNCHK; mynam.nam$l_rlf = NULL; + myfab.fab$b_dns = 0; (void) sys$parse(&myfab,0,0); set_vaxc_errno(retsts); if (retsts == RMS$_PRV) set_errno(EACCES); else if (retsts == RMS$_FNF) set_errno(ENOENT); @@ -4236,6 +4377,8 @@ int my_utime(char *file, struct utimbuf *utimes) retsts = sys$assign(&devdsc,&chan,0,0); if (!(retsts & 1)) { + mynam.nam$b_nop |= NAM$M_SYNCHK; mynam.nam$l_rlf = NULL; + myfab.fab$b_dns = 0; (void) sys$parse(&myfab,0,0); set_vaxc_errno(retsts); if (retsts == SS$_IVDEVNAM) set_errno(ENOTDIR); else if (retsts == SS$_NOPRIV) set_errno(EACCES); @@ -4260,6 +4403,8 @@ int my_utime(char *file, struct utimbuf *utimes) myfib.fib$r_acctl_overlay.fib$l_acctl = FIB$M_NORECORD; #endif retsts = sys$qiow(0,chan,IO$_MODIFY,iosb,0,0,&fibdsc,&fnmdsc,0,0,myatr,0); + mynam.nam$b_nop |= NAM$M_SYNCHK; mynam.nam$l_rlf = NULL; + myfab.fab$b_dns = 0; (void) sys$parse(&myfab,0,0); _ckvmssts(sys$dassgn(chan)); if (retsts & 1) retsts = iosb[0]; if (!(retsts & 1)) { @@ -4315,6 +4460,7 @@ static mydev_t encode_dev (const char *dev) mydev_t enc; char c; const char *q; + dTHX; if (!dev || !dev[0]) return 0; @@ -4360,6 +4506,7 @@ static int is_null_device(name) const char *name; { + dTHX; /* The VMS null device is named "_NLA0:", usually abbreviated as "NL:". The underscore prefix, controller letter, and unit number are independently optional; for our purposes, the colon punctuation @@ -4378,11 +4525,9 @@ is_null_device(name) /* Do this via $Check_Access on VMS, since the CRTL stat() returns only a * subset of the applicable information. */ -/*{{{I32 cando(I32 bit, I32 effective, struct stat *statbufp)*/ -I32 -cando(I32 bit, I32 effective, Stat_t *statbufp) +bool +Perl_cando(pTHX_ Mode_t bit, Uid_t effective, Stat_t *statbufp) { - dTHR; if (statbufp == &PL_statcache) return cando_by_name(bit,effective,namecache); else { char fname[NAM$C_MAXRSS+1]; @@ -4404,7 +4549,7 @@ cando(I32 bit, I32 effective, Stat_t *statbufp) return cando_by_name(bit,effective,fname); } else if (retsts == SS$_NOSUCHDEV || retsts == SS$_NOSUCHFILE) { - warn("Can't get filespec - stale stat buffer?\n"); + Perl_warn(aTHX_ "Can't get filespec - stale stat buffer?\n"); return FALSE; } _ckvmssts(retsts); @@ -4414,9 +4559,9 @@ cando(I32 bit, I32 effective, Stat_t *statbufp) /*}}}*/ -/*{{{I32 cando_by_name(I32 bit, I32 effective, char *fname)*/ +/*{{{I32 cando_by_name(I32 bit, Uid_t effective, char *fname)*/ I32 -cando_by_name(I32 bit, I32 effective, char *fname) +cando_by_name(I32 bit, Uid_t effective, char *fname) { static char usrname[L_cuserid]; static struct dsc$descriptor_s usrdsc = @@ -4424,6 +4569,7 @@ cando_by_name(I32 bit, I32 effective, char *fname) char vmsname[NAM$C_MAXRSS+1], fileified[NAM$C_MAXRSS+1]; unsigned long int objtyp = ACL$C_FILE, access, retsts, privused, iosb[2]; unsigned short int retlen; + dTHX; struct dsc$descriptor_s namdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; union prvdef curprv; struct itmlst_3 armlst[3] = {{sizeof access, CHP$_ACCESS, &access, &retlen}, @@ -4516,7 +4662,7 @@ cando_by_name(I32 bit, I32 effective, char *fname) int flex_fstat(int fd, Stat_t *statbufp) { - dTHR; + dTHX; if (!fstat(fd,(stat_t *) statbufp)) { if (statbufp == (Stat_t *) &PL_statcache) *namecache == '\0'; statbufp->st_dev = encode_dev(statbufp->st_devnam); @@ -4550,7 +4696,7 @@ flex_fstat(int fd, Stat_t *statbufp) int flex_stat(const char *fspec, Stat_t *statbufp) { - dTHR; + dTHX; char fileified[NAM$C_MAXRSS+1]; char temp_fspec[NAM$C_MAXRSS+300]; int retval = -1; @@ -4819,14 +4965,14 @@ rmscopy(char *spec_in, char *spec_out, int preserve_dates) */ void -rmsexpand_fromperl(CV *cv) +rmsexpand_fromperl(pTHX_ CV *cv) { dXSARGS; char *fspec, *defspec = NULL, *rslt; STRLEN n_a; if (!items || items > 2) - croak("Usage: VMS::Filespec::rmsexpand(spec[,defspec])"); + Perl_croak(aTHX_ "Usage: VMS::Filespec::rmsexpand(spec[,defspec])"); fspec = SvPV(ST(0),n_a); if (!fspec || !*fspec) XSRETURN_UNDEF; if (items == 2) defspec = SvPV(ST(1),n_a); @@ -4838,13 +4984,13 @@ rmsexpand_fromperl(CV *cv) } void -vmsify_fromperl(CV *cv) +vmsify_fromperl(pTHX_ CV *cv) { dXSARGS; char *vmsified; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::vmsify(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::vmsify(spec)"); vmsified = do_tovmsspec(SvPV(ST(0),n_a),NULL,1); ST(0) = sv_newmortal(); if (vmsified != NULL) sv_usepvn(ST(0),vmsified,strlen(vmsified)); @@ -4852,13 +4998,13 @@ vmsify_fromperl(CV *cv) } void -unixify_fromperl(CV *cv) +unixify_fromperl(pTHX_ CV *cv) { dXSARGS; char *unixified; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::unixify(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::unixify(spec)"); unixified = do_tounixspec(SvPV(ST(0),n_a),NULL,1); ST(0) = sv_newmortal(); if (unixified != NULL) sv_usepvn(ST(0),unixified,strlen(unixified)); @@ -4866,13 +5012,13 @@ unixify_fromperl(CV *cv) } void -fileify_fromperl(CV *cv) +fileify_fromperl(pTHX_ CV *cv) { dXSARGS; char *fileified; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::fileify(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::fileify(spec)"); fileified = do_fileify_dirspec(SvPV(ST(0),n_a),NULL,1); ST(0) = sv_newmortal(); if (fileified != NULL) sv_usepvn(ST(0),fileified,strlen(fileified)); @@ -4880,13 +5026,13 @@ fileify_fromperl(CV *cv) } void -pathify_fromperl(CV *cv) +pathify_fromperl(pTHX_ CV *cv) { dXSARGS; char *pathified; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::pathify(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::pathify(spec)"); pathified = do_pathify_dirspec(SvPV(ST(0),n_a),NULL,1); ST(0) = sv_newmortal(); if (pathified != NULL) sv_usepvn(ST(0),pathified,strlen(pathified)); @@ -4894,13 +5040,13 @@ pathify_fromperl(CV *cv) } void -vmspath_fromperl(CV *cv) +vmspath_fromperl(pTHX_ CV *cv) { dXSARGS; char *vmspath; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::vmspath(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::vmspath(spec)"); vmspath = do_tovmspath(SvPV(ST(0),n_a),NULL,1); ST(0) = sv_newmortal(); if (vmspath != NULL) sv_usepvn(ST(0),vmspath,strlen(vmspath)); @@ -4908,13 +5054,13 @@ vmspath_fromperl(CV *cv) } void -unixpath_fromperl(CV *cv) +unixpath_fromperl(pTHX_ CV *cv) { dXSARGS; char *unixpath; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::unixpath(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::unixpath(spec)"); unixpath = do_tounixpath(SvPV(ST(0),n_a),NULL,1); ST(0) = sv_newmortal(); if (unixpath != NULL) sv_usepvn(ST(0),unixpath,strlen(unixpath)); @@ -4922,7 +5068,7 @@ unixpath_fromperl(CV *cv) } void -candelete_fromperl(CV *cv) +candelete_fromperl(pTHX_ CV *cv) { dXSARGS; char fspec[NAM$C_MAXRSS+1], *fsp; @@ -4930,7 +5076,7 @@ candelete_fromperl(CV *cv) IO *io; STRLEN n_a; - if (items != 1) croak("Usage: VMS::Filespec::candelete(spec)"); + if (items != 1) Perl_croak(aTHX_ "Usage: VMS::Filespec::candelete(spec)"); mysv = SvROK(ST(0)) ? SvRV(ST(0)) : ST(0); if (SvTYPE(mysv) == SVt_PVGV) { @@ -4954,7 +5100,7 @@ candelete_fromperl(CV *cv) } void -rmscopy_fromperl(CV *cv) +rmscopy_fromperl(pTHX_ CV *cv) { dXSARGS; char inspec[NAM$C_MAXRSS+1], outspec[NAM$C_MAXRSS+1], *inp, *outp; @@ -4967,7 +5113,7 @@ rmscopy_fromperl(CV *cv) STRLEN n_a; if (items < 2 || items > 3) - croak("Usage: File::Copy::rmscopy(from,to[,date_flag])"); + Perl_croak(aTHX_ "Usage: File::Copy::rmscopy(from,to[,date_flag])"); mysv = SvROK(ST(0)) ? SvRV(ST(0)) : ST(0); if (SvTYPE(mysv) == SVt_PVGV) { @@ -5011,6 +5157,13 @@ void init_os_extras() { char* file = __FILE__; + dTHX; + char temp_buff[512]; + if (my_trnlnm("DECC$DISABLE_TO_VMS_LOGNAME_TRANSLATION", temp_buff, 0)) { + no_translate_barewords = TRUE; + } else { + no_translate_barewords = FALSE; + } newXSproto("VMS::Filespec::rmsexpand",rmsexpand_fromperl,file,"$;$"); newXSproto("VMS::Filespec::vmsify",vmsify_fromperl,file,"$");