| /* |
| * 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 <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <iodef.h> |
| #include <ssdef.h> |
| #include <descrip.h> |
| #include <dvidef.h> |
| #include <clidef.h> |
| |
| /* |
| * 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 */ |