8int cw_selectors(
void) {
10 struct cw_child leader = CW_CHILD_INIT, member = CW_CHILD_INIT, own = CW_CHILD_INIT;
11 struct cw_child any = CW_CHILD_INIT, numeric = CW_CHILD_INIT;
13 const uid_t uid = getuid();
14 CHECK(setpgid(0, 0) == 0 && getpgrp() == getpid());
15 CHECK(cw_spawn(&leader, 0, (uid_t)-1, 21) == 0);
16 CHECK(cw_spawn(&member, leader.pid, (uid_t)-1, 22) == 0);
17 CHECK(cw_spawn(&own, -1, (uid_t)-1, 23) == 0);
18 CHECK(getpgid(leader.pid) == leader.pid && getpgid(member.pid) == leader.pid);
19 CHECK(getpgid(own.pid) == getpgrp());
20 const pid_t other_group = leader.pid;
22 memset(&info, 0xa5,
sizeof(info));
23 CHECK(waitid(P_PID, own.pid, &info, WEXITED | WNOHANG) == 0 && !cw_empty_info(&info));
24 CHECK(cw_send(leader.command,
'E') == 0);
25 CHECK(waitid(P_PID, leader.pid, &info, WEXITED | WNOWAIT) == 0);
26 CHECK(cw_info(&info, leader.pid, uid, CLD_EXITED, 21) == 0);
27 CHECK(waitid(P_PGID, leader.pid, &info, WEXITED) == 0);
28 CHECK(cw_info(&info, leader.pid, uid, CLD_EXITED, 21) == 0);
30 CHECK(cw_send(member.command,
'E') == 0);
31 CHECK(waitid(P_PGID, other_group, &info, WEXITED) == 0);
32 CHECK(cw_info(&info, member.pid, uid, CLD_EXITED, 22) == 0);
34 CHECK(cw_send(own.command,
'E') == 0);
35 CHECK(waitid(P_PGID, 0, &info, WEXITED) == 0);
36 CHECK(cw_info(&info, own.pid, uid, CLD_EXITED, 23) == 0);
39 CHECK(cw_spawn(&any, -1, (uid_t)-1, 0x1ab) == 0 && cw_send(any.command,
'E') == 0);
40 CHECK(waitid(P_ALL, (id_t)UINT_MAX, &info, WEXITED) == 0);
41 CHECK(cw_info(&info, any.pid, uid, CLD_EXITED, 0xab) == 0);
45 CHECK(cw_spawn(&numeric, -1, 17001, 31) == 0);
46 CHECK(cw_send(numeric.command,
'E') == 0);
47 CHECK(waitid(P_PID, numeric.pid, &info, WEXITED) == 0);
48 CHECK(cw_info(&info, numeric.pid, 17001, CLD_EXITED, 31) == 0);
51 puts(
"CHILD-WAIT-CONTRACT: SKIP distinct numeric real UID (requires root)");