]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/execvms.c
2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * Copyright 2001-2004 David Abrahams.
9 * Copyright 2015 Artur Shepilko.
10 * Distributed under the Boost Software License, Version 1.0.
11 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
16 * execvms.c - execute a shell script, ala VMS.
18 * The approach is this:
20 * If the command is a single line, and shorter than WRTLEN (what we believe to
21 * be the maximum line length), we just system() it.
23 * If the command is multi-line, or longer than WRTLEN, we write the command
24 * block to a temp file, splitting long lines (using "-" at the end of the line
25 * to indicate contiuation), and then source that temp file. We use special
26 * logic to make sure we do not continue in the middle of a quoted string.
28 * 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
29 * 12/20/96 (seiwald) - rewritten to handle multi-line commands well
30 * 01/14/96 (seiwald) - do not put -'s between "'s
31 * 01/19/15 (shepilko)- adapt for jam-3.1.19
52 #define MIN( a, b ) ((a) < (b) ? (a) : (b))
54 #define CHAR_DQUOTE '"'
56 #define VMS_PATH_MAX 1024
57 #define VMS_COMMAND_MAX 1024
64 char commandbuf
[ VMS_COMMAND_MAX
] = { 0 };
67 static int get_status(int vms_status
);
68 static clock_t get_cpu_time();
71 * exec_check() - preprocess and validate the command.
76 string
const * command
,
79 int * error_max_length
82 int const is_raw_cmd
= 1;
84 /* We allow empty commands for non-default shells since we do not really
85 * know what they are going to do with such commands.
87 if ( !command
->size
&& ( is_raw_cmd
|| list_empty( *pShell
) ) )
88 return EXEC_CHECK_NOOP
;
92 : check_cmd_for_too_long_lines( command
->value
, MAXLINE
, error_length
,
98 * exec_cmd() - execute system command.
103 string
const * command
,
104 ExecCmdCallback func
,
114 int rstat
= EXEC_CMD_OK
;
115 int exit_reason
= EXIT_OK
;
116 timing_info time_info
;
118 struct tms start_time
;
120 char * cmd_string
= command
->value
;
123 /* Start the command */
125 timestamp_current( &time_info
.start
);
126 times( &start_time
);
128 /* See if command is more than one line discounting leading/trailing white
131 for ( s
= cmd_string
; *s
&& isspace( *s
); ++s
);
133 e
= p
= strchr( s
, '\n' );
135 while ( p
&& isspace( *p
) )
138 /* If multi line or long, write to com file. Otherwise, exec directly. */
139 if ( ( p
&& *p
) || ( e
- s
> WRTLEN
) )
143 /* Create temp file invocation. */
147 OBJECT
* tmp_filename
= 0;
149 tmp_filename
= path_tmpfile();
152 /* Get tmp file name is VMS-format. */
154 string os_filename
[ 1 ];
155 string_new( os_filename
);
156 path_translate_to_os( object_str( tmp_filename
), os_filename
);
157 object_free( tmp_filename
);
158 tmp_filename
= object_new( os_filename
->value
);
159 string_free( os_filename
);
163 strncat( commandbuf
+ 1, object_str( tmp_filename
),
164 VMS_COMMAND_MAX
- 2);
169 if ( !( f
= fopen( commandbuf
+ 1, "w" ) ) )
171 printf( "can't open cmd_string file\n" );
172 rstat
= EXEC_CMD_FAIL
;
173 exit_reason
= EXIT_FAIL
;
177 timestamp_current( &time_info
.end
);
178 time_info
.system
= (double)( end_time
.tms_cstime
-
179 start_time
.tms_cstime
) / 100.;
180 time_info
.user
= (double)( end_time
.tms_cutime
-
181 start_time
.tms_cutime
) / 100.;
183 (*func
)( closure
, rstat
, &time_info
, "" , "", exit_reason
);
188 /* Running from TMP, so explicitly set default to CWD. */
191 int cwd_buf_size
= VMS_PATH_MAX
;
193 while ( !(cwd
= getcwd( NULL
, cwd_buf_size
) ) /* alloc internally */
196 cwd_buf_size
+= VMS_PATH_MAX
;
201 perror( "can not get current working directory" );
205 fprintf( f
, "$ SET DEFAULT %s\n", cwd
);
211 /* For each line of the command. */
212 while ( *cmd_string
)
214 char * s
= strchr( cmd_string
,'\n' );
215 int len
= s
? s
+ 1 - cmd_string
: strlen( cmd_string
);
219 /* For each chunk of a line that needs to be split. */
222 char * q
= cmd_string
;
223 char * qe
= cmd_string
+ MIN( len
, WRTLEN
);
227 /* Look for matching "s -- expected in the same line. */
228 for ( ; q
< qe
; ++q
)
229 if ( ( *q
== CHAR_DQUOTE
) && ( quote
= !quote
) )
232 /* When needs splitting and is inside an open quote,
233 * back up to opening quote and split off at it.
234 * When the quoted string spans over a chunk,
235 * pass string as a whole.
236 * If no matching quote found, dump the rest of command.
238 if ( len
> WRTLEN
&& quote
)
242 if ( q
== cmd_string
)
244 for ( q
= qe
; q
< ( cmd_string
+ len
)
245 && *q
!= CHAR_DQUOTE
; ++q
) {}
246 q
= ( *q
== CHAR_DQUOTE
) ? ( q
+ 1 ) : ( cmd_string
+ len
);
250 fwrite( cmd_string
, ( q
- cmd_string
), 1, f
);
252 len
-= ( q
- cmd_string
);
268 char buf
[ WRTLEN
+ 1 ] = { 0 };
270 if ( (f
= fopen( commandbuf
+ 1, "r" ) ) )
273 printf( "Command file: %s\n", commandbuf
+ 1 );
277 nbytes
= fread( buf
, sizeof( buf
[0] ), sizeof( buf
) - 1, f
);
279 if ( nbytes
) fwrite(buf
, sizeof( buf
[0] ), nbytes
, stdout
);
287 /* Execute command file */
288 vms_status
= system( commandbuf
);
289 status
= get_status( vms_status
);
291 unlink( commandbuf
+ 1 );
295 /* Execute single line command. Strip trailing newline before execing.
296 * TODO:Call via popen() with capture of the output may be better here.
300 status
= VMS_SUCCESS
; /* success on empty command */
303 vms_status
= system( s
);
304 status
= get_status( vms_status
);
311 timestamp_current( &time_info
.end
);
312 time_info
.system
= (double)( end_time
.tms_cstime
-
313 start_time
.tms_cstime
) / 100.;
314 time_info
.user
= (double)( end_time
.tms_cutime
-
315 start_time
.tms_cutime
) / 100.;
318 /* Fail for error or fatal error. OK on OK, warning or info exit. */
319 if ( ( status
== VMS_ERROR
) || ( status
== VMS_FATAL
) )
321 rstat
= EXEC_CMD_FAIL
;
322 exit_reason
= EXIT_FAIL
;
325 (*func
)( closure
, rstat
, &time_info
, "" , "", exit_reason
);
335 /* get_status() - returns status of the VMS command execution.
336 - Map VMS status to its severity (lower 3-bits)
337 - W-DCL-IVVERB is returned on unrecognized command -- map to general ERROR
339 int get_status( int vms_status
)
341 #define VMS_STATUS_DCL_IVVERB 0x00038090
347 case VMS_STATUS_DCL_IVVERB
:
352 status
= vms_status
& 0x07; /* $SEVERITY bits */
359 #define __NEW_STARLET 1
370 #include <lib$routines.h>
375 * get_cpu_time() - returns CPU time in CLOCKS_PER_SEC since process start.
376 * on error returns (clock_t)-1.
378 * Intended to emulate (system + user) result of *NIX times(), if CRTL times()
380 * However, this accounts only for the current process. To account for child
381 * processes, these need to be directly spawned/forked via exec().
382 * Moreover, child processes should be running a C main program or a program
383 * that calls VAXC$CRTL_INIT or DECC$CRTL_INIT.
386 clock_t get_cpu_time()
388 clock_t result
= (clock_t) 0;
396 { sizeof( cputime
), JPI$_CPUTIM
, &cputime
, NULL
}, /* longword int, 10ms */
400 status
= sys$
getjpiw (EFN$C_ENF
, 0, 0, jpi_items
, &iosb
, 0, 0);
402 if ( !$
VMS_STATUS_SUCCESS( status
) )
404 lib$
signal( status
);
406 result
= (clock_t) -1;
411 result
= ( cputime
/ 100 ) * CLOCKS_PER_SEC
;