Two new things:
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
This commit is contained in:
parent
41d038ef3e
commit
24cb396d16
1
TODO
1
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.
|
||||
|
|
20
config.l
20
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; }
|
||||
|
||||
|
|
307
config.y
307
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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -16,6 +16,23 @@
|
|||
/* 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);
|
||||
|
|
76
dgl-common.c
76
dgl-common.c
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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/"
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue