]> skyeroc.xyz Git - dgamelaunch/commitdiff
Admin-defineable menu structures.
authorPasi Kallinen <paxed@alt.org>
Sat, 5 Apr 2008 13:29:19 +0000 (13:29 +0000)
committerPasi Kallinen <paxed@alt.org>
Sat, 5 Apr 2008 13:29:19 +0000 (13:29 +0000)
git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@432 db0b04b0-f4d1-0310-9a6d-de3e77497b0e

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

index 7c77b8191a03276f38250494dd9e56a2732cac2d..d688637f03cdebe4188dc13befd55371115afcec 100644 (file)
--- a/config.l
+++ b/config.l
@@ -56,6 +56,8 @@ WHITE         [\t ]*
 "]"            { return ']'; }
 "{"            { return '{'; }
 "}"            { return '}'; }
+"("            { return '('; }
+")"            { return ')'; }
 "shed_user"    { return TYPE_SUSER; }
 "shed_group"   { return TYPE_SGROUP; }
 "shed_uid"     { return TYPE_SUID; }
@@ -65,6 +67,9 @@ WHITE         [\t ]*
 "allow_new_nicks"      { return TYPE_ALLOW_REGISTRATION; }
 
 
+menu           { return TYPE_DEFINE_MENU; }
+bannerfile     { return TYPE_BANNER_FILE; }
+cursor         { return TYPE_CURSOR; }
 "chroot_path"  { return TYPE_PATH_CHROOT; }
 "game_name"     { return TYPE_NAME_GAME; }
 "short_name"   { return TYPE_GAME_SHORT_NAME; }
@@ -98,6 +103,10 @@ watch_menu  { yylval.i = DGLCMD_WATCH_MENU; return TYPE_DGLCMD0; }
 ask_login      { yylval.i = DGLCMD_LOGIN;      return TYPE_DGLCMD0; }
 ask_register   { yylval.i = DGLCMD_REGISTER;   return TYPE_DGLCMD0; }
 quit           { yylval.i = DGLCMD_QUIT;       return TYPE_DGLCMD0; }
+edit_options   { yylval.i = DGLCMD_EDITOPTIONS; return TYPE_DGLCMD1; }
+play_game      { yylval.i = DGLCMD_PLAYGAME;    return TYPE_DGLCMD1; }
+submenu                { yylval.i = DGLCMD_SUBMENU;     return TYPE_DGLCMD1; }
+return         { yylval.i = DGLCMD_RETURN;      return TYPE_DGLCMD0; }
 DEFINE         { return TYPE_DEFINE_GAME; }
 
 
index 8a63bd329f903eb7f1f0aa7f21bdd4727387f138..3f272fa955a5ff0e0684d0715e55d53d0c5ed51d 100644 (file)
--- a/config.y
+++ b/config.y
@@ -19,7 +19,8 @@ extern unsigned int line, col;
 
 extern int num_games;
 int ncnf = 0;
-struct dg_cmdpart *curr_cmdqueue;
+struct dg_cmdpart *curr_cmdqueue = NULL;
+struct dg_menu *curr_menu = NULL;
 int cmdqueue_num = -1;
 
 static const char* lookup_token (int t);
@@ -39,7 +40,7 @@ static const char* lookup_token (int t);
 %token TYPE_PATH_BANNER TYPE_PATH_CANNED TYPE_PATH_CHROOT
 %token TYPE_PATH_PASSWD TYPE_PATH_LOCKFILE
 %token TYPE_MALSTRING TYPE_PATH_INPROGRESS TYPE_GAME_ARGS TYPE_RC_FMT
-%token TYPE_CMDQUEUE
+%token TYPE_CMDQUEUE TYPE_DEFINE_MENU TYPE_BANNER_FILE TYPE_CURSOR
 %token <s> TYPE_VALUE
 %token <i> TYPE_NUMBER TYPE_CMDQUEUENAME
 %type  <kt> KeyType
@@ -80,6 +81,10 @@ KeyPair: TYPE_CMDQUEUE '[' TYPE_CMDQUEUENAME ']'
            globalconfig.cmdqueue[cmdqueue_num] = curr_cmdqueue;
            curr_cmdqueue = NULL;
        }
+       | definemenu
+       {
+           /* nothing */
+       }
        | definegame
        {
            /* nothing */
@@ -238,6 +243,86 @@ KeyPair: TYPE_CMDQUEUE '[' TYPE_CMDQUEUENAME ']'
   }
 };
 
+
+
+
+menu_definition : TYPE_BANNER_FILE '=' TYPE_VALUE
+         {
+           if (curr_menu->banner_fn) {
+               fprintf(stderr, "%s:%d: banner file already defined.\n", config, line);
+               exit(1);
+           }
+           curr_menu->banner_fn = strdup( $3 );
+         }
+       | TYPE_CURSOR '=' '(' TYPE_NUMBER ',' TYPE_NUMBER ')'
+         {
+           if (curr_menu->cursor_x != -1) {
+               fprintf(stderr, "%s:%d: cursor position already defined.\n", config, line);
+               exit(1);
+           }
+           curr_menu->cursor_x = $4;
+           curr_menu->cursor_y = $6;
+         }
+       | TYPE_CMDQUEUE '[' TYPE_VALUE ']'
+         {
+             struct dg_menuoption *tmp;
+             struct dg_menuoption *tmpmenuopt;
+             if (curr_cmdqueue) {
+                 fprintf(stderr, "%s:%d: command queue already in use?\n", config, line);
+                 exit(1);
+             }
+             tmp = malloc(sizeof(struct dg_menuoption));
+             tmp->keys = strdup( $3 );
+             tmp->cmdqueue = NULL;
+             tmp->next = curr_menu->options;
+            curr_menu->options = tmp;
+         }
+       '=' cmdlist
+         {
+            curr_menu->options->cmdqueue = curr_cmdqueue;
+             curr_cmdqueue = NULL;
+         }
+       ;
+
+
+menu_definitions : menu_definition
+       | menu_definition menu_definitions
+       ;
+
+
+definemenu : TYPE_DEFINE_MENU '[' TYPE_VALUE ']'
+       {
+          struct dg_menulist *tmp_menulist = globalconfig.menulist;
+
+          while (tmp_menulist) {
+              if (!strcmp(tmp_menulist->menuname, $<s>3 )) {
+                   fprintf(stderr, "%s:%d: menu \"%s\" already defined.\n", config, line, $<s>3 );
+                   exit(1);
+              }
+              tmp_menulist = tmp_menulist->next;
+          }
+
+           tmp_menulist = malloc(sizeof(struct dg_menulist));
+           tmp_menulist->menuname = strdup( $<s>3 );
+           tmp_menulist->next = globalconfig.menulist;
+
+          globalconfig.menulist = tmp_menulist;
+
+           tmp_menulist->menu = malloc(sizeof(struct dg_menu));
+          curr_menu = tmp_menulist->menu;
+
+          curr_menu->options = NULL;
+          curr_menu->cursor_x = curr_menu->cursor_y = -1;
+          curr_menu->banner_fn = NULL;
+       }
+       '{' menu_definitions '}'
+       {
+           curr_menu = NULL;
+       }
+       ;
+
+
+
 game_definition : TYPE_CMDQUEUE
        {
            if (myconfig[ncnf]->cmdqueue) {
index d8d7b26d42e3fe814d3082960331bf6158a76abc..9bf13be6d7c0006376d6639563691d007c69db20 100644 (file)
@@ -250,15 +250,49 @@ catch_sighup (int signum)
 
 /* ************************************************************* */
 
+char *
+bannerstrmangle(char *buf, char *fromstr, char *tostr)
+{
+    static char bufnew[81];
+    char *loc;
+    char *b = buf;
+
+    memset (bufnew, 0, 80);
+
+    if (strstr(b, fromstr)) {
+       int i = 0;
+       while ((loc = strstr (b, fromstr)) != NULL) {
+           for (; i < 80; i++) {
+               if (loc != b)
+                   bufnew[i] = *(b++);
+               else {
+                   strlcat (bufnew, tostr, 80);
+                   b += strlen(fromstr);
+                   i += strlen(tostr);
+                   break;
+                }
+
+               if (strlen (b) == 0)
+                   break;
+           }
+       }
+
+       if (*b)
+           strlcat(bufnew, b, 80);
+    } else strncpy(bufnew, buf, 80);
+
+    return bufnew;
+}
+
 void
-loadbanner (int game, struct dg_banner *ban)
+loadbanner (char *fname, struct dg_banner *ban)
 {
   FILE *bannerfile;
   char buf[80];
 
   memset (buf, 0, 80);
 
-  bannerfile = fopen (globalconfig.banner, "r");
+  bannerfile = fopen (fname, "r");
 
   if (!bannerfile)
     {
@@ -268,9 +302,9 @@ loadbanner (int game, struct dg_banner *ban)
       ban->lines[0] =
         strdup ("### dgamelaunch " PACKAGE_VERSION
                 " - network console game launcher");
-      len = strlen(globalconfig.banner) + ARRAY_SIZE("### NOTE: administrator has not installed a  file");
+      len = strlen(fname) + 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", globalconfig.banner);
+      snprintf(ban->lines[1], len, "### NOTE: administrator has not installed a %s file", fname);
       return;
     }
 
@@ -278,70 +312,41 @@ loadbanner (int game, struct dg_banner *ban)
 
   while (fgets (buf, 80, bannerfile) != NULL)
     {
-      char *loc, *b = buf;
       char bufnew[80];
-      
+
       memset (bufnew, 0, 80);
 
       ban->len++;
       ban->lines = realloc (ban->lines, sizeof (char *) * ban->len);
 
-      if (strstr(b, "$VERSION"))
-      {
-       int i = 0; 
-       while ((loc = strstr (b, "$VERSION")) != NULL)
-       {
-          for (; i < 80; i++)
-            {
-              if (loc != b)
-                bufnew[i] = *(b++);
-              else
-                {
-                  strlcat (bufnew, PACKAGE_VERSION, 80);
-                  b += 8;       /* skip the whole $PACKAGE_VERSION string */
-                  i += ARRAY_SIZE (PACKAGE_VERSION) - 1;
-                 break;
-                }
-
-              if (strlen (b) == 0)
-                break;
-           }
-       }
-        
-       if (*b)
-         strlcat(bufnew, b, 80);
-       
-       ban->lines[ban->len - 1] = strdup (bufnew);
+      strncpy(bufnew, buf, 80);
+      strncpy(bufnew, bannerstrmangle(bufnew, "$VERSION", PACKAGE_STRING), 80);
+      if (me && loggedin) {
+         strncpy(bufnew, bannerstrmangle(bufnew, "$USERNAME", me->username), 80);
       }
-      else
-        ban->lines[ban->len - 1] = strdup (buf);
+      ban->lines[ban->len - 1] = strdup(bufnew);
 
       memset (buf, 0, 80);
 
-      if (ban->len == 11)       /* menu itself needs 13 lines, 24 - 11 */
-         break;
+      if (ban->len == 24)
+         break;
   }
 
   fclose (bannerfile);
 }
 
 void
-drawbanner (unsigned int start_line, unsigned int howmany)
+drawbanner (struct dg_banner *ban, unsigned int start_line, unsigned int howmany)
 {
-  static short loaded_banner = 0;
   unsigned int i;
 
-  if (!loaded_banner)
-    {
-       loadbanner (0, &banner);
-      loaded_banner = 1;
-    }
+  if (!ban) return;
 
-  if (howmany > banner.len || howmany == 0)
-    howmany = banner.len;
+  if (howmany > ban->len || howmany == 0)
+    howmany = ban->len;
 
   for (i = 0; i < howmany; i++)
-    mvaddstr (start_line + i, 1, banner.lines[i]);
+    mvaddstr (start_line + i, 1, ban->lines[i]);
 }
 
 void
@@ -369,7 +374,7 @@ inprogressmenu (int gameid)
        }
 
       erase ();
-      drawbanner (1, 1);
+      drawbanner (&banner, 1, 1);
       mvprintw (3, 1,
                 "During playback, hit 'q' to return here, 'm' to send mail (requires login),");
       mvaddstr (4, 1,
@@ -552,7 +557,7 @@ change_email ()
 
   for (;;)
   {
-    drawbanner(1,1);
+      drawbanner(&banner, 1,1);
 
     mvprintw(3, 1, "Your current email is: %s", me->email);
     mvaddstr(4, 1, "Please enter a new one (max 80 chars; blank line aborts)");
@@ -610,7 +615,7 @@ changepw (int dowrite)
       char repeatbuf[21];
       clear ();
 
-      drawbanner (1, 1);
+      drawbanner (&banner, 1, 1);
 
       mvprintw (5, 1,
                 "Please enter a%s password. Remember that this is sent over the net",
@@ -691,7 +696,7 @@ domailuser (char *username)
 
   /* print the enter your message line */
   clear ();
-  drawbanner (1, 1);
+  drawbanner (&banner, 1, 1);
   mvaddstr (5, 1,
             "Enter your message here. It is to be one line only and 80 characters or less.");
   mvaddstr (7, 1, "=> ");
@@ -760,6 +765,7 @@ domailuser (char *username)
   return;
 }
 
+/*
 void
 drawgamemenu(int game)
 {
@@ -767,7 +773,7 @@ drawgamemenu(int game)
 
       clear();
 
-      drawbanner(1,0);
+      drawbanner(&banner, 1,0);
 
       mvprintw(banner.len + 2, 1, "Logged in as: %s", me->username);
 
@@ -789,6 +795,7 @@ drawgamemenu(int game)
   }
 
 }
+*/
 
 void
 drawmenu ()
@@ -797,7 +804,7 @@ drawmenu ()
 
   clear ();
 
-  drawbanner (1, 0);
+  drawbanner (&banner, 1, 0);
 
   if (loggedin)
     {
@@ -908,7 +915,7 @@ loginprompt (int from_ttyplay)
     {
       clear ();
 
-      drawbanner (1, 1);
+      drawbanner (&banner, 1, 1);
 
       if (from_ttyplay == 1)
        mvaddstr (4, 1, "This operation requires you to be logged in.");
@@ -945,7 +952,7 @@ loginprompt (int from_ttyplay)
 
   clear ();
 
-  drawbanner (1, 1);
+  drawbanner (&banner, 1, 1);
 
   mvaddstr (5, 1, "Please enter your password.");
   mvaddstr (7, 1, "=> ");
@@ -992,7 +999,7 @@ newuser ()
   {
       clear ();
 
-      drawbanner (1, 1);
+      drawbanner (&banner, 1, 1);
 
       mvaddstr (5, 1, "Sorry, too many users have registered now.");
       mvaddstr (6, 1, "You might email the server administrator.");
@@ -1014,7 +1021,7 @@ newuser ()
 
       sprintf(buf, "%i character max.", globalconfig.max_newnick_len);
 
-      drawbanner (1, 1);
+      drawbanner (&banner, 1, 1);
 
       mvaddstr (5, 1, "Welcome new user. Please enter a username.");
       mvaddstr (6, 1,
@@ -1082,7 +1089,7 @@ newuser ()
     {
       clear ();
 
-      drawbanner (1, 1);
+      drawbanner (&banner, 1, 1);
 
       mvaddstr (5, 1, "Please enter your email address.");
       mvaddstr (6, 1, "This is sent _nowhere_ but will be used if you ask"
@@ -1655,7 +1662,7 @@ purge_stale_locks (int game)
       if (firsttime)
       {
        clear ();
-       drawbanner (1, 1);
+       drawbanner (&banner, 1, 1);
 
 #define HUP_WAIT 10 /* seconds before HUPPING */
        mvprintw (3, 1,
@@ -1728,6 +1735,7 @@ purge_stale_locks (int game)
   return 1;
 }
 
+/*
 int
 gamemenuloop(int game)
 {
@@ -1767,66 +1775,49 @@ gamemenuloop(int game)
             newuser ();
           break;
         case 'l':
-          if (!loggedin)        /* not visible to loggedin */
+          if (!loggedin)
             loginprompt (0);
         }
     }
   return 0;
 }
+*/
 
-int
-menuloop (void)
+void
+runmenuloop(struct dg_menu *menu)
 {
-  int userchoice = 0;
-  while (1)
-    {
-      drawmenu ();
-      userchoice = getch ();
+    struct dg_banner ban;
+    struct dg_menuoption *tmpopt;
+    int userchoice = 0;
+
+    if (!menu) return;
+
+    ban.lines = NULL;
+    ban.len = 0;
+
+    loadbanner(menu->banner_fn, &ban);
+    while (1) {
+       clear();
+       drawbanner(&ban, 1, 0);
+       mvprintw(menu->cursor_y, menu->cursor_x, "");
+       refresh();
+       userchoice = getch();
+       if (userchoice == ERR) return;
+       tmpopt = menu->options;
+       while (tmpopt) {
+           if (strchr(tmpopt->keys, userchoice)) {
+               dgl_exec_cmdqueue(tmpopt->cmdqueue, selected_game, me);
+               break;
+           } else {
+               tmpopt = tmpopt->next;
+           }
+       }
 
-      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 ERR:
-             case 'q':
-                 graceful_exit(0);
-                 /* break; */
-             case 'r':
-                 if (!loggedin && globalconfig.allow_registration)
-                     newuser ();
-                 break;
-             case 'l':
-                 if (!loggedin)        /* not visible to loggedin */
-                     loginprompt (0);
-             }
-      }
+       if (return_from_submenu) {
+           return_from_submenu = 0;
+           return;
+       }
     }
-  return -1;
 }
 
 
@@ -1890,7 +1881,7 @@ int
 main (int argc, char** argv)
 {
   /* for chroot and program execution */
-    char atrcfilename[81], /**spool,*/ *p, *auth = NULL;
+    char atrcfilename[81], *p, *auth = NULL;
   unsigned int len;
   int c, i;
   int nhext = 0, nhauth = 0;
@@ -2011,6 +2002,8 @@ main (int argc, char** argv)
        }
     }
 
+  loadbanner(globalconfig.banner, &banner);
+
   dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_DGLSTART], 0, NULL);
 
   if (nhext)
@@ -2052,50 +2045,10 @@ main (int argc, char** argv)
     }
   }
 
-  while (1) {
-      initcurses ();
-
-      userchoice = menuloop();
+  initcurses ();
 
-      assert (loggedin);
-
-      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 %s]", me->username, myconfig[userchoice]->shortname);
-
-      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);
-
-      /* fix the variables in the arguments */
-      for (i = 0; i < myconfig[userchoice]->num_args; i++) {
-         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 (userchoice, me->username, gen_ttyrec_filename());
-      check_retard(1); /* reset retard counter */
-
-      setproctitle ("%s", me->username);
+  while (1) {
+      runmenuloop(dgl_find_menu(loggedin ? "mainmenu_user" : "mainmenu_anon"));
   }
 
   /* NOW we can safely kill this */
index 611fc8073f98b168f8595de4f3f80254f0441976..3951bc335ff8cf7f4d65c31bc371b4d083735734 100644 (file)
@@ -52,6 +52,28 @@ struct dg_banner
   unsigned int len;
 };
 
+struct dg_menuoption
+{
+    char *keys;
+    struct dg_cmdpart *cmdqueue;
+    struct dg_menuoption *next;
+};
+
+struct dg_menu
+{
+    char *banner_fn;
+    struct dg_banner banner;
+    int cursor_x, cursor_y;
+    struct dg_menuoption *options;
+};
+
+struct dg_menulist
+{
+    char *menuname;
+    struct dg_menu *menu;
+    struct dg_menulist *next;
+};
+
 struct dg_game
 {
   char *ttyrec_fn;
@@ -93,6 +115,8 @@ struct dg_globalconfig
     int allow_registration; /* allow registering new nicks */
 
     struct dg_cmdpart *cmdqueue[NUM_DGLTIMES];
+
+    struct dg_menulist *menulist;
 };
 
 typedef enum
@@ -110,7 +134,11 @@ typedef enum
     DGLCMD_REGISTER,   /* ask_register */
     DGLCMD_QUIT,       /* quit */
     DGLCMD_CHMAIL,     /* chmail */
-    DGLCMD_CHPASSWD    /* chpasswd */
+    DGLCMD_CHPASSWD,   /* chpasswd */
+    DGLCMD_EDITOPTIONS,        /* edit_options "foo" */
+    DGLCMD_PLAYGAME,   /* play_game "foo" */
+    DGLCMD_SUBMENU,    /* submenu "foo" */
+    DGLCMD_RETURN      /* return */
 } dglcmd_actions;
 
 typedef enum
@@ -137,6 +165,9 @@ extern int loggedin;
 extern int silent;
 extern int set_max;
 
+extern int selected_game;
+extern int return_from_submenu;
+
 extern struct dg_globalconfig globalconfig;
 
 extern int num_games;
@@ -149,17 +180,21 @@ extern void ttyrec_getmaster(void);
 extern char *gen_ttyrec_filename(void);
 extern char *gen_inprogress_lock(int game, pid_t pid, char *ttyrec_filename);
 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 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 struct dg_menu *dgl_find_menu(char *menuname);
+
 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);
 
+void runmenuloop(struct dg_menu *menu);
+
 extern void inprogressmenu(int gameid);
 extern void change_email(void);
 extern int changepw(int dowrite);
@@ -178,7 +213,7 @@ extern void editoptions(int game);
 extern void writefile(int requirenew);
 extern void graceful_exit(int status);
 extern int purge_stale_locks(int game);
-extern int menuloop(void);
+/*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 522e5aab24770a35e819a3b223d5c67080c976dc..0f8f4d5a92d04c2e1b914706f555ed4a72a372d2 100644 (file)
@@ -1,6 +1,7 @@
 /* Functions common to both dgamelaunch itself and dgl-wall. */
 
 #include "dgamelaunch.h"
+#include "ttyrec.h"
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -52,6 +53,9 @@ int loggedin = 0;
 char *chosen_name;
 int num_games = 0;
 
+int selected_game = 0;
+int return_from_submenu = 0;
+
 mode_t default_fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
 
 struct dg_globalconfig globalconfig;
@@ -66,6 +70,19 @@ check_retard(int reset)
     return ((retardation > 20) ? 1 : 0);
 }
 
+
+struct dg_menu *
+dgl_find_menu(char *menuname)
+{
+    struct dg_menulist *tmp = globalconfig.menulist;
+
+    while (tmp) {
+       if (!strcmp(tmp->menuname, menuname)) return tmp->menu;
+       tmp = tmp->next;
+    }
+    return NULL;
+}
+
 /*
  * replace following codes with variables:
  * %u == shed_uid (number)
@@ -136,14 +153,21 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me)
 {
     int i;
     struct dg_cmdpart *tmp = queue;
+    char *p1;
+    char *p2;
 
     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));
+    p1 = (char *)malloc(1024);
+    p2 = (char *)malloc(1024);
+
+    if (!p1 || !p2) return 1;
+
+    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));
 
        switch (tmp->cmd) {
        default: break;
@@ -221,6 +245,7 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me)
            break;
        case DGLCMD_LOGIN:
            if (!loggedin) loginprompt(0);
+           if (loggedin) runmenuloop(dgl_find_menu("mainmenu_user"));
            break;
        case DGLCMD_REGISTER:
            if (!loggedin && globalconfig.allow_registration) newuser();
@@ -228,12 +253,73 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me)
        case DGLCMD_QUIT:
            graceful_exit(0);
            /* break; */
+       case DGLCMD_SUBMENU:
+           if (p1)
+               runmenuloop(dgl_find_menu(p1));
+           break;
+       case DGLCMD_RETURN:
+           return_from_submenu = 1;
+           break;
+       case DGLCMD_EDITOPTIONS:
+           if (loggedin && p1) {
+               int i;
+               for (i = 0; i < num_games; i++) {
+                   if ((!strcmp(myconfig[i]->game_name, p1) || !strcmp(myconfig[i]->shortname, p1)) && myconfig[i]->rcfile) {
+                       editoptions(i);
+                       break;
+                   }
+               }
+           }
+           break;
+       case DGLCMD_PLAYGAME:
+           if (loggedin && me && p1) {
+               int userchoice, i;
+               char *tmpstr;
+               for (userchoice = 0; userchoice < num_games; userchoice++) {
+                   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));
+                           }
+
+                           setproctitle("%s [playing %s]", me->username, myconfig[userchoice]->shortname);
+
+                           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);
+
+                           /* 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]));
+                               free(myconfig[userchoice]->bin_args[i]);
+                               myconfig[userchoice]->bin_args[i] = tmpstr;
+                           }
+
+                           /* launch program */
+                           ttyrec_main (userchoice, me->username, gen_ttyrec_filename());
+                           check_retard(1); /* reset retard counter */
+
+                           setproctitle ("%s", me->username);
+
+                           initcurses ();
+                       }
+                       break;
+                   }
+               }
+           }
+           break;
        }
-       free(p1);
-       free(p2);
-
        tmp = tmp->next;
     }
+
+    free(p1);
+    free(p2);
+
     return 0;
 }
 
@@ -436,6 +522,7 @@ create_config ()
   int tmp;
 
   if (!globalconfig.allow_registration) globalconfig.allow_registration = 1;
+  globalconfig.menulist = NULL;
 
   if (config)
   {
index d20e5ea61cabd0ee41ad73613d6cd4669dd15e1b..62fa1dfd65e96378e873c8ea261b8c66ba2f270a 100644 (file)
@@ -25,10 +25,9 @@ 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.
-# The topmost line will be shown even in submenus.
-# string $VERSION will be replaced with dgl version number.
+# From inside the jail, location of a banner file, the topmost line will be
+# shown in submenus that cannot be defined separately.
+# string $VERSION will be replaced with "dgamelaunch v" + dgl version number.
 banner = "/dgl-banner"
 
 # The following two options are fairly insecure. They will force us to
@@ -82,6 +81,12 @@ lockfile = "/dgl-lock"
 #   ask_login         = do the login prompting, if not logged in
 #   ask_register      = do register new user prompting, if not logged in and
 #                       registration of new nicks is allowed.
+#   edit_options "foo" = edit options for game which has the short name "foo"
+#                        (user must be logged in)
+#   play_game "foo"   = start game which has the short name "foo"
+#                       (user must be logged in)
+#   submenu "foo"     = go to submenu "foo"
+#   return            = return from submenu
 #
 # The commands will be done inside the chroot and with the uid and gid
 # defined above.
@@ -99,6 +104,40 @@ commands[register] = mkdir "%rttyrec/%n"
 
 
 
+# define the main menus. you _must_ define "mainmenu_anon"
+# and "mainmenu_user".
+# $VERSION will be replaced with dgl version string, as
+# in the bannerfile above.
+# first, the menu shown to anonymous user:
+menu["mainmenu_anon"] {
+        bannerfile = "dgl_menu_main_anon.txt"
+        cursor = (5,18)
+        commands["l"] = ask_login
+        commands["r"] = ask_register
+        commands["w"] = watch_menu
+        commands["q"] = quit
+}
+
+# then the menu shown when the user has logged in:
+# $USERNAME in here will be replaced with the user name.
+menu["mainmenu_user"] {
+# contents of this file are written to screen.
+# the file must be inside the chroot.
+        bannerfile = "dgl_menu_main_user.txt"
+# after which cursor is moved to this location
+        cursor = (5,18)
+# keys we accept. format is
+#  commands["string_of_keys"] = <commandlist>
+# for example, you could use commands["qQ"] = quit
+        commands["c"] = chpasswd
+        commands["e"] = chmail
+        commands["w"] = watch_menu
+        commands["o"] = edit_options "NH343"
+        commands["p"] = play_game "NH343"
+        commands["q"] = quit
+}
+
+
 
 
 # Next, we'll define one game's data: