/* * Copyright 1993, 1995 Christopher Seiwald. * * This file is part of Jam - see jam.c for Copyright information. */ #include "jam.h" #include "lists.h" #include "execcmd.h" #ifdef OS_VMS #include #include #include #include #include #include #include #include /* * execvms.c - execute a shell script, ala VMS. * * The approach is this: * * If the command is a single line, and shorter than WRTLEN (what we believe to * be the maximum line length), we just system() it. * * If the command is multi-line, or longer than WRTLEN, we write the command * block to a temp file, splitting long lines (using "-" at the end of the line * to indicate contiuation), and then source that temp file. We use special * logic to make sure we do not continue in the middle of a quoted string. * * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS * 12/20/96 (seiwald) - rewritten to handle multi-line commands well * 01/14/96 (seiwald) - do not put -'s between "'s */ #define WRTLEN 240 #define MIN( a, b ) ((a) < (b) ? (a) : (b)) /* 1 for the @ and 4 for the .com */ char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 }; void exec_cmd ( char * string, void (* func)( void * closure, int status, timing_info *, char *, char * ), void * closure, LIST * shell, char * rule_name, char * target ) { char * s; char * e; cahr * p; int rstat = EXEC_CMD_OK; int status; /* See if string is more than one line discounting leading/trailing white * space. */ for ( s = string; *s && isspace( *s ); ++s ); e = p = strchr( s, '\n' ); while ( p && isspace( *p ) ) ++p; /* If multi line or long, write to com file. Otherwise, exec directly. */ if ( ( p && *p ) || ( e - s > WRTLEN ) ) { FILE * f; /* Create temp file invocation "@sys$scratch:tempfile.com". */ if ( !*tempnambuf ) { tempnambuf[0] = '@'; (void)tmpnam( tempnambuf + 1 ); strcat( tempnambuf, ".com" ); } /* Open tempfile. */ if ( !( f = fopen( tempnambuf + 1, "w" ) ) ) { printf( "can't open command file\n" ); (*func)( closure, EXEC_CMD_FAIL ); return; } /* For each line of the string. */ while ( *string ) { char * s = strchr( string, '\n' ); int len = s ? s + 1 - string : strlen( string ); fputc( '$', f ); /* For each chunk of a line that needs to be split. */ while ( len > 0 ) { char * q = string; char * qe = string + MIN( len, WRTLEN ); char * qq = q; int quote = 0; /* Look for matching "s. */ for ( ; q < qe; ++q ) if ( ( *q == '"' ) && ( quote = !quote ) ) qq = q; /* Back up to opening quote, if in one. */ if ( quote ) q = qq; fwrite( string, ( q - string ), 1, f ); len -= ( q - string ); string = q; if ( len ) { fputc( '-', f ); fputc( '\n', f ); } } } fclose( f ); status = system( tempnambuf ) & 0x07; unlink( tempnambuf + 1 ); } else { /* Execute single line command. Strip trailing newline before execing. */ if ( e ) *e = 0; status = system( s ) & 0x07; } /* Fail for error or fatal error. OK on OK, warning or info exit. */ if ( ( status == 2 ) || ( status == 4 ) ) rstat = EXEC_CMD_FAIL; (*func)( closure, rstat ); } int exec_wait() { return 0; } # endif /* VMS */