From: Charles Bailey Date: Fri, 3 Mar 2000 03:54:10 +0000 (+0000) Subject: Try to intuit whether typeless file invoked in subprocess X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8012a33e8c336bcc87614284fe009157cf375ae1;p=p5sagit%2Fp5-mst-13.2.git Try to intuit whether typeless file invoked in subprocess is an executable image or DCL procedure. p4raw-id: //depot/vmsperl@5478 --- diff --git a/vms/perlvms.pod b/vms/perlvms.pod index 53925b2..3883233 100644 --- a/vms/perlvms.pod +++ b/vms/perlvms.pod @@ -463,7 +463,11 @@ is executed as a DCL command. Otherwise, the first token on the command line is treated as the filespec of an image to run, and an attempt is made to invoke it (using F<.Exe> and the process defaults to expand the filespec) and pass the -rest of C's argument to it as parameters. +rest of C's argument to it as parameters. If the token +has no file type, and matches a file with null type, then an +attempt is made to determine whether the file is an executable +image which should be invoked using C or a text file which +should be passed to DCL as a command procedure. You can use C in both ways within the same script, as long as you call C and C in pairs. Perl @@ -558,9 +562,16 @@ specification (e.g. C<:> or C<]>), an attempt is made to expand it using a default type of F<.Exe> and the process defaults, and if successful, the resulting file is invoked via C. This allows you to invoke an image directly simply by passing the file specification -to C, a common Unixish idiom. If LIST consists -of the empty string, C spawns an interactive DCL subprocess, -in the same fashion as typiing B at the DCL prompt. +to C, a common Unixish idiom. If the token has no file type, +and matches a file with null type, then an attempt is made to +determine whether the file is an executable image which should be +invoked using C or a text file which should be passed to DCL +as a command procedure. + +If LIST consists of the empty string, C spawns an +interactive DCL subprocess, in the same fashion as typiing +B at the DCL prompt. + Perl waits for the subprocess to complete before continuing execution in the current process. As described in L, the return value of C is a fake "status" which follows diff --git a/vms/vms.c b/vms/vms.c index 65f1d58..f1f62bd 100644 --- a/vms/vms.c +++ b/vms/vms.c @@ -3393,6 +3393,7 @@ setup_cmddsc(char *cmd, int check_img) { 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; @@ -3448,18 +3449,44 @@ setup_cmddsc(char *cmd, int check_img) 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)) { + _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);