9static int number(
const char* text) {
12 long value = strtol(text, &end, 10);
13 return errno || !*text || *end || value < 0 || value > INT_MAX ? -1 : (int)value;
16int main(
int argc,
char** argv) {
17 setvbuf(stdout, NULL, _IONBF, 0);
18 if (argc == 3 && !strcmp(argv[1],
"--exec-child")) {
19 int report = number(argv[2]);
20 return report < 0 ? 2 : tc_exec_child(report);
22 if (argc == 5 && !strcmp(argv[1],
"--exec-tracer")) {
23 int child = number(argv[2]), command = number(argv[3]), report = number(argv[4]);
24 return child <= 0 || command < 0 || report < 0 ? 2 : tc_exec_tracer(child, command, report);
28 tc_page = (size_t)sysconf(_SC_PAGESIZE);
29 if (!tc_page || tc_page > 65536)
34 } families[] = {{
"registers", tc_registers}, {
"inspect", tc_inspect}, {
"signals", tc_signals},
35 {
"ownership", tc_ownership}, {
"lifecycle", tc_lifecycle}, {
"errors", tc_errors}};
37 for (
size_t i = 0; i <
sizeof(families) /
sizeof(families[0]); ++i) {
38 if (argc == 2 && strcmp(argv[1],
"all") && strcmp(argv[1], families[i].name))
41 printf(
"PTRACE-CONTRACT: BEGIN %s\n", families[i].name);
42 pid_t family = fork();
47 int failed = families[i].run();
49 _exit(failed ? 1 : 0);
54 int result = tc_wait(family, &status, 55000);
55 if (result || !WIFEXITED(status) || WEXITSTATUS(status)) {
57 kill(-family, SIGKILL);
58 if (result || (!WIFEXITED(status) && !WIFSIGNALED(status)))
60 printf(
"PTRACE-CONTRACT: FAIL %s result=%d status=%#x errno=%d\n", families[i].name, result,
64 printf(
"PTRACE-CONTRACT: PASS %s\n", families[i].name);
68 puts(
"PTRACE-CONTRACT: END PASS");