diff --git a/config.l b/config.l index 17061af..b5e7b53 100644 --- a/config.l +++ b/config.l @@ -65,6 +65,7 @@ WHITE [\t ]* "maxusers" { return TYPE_MAX; } "maxnicklen" { return TYPE_MAXNICKLEN; } "allow_new_nicks" { return TYPE_ALLOW_REGISTRATION; } +"menu_max_idle_time" { return TYPE_MENU_MAX_IDLE_TIME; } menu { return TYPE_DEFINE_MENU; } diff --git a/config.y b/config.y index e10b990..77d8b13 100644 --- a/config.y +++ b/config.y @@ -41,7 +41,7 @@ static const char* lookup_token (int t); %token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE TYPE_PATH_TTYREC %token TYPE_MALSTRING TYPE_PATH_INPROGRESS TYPE_GAME_ARGS TYPE_RC_FMT %token TYPE_CMDQUEUE TYPE_DEFINE_MENU TYPE_BANNER_FILE TYPE_CURSOR -%token TYPE_MAX_IDLE_TIME +%token TYPE_MAX_IDLE_TIME TYPE_MENU_MAX_IDLE_TIME %token TYPE_VALUE %token TYPE_NUMBER TYPE_CMDQUEUENAME %type KeyType @@ -252,6 +252,10 @@ KeyPair: TYPE_CMDQUEUE '[' TYPE_CMDQUEUENAME ']' } break; + case TYPE_MENU_MAX_IDLE_TIME: + globalconfig.menu_max_idle_time = $3; + break; + default: fprintf(stderr, "%s:%d: token %s does not take a number, bailing out\n", config, line, lookup_token($1)); @@ -524,6 +528,7 @@ KeyType : TYPE_SUSER { $$ = TYPE_SUSER; } | TYPE_SGID { $$ = TYPE_SGID; } | TYPE_MAX { $$ = TYPE_MAX; } | TYPE_MAXNICKLEN { $$ = TYPE_MAXNICKLEN; } + | TYPE_MENU_MAX_IDLE_TIME { $$ = TYPE_MENU_MAX_IDLE_TIME; } | TYPE_PATH_CHROOT { $$ = TYPE_PATH_CHROOT; } | TYPE_ALLOW_REGISTRATION { $$ = TYPE_ALLOW_REGISTRATION; } | TYPE_PATH_GAME { $$ = TYPE_PATH_GAME; } @@ -554,6 +559,7 @@ const char* lookup_token (int t) case TYPE_SGID: return "shed_gid"; case TYPE_MAX: return "maxusers"; case TYPE_MAXNICKLEN: return "maxnicklen"; + case TYPE_MENU_MAX_IDLE_TIME: return "menu_max_idle_time"; case TYPE_PATH_CHROOT: return "chroot_path"; case TYPE_PATH_GAME: return "game_path"; case TYPE_NAME_GAME: return "game_name"; diff --git a/dgamelaunch.c b/dgamelaunch.c index 244ebd1..53c8e6e 100644 --- a/dgamelaunch.c +++ b/dgamelaunch.c @@ -96,6 +96,7 @@ extern int editor_main (int argc, char **argv); /* global variables */ char * __progname; +int g_idle_alarm_enabled = 0; #ifndef USE_SQLITE3 int f_num = 0; @@ -261,6 +262,42 @@ catch_sighup (int signum) /* ************************************************************* */ +int +dgl_getch(void) +{ + const int c = getch(); + idle_alarm_reset(); + return c; +} + +/* ************************************************************* */ + +static void +dgl_idle_kill(int signal) +{ + kill(0, SIGHUP); +} + +void +idle_alarm_set_enabled(int enabled) +{ + signal(SIGALRM, SIG_IGN); + g_idle_alarm_enabled = enabled; + idle_alarm_reset(); + if (enabled) + signal(SIGALRM, dgl_idle_kill); +} + +void +idle_alarm_reset(void) +{ + if (g_idle_alarm_enabled && globalconfig.menu_max_idle_time > 0) + alarm(globalconfig.menu_max_idle_time); +} + +/* ************************************************************* */ + + char * bannerstrmangle(char *buf, char *fromstr, char *tostr) { @@ -499,7 +536,7 @@ inprogressmenu (int gameid) refresh (); - switch ((menuchoice = getch ())) + switch ((menuchoice = dgl_getch ())) { case '*': if (len > 0) { @@ -717,7 +754,7 @@ change_email () else if (check_email (buf)) { mvprintw (8, 1, "Changing email address to '%s'. Confirm (y/n): ", buf); - if (getch() == 'y') + if (dgl_getch() == 'y') { free(me->email); me->email = strdup(buf); @@ -727,7 +764,7 @@ change_email () else { mvaddstr(9, 1, "No changes made. Press any key to continue..."); - getch(); + dgl_getch(); return; } } @@ -915,7 +952,7 @@ domailuser (char *username) mvaddstr (9, 1, "This scroll appears to be blank."); mvaddstr (10, 1, "(Aborting your message.)"); mvaddstr (12, 1, "--More--"); - getch (); + dgl_getch (); return; } @@ -927,7 +964,7 @@ domailuser (char *username) "(Couldn't open %s'%c spool file. Aborting.)", username, (username[strlen (username) - 1] != 's') ? 's' : 0); mvaddstr (12, 1, "--More--"); - getch (); + dgl_getch (); return; } @@ -942,7 +979,7 @@ domailuser (char *username) mvaddstr (10, 1, "(Received a weird error from fcntl. Aborting.)"); mvaddstr (12, 1, "--More--"); - getch (); + dgl_getch (); return; } sleep (1); @@ -1125,7 +1162,7 @@ newuser () mvaddstr (5, 1, "Sorry, too many users have registered now."); mvaddstr (6, 1, "You might email the server administrator."); mvaddstr (7, 1, "Press return to return to the menu. "); - getch (); + dgl_getch (); return; } @@ -1811,7 +1848,7 @@ purge_stale_locks (int game) for (seconds = HUP_WAIT - 1; seconds >= 0; seconds--) { - if (getch() != ERR) + if (dgl_getch() != ERR) { nocbreak(); /* leave half-delay */ cbreak(); @@ -1846,7 +1883,7 @@ purge_stale_locks (int game) mvprintw (3, 1, "Couldn't terminate one of your stale %s processes gracefully.", myconfig[game]->game_name); mvaddstr (4, 1, "Force its termination? [yn] "); - if (tolower (getch ()) == 'y') + if (tolower (dgl_getch ()) == 'y') { kill (pid, SIGTERM); break; @@ -1885,6 +1922,7 @@ runmenuloop(struct dg_menu *menu) ban.lines = NULL; ban.len = 0; + idle_alarm_set_enabled(1); loadbanner(menu->banner_fn, &ban); while (1) { if (doclear) { @@ -1895,7 +1933,7 @@ runmenuloop(struct dg_menu *menu) if (menu->cursor_x >= 0 && menu->cursor_y >= 0) mvprintw(menu->cursor_y, menu->cursor_x, ""); refresh(); - userchoice = getch(); + userchoice = dgl_getch(); if (userchoice == ERR) return 1; tmpopt = menu->options; while (tmpopt) { diff --git a/dgamelaunch.h b/dgamelaunch.h index 636808e..b78cd42 100644 --- a/dgamelaunch.h +++ b/dgamelaunch.h @@ -124,6 +124,7 @@ struct dg_globalconfig struct dg_cmdpart *cmdqueue[NUM_DGLTIMES]; struct dg_menulist *menulist; + int menu_max_idle_time; }; typedef enum @@ -219,7 +220,9 @@ extern void debug_write(char *str); extern struct dg_game **sort_games(struct dg_game **games, int len, dg_sortmode sortmode); int runmenuloop(struct dg_menu *menu); - +extern int dgl_getch(void); +extern void idle_alarm_set_enabled(int enabled); +extern void idle_alarm_reset(void); extern void inprogressmenu(int gameid); extern void change_email(void); extern int changepw(int dowrite); diff --git a/dgl-common.c b/dgl-common.c index bd51108..dd45c15 100644 --- a/dgl-common.c +++ b/dgl-common.c @@ -257,6 +257,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) myargv[2] = 0; endwin(); + idle_alarm_set_enabled(0); child = fork(); if (child == -1) { perror("fork"); @@ -267,6 +268,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) exit(0); } else waitpid(child, NULL, 0); + idle_alarm_set_enabled(1); refresh(); check_retard(1); } @@ -306,7 +308,9 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) int i; for (i = 0; i < num_games; i++) { if ((!strcmp(myconfig[i]->game_name, p1) || !strcmp(myconfig[i]->shortname, p1)) && myconfig[i]->rcfile) { + idle_alarm_set_enabled(0); editoptions(i); + idle_alarm_set_enabled(1); check_retard(1); break; } @@ -342,6 +346,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) myconfig[userchoice]->bin_args[i] = tmpstr; } + idle_alarm_set_enabled(0); /* launch program */ ttyrec_main (userchoice, me->username, dgl_format_str(userchoice, me, myconfig[userchoice]->ttyrecdir, NULL), @@ -349,6 +354,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) /* lastly, run the generic "do these when a game is left" commands */ dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_GAMEEND], userchoice, me); + idle_alarm_set_enabled(1); setproctitle ("%s", me->username); initcurses (); diff --git a/examples/dgamelaunch.conf b/examples/dgamelaunch.conf index 827c645..1bd6d55 100644 --- a/examples/dgamelaunch.conf +++ b/examples/dgamelaunch.conf @@ -58,6 +58,12 @@ banner = "/dgl-banner" shed_uid = 5 shed_gid = 60 +# Maximum time in seconds user can idle in the dgamelaunch menus +# before dgl exits. Default value is 0, which disables the idling timer. +# Does not apply to external programs or config editors. +# For setting game idle time, use max_idle_time in the game DEFINE. +# menu_max_idle_time = 1024 + # The defaults are usually just fine for this. passwd refers to the file # that stores the user database, and lockfile is only used internally by # dgamelaunch. diff --git a/ttyplay.c b/ttyplay.c index 35347ee..99aa70a 100644 --- a/ttyplay.c +++ b/ttyplay.c @@ -194,7 +194,7 @@ ttyread (FILE * fp, Header * h, char **buf, int pread) if (kbhit()) { - const int c = wgetch(stdscr); + const int c = dgl_getch(); const int action = ttyplay_keyboard_action(c); if (action != READ_DATA) return (action); @@ -262,6 +262,7 @@ ttypread (FILE * fp, Header * h, char **buf, int pread) */ while ((action = ttyread (fp, h, buf, 1)) == READ_EOF) { + idle_alarm_reset(); fflush(stdout); clearerr (fp); #ifdef HAVE_KQUEUE @@ -318,9 +319,7 @@ ttypread (FILE * fp, Header * h, char **buf, int pread) } if (doread) { /* user hits a character? */ - char c; - read (STDIN_FILENO, &c, 1); /* drain the character */ - + const int c = dgl_getch(); action = ttyplay_keyboard_action(c); if (action != READ_DATA) return action; diff --git a/ttyrec.c b/ttyrec.c index ea9f0d7..318e2d7 100644 --- a/ttyrec.c +++ b/ttyrec.c @@ -167,6 +167,7 @@ ttyrec_main (int game, char *username, char *ttyrec_path, char* ttyrec_filename) } unlink (ipfile); + child = 0; return 0; }