nx_licdetect.nx source
↩ module page · 76 lines · 3177 B
1// nx_licdetect.nx -- thin CLI over nx_licdetect_lib. WHICH LICENCE IS THIS FILE?
2//
3// The decision lives in the LIB so this command line and any in-process consumer prove the SAME code,
4// and so the gate can IMPORT the logic instead of forking this binary -- a fork is a boundary the
5// mutation harness cannot see across.
6//
7// Exit codes are the estate's shared refusal vocabulary so a caller branching on nx_licgate or
8// nx_acquire branches identically here:
9// 0 DETECTED exactly one licence matched -- the only answer
10// 3 UNKNOWN nothing matched; the artifact does NOT advance to evidence=READ
11// 4 AMBIGUOUS two or more matched; a coin flip is not a verdict
12// 4 unreadable file
13// license_tier: ORIGINAL
14import "nx_syscalls.nx"
15import "nx_licdetect_lib.nx"
16
17func ldc_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
18func ldc_puts(s: *u8) -> i64 { sys_write(1, s, ldc_len(s)); return 0 }
19
20func ldc_num(v: i64) -> i64 {
21 let t: *u8 = sys_mmap(32)
22 var m: i64 = v
23 var k: i64 = 0
24 if m == 0 { t[0] = 48 as u8; k = 1 }
25 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
26 let o: *u8 = sys_mmap(32)
27 var i: i64 = 0
28 while i < k { o[i] = t[k - 1 - i]; i = i + 1 }
29 sys_write(1, o, k)
30 return 0
31}
32
33func main(argc: i64, argv: *i64) -> i64 {
34 if argc < 3 {
35 ldc_puts("usage: nx_licdetect file <path>\n" as *u8)
36 ldc_puts(" Reads the file and names its licence FROM THE TEXT, never from a declaration.\n" as *u8)
37 ldc_puts(" A README that merely says \"Apache 2.0\" does NOT detect -- that is a claim, not a licence.\n" as *u8)
38 ldc_puts(" exit 0 DETECTED | 3 UNKNOWN (fail-closed) | 4 AMBIGUOUS or unreadable\n" as *u8)
39 return 3
40 }
41 let path: *u8 = argv[2] as *u8
42 let lp: *i64 = sys_mmap(16) as *i64
43 let body: *u8 = sys_read_file(path, lp)
44 if (body as i64) == 0 {
45 ldc_puts("REFUSED unreadable-file -- no licence is named for bytes we do not hold\n" as *u8)
46 return 4
47 }
48 let n: i64 = lp[0]
49 let ctx: *i64 = ld_ctx()
50 if ctx[3] < 0 {
51 ldc_puts("REFUSED marker-table-unreadable (knowledge/license_markers.conf)\n" as *u8)
52 return 4
53 }
54 let out: *i64 = sys_mmap(32) as *i64
55 let r: i64 = ld_detect(ctx, body, n, out)
56 ldc_puts(ld_result_name(r))
57 if r == LD_DETECTED {
58 let cbuf: *u8 = ctx[0] as *u8
59 ldc_puts(" license=" as *u8)
60 sys_write(1, ((cbuf as i64) + out[0]) as *u8, out[1])
61 // THE DETECTOR'S OWN EVIDENCE STATE TRAVELS WITH ITS ANSWER. A marker set never confirmed
62 // against a licence text we hold is honest but unproven, and saying so is the same discipline
63 // this whole lane applies to the artifacts it judges.
64 if ld_marker_set_verified(ctx, out[0], out[1]) == 1 {
65 ldc_puts(" markers=VERIFIED-against-held-text" as *u8)
66 } else {
67 ldc_puts(" markers=UNVERIFIED-no-held-text-yet" as *u8)
68 }
69 }
70 ldc_puts(" bytes=" as *u8)
71 ldc_num(n)
72 ldc_puts("\n" as *u8)
73 if r == LD_DETECTED { return 0 }
74 if r == LD_AMBIGUOUS { return 4 }
75 return 3
76}