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

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