pledge("stdio rpath wpath cpath flock getpw id tty") for setup then play the game with "stdio rpath wpath getpw tty".
Most of the promises are needed for dealing with the score file. The function getscores() currently appears towards the end of the program's lifetime and it calls setegid() and flock(). By hoisting the latest possible call to getscores() to right after option parsing, we can drop the most powerful promises before starting game play, at the cost of refactoring a bit. The "getpw" promise is for an unlikely error path in thisuser() that might be called very late. Index: games/tetris/scores.c =================================================================== RCS file: /cvs/src/games/tetris/scores.c,v retrieving revision 1.12 diff -u -p -r1.12 scores.c --- games/tetris/scores.c 16 Nov 2014 04:49:49 -0000 1.12 +++ games/tetris/scores.c 15 Nov 2015 12:28:17 -0000 @@ -73,14 +73,13 @@ #define NUMSPOTS (MAXHISCORES + 1) #define NLEVELS (MAXLEVEL + 1) +extern int gotscores; static time_t now; static int nscores; -static int gotscores; static struct highscore scores[NUMSPOTS]; static int checkscores(struct highscore *, int); static int cmpscores(const void *, const void *); -static void getscores(FILE **); static void printem(int, int, struct highscore *, int, const char *); static char *thisuser(void); @@ -93,7 +92,7 @@ static char *thisuser(void); * * Note, we assume closing the stdio file releases the lock. */ -static void +void getscores(FILE **fpp) { int sd, mint, lck, mask, i; @@ -150,16 +149,13 @@ getscores(FILE **fpp) } void -savescore(int level) +savescore(FILE *sf, int level) { struct highscore *sp; int i; int change; - FILE *sf; const char *me; - getscores(&sf); - gotscores = 1; (void)time(&now); /* Index: games/tetris/scores.h =================================================================== RCS file: /cvs/src/games/tetris/scores.h,v retrieving revision 1.6 diff -u -p -r1.6 scores.h --- games/tetris/scores.h 16 Nov 2014 04:49:49 -0000 1.6 +++ games/tetris/scores.h 15 Nov 2015 12:28:17 -0000 @@ -49,5 +49,6 @@ struct highscore { #define MAXSCORES 9 /* maximum high score entries per person */ #define EXPIRATION (5L * 365 * 24 * 60 * 60) -void savescore(int); +void getscores(FILE **); +void savescore(FILE *, int); void showscores(int); Index: games/tetris/tetris.c =================================================================== RCS file: /cvs/src/games/tetris/tetris.c,v retrieving revision 1.25 diff -u -p -r1.25 tetris.c --- games/tetris/tetris.c 16 Nov 2014 04:49:49 -0000 1.25 +++ games/tetris/tetris.c 15 Nov 2015 12:28:17 -0000 @@ -60,6 +60,7 @@ int Rows, Cols; const struct shape *curshape; const struct shape *nextshape; long fallrate; +int gotscores; int score; gid_t gid, egid; char key_msg[100]; @@ -150,6 +151,7 @@ randshape(void) int main(int argc, char *argv[]) { + FILE *sf; int pos, c; char *keys; int level = 2; @@ -159,6 +161,9 @@ main(int argc, char *argv[]) keys = "jkl pq"; + if (pledge("stdio rpath wpath cpath flock getpw id tty", NULL) == -1) + err(1, "pledge"); + gid = getgid(); egid = getegid(); setegid(gid); @@ -201,6 +206,12 @@ main(int argc, char *argv[]) if (argc) usage(); + getscores(&sf); + gotscores = 1; + + if (pledge("stdio rpath wpath getpw tty", NULL) == -1) + err(1, "pledge"); + fallrate = 1000000 / level; for (i = 0; i <= 5; i++) { @@ -337,7 +348,7 @@ main(int argc, char *argv[]) (int)(score * level * PRE_PENALTY)); score = score * PRE_PENALTY; } - savescore(level); + savescore(sf, level); printf("\nHit RETURN to see high scores, ^C to skip.\n");