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