1 /*
2  * Copyright 1993, 1995 Christopher Seiwald.
3  * Copyright 2007 Noel Belcourt.
4  *
5  *   Utility functions shared between different exec*.c platform specific
6  * implementation modules.
7  *
8  * This file is part of Jam - see jam.c for Copyright information.
9  */
10 
11 #include "jam.h"
12 #include "execcmd.h"
13 #include "output.h"
14 
15 #include <assert.h>
16 #include <stdio.h>
17 #include <string.h>
18 
19 
20 /* Internal interrupt counter. */
21 static int intr;
22 
23 
24 /* Constructs a list of command-line elements using the format specified by the
25  * given shell list.
26  *
27  * Given argv array should have at least MAXARGC + 1 elements.
28  * Slot numbers may be between 0 and 998 (inclusive).
29  *
30  * Constructed argv list will be zero terminated. Character arrays referenced by
31  * the argv structure elements will be either elements from the give shell list,
32  * internal static buffers or the given command string and should thus not
33  * considered owned by or released via the argv structure and should be
34  * considered invalidated by the next argv_from_shell() call.
35  *
36  * Shell list elements:
37  *   - Starting with '%' - represent the command string.
38  *   - Starting with '!' - represent the slot number (increased by one).
39  *   - Anything else - used as a literal.
40  *   - If no '%' element is found, the command string is appended as an extra.
41  */
42 
argv_from_shell(char const ** argv,LIST * shell,char const * command,int const slot)43 void argv_from_shell( char const * * argv, LIST * shell, char const * command,
44     int const slot )
45 {
46     static char jobno[ 4 ];
47 
48     int i;
49     int gotpercent = 0;
50     LISTITER iter = list_begin( shell );
51     LISTITER end = list_end( shell );
52 
53     assert( 0 <= slot );
54     assert( slot < 999 );
55     sprintf( jobno, "%d", slot + 1 );
56 
57     for ( i = 0; iter != end && i < MAXARGC; ++i, iter = list_next( iter ) )
58     {
59         switch ( object_str( list_item( iter ) )[ 0 ] )
60         {
61             case '%': argv[ i ] = command; ++gotpercent; break;
62             case '!': argv[ i ] = jobno; break;
63             default : argv[ i ] = object_str( list_item( iter ) );
64         }
65     }
66 
67     if ( !gotpercent )
68         argv[ i++ ] = command;
69 
70     argv[ i ] = NULL;
71 }
72 
73 
74 /* Returns whether the given command string contains lines longer than the given
75  * maximum.
76  */
check_cmd_for_too_long_lines(char const * command,int const max,int * const error_length,int * const error_max_length)77 int check_cmd_for_too_long_lines( char const * command, int const max,
78     int * const error_length, int * const error_max_length )
79 {
80     while ( *command )
81     {
82         size_t const l = strcspn( command, "\n" );
83         if ( l > max )
84         {
85             *error_length = l;
86             *error_max_length = max;
87             return EXEC_CHECK_LINE_TOO_LONG;
88         }
89         command += l;
90         if ( *command )
91             ++command;
92     }
93     return EXEC_CHECK_OK;
94 }
95 
96 
97 /* Checks whether the given shell list is actually a request to execute raw
98  * commands without an external shell.
99  */
is_raw_command_request(LIST * shell)100 int is_raw_command_request( LIST * shell )
101 {
102     return !list_empty( shell ) &&
103         !strcmp( object_str( list_front( shell ) ), "%" ) &&
104         list_next( list_begin( shell ) ) == list_end( shell );
105 }
106 
107 
108 /* Returns whether an interrupt has been detected so far. */
109 
interrupted(void)110 int interrupted( void )
111 {
112     return intr != 0;
113 }
114 
115 
116 /* Internal interrupt handler. */
117 
onintr(int disp)118 void onintr( int disp )
119 {
120     ++intr;
121     out_printf( "...interrupted\n" );
122 }
123