2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
23 * execvms.c - execute a shell script, ala VMS.
25 * The approach is this:
27 * If the command is a single line, and shorter than WRTLEN (what we believe to
28 * be the maximum line length), we just system() it.
30 * If the command is multi-line, or longer than WRTLEN, we write the command
31 * block to a temp file, splitting long lines (using "-" at the end of the line
32 * to indicate contiuation), and then source that temp file. We use special
33 * logic to make sure we do not continue in the middle of a quoted string.
35 * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
36 * 12/20/96 (seiwald) - rewritten to handle multi-line commands well
37 * 01/14/96 (seiwald) - do not put -'s between "'s
42 #define MIN( a, b ) ((a) < (b) ? (a) : (b))
44 /* 1 for the @ and 4 for the .com */
46 char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 };
52 void (* func)( void * closure, int status, timing_info *, char *, char * ),
62 int rstat = EXEC_CMD_OK;
65 /* See if string is more than one line discounting leading/trailing white
68 for ( s = string; *s && isspace( *s ); ++s );
70 e = p = strchr( s, '\n' );
72 while ( p && isspace( *p ) )
75 /* If multi line or long, write to com file. Otherwise, exec directly. */
76 if ( ( p && *p ) || ( e - s > WRTLEN ) )
80 /* Create temp file invocation "@sys$scratch:tempfile.com". */
84 (void)tmpnam( tempnambuf + 1 );
85 strcat( tempnambuf, ".com" );
89 if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
91 printf( "can't open command file\n" );
92 (*func)( closure, EXEC_CMD_FAIL );
96 /* For each line of the string. */
99 char * s = strchr( string, '\n' );
100 int len = s ? s + 1 - string : strlen( string );
104 /* For each chunk of a line that needs to be split. */
108 char * qe = string + MIN( len, WRTLEN );
112 /* Look for matching "s. */
113 for ( ; q < qe; ++q )
114 if ( ( *q == '"' ) && ( quote = !quote ) )
117 /* Back up to opening quote, if in one. */
121 fwrite( string, ( q - string ), 1, f );
123 len -= ( q - string );
136 status = system( tempnambuf ) & 0x07;
138 unlink( tempnambuf + 1 );
142 /* Execute single line command. Strip trailing newline before execing.
145 status = system( s ) & 0x07;
148 /* Fail for error or fatal error. OK on OK, warning or info exit. */
149 if ( ( status == 2 ) || ( status == 4 ) )
150 rstat = EXEC_CMD_FAIL;
152 (*func)( closure, rstat );