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<exec>'s argument to it as parameters.
+rest of C<exec>'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<MCR> or a text file which
+should be passed to DCL as a command procedure.
You can use C<exec> in both ways within the same script, as
long as you call C<fork> and C<exec> in pairs. Perl
using a default type of F<.Exe> and the process defaults, and if
successful, the resulting file is invoked via C<MCR>. This allows you
to invoke an image directly simply by passing the file specification
-to C<system>, a common Unixish idiom. If LIST consists
-of the empty string, C<system> spawns an interactive DCL subprocess,
-in the same fashion as typiing B<SPAWN> at the DCL prompt.
+to C<system>, 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<MCR> or a text file which should be passed to DCL
+as a command procedure.
+
+If LIST consists of the empty string, C<system> spawns an
+interactive DCL subprocess, in the same fashion as typiing
+B<SPAWN> at the DCL prompt.
+
Perl waits for the subprocess to complete before continuing
execution in the current process. As described in L<perlfunc>,
the return value of C<system> is a fake "status" which follows
{
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;
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);