]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/execvms.cpp
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
,
105 ExecCmdCallback func
,
115 int rstat
= EXEC_CMD_OK
;
116 int exit_reason
= EXIT_OK
;
117 timing_info time_info
;
119 struct tms start_time
;
121 char * cmd_string
= command
->value
;
124 /* Start the command */
126 timestamp_current( &time_info
.start
);
127 times( &start_time
);
129 /* See if command is more than one line discounting leading/trailing white
132 for ( s
= cmd_string
; *s
&& isspace( *s
); ++s
);
134 e
= p
= strchr( s
, '\n' );
136 while ( p
&& isspace( *p
) )
139 /* If multi line or long, write to com file. Otherwise, exec directly. */
140 if ( ( p
&& *p
) || ( e
- s
> WRTLEN
) )
144 /* Create temp file invocation. */
148 OBJECT
* tmp_filename
= 0;
150 tmp_filename
= path_tmpfile();
153 /* Get tmp file name is VMS-format. */
155 string os_filename
[ 1 ];
156 string_new( os_filename
);
157 path_translate_to_os( object_str( tmp_filename
), os_filename
);
158 object_free( tmp_filename
);
159 tmp_filename
= object_new( os_filename
->value
);
160 string_free( os_filename
);
164 strncat( commandbuf
+ 1, object_str( tmp_filename
),
165 VMS_COMMAND_MAX
- 2);
170 if ( !( f
= fopen( commandbuf
+ 1, "w" ) ) )
172 printf( "can't open cmd_string file\n" );
173 rstat
= EXEC_CMD_FAIL
;
174 exit_reason
= EXIT_FAIL
;
178 timestamp_current( &time_info
.end
);
179 time_info
.system
= (double)( end_time
.tms_cstime
-
180 start_time
.tms_cstime
) / 100.;
181 time_info
.user
= (double)( end_time
.tms_cutime
-
182 start_time
.tms_cutime
) / 100.;
184 (*func
)( closure
, rstat
, &time_info
, "" , "", exit_reason
);
189 /* Running from TMP, so explicitly set default to CWD. */
192 int cwd_buf_size
= VMS_PATH_MAX
;
194 while ( !(cwd
= getcwd( NULL
, cwd_buf_size
) ) /* alloc internally */
197 cwd_buf_size
+= VMS_PATH_MAX
;
202 perror( "can not get current working directory" );
206 fprintf( f
, "$ SET DEFAULT %s\n", cwd
);
212 /* For each line of the command. */
213 while ( *cmd_string
)
215 char * s
= strchr( cmd_string
,'\n' );
216 int len
= s
? s
+ 1 - cmd_string
: strlen( cmd_string
);
220 /* For each chunk of a line that needs to be split. */
223 char * q
= cmd_string
;
224 char * qe
= cmd_string
+ MIN( len
, WRTLEN
);
228 /* Look for matching "s -- expected in the same line. */
229 for ( ; q
< qe
; ++q
)
230 if ( ( *q
== CHAR_DQUOTE
) && ( quote
= !quote
) )
233 /* When needs splitting and is inside an open quote,
234 * back up to opening quote and split off at it.
235 * When the quoted string spans over a chunk,
236 * pass string as a whole.
237 * If no matching quote found, dump the rest of command.
239 if ( len
> WRTLEN
&& quote
)
243 if ( q
== cmd_string
)
245 for ( q
= qe
; q
< ( cmd_string
+ len
)
246 && *q
!= CHAR_DQUOTE
; ++q
) {}
247 q
= ( *q
== CHAR_DQUOTE
) ? ( q
+ 1 ) : ( cmd_string
+ len
);
251 fwrite( cmd_string
, ( q
- cmd_string
), 1, f
);
253 len
-= ( q
- cmd_string
);
269 char buf
[ WRTLEN
+ 1 ] = { 0 };
271 if ( (f
= fopen( commandbuf
+ 1, "r" ) ) )
274 printf( "Command file: %s\n", commandbuf
+ 1 );
278 nbytes
= fread( buf
, sizeof( buf
[0] ), sizeof( buf
) - 1, f
);
280 if ( nbytes
) fwrite(buf
, sizeof( buf
[0] ), nbytes
, stdout
);
288 /* Execute command file */
289 vms_status
= system( commandbuf
);
290 status
= get_status( vms_status
);
292 unlink( commandbuf
+ 1 );
296 /* Execute single line command. Strip trailing newline before execing.
297 * TODO:Call via popen() with capture of the output may be better here.
301 status
= VMS_SUCCESS
; /* success on empty command */
304 vms_status
= system( s
);
305 status
= get_status( vms_status
);
312 timestamp_current( &time_info
.end
);
313 time_info
.system
= (double)( end_time
.tms_cstime
-
314 start_time
.tms_cstime
) / 100.;
315 time_info
.user
= (double)( end_time
.tms_cutime
-
316 start_time
.tms_cutime
) / 100.;
319 /* Fail for error or fatal error. OK on OK, warning or info exit. */
320 if ( ( status
== VMS_ERROR
) || ( status
== VMS_FATAL
) )
322 rstat
= EXEC_CMD_FAIL
;
323 exit_reason
= EXIT_FAIL
;
326 (*func
)( closure
, rstat
, &time_info
, "" , "", exit_reason
);
336 /* get_status() - returns status of the VMS command execution.
337 - Map VMS status to its severity (lower 3-bits)
338 - W-DCL-IVVERB is returned on unrecognized command -- map to general ERROR
340 int get_status( int vms_status
)
342 #define VMS_STATUS_DCL_IVVERB 0x00038090
348 case VMS_STATUS_DCL_IVVERB
:
353 status
= vms_status
& 0x07; /* $SEVERITY bits */
360 #define __NEW_STARLET 1
371 #include <lib$routines.h>
376 * get_cpu_time() - returns CPU time in CLOCKS_PER_SEC since process start.
377 * on error returns (clock_t)-1.
379 * Intended to emulate (system + user) result of *NIX times(), if CRTL times()
381 * However, this accounts only for the current process. To account for child
382 * processes, these need to be directly spawned/forked via exec().
383 * Moreover, child processes should be running a C main program or a program
384 * that calls VAXC$CRTL_INIT or DECC$CRTL_INIT.
387 clock_t get_cpu_time()
389 clock_t result
= (clock_t) 0;
397 { sizeof( cputime
), JPI$_CPUTIM
, &cputime
, NULL
}, /* longword int, 10ms */
401 status
= sys$
getjpiw (EFN$C_ENF
, 0, 0, jpi_items
, &iosb
, 0, 0);
403 if ( !$
VMS_STATUS_SUCCESS( status
) )
405 lib$
signal( status
);
407 result
= (clock_t) -1;
412 result
= ( cputime
/ 100 ) * CLOCKS_PER_SEC
;