Allow more than one game per dgl installation.

git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@345 db0b04b0-f4d1-0310-9a6d-de3e77497b0e
This commit is contained in:
Pasi Kallinen 2007-03-29 20:14:55 +00:00
parent ee906001f2
commit 7ec2c4b9cc
10 changed files with 623 additions and 280 deletions

6
TODO
View File

@ -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

View File

@ -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; }

166
config.y
View File

@ -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();
}
}

View 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;
}

View File

@ -12,6 +12,10 @@
# 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);

View 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;
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->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;
}
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 */
}
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;
}

View 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)
{

View 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/"

View File

@ -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 ();
}

View File

@ -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;