From 972bb6fa6bdd58cf4b05d8725142557f29ae4f75 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sat, 17 Oct 2009 20:26:56 +0000 Subject: [PATCH] Add per-game configurable ttyrec-dir; If it's not defined for some game, no ttyrecs are saved for that game, and those games cannot be spectated. Add more debugging output to dgldebug.log -file Add configure option --enable-debugfile to enable or disable the debugging log. git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@468 db0b04b0-f4d1-0310-9a6d-de3e77497b0e --- config.l | 1 + config.y | 9 ++- configure.ac | 10 ++++ dgamelaunch.c | 119 ++++++++++++++++++++++++++++---------- dgamelaunch.h | 9 ++- dgl-common.c | 76 ++++++++++++++++++------ examples/dgamelaunch.conf | 5 ++ ttyrec.c | 15 +++++ 8 files changed, 193 insertions(+), 51 deletions(-) diff --git a/config.l b/config.l index 8ffd76b..e94f252 100644 --- a/config.l +++ b/config.l @@ -83,6 +83,7 @@ cursor { return TYPE_CURSOR; } "inprogressdir" { return TYPE_PATH_INPROGRESS; } "game_args" { return TYPE_GAME_ARGS; } "rc_fmt" { return TYPE_RC_FMT; } +"ttyrecdir" { return TYPE_PATH_TTYREC; } server_id { return TYPE_SERVER_ID; } sortmode { return TYPE_WATCH_SORTMODE; } commands { return TYPE_CMDQUEUE; } diff --git a/config.y b/config.y index 9474bd0..065a783 100644 --- a/config.y +++ b/config.y @@ -38,7 +38,7 @@ static const char* lookup_token (int t); %token TYPE_ALLOW_REGISTRATION %token TYPE_PATH_GAME TYPE_NAME_GAME TYPE_PATH_DGLDIR TYPE_PATH_SPOOL %token TYPE_PATH_BANNER TYPE_PATH_CANNED TYPE_PATH_CHROOT -%token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE +%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_VALUE @@ -364,6 +364,11 @@ game_definition : TYPE_CMDQUEUE myconfig[ncnf]->spool = strdup($3); break; + case TYPE_PATH_TTYREC: + if (myconfig[ncnf]->ttyrecdir) free(myconfig[ncnf]->ttyrecdir); + myconfig[ncnf]->ttyrecdir = strdup($3); + break; + case TYPE_PATH_GAME: if (myconfig[ncnf]->game_path) free(myconfig[ncnf]->game_path); myconfig[ncnf]->game_path = strdup ($3); @@ -519,6 +524,7 @@ KeyType : TYPE_SUSER { $$ = TYPE_SUSER; } | TYPE_PATH_SPOOL { $$ = TYPE_PATH_SPOOL; } | TYPE_PATH_BANNER { $$ = TYPE_PATH_BANNER; } | TYPE_PATH_CANNED { $$ = TYPE_PATH_CANNED; } + | TYPE_PATH_TTYREC { $$ = TYPE_PATH_TTYREC; } | TYPE_PATH_PASSWD { $$ = TYPE_PATH_PASSWD; } | TYPE_PATH_LOCKFILE { $$ = TYPE_PATH_LOCKFILE; } | TYPE_PATH_INPROGRESS { $$ = TYPE_PATH_INPROGRESS; } @@ -548,6 +554,7 @@ const char* lookup_token (int t) case TYPE_PATH_SPOOL: return "spooldir"; case TYPE_PATH_BANNER: return "banner"; case TYPE_PATH_CANNED: return "rc_template"; + case TYPE_PATH_TTYREC: return "ttyrecdir"; case TYPE_PATH_INPROGRESS: return "inprogressdir"; case TYPE_GAME_ARGS: return "game_args"; case TYPE_RC_FMT: return "rc_fmt"; diff --git a/configure.ac b/configure.ac index fab5ca1..b5b8b85 100644 --- a/configure.ac +++ b/configure.ac @@ -72,6 +72,16 @@ AC_ARG_ENABLE(enable-virus, AC_SUBST(EDITOR) +AC_ARG_ENABLE(enable-debugfile, +[AC_HELP_STRING([--enable-debugfile], [Enable debugging output to a file.])], +[], []) + +if test "$enable_debugfile" = yes; then + AC_MSG_RESULT([Enabling debugging output to a file.]) + AC_DEFINE(USE_DEBUGFILE,1,[Output debugging into to a file in chroot.]) +fi + + AC_ARG_ENABLE(enable-sqlite, [AC_HELP_STRING([--enable-sqlite], [Use SQLite for the database instead of flat text file.])], [], []) diff --git a/dgamelaunch.c b/dgamelaunch.c index 07b1e48..4297ac9 100644 --- a/dgamelaunch.c +++ b/dgamelaunch.c @@ -149,15 +149,20 @@ void ttyrec_getpty () { #ifdef HAVE_OPENPTY - if (openpty (&master, &slave, NULL, NULL, NULL) == -1) - graceful_exit (62); + if (openpty (&master, &slave, NULL, NULL, NULL) == -1) { + debug_write("cannot openpty"); + graceful_exit (62); + } #else - if ((master = open ("/dev/ptmx", O_RDWR)) < 0) - graceful_exit (62); + if ((master = open ("/dev/ptmx", O_RDWR)) < 0) { + debug_write("cannot open /dev/ptmx"); + graceful_exit (62); + } grantpt (master); unlockpt (master); if ((slave = open ((const char *) ptsname (master), O_RDWR)) < 0) { + debug_write("cannot open master ptsname"); graceful_exit (65); } #endif @@ -219,15 +224,17 @@ gen_inprogress_lock (int game, pid_t pid, char* ttyrec_filename) fl.l_start = 0; fl.l_len = 0; - len = strlen(dgl_format_str(game, me, myconfig[game]->inprogressdir)) + strlen(me->username) + strlen(ttyrec_filename) + 13; + len = strlen(dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL)) + strlen(me->username) + strlen(ttyrec_filename) + 13; lockfile = calloc(len, sizeof(char)); - snprintf (lockfile, len, "%s%s:%s", dgl_format_str(game, me, myconfig[game]->inprogressdir), + snprintf (lockfile, len, "%s%s:%s", dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL), me->username, ttyrec_filename); fd = open (lockfile, O_WRONLY | O_CREAT, 0644); - if (fcntl (fd, F_SETLKW, &fl) == -1) + if (fcntl (fd, F_SETLKW, &fl) == -1) { + debug_write("cannot fnctl inprogress-lock"); graceful_exit (68); + } write (fd, filebuf, strlen (filebuf)); @@ -245,6 +252,7 @@ catch_sighup (int signum) kill (child, SIGHUP); sleep (5); } + debug_write("catchup sighup"); graceful_exit (2); } @@ -478,8 +486,10 @@ inprogressmenu (int gameid) /* reuse the char* */ replacestr = strchr (ttyrecname, ':'); - if (!replacestr) + if (!replacestr) { + debug_write("inprogressmenu replacestr"); graceful_exit (145); + } /*replacestr[0] = '/';*/ @@ -622,8 +632,10 @@ changepw (int dowrite) int error = 2; /* A precondition is that struct `me' exists because we can be not-yet-logged-in. */ - if (!me) + if (!me) { + debug_write("no 'me' in changepw"); graceful_exit (122); /* Die. */ + } while (error) { @@ -656,8 +668,10 @@ changepw (int dowrite) if (*buf == '\0') return 0; - if (strchr (buf, ':') != NULL) + if (strchr (buf, ':') != NULL) { + debug_write("cannot have ':' in passwd"); graceful_exit (112); + } mvaddstr (12, 1, "And again:"); mvaddstr (13, 1, "=> "); @@ -700,11 +714,13 @@ wall_email(char *from, char *msg) if (strlen(from) < 1) { fprintf(stderr, "Error: wall: 'from' username is too short!\n"); + debug_write("wall: 'from' username too short"); graceful_exit(121); } if (strlen(msg) >= 80) { fprintf(stderr, "Error: wall: message too long!\n"); + debug_write("wall: message too long"); graceful_exit(120); } @@ -712,6 +728,7 @@ wall_email(char *from, char *msg) if (len == 0) { fprintf(stderr, "Error: wall: no one's logged in!\n"); + debug_write("wall: no people playing"); graceful_exit(118); } @@ -1162,15 +1179,21 @@ readfile (int nolock) if (!nolock) { fpl = fopen (globalconfig.lockfile, "r"); - if (!fpl) + if (!fpl) { + debug_write("cannot fopen lockfile"); graceful_exit (106); - if (fcntl (fileno (fpl), F_SETLKW, &fl) == -1) + } + if (fcntl (fileno (fpl), F_SETLKW, &fl) == -1) { + debug_write("cannot fcntl lockfile"); graceful_exit (114); + } } fp = fopen (globalconfig.passwd, "r"); - if (!fp) + if (!fp) { + debug_write("cannot fopen passwd file"); graceful_exit (106); + } /* once per name in the file */ while (fgets (buf, 1200, fp)) @@ -1191,8 +1214,10 @@ readfile (int nolock) return 1; users[f_num]->username[(b - n)] = *b; b++; - if ((b - n) >= 21) + if ((b - n) >= 21) { + debug_write("name field too long"); graceful_exit (100); + } } /* advance to next field */ @@ -1204,8 +1229,10 @@ readfile (int nolock) { users[f_num]->email[(b - n)] = *b; b++; - if ((b - n) > 80) + if ((b - n) > 80) { + debug_write("email field too long"); graceful_exit (101); + } } /* advance to next field */ @@ -1217,8 +1244,10 @@ readfile (int nolock) { users[f_num]->password[(b - n)] = *b; b++; - if ((b - n) >= 20) + if ((b - n) >= 20) { + debug_write("passwd field too long"); graceful_exit (102); + } } /* advance to next field */ @@ -1230,8 +1259,10 @@ readfile (int nolock) { users[f_num]->env[(b - n)] = *b; b++; - if ((b - n) >= 1024) + if ((b - n) >= 1024) { + debug_write("env field too long"); graceful_exit (102); + } } f_num++; @@ -1239,6 +1270,7 @@ readfile (int nolock) if (f_num > globalconfig.max) { fprintf(stderr,"ERROR: number of users in database exceeds maximum. Exiting.\n"); + debug_write("too many users in database"); graceful_exit (109); } } @@ -1329,6 +1361,7 @@ userexist (char *cname, int isnew) ret = sqlite3_open(USE_SQLITE_DB, &db); /* FIXME: use globalconfig->passwd? */ if (ret) { sqlite3_close(db); + debug_write("sqlite3_open failed"); graceful_exit(109); } @@ -1348,6 +1381,7 @@ userexist (char *cname, int isnew) if (ret != SQLITE_OK) { sqlite3_close(db); + debug_write("sqlite3_exec failed"); graceful_exit(108); } sqlite3_close(db); @@ -1413,14 +1447,14 @@ editoptions (int game) char *myargv[3]; pid_t editor; - rcfile = fopen (dgl_format_str(game, me, myconfig[game]->rc_fmt), "r"); + rcfile = fopen (dgl_format_str(game, me, myconfig[game]->rc_fmt, NULL), "r"); if (!rcfile) - write_canned_rcfile (game, dgl_format_str(game, me, myconfig[game]->rc_fmt)); + write_canned_rcfile (game, dgl_format_str(game, me, myconfig[game]->rc_fmt, NULL)); /* use whatever editor_main to edit */ myargv[0] = ""; - myargv[1] = dgl_format_str(game, me, myconfig[game]->rc_fmt); + myargv[1] = dgl_format_str(game, me, myconfig[game]->rc_fmt, NULL); myargv[2] = 0; endwin (); @@ -1430,6 +1464,7 @@ editoptions (int game) if (editor == -1) { perror("fork"); + debug_write("edit fork failed"); graceful_exit(114); } else if (editor == 0) @@ -1472,11 +1507,13 @@ writefile (int requirenew) if (!fpl) { sigprocmask(SIG_SETMASK, &oldmask, NULL); + debug_write("writefile locking failed"); graceful_exit (115); } if (fcntl (fileno (fpl), F_SETLK, &fl)) { sigprocmask(SIG_SETMASK, &oldmask, NULL); + debug_write("writefile fcntl failed"); graceful_exit (107); } @@ -1489,6 +1526,7 @@ writefile (int requirenew) if (!fp) { sigprocmask(SIG_SETMASK, &oldmask, NULL); + debug_write("passwd file fopen failed"); graceful_exit (104); } @@ -1503,6 +1541,7 @@ writefile (int requirenew) fclose(fp); fclose(fpl); sigprocmask(SIG_SETMASK, &oldmask, NULL); + debug_write("two users registering at the same time"); graceful_exit (111); } fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password, @@ -1525,6 +1564,7 @@ writefile (int requirenew) fclose(fp); fclose(fpl); sigprocmask(SIG_SETMASK, &oldmask, NULL); + debug_write("too many users in passwd db already"); graceful_exit (116); } } @@ -1554,6 +1594,7 @@ writefile (int requirenew) ret = sqlite3_open(USE_SQLITE_DB, &db); /* FIXME: use globalconfig->passwd? */ if (ret) { sqlite3_close(db); + debug_write("writefile sqlite3_open failed"); graceful_exit(107); } @@ -1564,6 +1605,7 @@ writefile (int requirenew) if (ret != SQLITE_OK) { sqlite3_close(db); + debug_write("writefile sqlite3_exec failed"); graceful_exit(106); } sqlite3_close(db); @@ -1588,10 +1630,12 @@ purge_stale_locks (int game) size_t len; short firsttime = 1; - dir = strdup(dgl_format_str(game, me, myconfig[game]->inprogressdir)); + dir = strdup(dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL)); - if (!(pdir = opendir (dir))) + if (!(pdir = opendir (dir))) { + debug_write("purge_stale_locks dir open failed"); graceful_exit (200); + } free(dir); @@ -1609,24 +1653,29 @@ purge_stale_locks (int game) colon = strchr (dent->d_name, ':'); /* should never happen */ - if (!colon) + if (!colon) { + debug_write("purge_stale_locks !colon"); graceful_exit (201); - + } if (colon - dent->d_name != strlen(me->username)) continue; if (strncmp (dent->d_name, me->username, colon - dent->d_name)) continue; - len = strlen (dent->d_name) + strlen(dgl_format_str(game, me, myconfig[game]->inprogressdir)) + 1; + len = strlen (dent->d_name) + strlen(dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL)) + 1; fn = malloc (len); - snprintf (fn, len, "%s%s", dgl_format_str(game, me, myconfig[game]->inprogressdir), dent->d_name); + snprintf (fn, len, "%s%s", dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL), dent->d_name); - if (!(ipfile = fopen (fn, "r"))) + if (!(ipfile = fopen (fn, "r"))) { + debug_write("purge_stale_locks fopen inprogressdir fail"); graceful_exit (202); + } - if (fgets (buf, 16, ipfile) == NULL) + if (fgets (buf, 16, ipfile) == NULL) { + debug_write("purge_stale_locks fgets ipfile fail"); graceful_exit (203); + } fclose (ipfile); @@ -1692,6 +1741,7 @@ purge_stale_locks (int game) endwin (); fprintf (stderr, "Sorry, no %s for you now, please " "contact the admin.\n", myconfig[game]->game_name); + debug_write("could not terminate stale processes"); graceful_exit (1); } } @@ -1743,6 +1793,7 @@ runmenuloop(struct dg_menu *menu) } if (check_retard(0)) { + debug_write("retard"); graceful_exit(119); } } @@ -1946,8 +1997,10 @@ main (int argc, char** argv) if (wall_email_str) { char *emailfrom = wall_email_str; char *emailmsg = strchr(wall_email_str, ':'); - if (!emailmsg) + if (!emailmsg) { + debug_write("wall: no mail msg"); graceful_exit(117); + } *emailmsg = '\0'; emailmsg++; if (emailmsg) @@ -1974,11 +2027,15 @@ main (int argc, char** argv) } /* simple login routine, uses ncurses */ - if (readfile (0)) + if (readfile (0)) { + debug_write("log in fail"); graceful_exit (110); + } - if (nhauth) + if (nhauth) { + debug_write("nhauth"); graceful_exit (authenticate ()); + } if (auth) { diff --git a/dgamelaunch.h b/dgamelaunch.h index 3a6fe19..7872fc9 100644 --- a/dgamelaunch.h +++ b/dgamelaunch.h @@ -89,6 +89,7 @@ struct dg_config char* game_name; char* shortname; char* rcfile; + char* ttyrecdir; char* spool; char* inprogressdir; int num_args; /* # of bin_args */ @@ -182,7 +183,7 @@ extern void catch_sighup(int signum); extern void loadbanner(char *fname, struct dg_banner *ban); extern void drawbanner(struct dg_banner *ban, unsigned int start_line, unsigned int howmany); extern int check_retard(int reset); -extern char *dgl_format_str(int game, struct dg_user *me, char *str); +extern char *dgl_format_str(int game, struct dg_user *me, char *str, char *plrname); extern struct dg_menu *dgl_find_menu(char *menuname); @@ -190,6 +191,12 @@ extern int dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user extern struct dg_game **populate_games(int game, int *l, struct dg_user *me); +#ifdef USE_DEBUGFILE +extern void debug_write(char *str); +#else +#define debug_write(str) +#endif + extern struct dg_game **sort_games(struct dg_game **games, int len, dg_sortmode sortmode); int runmenuloop(struct dg_menu *menu); diff --git a/dgl-common.c b/dgl-common.c index 3647ab5..b4aca6d 100644 --- a/dgl-common.c +++ b/dgl-common.c @@ -41,6 +41,7 @@ struct dg_config defconfig = { /* max = */ /*64000,*/ /* savefilefmt = */ /*"",*/ /* don't do this by default */ /* inprogressdir = */ "%rinprogress/", + NULL, /* num_args = */ 0, /* bin_args = */ NULL, /* rc_fmt = */ "%rrcfiles/%n.nethackrc", /* [dglroot]rcfiles/[username].nethackrc */ @@ -86,12 +87,12 @@ dgl_find_menu(char *menuname) /* * replace following codes with variables: * %u == shed_uid (number) - * %n == user name (string) + * %n == user name (string; gotten from 'me', or from 'plrname' if 'me' is null) * %r == chroot (string) (aka "dglroot" config var) * %g == game name */ char * -dgl_format_str(int game, struct dg_user *me, char *str) +dgl_format_str(int game, struct dg_user *me, char *str, char *plrname) { static char buf[1024]; char *f, *p, *end; @@ -113,11 +114,14 @@ dgl_format_str(int game, struct dg_user *me, char *str) break; case 'n': if (me) snprintf (p, end + 1 - p, "%s", me->username); + else if (plrname) snprintf(p, end + 1 - p, "%s", plrname); + else return NULL; while (*p != '\0') p++; break; case 'g': if (game >= 0 && game < num_games && myconfig[game]) snprintf (p, end + 1 - p, "%s", myconfig[game]->game_name); + else return NULL; while (*p != '\0') p++; break; @@ -166,8 +170,8 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) return_from_submenu = 0; while (tmp && !return_from_submenu) { - if (tmp->param1) strcpy(p1, dgl_format_str(game, me, tmp->param1)); - if (tmp->param2) strcpy(p2, dgl_format_str(game, me, tmp->param2)); + if (tmp->param1) strcpy(p1, dgl_format_str(game, me, tmp->param1, NULL)); + if (tmp->param2) strcpy(p2, dgl_format_str(game, me, tmp->param2, NULL)); switch (tmp->cmd) { default: break; @@ -222,6 +226,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) child = fork(); if (child == -1) { perror("fork"); + debug_write("exec-command fork failed"); graceful_exit(114); } else if (child == 0) { execvp(p1, myargv); @@ -252,6 +257,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) if (!loggedin && globalconfig.allow_registration) newuser(); break; case DGLCMD_QUIT: + debug_write("command: quit"); graceful_exit(0); /* break; */ case DGLCMD_SUBMENU: @@ -281,8 +287,8 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) if (!strcmp(myconfig[userchoice]->game_name, p1) || !strcmp(myconfig[userchoice]->shortname, p1)) { if (purge_stale_locks(userchoice)) { if (myconfig[userchoice]->rcfile) { - if (access (dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt), R_OK) == -1) - write_canned_rcfile (userchoice, dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt)); + if (access (dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt, NULL), R_OK) == -1) + write_canned_rcfile (userchoice, dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt, NULL)); } setproctitle("%s [playing %s]", me->username, myconfig[userchoice]->shortname); @@ -297,13 +303,15 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) /* fix the variables in the arguments */ for (i = 0; i < myconfig[userchoice]->num_args; i++) { - tmpstr = strdup(dgl_format_str(userchoice, me, myconfig[userchoice]->bin_args[i])); + tmpstr = strdup(dgl_format_str(userchoice, me, myconfig[userchoice]->bin_args[i], NULL)); free(myconfig[userchoice]->bin_args[i]); myconfig[userchoice]->bin_args[i] = tmpstr; } /* launch program */ - ttyrec_main (userchoice, me->username, dgl_format_str(userchoice, me, "%ruserdata/%n/ttyrec"), gen_ttyrec_filename()); + ttyrec_main (userchoice, me->username, + dgl_format_str(userchoice, me, myconfig[userchoice]->ttyrecdir, NULL), + gen_ttyrec_filename()); /* lastly, run the generic "do these when a game is left" commands */ dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_GAMEEND], userchoice, me); @@ -359,6 +367,19 @@ sort_games (struct dg_game **games, int len, dg_sortmode sortmode) return games; } +#ifdef USE_DEBUGFILE +void +debug_write(char *str) +{ + FILE *fp; + fp = fopen("/dgldebug.log", "a"); + if (!fp) return; + fprintf(fp, "%s\n", str); + fclose(fp); + +} +#endif /* USE_DEBUGFILE */ + struct dg_game ** populate_games (int xgame, int *l, struct dg_user *me) { @@ -382,19 +403,27 @@ populate_games (int xgame, int *l, struct dg_user *me) for (game = ((xgame < 0) ? 0 : xgame); game < ((xgame <= 0) ? num_games : (xgame+1)); game++) { - dir = strdup(dgl_format_str(game, me, myconfig[game]->inprogressdir)); + dir = strdup(dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL)); + if (!dir) continue; - if (!(pdir = opendir (dir))) - graceful_exit (140); + if (!(pdir = opendir (dir))) { + debug_write("cannot open inprogress-dir"); + graceful_exit (140); + } while ((pdirent = readdir (pdir))) { + char *inprog = NULL; if (!strcmp (pdirent->d_name, ".") || !strcmp (pdirent->d_name, "..")) continue; is_nhext = !strcmp (pdirent->d_name + strlen (pdirent->d_name) - 6, ".nhext"); - snprintf (fullname, 130, "%s%s", dgl_format_str(game, me, myconfig[game]->inprogressdir), pdirent->d_name); + inprog = dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL); + + if (!inprog) continue; + + snprintf (fullname, 130, "%s%s", inprog, pdirent->d_name); fd = 0; /* O_RDWR here should be O_RDONLY, but we need to test for @@ -406,15 +435,22 @@ populate_games (int xgame, int *l, struct dg_user *me) /* stat to check idle status */ if (!is_nhext) { + char *ttrecdir = NULL; strncpy(playername, pdirent->d_name, 29); playername[29] = '\0'; if ((replacestr = strchr(playername, ':'))) *replacestr = '\0'; replacestr = strchr(pdirent->d_name, ':'); - if (!replacestr) graceful_exit(145); + if (!replacestr) { + debug_write("inprogress-filename does not have ':'"); + graceful_exit(145); + } replacestr++; - snprintf (ttyrecname, 130, "%suserdata/%s/ttyrec/%s", globalconfig.dglroot, playername, replacestr); + + ttrecdir = dgl_format_str(game, me, myconfig[game]->ttyrecdir, playername); + if (!ttrecdir) continue; + snprintf (ttyrecname, 130, "%s%s", ttrecdir, replacestr); } if (is_nhext || !stat (ttyrecname, &pstat)) { @@ -423,9 +459,10 @@ populate_games (int xgame, int *l, struct dg_user *me) games[len] = malloc (sizeof (struct dg_game)); games[len]->ttyrec_fn = strdup (ttyrecname); - if (!(replacestr = strchr (pdirent->d_name, ':'))) - graceful_exit (146); - else + if (!(replacestr = strchr (pdirent->d_name, ':'))) { + debug_write("inprogress-filename does not have ':', pt. 2"); + graceful_exit (146); + } else *replacestr = '\0'; games[len]->name = malloc (strlen (pdirent->d_name) + 1); @@ -547,6 +584,7 @@ create_config () else { fprintf(stderr, "ERROR: can't find or open %s for reading\n", config); + debug_write("cannot read config file"); graceful_exit(104); return; } @@ -562,7 +600,8 @@ create_config () fclose(config_file); } else { fprintf(stderr, "ERROR: can't find or open %s for reading\n", config); - graceful_exit(104); + debug_write("cannot read default config file"); + graceful_exit(105); return; } #else @@ -576,6 +615,7 @@ create_config () if (!myconfig) /* a parse error occurred */ { fprintf(stderr, "ERROR: configuration parsing failed\n"); + debug_write("config file parsing failed"); graceful_exit(113); } diff --git a/examples/dgamelaunch.conf b/examples/dgamelaunch.conf index 6a33d2d..c40a32c 100644 --- a/examples/dgamelaunch.conf +++ b/examples/dgamelaunch.conf @@ -213,6 +213,11 @@ DEFINE { inprogressdir = "%rinprogress-nh343/" +# The place where ttyrecs are stored for this game. +# If this is not defined, ttyrecs are not saved for this game. +# Leaving this undefined also means the games cannot be spectated. + ttyrecdir = "%ruserdata/%n/ttyrec/" + # back up savefile commands = cp "/nh343/var/save/%u%n.gz" "/nh343/var/save/%u%n.gz.bak", diff --git a/ttyrec.c b/ttyrec.c index 9e348a7..28af7e3 100644 --- a/ttyrec.c +++ b/ttyrec.c @@ -91,6 +91,21 @@ ttyrec_main (int game, char *username, char *ttyrec_path, char* ttyrec_filename) child = subchild = input_child = 0; + if (!ttyrec_path) { + child = fork(); + if (child < 0) { + perror ("fork"); + fail (); + } + if (child == 0) { + execvp (myconfig[game]->game_path, myconfig[game]->bin_args); + } else { + int status; + (void) wait(&status); + } + return 0; + } + if (ttyrec_path[strlen(ttyrec_path)-1] == '/') snprintf (dirname, 100, "%s%s", ttyrec_path, ttyrec_filename); else -- 2.47.3