codec cleanup
[platform/upstream/boost-jam.git] / execvms.c
1 /*
2  * Copyright 1993, 1995 Christopher Seiwald.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
6
7 #include "jam.h"
8 #include "lists.h"
9 #include "execcmd.h"
10
11 #ifdef OS_VMS
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <iodef.h>
17 #include <ssdef.h>
18 #include <descrip.h>
19 #include <dvidef.h>
20 #include <clidef.h>
21
22 /*
23  * execvms.c - execute a shell script, ala VMS.
24  *
25  * The approach is this:
26  *
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.
29  *
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.
34  *
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
38  */
39
40 #define WRTLEN 240
41
42 #define MIN( a, b ) ((a) < (b) ? (a) : (b))
43
44 /* 1 for the @ and 4 for the .com */
45
46 char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 };
47
48
49 void exec_cmd
50 (
51     char * string,
52     void (* func)( void * closure, int status, timing_info *, char *, char * ),
53     void * closure,
54     LIST * shell,
55     char * rule_name,
56     char * target
57 )
58 {
59     char * s;
60     char * e;
61     cahr * p;
62     int rstat = EXEC_CMD_OK;
63     int status;
64
65     /* See if string is more than one line discounting leading/trailing white
66      * space.
67      */
68     for ( s = string; *s && isspace( *s ); ++s );
69
70     e = p = strchr( s, '\n' );
71
72     while ( p && isspace( *p ) )
73         ++p;
74
75     /* If multi line or long, write to com file. Otherwise, exec directly. */
76     if ( ( p && *p ) || ( e - s > WRTLEN ) )
77     {
78         FILE * f;
79
80         /* Create temp file invocation "@sys$scratch:tempfile.com". */
81         if ( !*tempnambuf )
82         {
83             tempnambuf[0] = '@';
84             (void)tmpnam( tempnambuf + 1 );
85             strcat( tempnambuf, ".com" );
86         }
87
88         /* Open tempfile. */
89         if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
90         {
91             printf( "can't open command file\n" );
92             (*func)( closure, EXEC_CMD_FAIL );
93             return;
94         }
95
96         /* For each line of the string. */
97         while ( *string )
98         {
99             char * s = strchr( string, '\n' );
100             int len = s ? s + 1 - string : strlen( string );
101
102             fputc( '$', f );
103
104             /* For each chunk of a line that needs to be split. */
105             while ( len > 0 )
106             {
107                 char * q = string;
108                 char * qe = string + MIN( len, WRTLEN );
109                 char * qq = q;
110                 int quote = 0;
111
112                 /* Look for matching "s. */
113                 for ( ; q < qe; ++q )
114                     if ( ( *q == '"' ) && ( quote = !quote ) )
115                         qq = q;
116
117                 /* Back up to opening quote, if in one. */
118                 if ( quote )
119                     q = qq;
120
121                 fwrite( string, ( q - string ), 1, f );
122
123                 len -= ( q - string );
124                 string = q;
125
126                 if ( len )
127                 {
128                     fputc( '-', f );
129                     fputc( '\n', f );
130                 }
131             }
132         }
133
134         fclose( f );
135
136         status = system( tempnambuf ) & 0x07;
137
138         unlink( tempnambuf + 1 );
139     }
140     else
141     {
142         /* Execute single line command. Strip trailing newline before execing.
143          */
144         if ( e ) *e = 0;
145         status = system( s ) & 0x07;
146     }
147
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;
151
152     (*func)( closure, rstat );
153 }
154
155
156 int exec_wait()
157 {
158     return 0;
159 }
160
161 # endif /* VMS */