Annotation of dgamelaunch-openbsd/dgl-common.c, Revision 1.1
1.1 ! rubenllo 1: /* Functions common to both dgamelaunch itself and dgl-wall. */
! 2:
! 3: #include "dgamelaunch.h"
! 4: #include "ttyrec.h"
! 5: #include <sys/stat.h>
! 6: #include <sys/types.h>
! 7: #include <sys/wait.h>
! 8: #include <dirent.h>
! 9: #include <stdio.h>
! 10: #include <fcntl.h>
! 11: #include <string.h>
! 12: #include <stdlib.h>
! 13: #include <signal.h>
! 14: #include <unistd.h>
! 15: #include <pwd.h>
! 16: #include <grp.h>
! 17: #include <curses.h>
! 18:
! 19: extern FILE* yyin;
! 20: extern int yyparse ();
! 21: extern void (*g_chain_winch)(int);
! 22:
! 23: /* Data structures */
! 24: struct dg_config **myconfig = NULL;
! 25: struct dg_config defconfig = {
! 26: /* game_path = */ "/bin/nethack",
! 27: /* game_name = */ "NetHack",
! 28: /* game_id = */ NULL,
! 29: /* shortname = */ "NH",
! 30: /* rcfile = */ NULL, /*"/dgl-default-rcfile",*/
! 31: /* ttyrecdir =*/ "%ruserdata/%n/ttyrec/",
! 32: /* spool = */ "/var/mail/",
! 33: /* inprogressdir = */ "%rinprogress/",
! 34: /* num_args = */ 0,
! 35: /* bin_args = */ NULL,
! 36: /* rc_fmt = */ "%rrcfiles/%n.nethackrc", /* [dglroot]rcfiles/[username].nethackrc */
! 37: /* cmdqueue = */ NULL,
! 38: /* postcmdqueue = */ NULL,
! 39: /* max_idle_time = */ 0,
! 40: /* extra_info_file = */ NULL,
! 41: /* encoding */ 0
! 42: };
! 43:
! 44: char* config = NULL;
! 45: int silent = 0;
! 46: int loggedin = 0;
! 47: char *chosen_name;
! 48: int num_games = 0;
! 49:
! 50: int shm_n_games = 200;
! 51:
! 52: int dgl_local_COLS = -1, dgl_local_LINES = -1;
! 53: int curses_resize = 0;
! 54:
! 55: int selected_game = 0;
! 56: int return_from_submenu = 0;
! 57:
! 58: mode_t default_fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
! 59:
! 60: struct dg_globalconfig globalconfig;
! 61:
! 62: void
! 63: sigwinch_func(int sig)
! 64: {
! 65: signal(SIGWINCH, sigwinch_func);
! 66: curses_resize = 1;
! 67: g_chain_winch(sig);
! 68: }
! 69:
! 70: void
! 71: term_resize_check()
! 72: {
! 73: if ((COLS == dgl_local_COLS) && (LINES == dgl_local_LINES) && !curses_resize) return;
! 74:
! 75: signal(SIGWINCH, SIG_IGN);
! 76: endwin();
! 77: initcurses();
! 78: dgl_local_COLS = COLS;
! 79: dgl_local_LINES = LINES;
! 80: curses_resize = 0;
! 81: signal(SIGWINCH, sigwinch_func);
! 82: }
! 83:
! 84: int
! 85: check_retard(int reset)
! 86: {
! 87: static int retardation = 0; /* counter for retarded clients & flooding */
! 88: if (reset) retardation = 0;
! 89: else retardation++;
! 90: return ((retardation > 20) ? 1 : 0);
! 91: }
! 92:
! 93:
! 94: struct dg_menu *
! 95: dgl_find_menu(char *menuname)
! 96: {
! 97: struct dg_menulist *tmp = globalconfig.menulist;
! 98:
! 99: while (tmp) {
! 100: if (!strcmp(tmp->menuname, menuname)) return tmp->menu;
! 101: tmp = tmp->next;
! 102: }
! 103: return NULL;
! 104: }
! 105:
! 106: /*
! 107: * replace following codes with variables:
! 108: * %u == shed_uid (number)
! 109: * %n == user name (string; gotten from 'me', or from 'plrname' if 'me' is null)
! 110: * %r == chroot (string) (aka "dglroot" config var)
! 111: * %g == game name
! 112: * %s == short game name
! 113: * %t == ttyrec file (full path&name) of the last game played.
! 114: */
! 115: char *
! 116: dgl_format_str(int game, struct dg_user *me, char *str, char *plrname)
! 117: {
! 118: static char buf[1024];
! 119: char *f, *p, *end;
! 120: int ispercent = 0;
! 121: int isbackslash = 0;
! 122:
! 123: if (!str) return NULL;
! 124:
! 125: f = str;
! 126: p = buf;
! 127: end = buf + sizeof(buf) - 10;
! 128:
! 129: while (*f) {
! 130: if (ispercent) {
! 131: switch (*f) {
! 132: case 'u':
! 133: snprintf (p, end + 1 - p, "%d", globalconfig.shed_uid);
! 134: while (*p != '\0')
! 135: p++;
! 136: break;
! 137: case 'N':
! 138: if (me) *p = me->username[0];
! 139: else if (plrname) *p = plrname[0];
! 140: else return NULL;
! 141: p++;
! 142: *p = '\0';
! 143: break;
! 144: case 'n':
! 145: if (me) snprintf (p, end + 1 - p, "%s", me->username);
! 146: else if (plrname) snprintf(p, end + 1 - p, "%s", plrname);
! 147: else return NULL;
! 148: while (*p != '\0')
! 149: p++;
! 150: break;
! 151: case 'g':
! 152: if (game >= 0 && game < num_games && myconfig[game]) snprintf (p, end + 1 - p, "%s", myconfig[game]->game_name);
! 153: else return NULL;
! 154: while (*p != '\0')
! 155: p++;
! 156: break;
! 157: case 's':
! 158: if (game >= 0 && game < num_games && myconfig[game]) snprintf (p, end + 1 - p, "%s", myconfig[game]->shortname);
! 159: else return NULL;
! 160: while (*p != '\0')
! 161: p++;
! 162: break;
! 163: case 'r':
! 164: snprintf (p, end + 1 - p, "%s", globalconfig.dglroot);
! 165: while (*p != '\0')
! 166: p++;
! 167: break;
! 168: case 't':
! 169: snprintf (p, end + 1 - p, "%s", last_ttyrec);
! 170: while (*p != '\0')
! 171: p++;
! 172: break;
! 173: default:
! 174: *p = *f;
! 175: if (p < end)
! 176: p++;
! 177: }
! 178: ispercent = 0;
! 179: } else if (isbackslash) {
! 180: switch (*f) {
! 181: case 'a': *p = '\007'; break;
! 182: case 'b': *p = '\010'; break;
! 183: case 't': *p = '\011'; break;
! 184: case 'n': *p = '\012'; break;
! 185: case 'v': *p = '\013'; break;
! 186: case 'f': *p = '\014'; break;
! 187: case 'r': *p = '\015'; break;
! 188: case 'e': *p = '\033'; break;
! 189: default: *p = *f;
! 190: }
! 191: if (p < end)
! 192: p++;
! 193: isbackslash = 0;
! 194: } else {
! 195: if (*f == '%') {
! 196: ispercent = 1;
! 197: } else if (*f == '\\') {
! 198: isbackslash = 1;
! 199: } else {
! 200: *p = *f;
! 201: if (p < end)
! 202: p++;
! 203: }
! 204: }
! 205: f++;
! 206: }
! 207: *p = '\0';
! 208:
! 209: return buf;
! 210: }
! 211:
! 212: int
! 213: dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me)
! 214: {
! 215: int i;
! 216: struct dg_cmdpart *tmp = queue;
! 217: char *p1;
! 218: char *p2;
! 219: int played = 0;
! 220:
! 221: if (!queue) return 1;
! 222:
! 223: p1 = (char *)malloc(1024);
! 224: p2 = (char *)malloc(1024);
! 225:
! 226: if (!p1 || !p2) return 1;
! 227:
! 228: return_from_submenu = 0;
! 229:
! 230: while (tmp && !return_from_submenu) {
! 231: if (tmp->param1) strcpy(p1, dgl_format_str(game, me, tmp->param1, NULL));
! 232: if (tmp->param2) strcpy(p2, dgl_format_str(game, me, tmp->param2, NULL));
! 233:
! 234: switch (tmp->cmd) {
! 235: default: break;
! 236: case DGLCMD_RAWPRINT:
! 237: if (p1) fprintf(stdout, "%s", p1);
! 238: break;
! 239: case DGLCMD_MKDIR:
! 240: if (p1 && (access(p1, F_OK) != 0)) mkdir(p1, 0755);
! 241: break;
! 242: case DGLCMD_UNLINK:
! 243: if (p1 && (access(p1, F_OK) == 0)) unlink(p1);
! 244: break;
! 245: case DGLCMD_CHDIR:
! 246: if (p1) {
! 247: if (chdir(p1) == -1) {
! 248: debug_write("chdir-command failed");
! 249: graceful_exit(123);
! 250: }
! 251: }
! 252: break;
! 253: case DGLCMD_IF_NX_CP:
! 254: if (p1 && p2) {
! 255: FILE *tmpfile;
! 256: tmpfile = fopen(p2, "r");
! 257: if (tmpfile) {
! 258: fclose(tmpfile);
! 259: break;
! 260: }
! 261: }
! 262: /* else fall through to cp */
! 263: case DGLCMD_CP:
! 264: if (p1 && p2) {
! 265: FILE *cannedf, *newfile;
! 266: char buf[1024];
! 267: size_t bytes;
! 268: /* FIXME: use nethack-themed error messages here, as per write_canned_rcfile() */
! 269: if (!(cannedf = fopen (p1, "r"))) break;
! 270: if (!(newfile = fopen (p2, "w"))) break;
! 271: while ((bytes = fread (buf, 1, 1024, cannedf)) > 0) {
! 272: if (fwrite (buf, 1, bytes, newfile) != bytes) {
! 273: if (ferror (newfile)) {
! 274: fclose (cannedf);
! 275: fclose (newfile);
! 276: break;
! 277: }
! 278: }
! 279: }
! 280: fclose (cannedf);
! 281: fclose (newfile);
! 282: chmod (p2, default_fmode);
! 283: }
! 284: break;
! 285: case DGLCMD_EXEC:
! 286: if (p1 && p2) {
! 287: pid_t child;
! 288: char *myargv[3];
! 289:
! 290: myargv[0] = p1;
! 291: myargv[1] = p2;
! 292: myargv[2] = 0;
! 293:
! 294: clear();
! 295: refresh();
! 296: endwin();
! 297: idle_alarm_set_enabled(0);
! 298: child = fork();
! 299: if (child == -1) {
! 300: perror("fork");
! 301: debug_write("exec-command fork failed");
! 302: graceful_exit(114);
! 303: } else if (child == 0) {
! 304: execvp(p1, myargv);
! 305: exit(0);
! 306: } else
! 307: waitpid(child, NULL, 0);
! 308: idle_alarm_set_enabled(1);
! 309: initcurses();
! 310: check_retard(1);
! 311: }
! 312: break;
! 313: case DGLCMD_SETENV:
! 314: if (p1 && p2) mysetenv(p1, p2, 1);
! 315: break;
! 316: case DGLCMD_CHPASSWD:
! 317: if (loggedin) changepw(1);
! 318: break;
! 319: case DGLCMD_CHMAIL:
! 320: if (loggedin) change_email();
! 321: break;
! 322: case DGLCMD_WATCH_MENU:
! 323: inprogressmenu(-1);
! 324: break;
! 325: case DGLCMD_LOGIN:
! 326: if (!loggedin) loginprompt(0);
! 327: if (loggedin) runmenuloop(dgl_find_menu(get_mainmenu_name()));
! 328: break;
! 329: case DGLCMD_REGISTER:
! 330: if (!loggedin && globalconfig.allow_registration) newuser();
! 331: break;
! 332: case DGLCMD_QUIT:
! 333: debug_write("command: quit");
! 334: graceful_exit(0);
! 335: /* break; */
! 336: case DGLCMD_SUBMENU:
! 337: if (p1)
! 338: runmenuloop(dgl_find_menu(p1));
! 339: break;
! 340: case DGLCMD_RETURN:
! 341: return_from_submenu = 1;
! 342: break;
! 343: case DGLCMD_PLAY_IF_EXIST:
! 344: if (!(loggedin && me && p1 && p2)) break;
! 345: {
! 346: FILE *tmpfile;
! 347: tmpfile = fopen(p2, "r");
! 348: if (tmpfile) {
! 349: fclose(tmpfile);
! 350: } else break;
! 351: }
! 352: /* else fall through to playgame */
! 353: case DGLCMD_PLAYGAME:
! 354: if (loggedin && me && p1 && !played) {
! 355: int userchoice, i;
! 356: char *tmpstr;
! 357: for (userchoice = 0; userchoice < num_games; userchoice++) {
! 358: if (!strcmp(myconfig[userchoice]->game_id, p1) || !strcmp(myconfig[userchoice]->game_name, p1) || !strcmp(myconfig[userchoice]->shortname, p1)) {
! 359: if (purge_stale_locks(userchoice)) {
! 360: if (myconfig[userchoice]->rcfile) {
! 361: if (access (dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt, NULL), R_OK) == -1)
! 362: write_canned_rcfile (userchoice, dgl_format_str(userchoice, me, myconfig[userchoice]->rc_fmt, NULL));
! 363: }
! 364:
! 365: setproctitle("%s [playing %s]", me->username, myconfig[userchoice]->shortname);
! 366:
! 367: clear();
! 368: refresh();
! 369: endwin ();
! 370:
! 371: /* first run the generic "do these when a game is started" commands */
! 372: dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_GAMESTART], userchoice, me);
! 373: /* then run the game-specific commands */
! 374: dgl_exec_cmdqueue(myconfig[userchoice]->cmdqueue, userchoice, me);
! 375:
! 376: /* fix the variables in the arguments */
! 377: for (i = 0; i < myconfig[userchoice]->num_args; i++) {
! 378: tmpstr = strdup(dgl_format_str(userchoice, me, myconfig[userchoice]->bin_args[i], NULL));
! 379: free(myconfig[userchoice]->bin_args[i]);
! 380: myconfig[userchoice]->bin_args[i] = tmpstr;
! 381: }
! 382:
! 383: signal(SIGWINCH, SIG_DFL);
! 384: signal(SIGINT, SIG_DFL);
! 385: signal(SIGQUIT, SIG_DFL);
! 386: signal(SIGTERM, SIG_DFL);
! 387: idle_alarm_set_enabled(0);
! 388: /* launch program */
! 389: ttyrec_main (userchoice, me->username,
! 390: dgl_format_str(userchoice, me, myconfig[userchoice]->ttyrecdir, NULL),
! 391: gen_ttyrec_filename());
! 392: idle_alarm_set_enabled(1);
! 393: played = 1;
! 394: /* lastly, run the generic "do these when a game is left" commands */
! 395: signal (SIGHUP, catch_sighup);
! 396: signal (SIGINT, catch_sighup);
! 397: signal (SIGQUIT, catch_sighup);
! 398: signal (SIGTERM, catch_sighup);
! 399: signal(SIGWINCH, sigwinch_func);
! 400:
! 401: dgl_exec_cmdqueue(myconfig[userchoice]->postcmdqueue, userchoice, me);
! 402:
! 403: dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_GAMEEND], userchoice, me);
! 404:
! 405: setproctitle ("%s", me->username);
! 406: initcurses ();
! 407: check_retard(1); /* reset retard counter */
! 408: }
! 409: break;
! 410: }
! 411: }
! 412: }
! 413: break;
! 414: }
! 415: tmp = tmp->next;
! 416: }
! 417:
! 418: free(p1);
! 419: free(p2);
! 420:
! 421: return 0;
! 422: }
! 423:
! 424:
! 425:
! 426: static int
! 427: sort_game_username(const void *g1, const void *g2)
! 428: {
! 429: const struct dg_game *game1 = *(const struct dg_game **)g1;
! 430: const struct dg_game *game2 = *(const struct dg_game **)g2;
! 431: return strcasecmp(game1->name, game2->name);
! 432: }
! 433:
! 434: time_t sort_ctime;
! 435:
! 436: static int
! 437: sort_game_idletime(const void *g1, const void *g2)
! 438: {
! 439: const struct dg_game *game1 = *(const struct dg_game **)g1;
! 440: const struct dg_game *game2 = *(const struct dg_game **)g2;
! 441: if ((sort_ctime - game1->idle_time < 5) && (sort_ctime - game2->idle_time < 5))
! 442: return strcasecmp(game1->name, game2->name);
! 443: if (game2->idle_time != game1->idle_time)
! 444: return difftime(game2->idle_time, game1->idle_time);
! 445: else
! 446: return strcasecmp(game1->name, game2->name);
! 447: }
! 448:
! 449: static int
! 450: sort_game_extrainfo(const void *g1, const void *g2)
! 451: {
! 452: const int extra_weight1 =
! 453: (*(const struct dg_game **) g1)->extra_info_weight;
! 454: const int extra_weight2 =
! 455: (*(const struct dg_game **) g2)->extra_info_weight;
! 456: return dglsign(extra_weight2 - extra_weight1);
! 457: }
! 458:
! 459: static int
! 460: sort_game_gamenum(const void *g1, const void *g2)
! 461: {
! 462: const struct dg_game *game1 = *(const struct dg_game **)g1;
! 463: const struct dg_game *game2 = *(const struct dg_game **)g2;
! 464: if (game2->gamenum != game1->gamenum)
! 465: return dglsign(game2->gamenum - game1->gamenum);
! 466: else
! 467: return strcasecmp(game1->name, game2->name);
! 468: }
! 469:
! 470: static int
! 471: sort_game_windowsize(const void *g1, const void *g2)
! 472: {
! 473: const struct dg_game *game1 = *(const struct dg_game **)g1;
! 474: const struct dg_game *game2 = *(const struct dg_game **)g2;
! 475: if (game2->ws_col != game1->ws_col)
! 476: return dglsign(game1->ws_col - game2->ws_col);
! 477: if (game2->ws_row != game1->ws_row)
! 478: return dglsign(game1->ws_row - game2->ws_row);
! 479: return strcasecmp(game1->name, game2->name);
! 480: }
! 481:
! 482: static int
! 483: sort_game_starttime(const void *g1, const void *g2)
! 484: {
! 485: const struct dg_game *game1 = *(const struct dg_game **)g1;
! 486: const struct dg_game *game2 = *(const struct dg_game **)g2;
! 487: int i = strcmp(game1->date, game2->date);
! 488: if (!i)
! 489: i = strcmp(game1->time, game2->time);
! 490: if (!i)
! 491: return strcasecmp(game1->name, game2->name);
! 492: return i;
! 493: }
! 494:
! 495: static int
! 496: sort_game_watchers(const void *g1, const void *g2)
! 497: {
! 498: const struct dg_game *game1 = *(const struct dg_game **)g1;
! 499: const struct dg_game *game2 = *(const struct dg_game **)g2;
! 500: int i = dglsign(game2->nwatchers - game1->nwatchers);
! 501: if (!i && (sort_ctime - game1->idle_time < 5) && (sort_ctime - game2->idle_time < 5))
! 502: return strcasecmp(game1->name, game2->name);
! 503: if (!i)
! 504: i = dglsign(game2->idle_time - game1->idle_time);
! 505: if (!i)
! 506: return strcasecmp(game1->name, game2->name);
! 507: return i;
! 508: }
! 509:
! 510: struct dg_game **
! 511: sort_games (struct dg_game **games, int len, dg_sortmode sortmode)
! 512: {
! 513: switch (sortmode) {
! 514: case SORTMODE_USERNAME: qsort(games, len, sizeof(struct dg_game *), sort_game_username); break;
! 515: case SORTMODE_GAMENUM: qsort(games, len, sizeof(struct dg_game *), sort_game_gamenum); break;
! 516: case SORTMODE_WINDOWSIZE: qsort(games, len, sizeof(struct dg_game *), sort_game_windowsize); break;
! 517: case SORTMODE_IDLETIME:
! 518: (void) time(&sort_ctime);
! 519: qsort(games, len, sizeof(struct dg_game *), sort_game_idletime);
! 520: break;
! 521: case SORTMODE_DURATION:
! 522: case SORTMODE_STARTTIME: qsort(games, len, sizeof(struct dg_game *), sort_game_starttime); break;
! 523:
! 524: case SORTMODE_EXTRA_INFO:
! 525: qsort(games, len, sizeof(struct dg_game *),
! 526: sort_game_extrainfo);
! 527: break;
! 528:
! 529: #ifdef USE_SHMEM
! 530: case SORTMODE_WATCHERS:
! 531: (void) time(&sort_ctime);
! 532: qsort(games, len, sizeof(struct dg_game *), sort_game_watchers);
! 533: break;
! 534: #endif
! 535: default: ;
! 536: }
! 537: return games;
! 538: }
! 539:
! 540: #ifdef USE_DEBUGFILE
! 541: void
! 542: debug_write(char *str)
! 543: {
! 544: FILE *fp;
! 545: fp = fopen("/dgldebug.log", "a");
! 546: if (!fp) return;
! 547: fprintf(fp, "%s\n", str);
! 548: fclose(fp);
! 549:
! 550: }
! 551: #endif /* USE_DEBUGFILE */
! 552:
! 553: void
! 554: free_populated_games(struct dg_game **games, int len)
! 555: {
! 556: int i;
! 557: if (!games || (len < 1)) return;
! 558:
! 559: for (i = 0; i < len; i++) {
! 560: if (games[i]->ttyrec_fn) free(games[i]->ttyrec_fn);
! 561: if (games[i]->name) free(games[i]->name);
! 562: if (games[i]->date) free(games[i]->date);
! 563: if (games[i]->time) free(games[i]->time);
! 564: if (games[i]->extra_info) free(games[i]->extra_info);
! 565: free(games[i]);
! 566: }
! 567: free(games);
! 568: }
! 569:
! 570: static
! 571: void
! 572: game_read_extra_info(struct dg_game *game, const char *extra_info_file)
! 573: {
! 574: FILE *ei = NULL;
! 575: char *sep = NULL;
! 576: char buffer[120];
! 577: int buflen;
! 578:
! 579: if (game->extra_info) {
! 580: free(game->extra_info);
! 581: game->extra_info = NULL;
! 582: }
! 583: game->extra_info_weight = 0;
! 584:
! 585: if (!extra_info_file)
! 586: return;
! 587:
! 588: if (!(ei = fopen(extra_info_file, "r")))
! 589: return;
! 590: *buffer = 0;
! 591: fgets(buffer, sizeof buffer, ei);
! 592: fclose(ei);
! 593:
! 594: buflen = strlen(buffer);
! 595: if (buflen && buffer[buflen - 1] == '\n')
! 596: buffer[buflen - 1] = 0;
! 597:
! 598: /* The extra info file format is <sort-weight>|<info> */
! 599: sep = strchr(buffer, '|');
! 600: game->extra_info = strdup(sep? sep + 1 : buffer);
! 601:
! 602: if (sep) {
! 603: *sep = 0;
! 604: game->extra_info_weight = atoi(buffer);
! 605: }
! 606: }
! 607:
! 608: struct dg_game **
! 609: populate_games (int xgame, int *l, struct dg_user *me)
! 610: {
! 611: int fd, len, n, pid;
! 612: DIR *pdir;
! 613: struct dirent *pdirent;
! 614: struct stat pstat;
! 615: char fullname[130], ttyrecname[130], pidws[80], playername[DGL_PLAYERNAMELEN+1];
! 616: char *replacestr, *dir, *p;
! 617: struct dg_game **games = NULL;
! 618: struct flock fl = { 0 };
! 619:
! 620: int game;
! 621:
! 622: fl.l_type = F_WRLCK;
! 623: fl.l_whence = SEEK_SET;
! 624: fl.l_start = 0;
! 625: fl.l_len = 0;
! 626:
! 627: len = 0;
! 628:
! 629: for (game = ((xgame < 0) ? 0 : xgame); game < ((xgame <= 0) ? num_games : (xgame+1)); game++) {
! 630:
! 631: dir = strdup(dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL));
! 632: if (!dir) continue;
! 633:
! 634: if (!(pdir = opendir (dir))) {
! 635: debug_write("cannot open inprogress-dir");
! 636: graceful_exit (140);
! 637: }
! 638:
! 639: while ((pdirent = readdir (pdir)))
! 640: {
! 641: char *inprog = NULL;
! 642: if (!strcmp (pdirent->d_name, ".") || !strcmp (pdirent->d_name, ".."))
! 643: continue;
! 644:
! 645: inprog = dgl_format_str(game, me, myconfig[game]->inprogressdir, NULL);
! 646:
! 647: if (!inprog) continue;
! 648:
! 649: snprintf (fullname, 130, "%s%s", inprog, pdirent->d_name);
! 650:
! 651: fd = 0;
! 652: /* O_RDWR here should be O_RDONLY, but we need to test for
! 653: * an exclusive lock */
! 654: fd = open (fullname, O_RDWR);
! 655: if (fd >= 0 && (fcntl (fd, F_SETLK, &fl) == -1))
! 656: {
! 657: char *ttrecdir = NULL;
! 658: strncpy(playername, pdirent->d_name, DGL_PLAYERNAMELEN);
! 659: playername[DGL_PLAYERNAMELEN] = '\0';
! 660: if ((replacestr = strchr(playername, ':')))
! 661: *replacestr = '\0';
! 662:
! 663: replacestr = strchr(pdirent->d_name, ':');
! 664: if (!replacestr) {
! 665: debug_write("inprogress-filename does not have ':'");
! 666: graceful_exit(145);
! 667: }
! 668: replacestr++;
! 669:
! 670: ttrecdir = dgl_format_str(game, me, myconfig[game]->ttyrecdir, playername);
! 671: if (!ttrecdir) continue;
! 672: snprintf (ttyrecname, 130, "%s%s", ttrecdir, replacestr);
! 673:
! 674: if (!stat (ttyrecname, &pstat))
! 675: {
! 676: /* now it's a valid game for sure */
! 677: games = realloc (games, sizeof (struct dg_game) * (len + 1));
! 678: games[len] = malloc (sizeof (struct dg_game));
! 679: games[len]->ttyrec_fn = strdup (ttyrecname);
! 680:
! 681: if (!(replacestr = strchr (pdirent->d_name, ':'))) {
! 682: debug_write("inprogress-filename does not have ':', pt. 2");
! 683: graceful_exit (146);
! 684: } else
! 685: *replacestr = '\0';
! 686:
! 687: games[len]->name = malloc (strlen (pdirent->d_name) + 1);
! 688: strlcpy (games[len]->name, pdirent->d_name,
! 689: strlen (pdirent->d_name) + 1);
! 690:
! 691: games[len]->date = malloc (11);
! 692: strlcpy (games[len]->date, replacestr + 1, 11);
! 693:
! 694: games[len]->time = malloc (9);
! 695: strlcpy (games[len]->time, replacestr + 12, 9);
! 696:
! 697: games[len]->idle_time = pstat.st_mtime;
! 698:
! 699: games[len]->gamenum = game;
! 700: games[len]->is_in_shm = 0;
! 701: games[len]->nwatchers = 0;
! 702: games[len]->shm_idx = -1;
! 703:
! 704: n = read(fd, pidws, sizeof(pidws) - 1);
! 705: if (n > 0)
! 706: {
! 707: pidws[n] = '\0';
! 708: p = pidws;
! 709: }
! 710: else
! 711: p = "";
! 712: pid = atoi(p);
! 713: while (*p != '\0' && *p != '\n')
! 714: p++;
! 715: if (*p != '\0')
! 716: p++;
! 717: games[len]->ws_row = atoi(p);
! 718: while (*p != '\0' && *p != '\n')
! 719: p++;
! 720: if (*p != '\0')
! 721: p++;
! 722: games[len]->ws_col = atoi(p);
! 723:
! 724: if (games[len]->ws_row < 4 || games[len]->ws_col < 4) {
! 725: games[len]->ws_row = 24;
! 726: games[len]->ws_col = 80;
! 727: }
! 728:
! 729: games[len]->extra_info = NULL;
! 730: games[len]->extra_info_weight = 0;
! 731: if (myconfig[game]->extra_info_file) {
! 732: char *extra_info_file =
! 733: dgl_format_str(game, NULL,
! 734: myconfig[game]->extra_info_file,
! 735: games[len]->name);
! 736: game_read_extra_info(games[len], extra_info_file);
! 737: }
! 738:
! 739: len++;
! 740: }
! 741: }
! 742: else
! 743: {
! 744: /* clean dead ones */
! 745: unlink (fullname);
! 746: }
! 747: close (fd);
! 748:
! 749: fl.l_type = F_WRLCK;
! 750: }
! 751:
! 752: closedir (pdir);
! 753: }
! 754: *l = len;
! 755: return games;
! 756: }
! 757:
! 758: void
! 759: graceful_exit (int status)
! 760: {
! 761: /*FILE *fp;
! 762: if (status != 1)
! 763: {
! 764: fp = fopen ("/crash.log", "a");
! 765: char buf[100];
! 766: sprintf (buf, "graceful_exit called with status %d", status);
! 767: fputs (buf, fp);
! 768: }
! 769: This doesn't work. Ever.
! 770: */
! 771: endwin();
! 772: exit (status);
! 773: }
! 774:
! 775: void
! 776: create_config ()
! 777: {
! 778: FILE *config_file = NULL;
! 779: int tmp;
! 780:
! 781: if (!globalconfig.allow_registration) globalconfig.allow_registration = 1;
! 782: globalconfig.menulist = NULL;
! 783: globalconfig.banner_var_list = NULL;
! 784: globalconfig.locale = NULL;
! 785: globalconfig.defterm = NULL;
! 786:
! 787: globalconfig.shed_uid = (uid_t)-1;
! 788: globalconfig.shed_gid = (gid_t)-1;
! 789:
! 790: globalconfig.sortmode = SORTMODE_USERNAME;
! 791: globalconfig.utf8esc = 0;
! 792: globalconfig.flowctrl = -1; /* undefined, don't touch it */
! 793:
! 794: if (config)
! 795: {
! 796: if ((config_file = fopen(config, "r")) != NULL)
! 797: {
! 798: yyin = config_file;
! 799: yyparse();
! 800: fclose(config_file);
! 801: free (config);
! 802: }
! 803: else
! 804: {
! 805: fprintf(stderr, "ERROR: can't find or open %s for reading\n", config);
! 806: debug_write("cannot read config file");
! 807: graceful_exit(104);
! 808: return;
! 809: }
! 810: }
! 811: else
! 812: {
! 813: #ifdef DEFCONFIG
! 814: config = DEFCONFIG;
! 815: if ((config_file = fopen(DEFCONFIG, "r")) != NULL)
! 816: {
! 817: yyin = config_file;
! 818: yyparse();
! 819: fclose(config_file);
! 820: } else {
! 821: fprintf(stderr, "ERROR: can't find or open %s for reading\n", config);
! 822: debug_write("cannot read default config file");
! 823: graceful_exit(105);
! 824: return;
! 825: }
! 826: #else
! 827: num_games = 0;
! 828: myconfig = calloc(1, sizeof(myconfig[0]));
! 829: myconfig[0] = &defconfig;
! 830: return;
! 831: #endif
! 832: }
! 833:
! 834: if (!myconfig) /* a parse error occurred */
! 835: {
! 836: fprintf(stderr, "ERROR: configuration parsing failed\n");
! 837: debug_write("config file parsing failed");
! 838: graceful_exit(113);
! 839: }
! 840:
! 841: if (!globalconfig.chroot) globalconfig.chroot = "/var/lib/dgamelaunch/";
! 842:
! 843: if (globalconfig.max == 0) globalconfig.max = 64000;
! 844: if (globalconfig.max_newnick_len == 0) globalconfig.max_newnick_len = DGL_PLAYERNAMELEN;
! 845: if (!globalconfig.dglroot) globalconfig.dglroot = "/dgldir/";
! 846: if (!globalconfig.banner) globalconfig.banner = "/dgl-banner";
! 847:
! 848: #ifndef USE_SQLITE3
! 849: if (!globalconfig.passwd) globalconfig.passwd = "/dgl-login";
! 850: #else
! 851: if (!globalconfig.passwd) globalconfig.passwd = USE_SQLITE_DB;
! 852: #endif
! 853: if (!globalconfig.lockfile) globalconfig.lockfile = "/dgl-lock";
! 854: if (!globalconfig.shed_user && globalconfig.shed_uid == (uid_t)-1)
! 855: {
! 856: struct passwd *pw;
! 857: if ((pw = getpwnam("games")))
! 858: globalconfig.shed_uid = pw->pw_uid;
! 859: else
! 860: globalconfig.shed_uid = 5; /* games uid in debian */
! 861: }
! 862:
! 863: if (!globalconfig.shed_group && globalconfig.shed_gid == (gid_t)-1)
! 864: {
! 865: struct group *gr;
! 866: if ((gr = getgrnam("games")))
! 867: globalconfig.shed_gid = gr->gr_gid;
! 868: else
! 869: globalconfig.shed_gid = 60; /* games gid in debian */
! 870: }
! 871:
! 872: }
CVSweb