]> skyeroc.xyz Git - dgamelaunch/commitdiff
Merge J. Ali Harlow's patch for NhExt support, with a few changes.
authorJilles Tjoelker <jilles@stack.nl>
Wed, 21 Apr 2004 16:22:55 +0000 (16:22 +0000)
committerJilles Tjoelker <jilles@stack.nl>
Wed, 21 Apr 2004 16:22:55 +0000 (16:22 +0000)
Tested a little whether nethack still works.

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

dgamelaunch.8
dgamelaunch.c
dgl-common.c

index 8a35c04e734472ae11353a982c9eeb9a88cb63f7..87fe2a7094c55ad5ee0dc847cb2f4835585cbbb8 100644 (file)
@@ -19,14 +19,20 @@ dgamelaunch \- Network console game launcher
 [
 .B \-p
 ]
+[
+.B \-a
+]
+[
+.B \-e
+]
 .ad
 .hy 14
 .SH DESCRIPTION
 .PP
 .I dgamelaunch
 is a network-based game shell where anyone can sign up for an
-account and start playing any game which suits your fancy - currently, though,
-it only supports NetHack.
+account and start playing any game which suits your fancy - currently
+it supports NetHack and Slash'Em.
 
 The user is presented with a curses-based menu to watch other games, edit the
 options or play the game.
@@ -42,6 +48,22 @@ Specify the location of the configuration file.
 Don't print errors pertaining to the server configuration.
 .TP
 .B
+-a
+Enter user authentication mode.
+.I
+dgamelaunch
+will read user name and password from stdin, check them, check whether the
+user doesn't have a game in progress already, then write the inprogress lock.
+Returns 0 if everything was successful.
+.TP
+.B
+-e
+Start game server to handle incoming NhExt connection.
+.I
+dgamelaunch
+will execute /bin/nethack --proxy after chroot and shedding privs.
+.TP
+.B
 -p
 Ignored; solely for compatibility with
 .B
@@ -86,6 +108,8 @@ M. Drew Streib wrote the original version.
 .PP
 Later, Joshua Kwan, Brett Carrington and Jilles Tjoelker added many new
 features.
+.PP
+NhExt support was written by J. Ali Harlow.
 .SH FILES
 .DT
 .ta \w'dgldir/ttyrec/<login>/*.ttyrec\ \ \ 'u
@@ -122,7 +146,7 @@ dgldir/ttyrec/<login>/*.ttyrec      Recorded games, this may get
 .\".SH ENVIRONMENT
 .SH "SEE ALSO"
 .PP
-nethack(6), telnetd(8), login(1), curses(3), fcntl(2)
+nethack(6), slashem(6), telnetd(8), login(1), curses(3), fcntl(2)
 .SH BUGS
 .PP
 None known.
index e617aef6a2566ec4beee5f42a57119f1cd0ad2fd..767b66bd6a25a2f1541487b3e3e54274dc417f17 100644 (file)
@@ -165,6 +165,24 @@ gen_ttyrec_filename ()
 
 /* ************************************************************* */
 
+char*
+gen_nhext_filename ()
+{
+  time_t rawtime;
+  struct tm *ptm;
+  char *nhext_filename = calloc(100, sizeof(char));
+
+  /* append time to filename */
+  time (&rawtime);
+  ptm = gmtime (&rawtime);
+  snprintf (nhext_filename, 100, "%04i-%02i-%02i.%02i:%02i:%02i.nhext",
+            ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
+            ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
+  return nhext_filename;
+}
+
+/* ************************************************************* */
+
 char*
 gen_inprogress_lock (pid_t pid, char* ttyrec_filename)
 {
@@ -312,7 +330,8 @@ inprogressmenu ()
   int i, menuchoice, len = 20, offset = 0, doresizewin = 0;
   time_t ctime;
   struct dg_game **games;
-  char ttyrecname[130], *replacestr = NULL;
+  char ttyrecname[130], *replacestr = NULL, gametype[10];
+  int is_nhext[14];
   sigset_t oldmask, toblock;
 
   games = populate_games (&len);
@@ -343,9 +362,16 @@ inprogressmenu ()
           if (i + offset >= len)
             break;
 
-          mvprintw (7 + i, 1, "%c) %-15s (%3dx%3d) %s %s (%ldm %lds idle)",
-                    i + 97, games[i + offset]->name,
-                   games[i + offset]->ws_col, games[i + offset]->ws_row,
+         is_nhext[i] = !strcmp (games[i + offset]->ttyrec_fn + strlen (games[i + offset]->ttyrec_fn) - 6, ".nhext");
+
+         if (is_nhext[i])
+           strcpy (gametype, "  NhExt");
+         else
+           snprintf (gametype, sizeof gametype, "%3dx%3d",
+               games[i + offset]->ws_col, games[i + offset]->ws_row);
+
+          mvprintw (7 + i, 1, "%c) %-15s (%s) %s %s (%ldm %lds idle)",
+                    i + 97, games[i + offset]->name, gametype,
                     games[i + offset]->date, games[i + offset]->time,
                     (time (&ctime) - games[i + offset]->idle_time) / 60,
                     (time (&ctime) - games[i + offset]->idle_time) % 60);
@@ -385,6 +411,9 @@ inprogressmenu ()
            }
           if ((menuchoice - 'a') >= 0 && (menuchoice - 'a') < i)
             {
+             if (is_nhext[menuchoice - 97]) /* Cannot watch NhExt game */
+               break;
+
               /* valid choice has been made */
               snprintf (ttyrecname, 130, "%sttyrec/%s", myconfig->dglroot,
                         games[menuchoice - 97 + offset]->ttyrec_fn);
@@ -1561,6 +1590,60 @@ menuloop (void)
     }
 }
 
+int
+authenticate ()
+{
+  int i, len, me_index;
+  char user_buf[22], pw_buf[22];
+  struct dg_game **games;
+
+  /* We use simple password authentication, rather than challenge/response. */
+  printf ("\n");
+  fflush(stdout);
+
+  fgets (user_buf, sizeof(user_buf), stdin);
+  len = strlen (user_buf);
+  if (user_buf[len - 1] == '\n')
+    user_buf[--len] = '\0';
+  else
+    {
+      fprintf (stderr, "Username too long (max 20 chars).\n");
+      return 1;
+    }
+
+  fgets (pw_buf, sizeof(pw_buf), stdin);
+  len = strlen (pw_buf);
+  if (pw_buf[len - 1] == '\n')
+    pw_buf[--len] = '\0';
+  else
+    {
+      fprintf (stderr, "Password too long (max 20 chars).\n");
+      return 1;
+    }
+
+  if ((me_index = userexist (user_buf)) != -1)
+    {
+      me = users[me_index];
+      if (passwordgood (pw_buf))
+        {
+         games = populate_games (&len);
+         for (i = 0; i < len; i++)
+           if (!strcmp (games[i]->name, user_buf))
+             {
+               fprintf (stderr, "Game already in progress.\n");
+               return 1;
+             }
+         win.ws_row = win.ws_col = 0;
+         gen_inprogress_lock (getppid (), gen_nhext_filename ());
+         return 0;
+       }
+    }
+
+  sleep (2);
+  fprintf (stderr, "Login failed.\n");
+  return 1;
+}
+
 int
 main (int argc, char** argv)
 {
@@ -1568,14 +1651,21 @@ main (int argc, char** argv)
   char atrcfilename[81], *spool;
   unsigned int len;
   int c;
+  int nhext = 0, nhauth = 0;
 
-  while ((c = getopt(argc, argv, "qh:pp:f:")) != -1)
+  while ((c = getopt(argc, argv, "qh:pp:f:ae")) != -1)
   {
     switch (c)
     {
       case 'q':
        silent = 1; break;
 
+      case 'a':
+       nhauth = 1; break;
+
+      case 'e':
+       nhext = 1; break;
+
       case 'f':
        if (config)
        {
@@ -1608,37 +1698,54 @@ main (int argc, char** argv)
     }
 
   /* get master tty just before chroot (lives in /dev) */
-  ttyrec_getpty ();
+  if (!nhext && !nhauth)
+    ttyrec_getpty ();
 
-  /* chroot */
-  if (chroot (myconfig->chroot))
+  if (geteuid () != myconfig->shed_uid)
     {
-      perror ("cannot change root directory");
-      graceful_exit (1);
-    }
+      /* chroot */
+      if (chroot (myconfig->chroot))
+       {
+         perror ("cannot change root directory");
+         graceful_exit (1);
+       }
 
-  if (chdir ("/"))
-    {
-      perror ("cannot chdir to root directory");
-      graceful_exit (1);
-    }
+      if (chdir ("/"))
+       {
+         perror ("cannot chdir to root directory");
+         graceful_exit (1);
+       }
 
-  /* shed privs. this is done immediately after chroot. */
-  if (setgroups (1, &myconfig->shed_gid) == -1)
-    {
-      perror ("setgroups");
-      graceful_exit (1);
-    }
+      /* shed privs. this is done immediately after chroot. */
+      if (setgroups (1, &myconfig->shed_gid) == -1)
+       {
+         perror ("setgroups");
+         graceful_exit (1);
+       }
 
-  if (setgid (myconfig->shed_gid) == -1)
-    {
-      perror ("setgid");
-      graceful_exit (1);
+      if (setgid (myconfig->shed_gid) == -1)
+       {
+         perror ("setgid");
+         graceful_exit (1);
+       }
+
+      if (setuid (myconfig->shed_uid) == -1)
+       {
+         perror ("setuid");
+         graceful_exit (1);
+       }
     }
 
-  if (setuid (myconfig->shed_uid) == -1)
+  if (nhext)
     {
-      perror ("setuid");
+      char *myargv[3];
+
+      myargv[0] = myconfig->game_path;
+      myargv[1] = "--proxy";
+      myargv[2] = 0;
+
+      execvp (myconfig->game_path, myargv);
+      perror (myconfig->game_path);
       graceful_exit (1);
     }
 
@@ -1646,6 +1753,9 @@ main (int argc, char** argv)
   if (readfile (0))
     graceful_exit (110);
 
+  if (nhauth)
+    graceful_exit (authenticate ());
+
   initcurses ();
   menuloop();
 
index d49c0397dacaa7ce62decca3fb3140ba00fb0440..727ec1b76f20515dc7a68e0e9d8c7fbf8c0b83fc 100644 (file)
@@ -7,6 +7,7 @@
 #include <fcntl.h>
 #include <string.h>
 #include <stdlib.h>
+#include <signal.h>
 #include <unistd.h>
 #include <pwd.h>
 #include <grp.h>
@@ -43,7 +44,7 @@ char *chosen_name;
 struct dg_game **
 populate_games (int *l)
 {
-  int fd, len, n;
+  int fd, len, n, is_nhext, pid;
   DIR *pdir;
   struct dirent *pdirent;
   struct stat pstat;
@@ -72,22 +73,27 @@ populate_games (int *l)
       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);
 
       fd = 0;
       /* O_RDWR here should be O_RDONLY, but we need to test for
        * an exclusive lock */
       fd = open (fullname, O_RDWR);
-      if ((fd > 0) && fcntl (fd, F_SETLK, &fl) == -1)
+      if (fd >= 0 && (is_nhext || fcntl (fd, F_SETLK, &fl) == -1))
         {
 
           /* stat to check idle status */
-          snprintf (ttyrecname, 130, "%sttyrec/%s", myconfig->dglroot, pdirent->d_name);
-          replacestr = strchr (ttyrecname, ':');
-          if (!replacestr)
-            graceful_exit (145);
-          replacestr[0] = '/';
-          if (!stat (ttyrecname, &pstat))
+         if (!is_nhext)
+           {
+             snprintf (ttyrecname, 130, "%sttyrec/%s", myconfig->dglroot, pdirent->d_name);
+             replacestr = strchr (ttyrecname, ':');
+             if (!replacestr)
+               graceful_exit (145);
+             replacestr[0] = '/';
+           }
+          if (is_nhext || !stat (ttyrecname, &pstat))
             {
               /* now it's a valid game for sure */
               games = realloc (games, sizeof (struct dg_game) * (len + 1));
@@ -119,6 +125,7 @@ populate_games (int *l)
                }
              else
                p = "";
+             pid = atoi(p);
              while (*p != '\0' && *p != '\n')
                p++;
              if (*p != '\0')
@@ -129,13 +136,30 @@ populate_games (int *l)
              if (*p != '\0')
                p++;
              games[len]->ws_col = atoi(p);
-             if (games[len]->ws_row < 4 || games[len]->ws_col < 4)
+             if (is_nhext)
                {
-                 games[len]->ws_row = 24;
-                 games[len]->ws_col = 80;
-               }
-
-              len++;
+                 if (kill (pid, 0) != 0)
+                   {
+                     /* Dead game */
+                     free (games[len]->ttyrec_fn);
+                     free (games[len]->name);
+                     free (games[len]->date);
+                     free (games[len]->time);
+                     free (games[len]);
+                     unlink (fullname);
+                   }
+                 else
+                   len++;
+               }
+             else
+               {
+                 if (games[len]->ws_row < 4 || games[len]->ws_col < 4)
+                 {
+                   games[len]->ws_row = 24;
+                   games[len]->ws_col = 80;
+                 }
+                 len++;
+               }
             }
         }
       else