1/* 2 * Copyright 1993, 1995 Christopher Seiwald. 3 * 4 * This file is part of Jam - see jam.c for Copyright information. 5 */ 6 7/* 8 * execvms.c - execute a shell script, ala VMS 9 * 10 * The approach is this: 11 * 12 * If the command is a single line, and shorter than WRTLEN (what we 13 * believe to be the maximum line length), we just system() it. 14 * 15 * If the command is multi-line, or longer than WRTLEN, we write the 16 * command block to a temp file, splitting long lines (using "-" at 17 * the end of the line to indicate contiuation), and then source that 18 * temp file. We use special logic to make sure we don't continue in 19 * the middle of a quoted string. 20 * 21 * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS 22 * 12/20/96 (seiwald) - rewritten to handle multi-line commands well 23 * 01/14/96 (seiwald) - don't put -'s between "'s 24 * 01/20/00 (seiwald) - Upgraded from K&R to ANSI C 25 */ 26 27# include "jam.h" 28# include "lists.h" 29# include "execcmd.h" 30 31# ifdef OS_VMS 32 33#include <stdio.h> 34#include <string.h> 35#include <stdlib.h> 36#include <iodef.h> 37#include <ssdef.h> 38#include <descrip.h> 39#include <dvidef.h> 40#include <clidef.h> 41 42#define WRTLEN 240 43 44#define MIN( a, b ) ((a) < (b) ? (a) : (b)) 45 46/* 1 for the @ and 4 for the .com */ 47 48char tempnambuf[ L_tmpnam + 1 + 4 ] = {0}; 49 50void 51execcmd( 52 char *string, 53 void (*func)( void *closure, int status ), 54 void *closure, 55 LIST *shell ) 56{ 57 char *s, *e, *p; 58 int rstat = EXEC_CMD_OK; 59 int status; 60 61 /* See if string is more than one line */ 62 /* discounting leading/trailing white space */ 63 64 for( s = string; *s && isspace( *s ); s++ ) 65 ; 66 67 e = p = strchr( s, '\n' ); 68 69 while( p && isspace( *p ) ) 70 ++p; 71 72 /* If multi line or long, write to com file. */ 73 /* Otherwise, exec directly. */ 74 75 if( p && *p || e - s > WRTLEN ) 76 { 77 FILE *f; 78 79 /* Create temp file invocation "@sys$scratch:tempfile.com" */ 80 81 if( !*tempnambuf ) 82 { 83 tempnambuf[0] = '@'; 84 (void)tmpnam( tempnambuf + 1 ); 85 strcat( tempnambuf, ".com" ); 86 } 87 88 /* Open tempfile */ 89 90 if( !( f = fopen( tempnambuf + 1, "w" ) ) ) 91 { 92 printf( "can't open command file\n" ); 93 (*func)( closure, EXEC_CMD_FAIL ); 94 return; 95 } 96 97 /* For each line of the string */ 98 99 while( *string ) 100 { 101 char *s = strchr( string, '\n' ); 102 int len = s ? s + 1 - string : strlen( string ); 103 104 fputc( '$', f ); 105 106 /* For each chunk of a line that needs to be split */ 107 108 while( len > 0 ) 109 { 110 char *q = string; 111 char *qe = string + MIN( len, WRTLEN ); 112 char *qq = q; 113 int quote = 0; 114 115 /* Look for matching "'s */ 116 117 for( ; q < qe; q++ ) 118 if( *q == '"' && ( quote = !quote ) ) 119 qq = q; 120 121 /* Back up to opening quote, if in one */ 122 123 if( quote ) 124 q = qq; 125 126 fwrite( string, ( q - string ), 1, f ); 127 128 len -= ( q - string ); 129 string = q; 130 131 if( len ) 132 { 133 fputc( '-', f ); 134 fputc( '\n', f ); 135 } 136 } 137 } 138 139 fclose( f ); 140 141 status = system( tempnambuf ) & 0x07; 142 143 unlink( tempnambuf + 1 ); 144 } 145 else 146 { 147 /* Execute single line command */ 148 /* Strip trailing newline before execing */ 149 if( e ) *e = 0; 150 status = system( s ) & 0x07; 151 } 152 153 /* Fail for error or fatal error */ 154 /* OK on OK, warning, or info exit */ 155 156 if( status == 2 || status == 4 ) 157 rstat = EXEC_CMD_FAIL; 158 159 (*func)( closure, rstat ); 160} 161 162int 163execwait() 164{ 165 return 0; 166} 167 168# endif /* VMS */ 169