]> skyeroc.xyz Git - dgamelaunch/commitdiff
Two new things:
authorPasi Kallinen <paxed@alt.org>
Tue, 1 Jan 2008 17:03:05 +0000 (17:03 +0000)
committerPasi Kallinen <paxed@alt.org>
Tue, 1 Jan 2008 17:03:05 +0000 (17:03 +0000)
1) Allow admin to define some commands that are run when something happens.
   format is

commands [ <time> ] = <command> ...

<time> can be one of:
 login     = when user logs in
 dglstart  = when someone telnets in
 register  = when a new user is registered
 gamestart = when a game is started

<command> is:
 mkdir "foo"       = creates a directory "foo"
 chdir "foo"       = changes current work dir to "foo"
 cp "foo" "bar"    = copies file "foo" to "bar"
 unlink "foo"      = deletes file "foo"
 setenv "foo "bar" = sets environment variable "foo" to "bar"

For example

commands[login] = mkdir "foo", unlink "bar", setenv "Z" "foo"

You can also define per-game commands that are executed when
the game is started.

2) Defining game info in the config file has changed slightly.
   Put "DEFINE { ... }" around the game-specific stuff.

See the example config file.

git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@391 db0b04b0-f4d1-0310-9a6d-de3e77497b0e

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

diff --git a/TODO b/TODO
index 34ba5c0db23a3269fd543bb81be7fd5e3fa84b0f..8b54a957518e738953f45d28dc67f63039d7e394 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
+-allow setting the default watch-screen sortmode in config file.
 -allow admin to define series of actions dgl makes when user does
  something. for example, do "mkdir dgldir/rcfiles/$nick" and
  "cp defaultrc dgldir/rcfiles/$nick/" when a new nick is registered.
index c736d1b0a830094a1c9fd95110cd4957bd441a6c..0340e16e689843b720844af89f462b00b9176073 100644 (file)
--- a/config.l
+++ b/config.l
@@ -17,7 +17,7 @@ unsigned int line = 1, col = 0;
 
 NEGNUMBER      -[0-9]+
 NUMBER         [0-9]+
-VALUE          \".*\"
+VALUE          \"[^"]*\"
 MALSTRING      \"[^\"\n]*\n
 WHITE          [\t ]*
 COMMENT                ^#.*
@@ -51,6 +51,11 @@ COMMENT              ^#.*
 {COMMENT}      { }
 
 "="            { return '='; }
+","            { return ','; }
+"["            { return '['; }
+"]"            { return ']'; }
+"{"            { return '{'; }
+"}"            { return '}'; }
 "shed_user"    { return TYPE_SUSER; }
 "shed_group"   { return TYPE_SGROUP; }
 "shed_uid"     { return TYPE_SUID; }
@@ -59,7 +64,6 @@ COMMENT               ^#.*
 "maxnicklen"   { return TYPE_MAXNICKLEN; }
 "allow_new_nicks"      { return TYPE_ALLOW_REGISTRATION; }
 
-"game_num"     { return TYPE_GAMENUM; }
 
 "chroot_path"  { return TYPE_PATH_CHROOT; }
 "game_name"     { return TYPE_NAME_GAME; }
@@ -77,6 +81,18 @@ COMMENT              ^#.*
 "inprogressdir" { return TYPE_PATH_INPROGRESS; }
 "game_args"    { return TYPE_GAME_ARGS; }
 "rc_fmt"       { return TYPE_RC_FMT; }
+commands       { return TYPE_CMDQUEUE; }
+dglstart       { yylval.i = DGLTIME_DGLSTART; return TYPE_CMDQUEUENAME; }
+login          { yylval.i = DGLTIME_LOGIN;    return TYPE_CMDQUEUENAME; }
+register       { yylval.i = DGLTIME_REGISTER; return TYPE_CMDQUEUENAME; }
+game_start     { yylval.i = DGLTIME_GAMESTART; return TYPE_CMDQUEUENAME; }
+cmdmkdir       { yylval.i = DGLCMD_MKDIR;  return TYPE_DGLCMD1; }
+cmdchdir       { yylval.i = DGLCMD_CHDIR;  return TYPE_DGLCMD1; }
+cmdcp          { yylval.i = DGLCMD_CP;     return TYPE_DGLCMD1; }
+cmdunlink      { yylval.i = DGLCMD_UNLINK; return TYPE_DGLCMD1; }
+cmdsetenv      { yylval.i = DGLCMD_SETENV; return TYPE_DGLCMD2; }
+DEFINE         { return TYPE_DEFINE_GAME; }
+
 
 \n             { line++; col = 0; }
 
index 465eb2eaecfd909bb65d41b0dd6d69a695a3455d..4c2fb665db0e63bc37d9f5693d04df85f664ca94 100644 (file)
--- a/config.y
+++ b/config.y
@@ -19,6 +19,8 @@ extern unsigned int line, col;
 
 extern int num_games;
 int ncnf = 0;
+struct dg_cmdpart *curr_cmdqueue;
+int cmdqueue_num = -1;
 
 static const char* lookup_token (int t);
 
@@ -34,12 +36,15 @@ static const char* lookup_token (int t);
 %token TYPE_PATH_CHDIR TYPE_PATH_MKDIR TYPE_GAME_SHORT_NAME
 %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 TYPE_GAMENUM
+%token TYPE_PATH_BANNER TYPE_PATH_CANNED TYPE_PATH_CHROOT
 %token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE TYPE_PATH_SAVEFILEFMT
 %token TYPE_MALSTRING TYPE_PATH_INPROGRESS TYPE_GAME_ARGS TYPE_RC_FMT
+%token TYPE_CMDQUEUE
 %token <s> TYPE_VALUE
-%token <i> TYPE_NUMBER
+%token <i> TYPE_NUMBER TYPE_CMDQUEUENAME
 %type  <kt> KeyType
+%token <i> TYPE_DGLCMD1 TYPE_DGLCMD2
+%token TYPE_DEFINE_GAME
 
 %%
 
@@ -51,26 +56,39 @@ KeyPairs: KeyPairs KeyPair
        | KeyPair
        ;
 
-KeyPair: KeyType '=' TYPE_VALUE {
+KeyPair: TYPE_CMDQUEUE '[' TYPE_CMDQUEUENAME ']'
+       {
+           int qnum = $<i>3;
+
+           if (globalconfig.cmdqueue[qnum]) {
+               fprintf(stderr, "%s:%d: command queue defined twice, bailing out\n",
+                       config, line);
+               exit(1);
+           }
+           cmdqueue_num = qnum;
+       }
+       '=' cmdlist
+       {
+           /*
+           struct dg_cmdpart *tmp = curr_cmdqueue;
+           while (tmp) {
+               fprintf(stderr, "cmd=%i, p1=%s, p2=%s\n", tmp->cmd, tmp->param1, tmp->param2);
+               tmp = tmp->next;
+           }
+           */
+           globalconfig.cmdqueue[cmdqueue_num] = curr_cmdqueue;
+       }
+       | definegame
+       {
+           /* nothing */
+       }
+       | 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)
-  {
-    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;
-  }
+  globalconfig.shed_uid = (uid_t)-1;
+  globalconfig.shed_gid = (gid_t)-1;
 
   switch ($1)
   {
@@ -130,30 +148,7 @@ KeyPair: KeyType '=' TYPE_VALUE {
       globalconfig.chroot = strdup ($3);
       break;
 
-    case TYPE_PATH_GAME:
-      if (myconfig[ncnf]->game_path) free(myconfig[ncnf]->game_path);
-      myconfig[ncnf]->game_path = strdup ($3);
-      break;
-
-    case TYPE_NAME_GAME:
-      if (myconfig[ncnf]->game_name) free (myconfig[ncnf]->game_name);
-      myconfig[ncnf]->game_name = strdup($3);
-      break;
-
-    case TYPE_GAME_SHORT_NAME:
-      if (myconfig[ncnf]->shortname) free (myconfig[ncnf]->shortname);
-      myconfig[ncnf]->shortname = strdup($3);
-      break;
-
-    case TYPE_PATH_CHDIR:
-      if (myconfig[ncnf]->chdir) free(myconfig[ncnf]->chdir);
-      myconfig[ncnf]->chdir = strdup ($3);
-      break;
 
-    case TYPE_PATH_MKDIR:
-      if (myconfig[ncnf]->mkdir) free(myconfig[ncnf]->mkdir);
-      myconfig[ncnf]->mkdir = strdup ($3);
-      break;
 
     case TYPE_PATH_DGLDIR:
       if (globalconfig.dglroot) free(globalconfig.dglroot);
@@ -165,16 +160,6 @@ KeyPair: KeyType '=' TYPE_VALUE {
       globalconfig.banner = strdup($3);
       break;
 
-    case TYPE_PATH_CANNED:
-      if (myconfig[ncnf]->rcfile) free(myconfig[ncnf]->rcfile);
-      myconfig[ncnf]->rcfile = strdup($3);
-      break;
-
-    case TYPE_PATH_SPOOL:
-      if (myconfig[ncnf]->spool) free (myconfig[ncnf]->spool);
-      myconfig[ncnf]->spool = strdup($3);
-      break;
-
     case TYPE_PATH_LOCKFILE:
       if (globalconfig.lockfile) free (globalconfig.lockfile);
       globalconfig.lockfile = strdup($3);
@@ -185,39 +170,6 @@ KeyPair: KeyType '=' TYPE_VALUE {
       globalconfig.passwd = strdup($3);
       break;
 
-    case TYPE_PATH_SAVEFILEFMT:
-      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));
@@ -230,22 +182,8 @@ KeyPair: KeyType '=' TYPE_VALUE {
        | 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)
-  {
-    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)
   {
@@ -260,7 +198,7 @@ KeyPair: KeyType '=' TYPE_VALUE {
         fprintf(stderr, "%s:%d: I refuse to run as uid 0 (root)! Aborting.\n", config, line);
         graceful_exit(1);
       }
-     
+
       globalconfig.shed_uid = $3;
       break;
 
@@ -268,19 +206,8 @@ KeyPair: KeyType '=' TYPE_VALUE {
       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, globalconfig.shed_gid);
-      
-      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;
+      globalconfig.shed_gid = $3;
       break;
 
   case TYPE_ALLOW_REGISTRATION:
@@ -302,13 +229,168 @@ KeyPair: KeyType '=' TYPE_VALUE {
   }
 };
 
+
+game_definition : TYPE_CMDQUEUE
+       {
+           if (myconfig[ncnf]->cmdqueue) {
+               fprintf(stderr, "%s:%d: command queue defined twice, bailing out\n",
+                       config, line);
+               exit(1);
+           }
+       }
+       '=' cmdlist
+       {
+           myconfig[ncnf]->cmdqueue = curr_cmdqueue;
+       }
+       | KeyType '=' TYPE_VALUE
+       {
+           switch ( $1 ) {
+           case TYPE_PATH_CANNED:
+               if (myconfig[ncnf]->rcfile) free(myconfig[ncnf]->rcfile);
+               myconfig[ncnf]->rcfile = strdup($3);
+               break;
+
+           case TYPE_PATH_SPOOL:
+               if (myconfig[ncnf]->spool) free (myconfig[ncnf]->spool);
+               myconfig[ncnf]->spool = strdup($3);
+               break;
+
+           case TYPE_PATH_GAME:
+               if (myconfig[ncnf]->game_path) free(myconfig[ncnf]->game_path);
+               myconfig[ncnf]->game_path = strdup ($3);
+               break;
+
+           case TYPE_NAME_GAME:
+               if (myconfig[ncnf]->game_name) free (myconfig[ncnf]->game_name);
+               myconfig[ncnf]->game_name = strdup($3);
+               break;
+
+           case TYPE_GAME_SHORT_NAME:
+               if (myconfig[ncnf]->shortname) free (myconfig[ncnf]->shortname);
+               myconfig[ncnf]->shortname = strdup($3);
+               break;
+
+           case TYPE_PATH_CHDIR:
+               if (myconfig[ncnf]->chdir) free(myconfig[ncnf]->chdir);
+               myconfig[ncnf]->chdir = strdup ($3);
+               break;
+
+           case TYPE_PATH_MKDIR:
+               if (myconfig[ncnf]->mkdir) free(myconfig[ncnf]->mkdir);
+               myconfig[ncnf]->mkdir = strdup ($3);
+               break;
+
+           case TYPE_PATH_SAVEFILEFMT:
+               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 does not belong into game definition, bailing out\n",
+                       config, line);
+               exit(1);
+           }
+       }
+       ;
+
+game_definitions : game_definitions game_definition
+       | game_definition
+       ;
+
+definegame : TYPE_DEFINE_GAME '{'
+       {
+           if ((ncnf < 0) || (ncnf >= DIFF_GAMES)) {
+               fprintf(stderr, "%s:%d: too many games defined, bailing out\n",
+                       config, line);
+               exit(1);
+           }
+
+           if (!myconfig) {
+               int tmp;
+               myconfig = calloc(DIFF_GAMES, sizeof(myconfig[0]));
+               for (tmp = 0; tmp < DIFF_GAMES; tmp++) {
+                   myconfig[tmp] = calloc(1, sizeof(struct dg_config));
+               }
+           }
+       }
+       game_definitions '}'
+       {
+           ncnf++;
+           num_games = ncnf;
+       }
+       ;
+
+cmdlist : cmdlist ',' dglcmd
+       | dglcmd
+       ;
+
+dglcmd : TYPE_DGLCMD1 TYPE_VALUE
+         {
+             struct dg_cmdpart *tmp = malloc(sizeof(struct dg_cmdpart));
+             if (tmp) {
+                 struct dg_cmdpart *foo = curr_cmdqueue;
+                 if (foo) {
+                     while (foo->next) foo = foo->next;
+                     foo->next = tmp;
+                 } else curr_cmdqueue = tmp;
+                 tmp->next = NULL;
+                 tmp->param1 = strdup( $2 );
+                 tmp->param2 = NULL;
+                 tmp->cmd = $<i>1;
+
+             }
+         }
+       | TYPE_DGLCMD2 TYPE_VALUE TYPE_VALUE
+         {
+             struct dg_cmdpart *tmp = malloc(sizeof(struct dg_cmdpart));
+             if (tmp) {
+                 struct dg_cmdpart *foo = curr_cmdqueue;
+                 if (foo) {
+                     while (foo->next) foo = foo->next;
+                     foo->next = tmp;
+                 } else curr_cmdqueue = tmp;
+                 tmp->next = NULL;
+                 tmp->param1 = strdup( $2 );
+                 tmp->param2 = strdup( $3 );
+                 tmp->cmd = $<i>1;
+             }
+         }
+       ;
+
 KeyType : TYPE_SUSER   { $$ = TYPE_SUSER; }
        | TYPE_SGROUP   { $$ = TYPE_SGROUP; }
        | TYPE_SUID     { $$ = TYPE_SUID; }
        | TYPE_SGID     { $$ = TYPE_SGID; }
        | TYPE_MAX      { $$ = TYPE_MAX; }
        | TYPE_MAXNICKLEN       { $$ = TYPE_MAXNICKLEN; }
-       | TYPE_GAMENUM  { $$ = TYPE_GAMENUM; }
        | TYPE_PATH_CHROOT      { $$ = TYPE_PATH_CHROOT; }
        | TYPE_ALLOW_REGISTRATION       { $$ = TYPE_ALLOW_REGISTRATION; }
        | TYPE_PATH_GAME        { $$ = TYPE_PATH_GAME; }
@@ -340,7 +422,6 @@ const char* lookup_token (int t)
     case TYPE_SGID: return "shed_gid";
     case TYPE_MAX: return "maxusers";
     case TYPE_MAXNICKLEN: return "maxnicklen";
-    case TYPE_GAMENUM: return "game_num";
     case TYPE_PATH_CHROOT: return "chroot_path";
     case TYPE_PATH_CHDIR: return "chdir";
     case TYPE_PATH_MKDIR: return "mkdir";
index 30ec34ec5f29663c9dd217fa8f2b88d80bd9c69e..d1684af61d0c3c8efa13ec5a3c15e25fba84cd44 100644 (file)
@@ -884,6 +884,7 @@ autologin (char* user, char *pass)
       if (passwordgood(pass)) {
          loggedin = 1;
          setproctitle ("%s", me->username);
+         dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_LOGIN], 0, me);
       }
   }
 }
@@ -949,6 +950,7 @@ loginprompt (int from_ttyplay)
     {
       loggedin = 1;
       setproctitle ("%s", me->username);
+      dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_LOGIN], 0, me);
     }
   else 
   {
@@ -1109,11 +1111,16 @@ newuser ()
 
   setproctitle ("%s", me->username);
 
+  dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_REGISTER], 0, me);
+
   /* create their ttyrec dir */
+  /*
   snprintf (dirname, 100, "%sttyrec/%s", globalconfig.dglroot, me->username);
 
   if (access (dirname, F_OK) != 0)
     mkdir (dirname, 0755);
+  */
+
   writefile (1);
 }
 
@@ -2051,6 +2058,8 @@ main (int argc, char** argv)
        }
     }
 
+  dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_DGLSTART], 0, NULL);
+
   if (nhext)
     {
       char *myargv[3];
@@ -2116,6 +2125,11 @@ main (int argc, char** argv)
   endwin ();
   signal(SIGWINCH, SIG_DFL);
 
+  /* first run the generic "do these when a game is started" commands */
+  dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_GAMESTART], userchoice, me);
+  /* then run the game-specific commands */
+  dgl_exec_cmdqueue(myconfig[userchoice]->cmdqueue, userchoice, me);
+
   if (!backup_savefile (userchoice))
     graceful_exit (5);
 
@@ -2183,6 +2197,8 @@ main (int argc, char** argv)
   if (me)
     free (me);
 
+  /* FIXME: free data in globalconfig */
+
   graceful_exit (1);
 
   return 1;
index 68afceb42bbe4acd66753cee5e5b78283dd71c08..00b646c55167c7ff4021f3062393079ad8ef2535 100644 (file)
 /* max # of different games playable from within this dgl */
 #define DIFF_GAMES 4
 
+typedef enum
+{
+    DGLTIME_DGLSTART = 0,      /* when someone telnets in */
+    DGLTIME_LOGIN,             /* right after user login */
+    DGLTIME_REGISTER,          /* right after new nick is registered */
+    DGLTIME_GAMESTART,         /* right before a game is started */
+    NUM_DGLTIMES
+} dglcmd_times;
+
+struct dg_cmdpart
+{
+    dglcmd_times cmd;
+    char *param1;
+    char *param2;
+    struct dg_cmdpart *next;
+};
+
 struct dg_user
 {
 #ifdef USE_SQLITE3
@@ -59,6 +76,7 @@ struct dg_config
     int num_args; /* # of bin_args */
     char **bin_args; /* args for game binary */
     char *rc_fmt;
+    struct dg_cmdpart *cmdqueue;
 };
 
 struct dg_globalconfig
@@ -75,8 +93,19 @@ struct dg_globalconfig
     char* passwd;
     char* lockfile;
     int allow_registration; /* allow registering new nicks */
+
+    struct dg_cmdpart *cmdqueue[NUM_DGLTIMES];
 };
 
+typedef enum
+{
+    DGLCMD_NONE = 0,
+    DGLCMD_MKDIR,      /* mkdir foo */
+    DGLCMD_CHDIR,      /* chdir foo */
+    DGLCMD_CP,         /* cp foo bar */
+    DGLCMD_UNLINK,     /* unlink foo */
+    DGLCMD_SETENV      /* setenv foo bar */
+} dglcmd_actions;
 
 typedef enum
 {
@@ -115,6 +144,9 @@ extern void catch_sighup(int signum);
 extern void loadbanner(int game, struct dg_banner *ban);
 extern void drawbanner(unsigned int start_line, unsigned int howmany);
 extern char *dgl_format_str(int game, struct dg_user *me, char *str);
+
+extern int dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me);
+
 extern struct dg_game **populate_games(int game, int *l);
 
 extern struct dg_game **sort_games(struct dg_game **games, int len, dg_sortmode sortmode);
index f410df840a66279815753512f8fa60286ab3efe5..3591f7e78bd2baf06c8d346e7c0171495471317e 100644 (file)
@@ -39,7 +39,8 @@ struct dg_config defconfig = {
   /* inprogressdir = */ "inprogress/",
   /* num_args = */ 0,
   /* bin_args = */ NULL,
-  /* rc_fmt = */ "%rrcfiles/%n.nethackrc" /* [dglroot]rcfiles/[username].nethackrc */
+  /* rc_fmt = */ "%rrcfiles/%n.nethackrc", /* [dglroot]rcfiles/[username].nethackrc */
+  /* cmdqueue = */ NULL
 };
 
 char* config = NULL;
@@ -55,7 +56,8 @@ struct dg_globalconfig globalconfig;
  * replace following codes with variables:
  * %u == shed_uid (number)
  * %n == user name (string)
- * %r == chroot (string)
+ * %r == chroot (string)  (aka "dglroot" config var)
+ * %g == game name
  */
 char *
 dgl_format_str(int game, struct dg_user *me, char *str)
@@ -79,7 +81,12 @@ dgl_format_str(int game, struct dg_user *me, char *str)
                    p++;
                break;
            case 'n':
-               snprintf (p, end + 1 - p, "%s", me->username);
+               if (me) snprintf (p, end + 1 - p, "%s", me->username);
+               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);
                while (*p != '\0')
                    p++;
                break;
@@ -110,6 +117,65 @@ dgl_format_str(int game, struct dg_user *me, char *str)
     return buf;
 }
 
+int
+dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me)
+{
+    int i;
+    struct dg_cmdpart *tmp = queue;
+
+    if (!queue) return 1;
+
+    while (tmp) {
+       char *p1 = NULL; /* FIXME: should probably use fixed-size buffers instead of doing strdup() every time */
+       char *p2 = NULL;
+       if (tmp->param1) p1 = strdup(dgl_format_str(game, me, tmp->param1));
+       if (tmp->param2) p2 = strdup(dgl_format_str(game, me, tmp->param2));
+
+       switch (tmp->cmd) {
+       default: break;
+       case DGLCMD_MKDIR:
+           if (p1 && (access(p1, F_OK) != 0)) mkdir(p1, 0755);
+           break;
+       case DGLCMD_UNLINK:
+           if (p1 && (access(p1, F_OK) != 0)) unlink(p1);
+           break;
+       case DGLCMD_CHDIR:
+           if (p1) chdir(p1);
+           break;
+       case DGLCMD_CP:
+           if (p1 && p2) {
+               FILE *cannedf, *newfile;
+               char buf[1024];
+               size_t bytes;
+               /* FIXME: use nethack-themed error messages here, as per write_canned_rcfile() */
+               if (!(newfile = fopen (p2, "w"))) return 1;
+               if (!(cannedf = fopen (p1, "r"))) return 1;
+               while ((bytes = fread (buf, 1, 1024, cannedf)) > 0) {
+                   if (fwrite (buf, 1, bytes, newfile) != bytes) {
+                       if (ferror (newfile)) {
+                           fclose (cannedf);
+                           fclose (newfile);
+                           return 1;
+                       }
+                   }
+               }
+               fclose (cannedf);
+               fclose (newfile);
+           }
+           break;
+       case DGLCMD_SETENV:
+           if (p1 && p2) mysetenv(p1, p2, 1);
+           break;
+       }
+       free(p1);
+       free(p2);
+
+       tmp = tmp->next;
+    }
+    return 0;
+}
+
+
 
 static int
 sort_game_username(const void *g1, const void *g2)
@@ -397,4 +463,8 @@ create_config ()
                  globalconfig.shed_gid = 60; /* games gid in debian */
          }
 
+  for (tmp = 0; tmp < NUM_DGLTIMES; tmp++) {
+         globalconfig.cmdqueue[0] = NULL;
+  }
+
 }
index 2925fef06416aec652f476946e38ac0726644e9c..6d179b2d29ac697b300ffaa2a00c8207ce1e2907 100644 (file)
@@ -54,9 +54,36 @@ passwd = "/dgl-login"
 lockfile = "/dgl-lock"
 
 
+#
+# define some commands that are run when something happens. format is
+# commands [ <time> ] = <command> ...
+#
+# <time> can be one of:
+#   login     = when user logs in
+#   dglstart  = when someone telnets in
+#   register  = when a new user is registered
+#   gamestart = when a game is started
+#
+# <command> is:
+#   mkdir "foo"       = creates a directory "foo"
+#   chdir "foo"       = changes current work dir to "foo"
+#   cp "foo" "bar"    = copies file "foo" to "bar"
+#   unlink "foo"      = deletes file "foo"
+#   setenv "foo "bar" = sets environment variable "foo" to "bar"
+#
+# eg. commands[login] = mkdir "foo", unlink "bar", setenv "Z" "foo"
+#
+
+# create the user's ttyrec dir when they register
+commands[register] = cmdmkdir "%rttyrec/%n"
+
+
+
+
 
 # Next, we'll define one game's data:
 
+DEFINE {
 
 # From inside the jail, the location of the binary to be launched.
 game_path = "/bin/nethackstub"
@@ -93,13 +120,19 @@ savefilefmt = "/var/games/nethack/save/%u%n.gz"
 # each game you define here must have it's own.
 inprogressdir = "inprogress-nethackstub/"
 
+# We can also define per-game commands, that are executed
+# when teh game starts:
+# commands = chdir "/dgldir", mkdir "foo_%u_%g"
+
+}
 
 
 #
 # the second game
 #
 #
-game_num = 1
+
+DEFINE {
 
 game_path = "/bin/nethack"
 game_name = "NetHack 3.4.3"
@@ -118,13 +151,15 @@ rc_fmt = "%rrcfiles/%n.nethackrc"
 savefilefmt = "/var/games/nethack/save/%u%n.gz"
 inprogressdir = "inprogress-nethack/"
 
+}
 
 #
 # third game
 #
 #
 
-game_num = 2
+DEFINE {
+
 game_path = "/bin/crawlss017"
 game_name = "Crawl Stone Soup 0.1.7"
 short_name = "Cr017"
@@ -148,12 +183,15 @@ rc_template = "/dgl-default-rcfile.crawl"
 rc_fmt = "%rrcfiles/%n.crawlrc"
 inprogressdir = "inprogress-crawlss017/"
 
+}
 
 #
 # fourth game
 #
 #
-game_num = 3
+
+DEFINE {
+
 game_path = "/bin/crawlss020"
 game_name = "Crawl Stone Soup 0.2.0"
 short_name = "Cr020"
@@ -177,4 +215,4 @@ rc_template = "/dgl-default-rcfile.crawl"
 rc_fmt = "/crawlss020/plr/%n/%n.crawlrc"
 inprogressdir = "inprogress-crawlss020/"
 
-
+}