mirror of
https://review.haiku-os.org/buildtools
synced 2024-11-23 07:18:49 +01:00
169 lines
3.3 KiB
C
169 lines
3.3 KiB
C
|
/*
|
||
|
* Copyright 1993, 1995 Christopher Seiwald.
|
||
|
*
|
||
|
* This file is part of Jam - see jam.c for Copyright information.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* 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 don't 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) - don't put -'s between "'s
|
||
|
* 01/20/00 (seiwald) - Upgraded from K&R to ANSI C
|
||
|
*/
|
||
|
|
||
|
# 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>
|
||
|
|
||
|
#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
|
||
|
execcmd(
|
||
|
char *string,
|
||
|
void (*func)( void *closure, int status ),
|
||
|
void *closure,
|
||
|
LIST *shell )
|
||
|
{
|
||
|
char *s, *e, *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
|
||
|
execwait()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
# endif /* VMS */
|