]> skyeroc.xyz Git - dgamelaunch/commitdiff
Allow more than one game per dgl installation.
authorPasi Kallinen <paxed@alt.org>
Thu, 29 Mar 2007 20:14:55 +0000 (20:14 +0000)
committerPasi Kallinen <paxed@alt.org>
Thu, 29 Mar 2007 20:14:55 +0000 (20:14 +0000)
git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@345 db0b04b0-f4d1-0310-9a6d-de3e77497b0e

TODO
config.l
config.y
dgamelaunch.c
dgamelaunch.h
dgl-common.c
dgl-wall.c
examples/dgamelaunch.conf
ttyrec.c
ttyrec.h

diff --git a/TODO b/TODO
index 25d9cd5e724634a6cb337c1bd31f464b47b96d39..70069e60183e2f41c190f40221b2e42b382fc186 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,9 @@
+-configurable environment variables for when the game is launched
+-configurable rcfilefmt and default rcfile name
+-configurable stuff: max user name len, allowed chars in usernames,
+ allow mailing, allow char stripping, ...
+-allow different banners for different games
+
 - Flags for operators/staff/admins or (optionally) user-bans.
 
 - Localization of variables, code clean up
index 3a73e858c913bfefe7daefd2c32f4c443ab454f3..4f6176f5009331d66ba0d42afb3938d4be224c12 100644 (file)
--- a/config.l
+++ b/config.l
@@ -57,6 +57,8 @@ COMMENT               ^#.*
 "shed_gid"     { return TYPE_SGID; }
 "maxusers"     { return TYPE_MAX; }
 
+"game_num"     { return TYPE_GAMENUM; }
+
 "chroot_path"  { return TYPE_PATH_CHROOT; }
 "game_name"     { return TYPE_NAME_GAME; }
 "game_path"    { return TYPE_PATH_GAME; }
@@ -67,6 +69,9 @@ COMMENT               ^#.*
 "passwd"       { return TYPE_PATH_PASSWD; }
 "lockfile"     { return TYPE_PATH_LOCKFILE; }
 "savefilefmt"  { return TYPE_PATH_SAVEFILEFMT; }
+"inprogressdir" { return TYPE_PATH_INPROGRESS; }
+"game_args"    { return TYPE_GAME_ARGS; }
+"rc_fmt"       { return TYPE_RC_FMT; }
 
 \n             { line++; col = 0; }
 
index b38d82ccc21173fe114332b7c17b222726ab0445..154baf4cb345584304df302ffa6c0653e31a7865 100644 (file)
--- a/config.y
+++ b/config.y
@@ -17,6 +17,9 @@ extern void yyerror(const char*);
 extern char *yytext;
 extern unsigned int line, col;
 
+extern int num_games;
+int ncnf = 0;
+
 static const char* lookup_token (int t);
 
 %}
@@ -29,9 +32,9 @@ static const char* lookup_token (int t);
 
 %token TYPE_SUSER TYPE_SGROUP TYPE_SGID TYPE_SUID TYPE_MAX
 %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_BANNER TYPE_PATH_CANNED TYPE_PATH_CHROOT TYPE_GAMENUM
 %token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE TYPE_PATH_SAVEFILEFMT
-%token TYPE_MALSTRING
+%token TYPE_MALSTRING TYPE_PATH_INPROGRESS TYPE_GAME_ARGS TYPE_RC_FMT
 %token <s> TYPE_VALUE
 %token <i> TYPE_NUMBER
 %type  <kt> KeyType
@@ -49,24 +52,34 @@ KeyPairs: KeyPairs KeyPair
 KeyPair: KeyType '=' TYPE_VALUE {
   struct group* gr;
   struct passwd* usr;
-  
+
+  if (ncnf < 0 || ncnf >= DIFF_GAMES) {
+      fprintf(stderr, "%s:%d: illegal game number, bailing out\n",
+        config, line);
+      exit(1);
+  }
+
   if (!myconfig)
   {
-    myconfig = calloc(1, sizeof(struct dg_config));
-    myconfig->shed_uid = (uid_t)-1;
-    myconfig->shed_gid = (gid_t)-1;
+    int tmp;
+    myconfig = calloc(DIFF_GAMES, sizeof(myconfig[0]));
+    for (tmp = 0; tmp < DIFF_GAMES; tmp++) {
+       myconfig[tmp] = calloc(1, sizeof(struct dg_config));
+    }
+    globalconfig.shed_uid = (uid_t)-1;
+    globalconfig.shed_gid = (gid_t)-1;
   }
 
   switch ($1)
   {
     case TYPE_SGROUP:
-      if (myconfig->shed_gid != (gid_t)-1)
+      if (globalconfig.shed_gid != (gid_t)-1)
         break;
-       
-      myconfig->shed_group = strdup($3);
+
+      globalconfig.shed_group = strdup($3);
       if ((gr = getgrnam($3)) != NULL)
       {
-       myconfig->shed_gid = gr->gr_gid;
+       globalconfig.shed_gid = gr->gr_gid;
        if (!silent)
          fprintf(stderr, "%s:%d: suggest replacing 'shed_group = \"%s\"' line with 'shed_gid = %d'\n",
          config, line, $3, gr->gr_gid);
@@ -76,23 +89,23 @@ KeyPair: KeyType '=' TYPE_VALUE {
         if (!silent)
           fprintf(stderr, "%s:%d: no such group '%s'\n", config, line, $3);
       }
-      
+
       break;
     case TYPE_SUSER:
-      if (myconfig->shed_uid != (uid_t)-1)
+      if (globalconfig.shed_uid != (uid_t)-1)
         break;
-       
+
       if (!strcmp($3, "root"))
       {
         fprintf(stderr, "%s:%d: I refuse to run as root! Aborting.\n", config, line);
        graceful_exit(1);
       }
-      myconfig->shed_user = strdup($3);
+      globalconfig.shed_user = strdup($3);
       if ((usr = getpwnam($3)) != NULL)
       {
         if (usr->pw_uid != 0)
        {
-          myconfig->shed_uid = usr->pw_uid;
+          globalconfig.shed_uid = usr->pw_uid;
          if (!silent)
            fprintf(stderr, "%s:%d: suggest replacing 'shed_user = \"%s\"' line with 'shed_uid = %d'\n",
              config, line, $3, usr->pw_uid);
@@ -111,79 +124,118 @@ KeyPair: KeyType '=' TYPE_VALUE {
       break;
 
     case TYPE_PATH_CHROOT:
-      if (myconfig->chroot) free(myconfig->chroot);
-      myconfig->chroot = strdup ($3);
+      if (globalconfig.chroot) free(globalconfig.chroot);
+      globalconfig.chroot = strdup ($3);
       break;
 
     case TYPE_PATH_GAME:
-      if (myconfig->game_path) free(myconfig->game_path);
-      myconfig->game_path = strdup ($3);
+      if (myconfig[ncnf]->game_path) free(myconfig[ncnf]->game_path);
+      myconfig[ncnf]->game_path = strdup ($3);
       break;
 
     case TYPE_NAME_GAME:
-      if (myconfig->game_name) free (myconfig->game_name);
-      myconfig->game_name = strdup($3);
+      if (myconfig[ncnf]->game_name) free (myconfig[ncnf]->game_name);
+      myconfig[ncnf]->game_name = strdup($3);
       break;
 
     case TYPE_PATH_DGLDIR:
-      if (myconfig->dglroot) free(myconfig->dglroot);
-      myconfig->dglroot = strdup ($3);
+      if (globalconfig.dglroot) free(globalconfig.dglroot);
+      globalconfig.dglroot = strdup($3);
       break;
 
     case TYPE_PATH_BANNER:
-      if (myconfig->banner) free(myconfig->banner);
-      myconfig->banner = strdup($3);
+      if (globalconfig.banner) free(globalconfig.banner);
+      globalconfig.banner = strdup($3);
       break;
 
     case TYPE_PATH_CANNED:
-      if (myconfig->rcfile) free(myconfig->rcfile);
-      myconfig->rcfile = strdup($3);
+      if (myconfig[ncnf]->rcfile) free(myconfig[ncnf]->rcfile);
+      myconfig[ncnf]->rcfile = strdup($3);
       break;
 
     case TYPE_PATH_SPOOL:
-      if (myconfig->spool) free (myconfig->spool);
-      myconfig->spool = strdup($3);
+      if (myconfig[ncnf]->spool) free (myconfig[ncnf]->spool);
+      myconfig[ncnf]->spool = strdup($3);
       break;
 
     case TYPE_PATH_LOCKFILE:
-      if (myconfig->lockfile) free (myconfig->lockfile);
-      myconfig->lockfile = strdup($3);
+      if (myconfig[ncnf]->lockfile) free (myconfig[ncnf]->lockfile);
+      myconfig[ncnf]->lockfile = strdup($3);
       break;
 
     case TYPE_PATH_PASSWD:
-      if (myconfig->passwd) free(myconfig->passwd);
-      myconfig->passwd = strdup($3);
+      if (myconfig[ncnf]->passwd) free(myconfig[ncnf]->passwd);
+      myconfig[ncnf]->passwd = strdup($3);
       break;
 
     case TYPE_PATH_SAVEFILEFMT:
-      if (myconfig->savefilefmt) free(myconfig->savefilefmt);
-      myconfig->savefilefmt = strdup($3);
+      if (myconfig[ncnf]->savefilefmt) free(myconfig[ncnf]->savefilefmt);
+      myconfig[ncnf]->savefilefmt = strdup($3);
+      break;
+
+  case TYPE_RC_FMT:
+      if (myconfig[ncnf]->rc_fmt) free(myconfig[ncnf]->rc_fmt);
+      myconfig[ncnf]->rc_fmt = strdup($3);
+      break;
+
+    case TYPE_PATH_INPROGRESS:
+      if (myconfig[ncnf]->inprogressdir) free(myconfig[ncnf]->inprogressdir);
+      myconfig[ncnf]->inprogressdir = strdup($3);
+      break;
+
+  case TYPE_GAME_ARGS:
+      {
+         char **tmpargs;
+         if (myconfig[ncnf]->bin_args) {
+             myconfig[ncnf]->num_args++;
+             tmpargs = calloc((myconfig[ncnf]->num_args+1), sizeof(char *));
+             memcpy(tmpargs, myconfig[ncnf]->bin_args, (myconfig[ncnf]->num_args * sizeof(char *)));
+             free(myconfig[ncnf]->bin_args);
+             myconfig[ncnf]->bin_args = tmpargs;
+         } else {
+             myconfig[ncnf]->num_args = 1;
+             myconfig[ncnf]->bin_args = calloc(2, sizeof(char *));
+         }
+         myconfig[ncnf]->bin_args[(myconfig[ncnf]->num_args)-1] = strdup($3);
+         myconfig[ncnf]->bin_args[(myconfig[ncnf]->num_args)] = 0;
+      }
       break;
 
     default:
       fprintf(stderr, "%s:%d: token %s does not take a string, bailing out\n",
         config, line, lookup_token($1));
       exit(1);
-      
+
   }
 
   free($3);
 }
        | KeyType '=' TYPE_MALSTRING {}
        | KeyType '=' TYPE_NUMBER {
+
+  if (ncnf < 0 || ncnf >= DIFF_GAMES) {
+      fprintf(stderr, "%s:%d: illegal game number, bailing out\n",
+        config, line);
+      exit(1);
+  }
+
   if (!myconfig)
   {
-    myconfig = calloc(1, sizeof(struct dg_config));
-    myconfig->shed_uid = (uid_t)-1;
-    myconfig->shed_gid = (gid_t)-1;
+    int tmp;
+    myconfig = calloc(DIFF_GAMES, sizeof(myconfig[0]));
+    for (tmp = 0; tmp < DIFF_GAMES; tmp++) {
+       myconfig[tmp] = calloc(1, sizeof(struct dg_config));
+    }
+    globalconfig.shed_uid = (uid_t)-1;
+    globalconfig.shed_gid = (gid_t)-1;
   }
-              
+
   switch ($1)
   {
     case TYPE_SUID:
-      if (!silent && myconfig->shed_uid != (uid_t)-1 && myconfig->shed_uid != $3)
+      if (!silent && globalconfig.shed_uid != (uid_t)-1 && globalconfig.shed_uid != $3)
         fprintf(stderr, "%s:%d: 'shed_uid = %lu' entry overrides old setting %d\n",
-         config, line, $3, myconfig->shed_uid);
+         config, line, $3, globalconfig.shed_uid);
 
       /* Naive user protection - do not allow running as user root */
       if ($3 == 0)
@@ -192,20 +244,30 @@ KeyPair: KeyType '=' TYPE_VALUE {
         graceful_exit(1);
       }
      
-      myconfig->shed_uid = $3;
+      globalconfig.shed_uid = $3;
       break;
 
     case TYPE_SGID:
-      if (!silent && myconfig->shed_gid != (gid_t)-1 && myconfig->shed_gid != $3)
+      if (!silent && globalconfig.shed_gid != (gid_t)-1 && globalconfig.shed_gid != $3)
         fprintf(stderr, "%s:%d: 'shed_gid = %lu' entry overrides old setting %d\n",
-         config, line, $3, myconfig->shed_gid);
+         config, line, $3, globalconfig.shed_gid);
       
-      myconfig->shed_gid = $3;
+      globalconfig.shed_gid = $3;
+      break;
+
+  case TYPE_GAMENUM:
+      if (($3 < 0) || ($3 >= DIFF_GAMES)) {
+         fprintf(stderr, "%s:%d: illegal game number, bailing out\n",
+                 config, line);
+         exit(1);
+      }
+      ncnf = $3;
+      if (ncnf > num_games)
+         num_games = ncnf;
       break;
 
     case TYPE_MAX:
-      set_max = 1; /* XXX XXX */
-      myconfig->max = $3;
+      globalconfig.max = $3;
       break;
 
     default:
@@ -220,6 +282,7 @@ KeyType : TYPE_SUSER        { $$ = TYPE_SUSER; }
        | TYPE_SUID     { $$ = TYPE_SUID; }
        | TYPE_SGID     { $$ = TYPE_SGID; }
        | TYPE_MAX      { $$ = TYPE_MAX; }
+       | TYPE_GAMENUM  { $$ = TYPE_GAMENUM; }
        | TYPE_PATH_CHROOT      { $$ = TYPE_PATH_CHROOT; }
        | TYPE_PATH_GAME        { $$ = TYPE_PATH_GAME; }
         | TYPE_NAME_GAME        { $$ = TYPE_NAME_GAME; }
@@ -230,6 +293,9 @@ KeyType : TYPE_SUSER        { $$ = TYPE_SUSER; }
        | TYPE_PATH_PASSWD      { $$ = TYPE_PATH_PASSWD; }
        | TYPE_PATH_LOCKFILE    { $$ = TYPE_PATH_LOCKFILE; }
        | TYPE_PATH_SAVEFILEFMT { $$ = TYPE_PATH_SAVEFILEFMT; }
+       | TYPE_PATH_INPROGRESS  { $$ = TYPE_PATH_INPROGRESS; }
+       | TYPE_GAME_ARGS        { $$ = TYPE_GAME_ARGS; }
+       | TYPE_RC_FMT           { $$ = TYPE_RC_FMT; }
        ;
 
 %%
@@ -243,6 +309,7 @@ const char* lookup_token (int t)
     case TYPE_SUID: return "shed_uid";
     case TYPE_SGID: return "shed_gid";
     case TYPE_MAX: return "maxusers";
+    case TYPE_GAMENUM: return "game_num";
     case TYPE_PATH_CHROOT: return "chroot_path";
     case TYPE_PATH_GAME: return "game_path";
     case TYPE_NAME_GAME: return "game_name";
@@ -251,6 +318,9 @@ const char* lookup_token (int t)
     case TYPE_PATH_BANNER: return "banner";
     case TYPE_PATH_CANNED: return "rc_template";
     case TYPE_PATH_SAVEFILEFMT: return "savefilefmt";
+    case TYPE_PATH_INPROGRESS: return "inprogressdir";
+    case TYPE_GAME_ARGS: return "game_args";
+    case TYPE_RC_FMT: return "rc_fmt";
     default: abort();
   }
 }
index ab4bf36a740d3ad30da9cabc746292681e11b6da..19f23b9a93ae9b200354b2c65c10fe96a34f8290 100644 (file)
@@ -89,7 +89,7 @@ extern int editor_main (int argc, char **argv);
 /* global variables */
 
 char * __progname;
-char rcfilename[80];
+/*char rcfilename[80];*/
 
 int f_num = 0;
 struct dg_user **users = NULL;
@@ -181,7 +181,7 @@ gen_nhext_filename ()
 /* ************************************************************* */
 
 char*
-gen_inprogress_lock (pid_t pid, char* ttyrec_filename)
+gen_inprogress_lock (int game, pid_t pid, char* ttyrec_filename)
 {
   char *lockfile = NULL, filebuf[80];
   int fd;
@@ -196,10 +196,10 @@ gen_inprogress_lock (pid_t pid, char* ttyrec_filename)
   fl.l_start = 0;
   fl.l_len = 0;
 
-  len = strlen(myconfig->dglroot) + strlen(me->username) + strlen(ttyrec_filename) + 13;
+  len = strlen(globalconfig.dglroot) + strlen(me->username) + strlen(ttyrec_filename) + 13;
   lockfile = calloc(len, sizeof(char));
   
-  snprintf (lockfile, len, "%sinprogress/%s:%s", myconfig->dglroot,
+  snprintf (lockfile, len, "%s%s%s:%s", globalconfig.dglroot, myconfig[game]->inprogressdir,
             me->username, ttyrec_filename);
 
   fd = open (lockfile, O_WRONLY | O_CREAT, 0644);
@@ -228,14 +228,14 @@ catch_sighup (int signum)
 /* ************************************************************* */
 
 void
-loadbanner (struct dg_banner *ban)
+loadbanner (int game, struct dg_banner *ban)
 {
   FILE *bannerfile;
   char buf[80];
 
   memset (buf, 0, 80);
 
-  bannerfile = fopen (myconfig->banner, "r");
+  bannerfile = fopen (globalconfig.banner, "r");
 
   if (!bannerfile)
     {
@@ -245,9 +245,9 @@ loadbanner (struct dg_banner *ban)
       ban->lines[0] =
         strdup ("### dgamelaunch " PACKAGE_VERSION
                 " - network console game launcher");
-      len = strlen(myconfig->banner) + ARRAY_SIZE("### NOTE: administrator has not installed a  file");
+      len = strlen(globalconfig.banner) + ARRAY_SIZE("### NOTE: administrator has not installed a  file");
       ban->lines[1] = malloc(len);
-      snprintf(ban->lines[1], len, "### NOTE: administrator has not installed a %s file", myconfig->banner);
+      snprintf(ban->lines[1], len, "### NOTE: administrator has not installed a %s file", globalconfig.banner);
       return;
     }
 
@@ -310,7 +310,7 @@ drawbanner (unsigned int start_line, unsigned int howmany)
 
   if (!loaded_banner)
     {
-      loadbanner (&banner);
+       loadbanner (0, &banner);
       loaded_banner = 1;
     }
 
@@ -322,7 +322,7 @@ drawbanner (unsigned int start_line, unsigned int howmany)
 }
 
 void
-inprogressmenu ()
+inprogressmenu (int gameid)
 {
   int i, menuchoice, len = 20, offset = 0, doresizewin = 0;
   time_t ctime;
@@ -331,7 +331,7 @@ inprogressmenu ()
   int is_nhext[14];
   sigset_t oldmask, toblock;
 
-  games = populate_games (&len);
+  games = populate_games (gameid, &len);
 
   while (1)
     {
@@ -416,7 +416,7 @@ inprogressmenu ()
                break;
 
               /* valid choice has been made */
-              snprintf (ttyrecname, 130, "%sttyrec/%s", myconfig->dglroot,
+              snprintf (ttyrecname, 130, "%sttyrec/%s", globalconfig.dglroot,
                         games[menuchoice - 97 + offset]->ttyrec_fn);
               chosen_name = strdup (games[menuchoice - 97 + offset]->name);
 
@@ -452,7 +452,7 @@ inprogressmenu ()
             }
         }
 
-      games = populate_games (&len);
+      games = populate_games (gameid, &len);
     }
 }
 
@@ -623,6 +623,7 @@ domailuser (char *username)
   FILE *user_spool = NULL;
   time_t now;
   int mail_empty = 1;
+  int game;
   struct flock fl = { 0 };
 
   fl.l_type = F_WRLCK;
@@ -632,10 +633,14 @@ domailuser (char *username)
 
   assert (loggedin);
 
-  len = strlen(myconfig->spool) + strlen (username) + 1;
+  game = 0; /*TODO: find_curr_player_game(username) */
+
+  if (strlen(myconfig[game]->spool) < 1) return;
+
+  len = strlen(myconfig[game]->spool) + strlen (username) + 1;
   spool_fn = malloc (len + 1);
   time (&now);
-  snprintf (spool_fn, len + 1, "%s/%s", myconfig->spool, username);
+  snprintf (spool_fn, len + 1, "%s/%s", myconfig[game]->spool, username);
 
   /* print the enter your message line */
   clear ();
@@ -703,10 +708,46 @@ domailuser (char *username)
   return;
 }
 
+void
+drawgamemenu(int game)
+{
+  static int flood = 0;
+
+  if (loggedin) {
+
+      clear();
+
+      drawbanner(1,0);
+
+      mvprintw(banner.len + 2, 1, "Logged in as: %s", me->username);
+
+      mvaddstr (banner.len + 4, 1, "c) Change password");
+      mvaddstr (banner.len + 5, 1, "e) Change email address");
+      mvaddstr (banner.len + 6, 1, "w) Watch games in progress");
+      if (myconfig[game]->rcfile)
+         mvprintw (banner.len + 7, 1, "o) Edit options for %s", myconfig[game]->game_name);
+      mvprintw (banner.len + 8, 1, "p) Play %s", myconfig[game]->game_name);
+      mvaddstr (banner.len + 9, 1, "q) Return to previous menu");
+      mvaddstr (banner.len + 11, 1, "=> ");
+
+      refresh ();
+  }
+
+  /* for retarded clients */
+  flood++;
+  if (flood >= 20)
+  {
+    endwin();
+    graceful_exit (119);
+  }
+
+}
+
 void
 drawmenu ()
 {
   static int flood = 0;
+  int game = 0;
 
   clear ();
 
@@ -717,11 +758,17 @@ drawmenu ()
       mvprintw (banner.len + 2, 1, "Logged in as: %s", me->username);
       mvaddstr (banner.len + 4, 1, "c) Change password");
       mvaddstr (banner.len + 5, 1, "e) Change email address");
-      mvaddstr (banner.len + 6, 1, "o) Edit option file");
-      mvaddstr (banner.len + 7, 1, "w) Watch games in progress");
-      mvprintw (banner.len + 8, 1, "p) Play %s!", myconfig->game_name);
-      mvaddstr (banner.len + 9, 1, "q) Quit");
-      mvaddstr (banner.len + 11, 1, "=> ");
+      mvaddstr (banner.len + 6, 1, "w) Watch games in progress");
+      if (num_games >= 1)
+         for (game = 0; (game <= num_games) && myconfig && myconfig[game] && myconfig[game]->game_name; game++)
+             mvprintw (banner.len + 7 + game, 1, "%c) Go to %s menu", '1'+game, myconfig[game]->game_name);
+      else {
+         if (myconfig[0]->rcfile)
+             mvprintw (banner.len + 7, 1, "o) Edit options");
+         mvprintw (banner.len + 8, 1, "p) Play %s", myconfig[0]->game_name);
+      }
+      mvaddstr (banner.len + 9 + game, 1, "q) Quit");
+      mvaddstr (banner.len + 11 + game, 1, "=> ");
     }
   else
     {
@@ -730,7 +777,7 @@ drawmenu ()
       mvaddstr (banner.len + 5, 1, "r) Register new user");
       mvaddstr (banner.len + 6, 1, "w) Watch games in progress");
       mvaddstr (banner.len + 7, 1, "q) Quit");
-      mvaddstr (banner.len + 9, 1, "=> ");
+      mvaddstr (banner.len + 11, 1, "=> ");
     }
 
   refresh ();
@@ -796,7 +843,6 @@ autologin (char* user, char *pass)
     if (passwordgood(pass))
     {
       loggedin = 1;
-      snprintf (rcfilename, 80, "%srcfiles/%s.nethackrc", myconfig->dglroot, me->username);
       setproctitle ("%s", me->username);
     }
   }
@@ -859,7 +905,6 @@ loginprompt (int from_ttyplay)
   if (passwordgood (pw_buf))
     {
       loggedin = 1;
-      snprintf (rcfilename, 80, "%srcfiles/%s.nethackrc", myconfig->dglroot, me->username);
       setproctitle ("%s", me->username);
     }
   else 
@@ -885,7 +930,7 @@ newuser ()
 
   loggedin = 0;
 
-  if (f_num >= myconfig->max)
+  if (f_num >= globalconfig.max)
   {
       clear ();
 
@@ -1008,14 +1053,10 @@ newuser ()
 
   loggedin = 1;
 
-  snprintf (rcfilename, 80, "%srcfiles/%s.nethackrc", myconfig->dglroot, me->username);
   setproctitle ("%s", me->username);
 
-  if (access (rcfilename, R_OK) == -1)
-    write_canned_rcfile (rcfilename);
-
   /* create their ttyrec dir */
-  snprintf (dirname, 100, "%sttyrec/%s", myconfig->dglroot, me->username);
+  snprintf (dirname, 100, "%sttyrec/%s", globalconfig.dglroot, me->username);
 
   if (access (dirname, F_OK) != 0)
     mkdir (dirname, 0755);
@@ -1057,14 +1098,14 @@ readfile (int nolock)
 
   if (!nolock)
     {
-      fpl = fopen (myconfig->lockfile, "r");
+      fpl = fopen (myconfig[0]->lockfile, "r");
       if (!fpl)
         graceful_exit (106);
       if (fcntl (fileno (fpl), F_SETLKW, &fl) == -1)
         graceful_exit (114);
     }
 
-  fp = fopen (myconfig->passwd, "r");
+  fp = fopen (myconfig[0]->passwd, "r");
   if (!fp)
     graceful_exit (106);
 
@@ -1132,7 +1173,7 @@ readfile (int nolock)
 
       f_num++;
       /* prevent a buffer overrun here */
-      if (f_num > myconfig->max)
+      if (f_num > globalconfig.max)
       {
        fprintf(stderr,"ERROR: number of users in database exceeds maximum. Exiting.\n");
         graceful_exit (109);
@@ -1164,15 +1205,15 @@ userexist (char *cname)
 /* ************************************************************* */
 
 void
-write_canned_rcfile (char *target)
+write_canned_rcfile (int game, char *target)
 {
   FILE *canned, *newfile;
   char buf[1024], *rfn;
   size_t bytes, len;
 
-  len = strlen(myconfig->rcfile) + 2;
+  len = strlen(myconfig[game]->rcfile) + 2;
   rfn = malloc(len);
-  snprintf (rfn, len, "/%s", myconfig->rcfile);
+  snprintf (rfn, len, "/%s", myconfig[game]->rcfile);
 
   if (!(newfile = fopen (target, "w")))
     {
@@ -1180,7 +1221,7 @@ write_canned_rcfile (char *target)
       mvaddstr (13, 1,
                 "You don't know how to write that! You write \"%s was here\" and the scroll disappears.");
       mvaddstr (14, 1,
-                "(Sorry, but I couldn't open one of the nethackrc files. This is a bug.)");
+                "(Sorry, but I couldn't open one of the config files. This is a bug.)");
       return;
     }
 
@@ -1211,20 +1252,20 @@ write_canned_rcfile (char *target)
 
 
 void
-editoptions ()
+editoptions (int game)
 {
   FILE *rcfile;
   char *myargv[3];
   pid_t editor;
 
-  rcfile = fopen (rcfilename, "r");
-  if (!rcfile)                  /* should not really happen except for old users */
-    write_canned_rcfile (rcfilename);
+  rcfile = fopen (dgl_format_str(game, me, myconfig[game]->rc_fmt), "r");
+  if (!rcfile)
+      write_canned_rcfile (game, dgl_format_str(game, me, myconfig[game]->rc_fmt));
 
   /* use whatever editor_main to edit */
 
   myargv[0] = "";
-  myargv[1] = rcfilename;
+  myargv[1] = dgl_format_str(game, me, myconfig[game]->rc_fmt);
   myargv[2] = 0;
 
   endwin ();
@@ -1270,7 +1311,7 @@ writefile (int requirenew)
   sigaddset(&toblock, SIGTERM);
   sigprocmask(SIG_BLOCK, &toblock, &oldmask);
 
-  fpl = fopen (myconfig->lockfile, "r+");
+  fpl = fopen (myconfig[0]->lockfile, "r+");
   if (!fpl)
     {
       sigprocmask(SIG_SETMASK, &oldmask, NULL);
@@ -1287,7 +1328,7 @@ writefile (int requirenew)
   freefile ();
   readfile (1);
 
-  fp = fopen (myconfig->passwd, "w");
+  fp = fopen (myconfig[0]->passwd, "w");
   if (!fp)
     {
       sigprocmask(SIG_SETMASK, &oldmask, NULL);
@@ -1319,7 +1360,7 @@ writefile (int requirenew)
     }
   if (loggedin && !my_done)
     {                           /* new entry */
-      if (f_num < myconfig->max)
+      if (f_num < globalconfig.max)
         fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password,
                  me->env);
       else /* Oops, someone else registered the last available slot first */
@@ -1345,65 +1386,30 @@ writefile (int requirenew)
 /* ************************************************************* */
 /* ************************************************************* */
 
+
 /*
  * Backup the savefile, if configured.
  * Returns non-zero if successful, otherwise an error message has been
  * given already.
  */
 int
-backup_savefile (void)
+backup_savefile (int game)
 {
-  char buf[1024];
-  char *f, *p, *end;
+    /*char buf[1024];*/
+    char *f, *p, *end, *buf;
   int ispercent = 0, n;
   int in, out;
 
-  f = myconfig->savefilefmt;
+  f = myconfig[game]->savefilefmt;
 
   if (*f == '\0')
     return 1;
   if (me == NULL)
     graceful_exit (147);
 
+  buf = dgl_format_str(game, me, f);
   p = buf;
-  end = buf + sizeof(buf) - 10; /* make sure we can add .bak */
-  while (*f)
-    {
-      if (ispercent)
-        {
-          switch (*f)
-         {
-           case 'u':
-             snprintf (p, end + 1 - p, "%d", myconfig->shed_uid);
-             while (*p != '\0')
-               p++;
-             break;
-           case 'n':
-             snprintf (p, end + 1 - p, "%s", me->username);
-             while (*p != '\0')
-               p++;
-             break;
-           default:
-             *p = *f;
-             if (p < end)
-               p++;
-         }
-         ispercent = 0;
-       }
-      else
-        {
-         if (*f == '%')
-           ispercent = 1;
-         else
-           {
-             *p = *f;
-             if (p < end)
-               p++;
-           }
-       }
-      f++;
-    }
-  *p = '\0';
+  p += strlen(buf);
 
   /*fprintf(stderr, "***\n[SAVEFILE=%s]\n***\n", buf);
   sleep(3);*/
@@ -1443,7 +1449,7 @@ backup_savefile (void)
 }
 
 int
-purge_stale_locks (void)
+purge_stale_locks (int game)
 {
   DIR *pdir;
   struct dirent *dent;
@@ -1451,10 +1457,10 @@ purge_stale_locks (void)
   size_t len;
   short firsttime = 1;
 
-  len = strlen(myconfig->dglroot) + ARRAY_SIZE("inprogress/") + 1;
+  len = strlen(globalconfig.dglroot) + strlen(myconfig[game]->inprogressdir) + 1;
   dir = malloc(len);
-  snprintf(dir, len, "%sinprogress/", myconfig->dglroot);
-  
+  snprintf(dir, len, "%s%s", globalconfig.dglroot, myconfig[game]->inprogressdir);
+
   if (!(pdir = opendir (dir)))
     graceful_exit (200);
 
@@ -1468,7 +1474,7 @@ purge_stale_locks (void)
       pid_t pid;
       size_t len;
       int seconds = 0;
-      
+
       if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, ".."))
         continue;
 
@@ -1482,10 +1488,12 @@ purge_stale_locks (void)
       if (strncmp (dent->d_name, me->username, colon - dent->d_name))
         continue;
 
-      len = strlen (dent->d_name) + strlen(myconfig->dglroot) + 12;
+      len = strlen (dent->d_name) + strlen(globalconfig.dglroot) + 12;
       fn = malloc (len);
 
-      snprintf (fn, len, "%sinprogress/%s", myconfig->dglroot, dent->d_name);
+      snprintf (fn, len, "%s%s%s", globalconfig.dglroot, myconfig[game]->inprogressdir, dent->d_name);
+
+      fprintf (stderr, "ERR:'%s'\n", fn);
 
       if (!(ipfile = fopen (fn, "r")))
         graceful_exit (202);
@@ -1503,13 +1511,13 @@ purge_stale_locks (void)
 #define HUP_WAIT 10 /* seconds before HUPPING */
        mvprintw (3, 1,
            "There are some stale %s processes, will recover in %d  seconds.",
-            myconfig->game_name, HUP_WAIT);
+            myconfig[game]->game_name, HUP_WAIT);
        mvaddstr (4, 1,
            "Press a key NOW if you don't want this to happen!");
 
-       move (3, 58); /* pedantry */
+       move (3, 51 + strlen(myconfig[game]->game_name)); /* pedantry */
        halfdelay(10);
-       
+
        for (seconds = HUP_WAIT - 1; seconds >= 0; seconds--)
        {
          if (getch() != ERR)
@@ -1518,12 +1526,12 @@ purge_stale_locks (void)
            cbreak();
            return 0;
          }
-         mvprintw (3, 57, "%d%s", seconds, (seconds > 9) ? "" : " ");
+         mvprintw (3, 50 + strlen(myconfig[game]->game_name), "%d%s", seconds, (seconds > 9) ? "" : " ");
        }
 
        nocbreak();
        cbreak();
-       
+
        firsttime = 0;
       }
 
@@ -1545,7 +1553,7 @@ purge_stale_locks (void)
           if (seconds == 10)
             {
               mvprintw (3, 1,
-                        "Couldn't terminate one of your stale %s processes gracefully.", myconfig->game_name);
+                        "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')
                 {
@@ -1556,7 +1564,7 @@ purge_stale_locks (void)
                 {
                   endwin ();
                   fprintf (stderr, "Sorry, no %s for you now, please "
-                           "contact the admin.\n", myconfig->game_name);
+                           "contact the admin.\n", myconfig[game]->game_name);
                   graceful_exit (1);
                 }
             }
@@ -1571,16 +1579,22 @@ purge_stale_locks (void)
   return 1;
 }
 
-void
-menuloop (void)
+int
+gamemenuloop(int game)
 {
   int userchoice = 0;
-  while ((userchoice != 'p') | (!loggedin))
+  while (1)
     {
-      drawmenu ();
+      drawgamemenu (game);
       userchoice = getch ();
       switch (tolower (userchoice))
         {
+       default:
+           break;
+       case 'p':
+           if (loggedin)
+               return 1;
+           break;
         case 'c':
           if (loggedin)
             changepw (1);
@@ -1590,15 +1604,16 @@ menuloop (void)
            change_email();
          break;
         case 'w':
-          inprogressmenu ();
-          break;
-        case 'o':
-          if (loggedin)
-            editoptions ();
+          inprogressmenu (game);
           break;
+       case 'o':
+          if (loggedin && myconfig[game]->rcfile)
+            editoptions (game);
+           break;
         case 'q':
-          endwin ();
-          graceful_exit(0);
+           return 0;
+           /*          endwin ();
+                       graceful_exit(0);*/
           /* break; */
         case 'r':
           if (!loggedin)        /*not visible to loggedin */
@@ -1607,11 +1622,67 @@ menuloop (void)
         case 'l':
           if (!loggedin)        /* not visible to loggedin */
             loginprompt (0);
-          break;
         }
     }
+  return 0;
 }
 
+int
+menuloop (void)
+{
+  int userchoice = 0;
+  while (1)
+    {
+      drawmenu ();
+      userchoice = getch ();
+
+      if ((num_games >= 1) && loggedin && (userchoice >= '1') && (userchoice <= ('1'+num_games))) {
+         int game = userchoice - '1';
+         if (myconfig[game] && myconfig[game]->game_name) {
+             if (gamemenuloop(game)) return game;
+         }
+      } else {
+         switch (tolower (userchoice))
+             {
+             default:
+                 break;
+             case 'c':
+                 if (loggedin)
+                     changepw (1);
+                 break;
+             case 'e':
+                 if (loggedin)
+                     change_email();
+                 break;
+             case 'w':
+                 inprogressmenu (-1);
+                 break;
+             case 'o':
+                 if (loggedin && (num_games == 0) && myconfig[0]->rcfile)
+                     editoptions(0);
+                 break;
+             case 'p':
+                 if (loggedin && (num_games == 0))
+                     return 0;
+                 break;
+             case 'q':
+                 endwin ();
+                 graceful_exit(0);
+                 /* break; */
+             case 'r':
+                 if (!loggedin)        /*not visible to loggedin */
+                     newuser ();
+                 break;
+             case 'l':
+                 if (!loggedin)        /* not visible to loggedin */
+                     loginprompt (0);
+             }
+      }
+    }
+  return -1;
+}
+
+
 int
 authenticate ()
 {
@@ -1648,7 +1719,7 @@ authenticate ()
       me = users[me_index];
       if (passwordgood (pw_buf))
         {
-         games = populate_games (&len);
+           games = populate_games (-1, &len);
          for (i = 0; i < len; i++)
            if (!strcmp (games[i]->name, user_buf))
              {
@@ -1656,7 +1727,7 @@ authenticate ()
                return 1;
              }
          win.ws_row = win.ws_col = 0;
-         gen_inprogress_lock (getppid (), gen_nhext_filename ());
+         gen_inprogress_lock (0, getppid (), gen_nhext_filename ());
          return 0;
        }
     }
@@ -1674,6 +1745,7 @@ main (int argc, char** argv)
   unsigned int len;
   int c;
   int nhext = 0, nhauth = 0;
+  int userchoice;
 
 #ifndef HAVE_SETPROCTITLE
   /* save argc, argv */
@@ -1754,10 +1826,10 @@ main (int argc, char** argv)
   if (!nhext && !nhauth)
     ttyrec_getpty ();
 
-  if (geteuid () != myconfig->shed_uid)
+  if (geteuid () != globalconfig.shed_uid)
     {
       /* chroot */
-      if (chroot (myconfig->chroot))
+      if (chroot (globalconfig.chroot))
        {
          perror ("cannot change root directory");
          graceful_exit (1);
@@ -1770,19 +1842,19 @@ main (int argc, char** argv)
        }
 
       /* shed privs. this is done immediately after chroot. */
-      if (setgroups (1, &myconfig->shed_gid) == -1)
+      if (setgroups (1, &globalconfig.shed_gid) == -1)
        {
          perror ("setgroups");
          graceful_exit (1);
        }
 
-      if (setgid (myconfig->shed_gid) == -1)
+      if (setgid (globalconfig.shed_gid) == -1)
        {
          perror ("setgid");
          graceful_exit (1);
        }
 
-      if (setuid (myconfig->shed_uid) == -1)
+      if (setuid (globalconfig.shed_uid) == -1)
        {
          perror ("setuid");
          graceful_exit (1);
@@ -1793,12 +1865,12 @@ main (int argc, char** argv)
     {
       char *myargv[3];
 
-      myargv[0] = myconfig->game_path;
+      myargv[0] = myconfig[0]->game_path;
       myargv[1] = "--proxy";
       myargv[2] = 0;
 
-      execvp (myconfig->game_path, myargv);
-      perror (myconfig->game_path);
+      execvp (myconfig[0]->game_path, myargv);
+      perror (myconfig[0]->game_path);
       graceful_exit (1);
     }
 
@@ -1829,29 +1901,44 @@ main (int argc, char** argv)
   }
   
   initcurses ();
-  menuloop();
+
+  userchoice = menuloop();
 
   assert (loggedin);
 
-  while (!purge_stale_locks())
-    menuloop();
+  if ((userchoice >= 0) && (userchoice <= num_games)) {
+      while (!purge_stale_locks(userchoice)) {
+         userchoice = gamemenuloop(userchoice);
+      }
+      if (!((userchoice >= 0) && (userchoice <= num_games)))
+         graceful_exit (1);
+  } else {
+      graceful_exit (1);
+  }
+
+  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));
+  }
 
   setproctitle ("%s [playing]", me->username);
 
   endwin ();
   signal(SIGWINCH, SIG_DFL);
 
-  if (!backup_savefile ())
+  if (!backup_savefile (userchoice))
     graceful_exit (5);
 
   /* environment */
-  snprintf (atrcfilename, 81, "@%s", rcfilename);
+  if (myconfig[userchoice]->rcfile) {
+      snprintf (atrcfilename, 81, "@%s", dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt));
+      mysetenv ("NETHACKOPTIONS", atrcfilename, 1);
+  }
 
-  len = strlen(myconfig->spool) + strlen (me->username) + 1;
+  len = strlen(myconfig[userchoice]->spool) + strlen (me->username) + 1;
   spool = malloc (len + 1);
-  snprintf (spool, len + 1, "%s/%s", myconfig->spool, me->username);
+  snprintf (spool, len + 1, "%s/%s", myconfig[userchoice]->spool, me->username);
 
-  mysetenv ("NETHACKOPTIONS", atrcfilename, 1);
   mysetenv ("MAIL", spool, 1);
   mysetenv ("SIMPLEMAIL", "1", 1);
 
@@ -1861,15 +1948,40 @@ main (int argc, char** argv)
 
   free (spool);
 
+  /* fix the variables in the arguments */
+  for (i = 0; i < myconfig[userchoice]->num_args; i++) {
+      char *tmp = strdup(dgl_format_str(userchoice, me, myconfig[userchoice]->bin_args[i]));
+      free(myconfig[userchoice]->bin_args[i]);
+      myconfig[userchoice]->bin_args[i] = tmp;
+  }
+
   /* launch program */
-  ttyrec_main (me->username, gen_ttyrec_filename());
+  ttyrec_main (userchoice, me->username, gen_ttyrec_filename());
 
   /* NOW we can safely kill this */
   freefile ();
 
+  /*
+  printf("config:'%s'\n", config);
+
+  printf("chroot:'%s'\n", globalconfig.chroot);
+  printf("gamepath:'%s'\n", myconfig[userchoice]->game_path);
+  printf("game:'%s'\n", myconfig[userchoice]->game_name);
+  printf("dglroot:'%s'\n", globalconfig.dglroot);
+  printf("lockfile:'%s'\n", myconfig[userchoice]->lockfile);
+  printf("passwd:'%s'\n", myconfig[userchoice]->passwd);
+  printf("banner:'%s'\n", globalconfig.banner);
+  printf("rcfile:'%s'\n", myconfig[userchoice]->rcfile);
+  printf("spool:'%s'\n", myconfig[userchoice]->spool);
+  printf("savefilefmt:'%s'\n", myconfig[userchoice]->savefilefmt);
+  printf("dgl_format_str(savefilefmt):'%s'\n", dgl_format_str(userchoice, myconfig[userchoice]->savefilefmt));
+  printf("inprogressdir:'%s'\n", myconfig[userchoice]->inprogressdir);
+  */
+
   if (me)
     free (me);
 
   graceful_exit (1);
+
   return 1;
 }
index 692cbe8ad1c16106d3f7b711c773ab165773ed6e..7eb7b31424cdc5c7c777e837db7e8f24971e38f6 100644 (file)
 # define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 #endif
 
+
+/* max # of different games playable from within this dgl */
+#define DIFF_GAMES 3
+
 struct dg_user
 {
   char *username;
@@ -39,41 +43,54 @@ struct dg_game
 
 struct dg_config
 {
-  char* chroot;
   char* game_path;
   char* game_name;
-  char* dglroot;
   char* lockfile;
   char* passwd;
-  char* banner;
   char* rcfile;
   char* spool;
-  char* shed_user;
-  char* shed_group;
-  uid_t shed_uid;
-  gid_t shed_gid;
-  unsigned long max;
   char* savefilefmt;
+  char* inprogressdir;
+    int num_args; /* # of bin_args */
+    char **bin_args; /* args for game binary */
+    char *rc_fmt;
+};
+
+struct dg_globalconfig
+{
+    char* chroot;
+    char* dglroot;
+    char* banner;
+    unsigned long max;
+    char* shed_user;
+    char* shed_group;
+    uid_t shed_uid;
+    gid_t shed_gid;
 };
 
 /* Global variables */
 extern char* config; /* file path */
-extern struct dg_config *myconfig;
+extern struct dg_config **myconfig;
 extern char *chosen_name;
 extern int loggedin;
 extern int silent;
 extern int set_max;
 
+extern struct dg_globalconfig globalconfig;
+
+extern int num_games;
+
 /* dgamelaunch.c */
 extern void create_config(void);
 extern void ttyrec_getmaster(void);
 extern char *gen_ttyrec_filename(void);
-extern char *gen_inprogress_lock(pid_t pid, char *ttyrec_filename);
+extern char *gen_inprogress_lock(int game, pid_t pid, char *ttyrec_filename);
 extern void catch_sighup(int signum);
-extern void loadbanner(struct dg_banner *ban);
+extern void loadbanner(int game, struct dg_banner *ban);
 extern void drawbanner(unsigned int start_line, unsigned int howmany);
-extern struct dg_game **populate_games(int *l);
-extern void inprogressmenu(void);
+extern char *dgl_format_str(int game, struct dg_user *me, char *str);
+extern struct dg_game **populate_games(int game, int *l);
+extern void inprogressmenu(int gameid);
 extern void change_email(void);
 extern int changepw(int dowrite);
 extern void domailuser(char *username);
@@ -86,12 +103,12 @@ extern void autologin(char *user, char *pass);
 extern int passwordgood(char *cpw);
 extern int readfile(int nolock);
 extern int userexist(char *cname);
-extern void write_canned_rcfile(char *target);
-extern void editoptions(void);
+extern void write_canned_rcfile(int game, char *target);
+extern void editoptions(int game);
 extern void writefile(int requirenew);
 extern void graceful_exit(int status);
-extern int purge_stale_locks(void);
-extern void menuloop(void);
+extern int purge_stale_locks(int game);
+extern int menuloop(void);
 extern void ttyrec_getpty(void);
 #if !defined(BSD) && !defined(__linux__)
 extern int mysetenv (const char* name, const char* value, int overwrite);
index 464566302bec327a5583dbee0d67cc468b1d0a45..870ec11883e662646eab8b48c05a77b218907255 100644 (file)
@@ -16,33 +16,100 @@ extern FILE* yyin;
 extern int yyparse ();
 
 /* Data structures */
-struct dg_config *myconfig = NULL;
+struct dg_config **myconfig = NULL;
 struct dg_config defconfig = {
-  /* chroot = */ "/var/lib/dgamelaunch/",
+    /* chroot = */ /*"/var/lib/dgamelaunch/",*/
   /* game_path = */ "/bin/nethack",
   /* game_name = */ "NetHack",
-  /* dglroot = */  "/dgldir/",
+  /* dglroot = *//*  "/dgldir/",*/
   /* lockfile = */ "/dgl-lock",
   /* passwd = */ "/dgl-login",
-  /* banner = */ "/dgl-banner",
-  /* rcfile = */ "/dgl-default-rcfile",
+  /* banner = */ /*"/dgl-banner",*/
+  /* rcfile = */ NULL, /*"/dgl-default-rcfile",*/
   /* spool = */ "/var/mail/",
-  /* shed_user = */ "games",
-  /* shed_group = */ "games",
-  /* shed_uid = */ 5,
-  /* shed_gid = */ 60, /* games:games in Debian */
-  /* max = */ 64000,
-  /* savefilefmt = */ "" /* don't do this by default */
+  /* shed_user = */ /*"games",*/
+  /* shed_group = */ /*"games",*/
+  /* shed_uid = *//* 5,*/
+  /* shed_gid = */ /*60,*/ /* games:games in Debian */
+  /* max = */ /*64000,*/
+  /* savefilefmt = */ "", /* don't do this by default */
+  /* inprogressdir = */ "inprogress/",
+  /* num_args = */ 0,
+  /* bin_args = */ NULL,
+  /* rc_fmt = */ "%rrcfiles/%n.nethackrc" /* [dglroot]rcfiles/[username].nethackrc */
 };
 
 char* config = NULL;
 int silent = 0;
-int set_max = 0; /* XXX */
+/*int set_max = 0;*/ /* XXX */
 int loggedin = 0;
 char *chosen_name;
+int num_games = 0;
+
+struct dg_globalconfig globalconfig;
+
+/*
+ * replace following codes with variables:
+ * %u == shed_uid (number)
+ * %n == user name (string)
+ * %r == chroot (string)
+ */
+char *
+dgl_format_str(int game, struct dg_user *me, char *str)
+{
+    static char buf[1024];
+    char *f, *p, *end;
+    int ispercent = 0;
+
+    if (!str) return NULL;
+
+    f = str;
+    p = buf;
+    end = buf + sizeof(buf) - 10;
+
+    while (*f) {
+       if (ispercent) {
+           switch (*f) {
+           case 'u':
+               snprintf (p, end + 1 - p, "%d", globalconfig.shed_uid);
+               while (*p != '\0')
+                   p++;
+               break;
+           case 'n':
+               snprintf (p, end + 1 - p, "%s", me->username);
+               while (*p != '\0')
+                   p++;
+               break;
+           case 'r':
+               snprintf (p, end + 1 - p, "%s", globalconfig.dglroot);
+               while (*p != '\0')
+                   p++;
+               break;
+           default:
+               *p = *f;
+               if (p < end)
+                   p++;
+           }
+           ispercent = 0;
+       } else {
+           if (*f == '%')
+               ispercent = 1;
+           else {
+               *p = *f;
+               if (p < end)
+                   p++;
+           }
+       }
+       f++;
+    }
+    *p = '\0';
+
+    return buf;
+}
+
 
 struct dg_game **
-populate_games (int *l)
+populate_games (int xgame, int *l)
 {
   int fd, len, n, is_nhext, pid;
   DIR *pdir;
@@ -54,28 +121,32 @@ populate_games (int *l)
   struct flock fl = { 0 };
   size_t slen;
 
+  int game;
+
   fl.l_type = F_WRLCK;
   fl.l_whence = SEEK_SET;
   fl.l_start = 0;
   fl.l_len = 0;
 
   len = 0;
-  
-  slen = strlen(myconfig->dglroot) + ARRAY_SIZE("inprogress/") + 1;
-  dir = malloc(slen);
-  snprintf(dir, slen, "%sinprogress/", myconfig->dglroot);
 
-  if (!(pdir = opendir (dir)))
+  for (game = ((xgame < 0) ? 0 : xgame); game <= ((xgame < 0) ? num_games : xgame); game++) {
+
+   slen = strlen(globalconfig.dglroot) + strlen(myconfig[game]->inprogressdir) + 1;
+   dir = malloc(slen);
+   snprintf(dir, slen, "%s%s", globalconfig.dglroot, myconfig[game]->inprogressdir);
+
+   if (!(pdir = opendir (dir)))
     graceful_exit (140);
 
-  while ((pdirent = readdir (pdir)))
+   while ((pdirent = readdir (pdir)))
     {
       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, "%sinprogress/%s", myconfig->dglroot, pdirent->d_name);
+      snprintf (fullname, 130, "%s%s%s", globalconfig.dglroot, myconfig[game]->inprogressdir, pdirent->d_name);
 
       fd = 0;
       /* O_RDWR here should be O_RDONLY, but we need to test for
@@ -87,7 +158,7 @@ populate_games (int *l)
           /* stat to check idle status */
          if (!is_nhext)
            {
-             snprintf (ttyrecname, 130, "%sttyrec/%s", myconfig->dglroot, pdirent->d_name);
+             snprintf (ttyrecname, 130, "%sttyrec/%s", globalconfig.dglroot, pdirent->d_name);
              replacestr = strchr (ttyrecname, ':');
              if (!replacestr)
                graceful_exit (145);
@@ -172,7 +243,8 @@ populate_games (int *l)
       fl.l_type = F_WRLCK;
     }
 
-  closedir (pdir);
+   closedir (pdir);
+  }
   *l = len;
   return games;
 }
@@ -197,6 +269,7 @@ void
 create_config ()
 {
   FILE *config_file = NULL;
+  int tmp;
 
   if (config)
   {
@@ -217,52 +290,73 @@ create_config ()
   else
   {
 #ifdef DEFCONFIG
+      /*      fprintf(stderr, "DEFCONFIG: %s\n", DEFCONFIG);*/
     config = DEFCONFIG;
     if ((config_file = fopen(DEFCONFIG, "r")) != NULL)
     {
       yyin = config_file;
+      /*      fprintf(stderr, "PARSING\n");*/
       yyparse();
+      /*      fprintf(stderr, "PARSED\n");*/
       fclose(config_file);
     }
 #else
-    myconfig = &defconfig;
+    /*      fprintf(stderr, "NO DEFCONFIG\n");*/
+      myconfig = calloc(DIFF_GAMES, sizeof(myconfig[0]));
+    for (tmp = 0; tmp < DIFF_GAMES; tmp++)
+       myconfig[tmp] = NULL;
+    myconfig[0] = &defconfig;
     return;
 #endif
   }
 
   if (!myconfig) /* a parse error occurred */
   {
-    myconfig = &defconfig;
+      /*      fprintf(stderr, "PARSE ERROR\n");*/
+      myconfig = calloc(DIFF_GAMES, sizeof(myconfig[0]));
+    for (tmp = 0; tmp < DIFF_GAMES; tmp++)
+       myconfig[tmp] = NULL;
+    myconfig[0] = &defconfig;
     return;
   }
   /* Fill the rest with defaults */
-  if (!myconfig->shed_user && myconfig->shed_uid == (uid_t)-1)
-  {
-    struct passwd *pw;
-    if ((pw = getpwnam(defconfig.shed_user)))
-      myconfig->shed_uid = pw->pw_uid;
-    else
-      myconfig->shed_uid = defconfig.shed_uid;
-  }
 
-  if (!myconfig->shed_group && myconfig->shed_gid == (gid_t)-1)
-  {
-    struct group *gr;
-    if ((gr = getgrnam(defconfig.shed_group)))
-      myconfig->shed_gid = gr->gr_gid;
-    else
-      myconfig->shed_gid = defconfig.shed_gid;
+  for (tmp = 0; tmp < DIFF_GAMES; tmp++) {
+
+      if (!myconfig[tmp]->game_path) myconfig[tmp]->game_path = defconfig.game_path;
+      if (!myconfig[tmp]->game_name) myconfig[tmp]->game_name = defconfig.game_name;
+      if (!myconfig[tmp]->rcfile) myconfig[tmp]->rcfile = defconfig.rcfile;
+      if (!myconfig[tmp]->spool) myconfig[tmp]->spool = defconfig.spool;
+      if (!myconfig[tmp]->passwd) myconfig[tmp]->passwd = defconfig.passwd;
+      if (!myconfig[tmp]->lockfile) myconfig[tmp]->lockfile = defconfig.lockfile;
+      if (!myconfig[tmp]->savefilefmt) myconfig[tmp]->savefilefmt = defconfig.savefilefmt;
+      if (!myconfig[tmp]->inprogressdir) myconfig[tmp]->inprogressdir = defconfig.inprogressdir;
+
+
   }
 
-  if (myconfig->max == 0 && !set_max) myconfig->max = defconfig.max;
-  if (!myconfig->banner) myconfig->banner = defconfig.banner;
-  if (!myconfig->chroot) myconfig->chroot = defconfig.chroot;
-  if (!myconfig->game_path) myconfig->game_path = defconfig.game_path;
-  if (!myconfig->game_name) myconfig->game_name = defconfig.game_name;
-  if (!myconfig->dglroot) myconfig->dglroot = defconfig.dglroot;
-  if (!myconfig->rcfile) myconfig->rcfile = defconfig.rcfile;
-  if (!myconfig->spool) myconfig->spool = defconfig.spool;
-  if (!myconfig->passwd) myconfig->passwd = defconfig.passwd;
-  if (!myconfig->lockfile) myconfig->lockfile = defconfig.lockfile;
-  if (!myconfig->savefilefmt) myconfig->savefilefmt = defconfig.savefilefmt;
+  if (!globalconfig.chroot) globalconfig.chroot = "/var/lib/dgamelaunch/";
+
+  if (globalconfig.max == 0) globalconfig.max = 64000;
+  if (!globalconfig.dglroot) globalconfig.dglroot = "/dgldir/";
+  if (!globalconfig.banner)  globalconfig.banner = "/dgl-banner";
+
+  if (!globalconfig.shed_user && globalconfig.shed_uid == (uid_t)-1)
+         {
+             struct passwd *pw;
+             if ((pw = getpwnam("games")))
+                 globalconfig.shed_uid = pw->pw_uid;
+             else
+                 globalconfig.shed_uid = 5; /* games uid in debian */
+         }
+
+  if (!globalconfig.shed_group && globalconfig.shed_gid == (gid_t)-1)
+         {
+             struct group *gr;
+             if ((gr = getgrnam("games")))
+                 globalconfig.shed_gid = gr->gr_gid;
+             else
+                 globalconfig.shed_gid = 60; /* games gid in debian */
+         }
+
 }
index 0888fe32d3f0bb5deff0e740b5b008cecbcec0f0..f074c6f5a45533f42367f17c147257ce059c6801 100644 (file)
@@ -70,7 +70,7 @@ usage:
 
   create_config();
 
-  if (chroot (myconfig->chroot))
+  if (chroot (globalconfig.chroot))
   {
     perror("Couldn't change root directory");
     return 1;
@@ -82,7 +82,7 @@ usage:
     return 1;
   }
   
-  games = populate_games (&len);
+  games = populate_games (-1, &len);
 
   if (len == 0)
   {
@@ -95,10 +95,10 @@ usage:
     char* fname = NULL;
     size_t len;
 
-    len = strlen(myconfig->spool) + strlen(games[i]->name) + 2;
+    len = strlen(myconfig[0]->spool) + strlen(games[i]->name) + 2;
     fname = malloc (len + 1);
 
-    snprintf(fname, len, "%s/%s", myconfig->spool, games[i]->name);
+    snprintf(fname, len, "%s/%s", myconfig[0]->spool, games[i]->name);
     
     if ((spool = fopen(fname, "a")) == NULL)
     {
index 431f329256a30665b1b77a35fb65cad37ca3a17f..dc972dee8707e2be34693b0117a66c170c1e0e3f 100644 (file)
@@ -2,6 +2,24 @@
 # are allowed, such as this. Each configuration option will be explained
 # along with its default value. 
 
+
+
+# Global config variables:
+
+
+# Max amount of registered users to allow.
+maxusers = 64000
+
+# Path to a prepared chroot jail.
+chroot_path = "/var/lib/dgamelaunch/"
+
+# From inside the jail, dgamelaunch's working directory for rcfiles/ttyrec/etc
+dglroot = "/dgldir/"
+
+# From inside the jail, location of a banner file that contains no more than
+# 14 lines of 80-column width text. Any more will be truncated.
+banner = "/dgl-banner"
+
 # The following two options are fairly insecure. They will force us to 
 # load the password/group database into memory while still having root
 # privileges. Replace them with shed_uid/shed_gid entries as soon as
@@ -20,29 +38,28 @@ shed_group = "games"
 shed_uid = 5
 shed_gid = 60
 
-# Max amount of registered users to allow.
-maxusers = 64000
 
-# Path to a prepared chroot jail.
-chroot_path = "/var/lib/dgamelaunch/"
+
+# Next, we'll define one game's data:
+
 
 # From inside the jail, the location of the binary to be launched.
-game_path = "/bin/nethack"
-game_name = "NetHack"
+game_path = "/bin/nethackstub"
+game_name = "NetHack stub"
 
-# From inside the jail, dgamelaunch's working directory for rcfiles/ttyrec/etc
-dglroot = "/dgldir/"
+# arguments for when we exec the binary
+game_args = "/bin/nethackstub"
+game_args = "foo"
+game_args = "user:%n"
+game_args = "shed_uid:%u"
+game_args = "bar"
 
 # From inside the jail, where dgamelaunch should put mail - should match up with
 # NetHack settings.
 spooldir = "/var/mail/"
 
-# From inside the jail, location of a banner file that contains no more than
-# 14 lines of 80-column width text. Any more will be truncated.
-banner = "/dgl-banner"
-
 # From inside the jail, the default .nethackrc that is copied for new users.
-rc_template = "/dgl-default-rcfile"
+rc_template = "/dgl-default-rcfile"
 
 # 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
@@ -55,4 +72,35 @@ lockfile = "/dgl-lock"
 # decimal representation of shed_uid, %n is replaced by the player's
 # user name. Before starting the game, this file is copied to its name
 # with ".bak" appended. Set to an empty string to disable this copying.
+
+savefilefmt = "/var/games/nethack/save/%u%n.gz"
+
+# make sure the inprogress dir actually exists. default is "inprogress/"
+# each game you define here must have it's own.
+inprogressdir = "inprogress/"
+
+
+
+#
+# the second game
+#
+#
+game_num = 1
+
+game_path = "/bin/nethack"
+game_name = "NetHack 3.4.3"
+
+game_args = "/bin/nethack"
+game_args = "-u"
+game_args = "%n"
+
+spooldir = "/var/mail/"
+rc_template = "/dgl-default-rcfile"
+# format where player rc files are saved.
+# %r == dglroot
+# %n == user name
+rc_fmt = "%rrcfiles/%n.nethackrc"
+passwd = "/dgl-login"
+lockfile = "/dgl-lock"
 savefilefmt = "/var/games/nethack/save/%u%n.gz"
+inprogressdir = "inprogress/"
index f148c9c1a19093a5f3e4d586b7a48d3e07a89f2d..274d8d0930177646cd6ef22291cd9108bab16f15 100644 (file)
--- a/ttyrec.c
+++ b/ttyrec.c
@@ -82,11 +82,11 @@ struct winsize win;
 int uflg;
 
 int
-ttyrec_main (char *username, char* ttyrec_filename)
+ttyrec_main (int game, char *username, char* ttyrec_filename)
 {
   char dirname[100];
 
-  snprintf (dirname, 100, "%sttyrec/%s/%s", myconfig->dglroot, username,
+  snprintf (dirname, 100, "%sttyrec/%s/%s", globalconfig.dglroot, username,
             ttyrec_filename);
 
   atexit(&remove_ipfile);
@@ -117,11 +117,11 @@ ttyrec_main (char *username, char* ttyrec_filename)
       if (child)
         {
           close (slave);
-          ipfile = gen_inprogress_lock (child, ttyrec_filename);
+          ipfile = gen_inprogress_lock (game, child, ttyrec_filename);
           dooutput ();
         }
       else
-        doshell (username);
+         doshell (game, username);
     }
   doinput ();
 
@@ -261,12 +261,8 @@ dooutput ()
 }
 
 void
-doshell (char *username)
+doshell (int game, char *username)
 {
-  char *argv1 = myconfig->game_path;
-  char *argv2 = "-u";
-  char *myargv[10];
-
   getslave ();
   (void) close (master);
   (void) fclose (fscript);
@@ -275,12 +271,7 @@ doshell (char *username)
   (void) dup2 (slave, 2);
   (void) close (slave);
 
-  myargv[0] = argv1;
-  myargv[1] = argv2;
-  myargv[2] = username;
-  myargv[3] = 0;
-
-  execvp (myconfig->game_path, myargv);
+  execvp (myconfig[game]->game_path, myconfig[game]->bin_args);
 
   fail ();
 }
index 237d115c964b8731720c7d342c1e4b8a1b1a88b8..ff2b9a8dfe88a067b58b38a46d99e5fe04d17757 100644 (file)
--- a/ttyrec.h
+++ b/ttyrec.h
@@ -17,11 +17,11 @@ extern void fixtty (void);
 extern void getslave (void);
 extern void doinput (void);
 extern void dooutput (void);
-extern void doshell (char *);
+extern void doshell (int, char *);
 extern void finish (int);
 extern void remove_ipfile (void);
 
-extern int ttyrec_main(char *username, char *ttyrec_filename);
+extern int ttyrec_main(int, char *username, char *ttyrec_filename);
 
 extern pid_t child; /* nethack process */
 extern int master, slave;