// exec-family regression for the GNO libc (punch-list #5 + #7). // Exercises access() over Kstat and the exec* wrappers over K_execve. // // Two halves, run in order so one boot can cover both: // 1. Negative / no-2nd-program tests (always run, fully deterministic): // - access(".", F_OK) succeeds on the login cwd (a directory). // - access("/nonesuch/no", F_OK) fails (-1) on a missing path. // - execvp("nosuchprog", ...) fails (-1, errno set): buildPath's // $PATH search finds no candidate and returns before ever reaching // the kernel, so this validates buildCmd/buildPath/access without // needing a second executable. // 2. exec-into (needs GNO_PROG2=demos/gnoExeced.omf placed on /bin): the // LAST action execvp's the tiny 2nd program "gnoexeced", which sets // its own bank-2 marker and the reached-end word. If GNO_PROG2 is // not supplied the exec-into fails, prog1 sets the fallback reached- // end word, and only the half-1 checks are meaningful. // // Bank-2 absolute uint16 markers (DBR-independent), gnoHeapProbe convention: // 0x025000 C0DE reached end (set by gnoExeced on success, else by prog1) // 0x025002 0001 execvp("nosuchprog") returned -1, else DEAD // 0x025004 0001 errno was set nonzero by the failed execvp, else DEAD // 0x025008 0001 access(".", F_OK) == 0 (existing dir), else DEAD // 0x02500A 0001 access("/nonesuch/no", F_OK) == -1 (missing), else DEAD // 0x025010 E0EC gnoExeced ran (exec-into transferred control), else DEAD #include extern int access(const char *path, int mode); extern int execvp(const char *file, char *const *argv); extern int errno; #define M(a) (*(volatile uint16_t *)(a)) #define OK 0x0001 #define BAD 0xDEAD #define F_OK 0 int main(void) { char *nope[2]; char *prog2[2]; int r; M(0x025000UL) = 0x0000; M(0x025002UL) = BAD; M(0x025004UL) = BAD; M(0x025008UL) = BAD; M(0x02500AUL) = BAD; M(0x025010UL) = BAD; // access() over Kstat: existing directory vs. missing path. if (access(".", F_OK) == 0) { M(0x025008UL) = OK; } if (access("/nonesuch/no", F_OK) == -1) { M(0x02500AUL) = OK; } // Failed exec: no such program on $PATH -> -1 with errno set. (This // fails in buildPath, before K_execve, so it is safe and deterministic.) nope[0] = "nosuchprog"; nope[1] = 0; errno = 0; r = execvp("nosuchprog", nope); if (r == -1) { M(0x025002UL) = OK; } if (errno != 0) { M(0x025004UL) = OK; } // exec-into the 2nd program (GNO_PROG2). On success this never returns; // gnoExeced sets 0x025010 and the reached-end word in the same image. prog2[0] = "gnoexeced"; prog2[1] = 0; execvp("gnoexeced", prog2); // Only reached if the exec-into failed (no GNO_PROG2 on /bin). M(0x025000UL) = 0xC0DE; for (volatile unsigned long j = 0; j < 300000UL; j++) { } return 0; }