extern int num_games;
int ncnf = 0;
+struct dg_cmdpart *curr_cmdqueue;
+int cmdqueue_num = -1;
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
%%
| 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)
{
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);
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);
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));
| 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)
{
fprintf(stderr, "%s:%d: I refuse to run as uid 0 (root)! Aborting.\n", config, line);
graceful_exit(1);
}
-
+
globalconfig.shed_uid = $3;
break;
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:
}
};
+
+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; }
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";
/* 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;
* 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)
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;
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)
globalconfig.shed_gid = 60; /* games gid in debian */
}
+ for (tmp = 0; tmp < NUM_DGLTIMES; tmp++) {
+ globalconfig.cmdqueue[0] = NULL;
+ }
+
}