Skip to content

Commit 35c471a

Browse files
committed
Add interactive black-belt prompt to C CLI
1 parent 205ce58 commit 35c471a

1 file changed

Lines changed: 81 additions & 26 deletions

File tree

‎bin/blackbelt-c.c‎

Lines changed: 81 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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

2787
int 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

Comments
 (0)