[BACK]Return to dgl-common.c CVS log [TXT][DIR] Up to [contributed] / dgamelaunch-openbsd

Annotation of dgamelaunch-openbsd/dgl-common.c, Revision 1.2

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
1.2     ! rubenllo  849:   if (!globalconfig.passwd) globalconfig.passwd = "/dgldir/dgl-login";
1.1       rubenllo  850: #else
                    851:   if (!globalconfig.passwd) globalconfig.passwd = USE_SQLITE_DB;
                    852: #endif
1.2     ! rubenllo  853:   if (!globalconfig.lockfile) globalconfig.lockfile = "/dgldir/dgl-lock";
1.1       rubenllo  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