11/* Black Belt Ethical Auditor - Linux C CLI
2- * Reads canonical BBEA JSON from --file or stdin and sends it to the
3- * shared Black Belt engine transport. The AI engine remains external.
2+ * Reads canonical BBEA JSON from --file, stdin, or the interactive prompt
3+ * and sends it to the shared Black Belt engine transport. The AI engine remains external.
44 */
55#define _POSIX_C_SOURCE 200809L
66#include <stdio.h>
@@ -16,12 +16,72 @@ static void usage(const char *p) {
1616 printf ("Environment: BBEA_ENGINE_URL, BBEA_MODEL, BBEA_SYSTEM_PROMPT.\n" );
1717}
1818
19- static int copy_stream (FILE * in ) {
20- int c ;
21- while ((c = fgetc (in )) != EOF ) {
22- if (fputc (c , stdout ) == EOF ) return 1 ;
19+ static int run_engine (const char * input ) {
20+ char tmp [] = "/tmp/blackbelt-c-XXXXXX" ;
21+ int fd = mkstemp (tmp );
22+ if (fd < 0 ) { perror ("mkstemp" ); return 2 ; }
23+
24+ FILE * out = fdopen (fd , "wb" );
25+ if (!out ) {
26+ perror ("fdopen" );
27+ close (fd );
28+ unlink (tmp );
29+ return 2 ;
30+ }
31+
32+ size_t length = strlen (input );
33+ if (fwrite (input , 1 , length , out ) != length || fputc ('\n' , out ) == EOF ) {
34+ perror ("write" );
35+ fclose (out );
36+ unlink (tmp );
37+ return 2 ;
38+ }
39+ fclose (out );
40+
41+ const char * engine = getenv ("BBEA_ENGINE_CMD" );
42+ if (!engine || !* engine ) engine = "bin/blackbelt-engine.sh" ;
43+
44+ char command [4096 ];
45+ int written = snprintf (command , sizeof (command ), "cat '%s' | '%s'" , tmp , engine );
46+ if (written < 0 || (size_t )written >= sizeof (command )) {
47+ fprintf (stderr , "Engine command is too long.\n" );
48+ unlink (tmp );
49+ return 3 ;
50+ }
51+
52+ int status = system (command );
53+ unlink (tmp );
54+ if (status == -1 ) return 3 ;
55+ return WIFEXITED (status ) ? WEXITSTATUS (status ) : 3 ;
56+ }
57+
58+ static int interactive (void ) {
59+ char * line = NULL ;
60+ size_t capacity = 0 ;
61+
62+ puts ("Black Belt Ethical Auditor" );
63+ puts ("Enter a JSON audit object, or type 'help' or 'quit'." );
64+
65+ for (;;) {
66+ fputs ("black-belt> " , stdout );
67+ fflush (stdout );
68+ ssize_t length = getline (& line , & capacity , stdin );
69+ if (length < 0 ) break ;
70+ while (length > 0 && (line [length - 1 ] == '\n' || line [length - 1 ] == '\r' ))
71+ line [-- length ] = '\0' ;
72+ if (length == 0 ) continue ;
73+ if (!strcmp (line , "quit" ) || !strcmp (line , "exit" )) break ;
74+ if (!strcmp (line , "help" )) {
75+ puts ("Paste a complete BBEA JSON audit object at the prompt." );
76+ puts ("Commands: help, quit, exit" );
77+ continue ;
78+ }
79+ int rc = run_engine (line );
80+ if (rc != 0 ) fprintf (stderr , "Audit failed (exit %d).\n" , rc );
2381 }
24- return ferror (in ) ? 1 : 0 ;
82+ free (line );
83+ putchar ('\n' );
84+ return 0 ;
2585}
2686
2787int main (int argc , char * * argv ) {
@@ -31,7 +91,7 @@ int main(int argc, char **argv) {
3191 usage (argv [0 ]); return 0 ;
3292 }
3393 if (!strcmp (argv [i ], "--version" )) {
34- puts ("blackbelt-c 1.0 (BBEA CLI v2 transport)" ); return 0 ;
94+ puts ("blackbelt-c 1.1 (BBEA CLI v2 transport)" ); return 0 ;
3595 }
3696 if (!strcmp (argv [i ], "--file" ) && i + 1 < argc ) {
3797 file = argv [++ i ]; continue ;
@@ -40,30 +100,25 @@ int main(int argc, char **argv) {
40100 usage (argv [0 ]); return 2 ;
41101 }
42102
103+ if (!file && isatty (STDIN_FILENO )) return interactive ();
104+
43105 FILE * in = stdin ;
44106 if (file ) {
45107 in = fopen (file , "rb" );
46108 if (!in ) { perror (file ); return 2 ; }
47109 }
48110
49- char tmp [] = "/tmp/blackbelt-c-XXXXXX" ;
50- int fd = mkstemp (tmp );
51- if (fd < 0 ) { perror ("mkstemp" ); if (file ) fclose (in ); return 2 ; }
52- FILE * out = fdopen (fd , "wb" );
53- if (!out ) { perror ("fdopen" ); close (fd ); unlink (tmp ); if (file ) fclose (in ); return 2 ; }
54- int rc = copy_stream (in );
111+ char * input = NULL ;
112+ size_t capacity = 0 ;
113+ ssize_t length = getdelim (& input , & capacity , '\0' , in );
55114 if (file ) fclose (in );
56- fclose ( out );
57- if ( rc ) { unlink ( tmp ); return 2 ; }
58-
59- const char * engine = getenv ( "BBEA_ENGINE_CMD" ) ;
60- if (! engine || ! * engine ) engine = "bin/blackbelt-engine.sh" ;
115+ if ( length < 0 || ! input || length == 0 ) {
116+ free ( input );
117+ fprintf ( stderr , "No JSON audit input received.\n" );
118+ return 2 ;
119+ }
61120
62- char command [4096 ];
63- snprintf (command , sizeof (command ), "cat '%s' | '%s'" , tmp , engine );
64- int status = system (command );
65- unlink (tmp );
66- if (status == -1 ) return 3 ;
67- if (WIFEXITED (status )) return WEXITSTATUS (status );
68- return 3 ;
121+ int rc = run_engine (input );
122+ free (input );
123+ return rc ;
69124}
0 commit comments