Command built-in can parse output into list (no need to Match it now)
[k8jam.git] / execvms.c
blob2765d5cfa75da4c883fa9d48e889fa9a51fc7a98
1 /*
2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
7 /*
8 * execvms.c - execute a shell script, ala VMS
10 * The approach is this:
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.
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.
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
27 # include "jam.h"
28 # include "lists.h"
29 # include "execcmd.h"
31 # ifdef OS_VMS
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>
42 #define WRTLEN 240
44 #define MIN( a, b ) ((a) < (b) ? (a) : (b))
46 /* 1 for the @ and 4 for the .com */
48 char tempnambuf[ L_tmpnam + 1 + 4 ] = {0};
50 void
51 execcmd(
52 char *string,
53 void (*func)( void *closure, int status ),
54 void *closure,
55 LIST *shell )
57 char *s, *e, *p;
58 int rstat = EXEC_CMD_OK;
59 int status;
61 /* See if string is more than one line */
62 /* discounting leading/trailing white space */
64 for( s = string; *s && isspace( *s ); s++ )
67 e = p = strchr( s, '\n' );
69 while( p && isspace( *p ) )
70 ++p;
72 /* If multi line or long, write to com file. */
73 /* Otherwise, exec directly. */
75 if( p && *p || e - s > WRTLEN )
77 FILE *f;
79 /* Create temp file invocation "@sys$scratch:tempfile.com" */
81 if( !*tempnambuf )
83 tempnambuf[0] = '@';
84 (void)tmpnam( tempnambuf + 1 );
85 strcat( tempnambuf, ".com" );
88 /* Open tempfile */
90 if( !( f = fopen( tempnambuf + 1, "w" ) ) )
92 printf( "can't open command file\n" );
93 (*func)( closure, EXEC_CMD_FAIL );
94 return;
97 /* For each line of the string */
99 while( *string )
101 char *s = strchr( string, '\n' );
102 int len = s ? s + 1 - string : strlen( string );
104 fputc( '$', f );
106 /* For each chunk of a line that needs to be split */
108 while( len > 0 )
110 char *q = string;
111 char *qe = string + MIN( len, WRTLEN );
112 char *qq = q;
113 int quote = 0;
115 /* Look for matching "'s */
117 for( ; q < qe; q++ )
118 if( *q == '"' && ( quote = !quote ) )
119 qq = q;
121 /* Back up to opening quote, if in one */
123 if( quote )
124 q = qq;
126 fwrite( string, ( q - string ), 1, f );
128 len -= ( q - string );
129 string = q;
131 if( len )
133 fputc( '-', f );
134 fputc( '\n', f );
139 fclose( f );
141 status = system( tempnambuf ) & 0x07;
143 unlink( tempnambuf + 1 );
145 else
147 /* Execute single line command */
148 /* Strip trailing newline before execing */
149 if( e ) *e = 0;
150 status = system( s ) & 0x07;
153 /* Fail for error or fatal error */
154 /* OK on OK, warning, or info exit */
156 if( status == 2 || status == 4 )
157 rstat = EXEC_CMD_FAIL;
159 (*func)( closure, rstat );
163 execwait()
165 return 0;
168 # endif /* VMS */