1*2c0ecb1aSdholland /* $NetBSD: hack.main.c,v 1.17 2011/08/06 20:42:43 dholland Exp $ */
23ea4a95cSchristos
302ded532Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft */
6302ded532Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*2c0ecb1aSdholland __RCSID("$NetBSD: hack.main.c,v 1.17 2011/08/06 20:42:43 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
6961f28255Scgd #include <signal.h>
703ea4a95cSchristos #include <stdlib.h>
713ea4a95cSchristos #include <unistd.h>
723ea4a95cSchristos #include <fcntl.h>
7361f28255Scgd #include "hack.h"
743ea4a95cSchristos #include "extern.h"
7561f28255Scgd
7661f28255Scgd #ifdef QUEST
7761f28255Scgd #define gamename "quest"
7861f28255Scgd #else
7961f28255Scgd #define gamename "hack"
8061f28255Scgd #endif
8161f28255Scgd
82cb5fd834Sjsm int (*afternmv)(void);
83cb5fd834Sjsm int (*occupation)(void);
84ab8b6343Sjsm const char *occtxt; /* defined when occupation != NULL */
8561f28255Scgd
8661f28255Scgd int hackpid; /* current pid */
8761f28255Scgd int locknum; /* max num of players */
8861f28255Scgd #ifdef DEF_PAGER
89ab8b6343Sjsm const char *catmore; /* default pager */
9061f28255Scgd #endif
9161f28255Scgd char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */
9261f28255Scgd char *hname; /* name of the game (argv[0] of call) */
939b92b189Sdholland
949b92b189Sdholland static char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */
9561f28255Scgd
96cb5fd834Sjsm int main(int, char *[]);
97cb5fd834Sjsm static void chdirx(const char *, boolean);
9861f28255Scgd
993ea4a95cSchristos int
main(int argc,char * argv[])1001fa8a9a6Sdholland main(int argc, char *argv[])
10161f28255Scgd {
1023ea4a95cSchristos int fd;
10361f28255Scgd #ifdef CHDIR
1043ea4a95cSchristos char *dir;
10561f28255Scgd #endif
10661f28255Scgd
107ab8b6343Sjsm /* Check for dirty tricks with closed fds 0, 1, 2 */
108ab8b6343Sjsm fd = open("/dev/null", O_RDONLY);
109ab8b6343Sjsm if (fd < 3)
110ab8b6343Sjsm exit(1);
111ab8b6343Sjsm close(fd);
112ab8b6343Sjsm
11361f28255Scgd hname = argv[0];
11461f28255Scgd hackpid = getpid();
11561f28255Scgd
11661f28255Scgd #ifdef CHDIR /* otherwise no chdir() */
11761f28255Scgd /*
11861f28255Scgd * See if we must change directory to the playground.
11961f28255Scgd * (Perhaps hack runs suid and playground is inaccessible
12061f28255Scgd * for the player.)
12161f28255Scgd * The environment variable HACKDIR is overridden by a
12261f28255Scgd * -d command line option (must be the first option given)
12361f28255Scgd */
12461f28255Scgd
12561f28255Scgd dir = getenv("HACKDIR");
12661f28255Scgd if (argc > 1 && !strncmp(argv[1], "-d", 2)) {
12761f28255Scgd argc--;
12861f28255Scgd argv++;
12961f28255Scgd dir = argv[0] + 2;
1303ea4a95cSchristos if (*dir == '=' || *dir == ':')
1313ea4a95cSchristos dir++;
13261f28255Scgd if (!*dir && argc > 1) {
13361f28255Scgd argc--;
13461f28255Scgd argv++;
13561f28255Scgd dir = argv[0];
13661f28255Scgd }
13761f28255Scgd if (!*dir)
13861f28255Scgd error("Flag -d must be followed by a directory name.");
13961f28255Scgd }
14061f28255Scgd #endif
14161f28255Scgd
14261f28255Scgd /*
14361f28255Scgd * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
14461f28255Scgd * 2. Use $USER or $LOGNAME (if 1. fails)
14561f28255Scgd * 3. Use getlogin() (if 2. fails)
14661f28255Scgd * The resulting name is overridden by command line options.
14761f28255Scgd * If everything fails, or if the resulting name is some generic
14861f28255Scgd * account like "games", "play", "player", "hack" then eventually
14961f28255Scgd * we'll ask him.
15061f28255Scgd * Note that we trust him here; it is possible to play under
15161f28255Scgd * somebody else's name.
15261f28255Scgd */
1533ea4a95cSchristos {
1543ea4a95cSchristos char *s;
15561f28255Scgd
15661f28255Scgd initoptions();
15761f28255Scgd if (!*plname && (s = getenv("USER")))
15861f28255Scgd (void) strncpy(plname, s, sizeof(plname) - 1);
15961f28255Scgd if (!*plname && (s = getenv("LOGNAME")))
16061f28255Scgd (void) strncpy(plname, s, sizeof(plname) - 1);
16161f28255Scgd if (!*plname && (s = getlogin()))
16261f28255Scgd (void) strncpy(plname, s, sizeof(plname) - 1);
16361f28255Scgd }
16461f28255Scgd
16561f28255Scgd /*
16661f28255Scgd * Now we know the directory containing 'record' and
16761f28255Scgd * may do a prscore().
16861f28255Scgd */
16961f28255Scgd if (argc > 1 && !strncmp(argv[1], "-s", 2)) {
17061f28255Scgd #ifdef CHDIR
17161f28255Scgd chdirx(dir, 0);
17261f28255Scgd #endif
17361f28255Scgd prscore(argc, argv);
17461f28255Scgd exit(0);
17561f28255Scgd }
17661f28255Scgd /*
17761f28255Scgd * It seems he really wants to play.
17861f28255Scgd * Remember tty modes, to be restored on exit.
17961f28255Scgd */
18061f28255Scgd gettty();
18161f28255Scgd setbuf(stdout, obuf);
18261f28255Scgd setrandom();
18361f28255Scgd startup();
18461f28255Scgd cls();
18561f28255Scgd u.uhp = 1; /* prevent RIP on early quits */
18661f28255Scgd u.ux = FAR; /* prevent nscr() */
18798eb8895Sroy (void) signal(SIGHUP, hang_up);
18861f28255Scgd
18961f28255Scgd /*
19061f28255Scgd * Find the creation date of this game,
19161f28255Scgd * so as to avoid restoring outdated savefiles.
19261f28255Scgd */
19361f28255Scgd gethdate(hname);
19461f28255Scgd
19561f28255Scgd /*
19661f28255Scgd * We cannot do chdir earlier, otherwise gethdate will fail.
19761f28255Scgd */
19861f28255Scgd #ifdef CHDIR
19961f28255Scgd chdirx(dir, 1);
20061f28255Scgd #endif
20161f28255Scgd
20261f28255Scgd /*
20361f28255Scgd * Process options.
20461f28255Scgd */
20561f28255Scgd while (argc > 1 && argv[1][0] == '-') {
20661f28255Scgd argv++;
20761f28255Scgd argc--;
20861f28255Scgd switch (argv[0][1]) {
20961f28255Scgd #ifdef WIZARD
21061f28255Scgd case 'D':
21161f28255Scgd /* if(!strcmp(getlogin(), WIZARD)) */
21261f28255Scgd wizard = TRUE;
2133ea4a95cSchristos /*
2143ea4a95cSchristos * else printf("Sorry.\n");
2153ea4a95cSchristos */
21661f28255Scgd break;
21761f28255Scgd #endif
21861f28255Scgd #ifdef NEWS
21961f28255Scgd case 'n':
22061f28255Scgd flags.nonews = TRUE;
22161f28255Scgd break;
22261f28255Scgd #endif
22361f28255Scgd case 'u':
22461f28255Scgd if (argv[0][2])
22561f28255Scgd (void) strncpy(plname, argv[0] + 2, sizeof(plname) - 1);
22661f28255Scgd else if (argc > 1) {
22761f28255Scgd argc--;
22861f28255Scgd argv++;
22961f28255Scgd (void) strncpy(plname, argv[0], sizeof(plname) - 1);
23061f28255Scgd } else
23161f28255Scgd printf("Player name expected after -u\n");
23261f28255Scgd break;
23361f28255Scgd default:
23461f28255Scgd /* allow -T for Tourist, etc. */
23561f28255Scgd (void) strncpy(pl_character, argv[0] + 1,
23661f28255Scgd sizeof(pl_character) - 1);
23761f28255Scgd
23861f28255Scgd /* printf("Unknown option: %s\n", *argv); */
23961f28255Scgd }
24061f28255Scgd }
24161f28255Scgd
24261f28255Scgd if (argc > 1)
24361f28255Scgd locknum = atoi(argv[1]);
24461f28255Scgd #ifdef MAX_NR_OF_PLAYERS
24561f28255Scgd if (!locknum || locknum > MAX_NR_OF_PLAYERS)
24661f28255Scgd locknum = MAX_NR_OF_PLAYERS;
24761f28255Scgd #endif
24861f28255Scgd #ifdef DEF_PAGER
249f48d30b9Skleink if (((catmore = getenv("HACKPAGER")) == NULL &&
250f48d30b9Skleink (catmore = getenv("PAGER")) == NULL) ||
251f48d30b9Skleink catmore[0] == '\0')
25261f28255Scgd catmore = DEF_PAGER;
25361f28255Scgd #endif
25461f28255Scgd #ifdef MAIL
25561f28255Scgd getmailstatus();
25661f28255Scgd #endif
25761f28255Scgd #ifdef WIZARD
2583ea4a95cSchristos if (wizard)
2593ea4a95cSchristos (void) strcpy(plname, "wizard");
2603ea4a95cSchristos else
26161f28255Scgd #endif
26261f28255Scgd if (!*plname || !strncmp(plname, "player", 4)
26361f28255Scgd || !strncmp(plname, "games", 4))
26461f28255Scgd askname();
26561f28255Scgd plnamesuffix(); /* strip suffix from name; calls askname() */
26661f28255Scgd /* again if suffix was whole name */
26761f28255Scgd /* accepts any suffix */
26861f28255Scgd #ifdef WIZARD
26961f28255Scgd if (!wizard) {
27061f28255Scgd #endif
27161f28255Scgd /*
27261f28255Scgd * check for multiple games under the same name
27361f28255Scgd * (if !locknum) or check max nr of players (otherwise)
27461f28255Scgd */
27561f28255Scgd (void) signal(SIGQUIT, SIG_IGN);
27661f28255Scgd (void) signal(SIGINT, SIG_IGN);
27761f28255Scgd if (!locknum)
27861f28255Scgd (void) strcpy(lock, plname);
27961f28255Scgd getlock(); /* sets lock if locknum != 0 */
28061f28255Scgd #ifdef WIZARD
28161f28255Scgd } else {
2823ea4a95cSchristos char *sfoo;
28361f28255Scgd (void) strcpy(lock, plname);
2843ea4a95cSchristos if ((sfoo = getenv("MAGIC")) != NULL)
28561f28255Scgd while (*sfoo) {
28661f28255Scgd switch (*sfoo++) {
2873ea4a95cSchristos case 'n':
2883ea4a95cSchristos (void) srandom(*sfoo++);
28961f28255Scgd break;
29061f28255Scgd }
29161f28255Scgd }
2923ea4a95cSchristos if ((sfoo = getenv("GENOCIDED")) != NULL) {
29361f28255Scgd if (*sfoo == '!') {
294ab8b6343Sjsm const struct permonst *pm = mons;
2953ea4a95cSchristos char *gp = genocided;
29661f28255Scgd
29761f28255Scgd while (pm < mons + CMNUM + 2) {
2983ea4a95cSchristos if (!strchr(sfoo, pm->mlet))
29961f28255Scgd *gp++ = pm->mlet;
30061f28255Scgd pm++;
30161f28255Scgd }
30261f28255Scgd *gp = 0;
30361f28255Scgd } else
304165c915bSdholland (void) strlcpy(genocided, sfoo,
305165c915bSdholland sizeof(genocided));
30661f28255Scgd (void) strcpy(fut_geno, genocided);
30761f28255Scgd }
30861f28255Scgd }
30961f28255Scgd #endif
31061f28255Scgd setftty();
311907fca1bSdholland (void) snprintf(SAVEF, sizeof(SAVEF), "save/%d%s", getuid(), plname);
31261f28255Scgd regularize(SAVEF + 5); /* avoid . or / in name */
313ab8b6343Sjsm if ((fd = open(SAVEF, O_RDONLY)) >= 0 &&
31461f28255Scgd (uptodate(fd) || unlink(SAVEF) == 666)) {
31561f28255Scgd (void) signal(SIGINT, done1);
31661f28255Scgd pline("Restoring old save file...");
31761f28255Scgd (void) fflush(stdout);
31861f28255Scgd if (!dorecover(fd))
31961f28255Scgd goto not_recovered;
32061f28255Scgd pline("Hello %s, welcome to %s!", plname, gamename);
32161f28255Scgd flags.move = 0;
32261f28255Scgd } else {
32361f28255Scgd not_recovered:
32461f28255Scgd fobj = fcobj = invent = 0;
32561f28255Scgd fmon = fallen_down = 0;
32661f28255Scgd ftrap = 0;
32761f28255Scgd fgold = 0;
32861f28255Scgd flags.ident = 1;
32961f28255Scgd init_objects();
33061f28255Scgd u_init();
33161f28255Scgd
33261f28255Scgd (void) signal(SIGINT, done1);
33361f28255Scgd mklev();
33461f28255Scgd u.ux = xupstair;
33561f28255Scgd u.uy = yupstair;
33661f28255Scgd (void) inshop();
33761f28255Scgd setsee();
33861f28255Scgd flags.botlx = 1;
33961f28255Scgd makedog();
3403ea4a95cSchristos {
3413ea4a95cSchristos struct monst *mtmp;
3423ea4a95cSchristos if ((mtmp = m_at(u.ux, u.uy)) != NULL)
3433ea4a95cSchristos mnexto(mtmp); /* riv05!a3 */
34461f28255Scgd }
34561f28255Scgd seemons();
34661f28255Scgd #ifdef NEWS
34761f28255Scgd if (flags.nonews || !readnews())
34861f28255Scgd /* after reading news we did docrt() already */
34961f28255Scgd #endif
35061f28255Scgd docrt();
35161f28255Scgd
35261f28255Scgd /* give welcome message before pickup messages */
35361f28255Scgd pline("Hello %s, welcome to %s!", plname, gamename);
35461f28255Scgd
35561f28255Scgd pickup(1);
35661f28255Scgd read_engr_at(u.ux, u.uy);
35761f28255Scgd flags.move = 1;
35861f28255Scgd }
35961f28255Scgd
36061f28255Scgd flags.moonphase = phase_of_the_moon();
36161f28255Scgd if (flags.moonphase == FULL_MOON) {
36261f28255Scgd pline("You are lucky! Full moon tonight.");
36361f28255Scgd u.uluck++;
36461f28255Scgd } else if (flags.moonphase == NEW_MOON) {
36561f28255Scgd pline("Be careful! New moon tonight.");
36661f28255Scgd }
36761f28255Scgd initrack();
36861f28255Scgd
36961f28255Scgd for (;;) {
37061f28255Scgd if (flags.move) { /* actual time passed */
37161f28255Scgd
37261f28255Scgd settrack();
37361f28255Scgd
37461f28255Scgd if (moves % 2 == 0 ||
37561f28255Scgd (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
37661f28255Scgd movemon();
37761f28255Scgd if (!rn2(70))
37861f28255Scgd (void) makemon((struct permonst *) 0, 0, 0);
37961f28255Scgd }
3803ea4a95cSchristos if (Glib)
3813ea4a95cSchristos glibr();
38261f28255Scgd timeout();
38361f28255Scgd ++moves;
3843ea4a95cSchristos if (flags.time)
3853ea4a95cSchristos flags.botl = 1;
38661f28255Scgd if (u.uhp < 1) {
38761f28255Scgd pline("You die...");
38861f28255Scgd done("died");
38961f28255Scgd }
39061f28255Scgd if (u.uhp * 10 < u.uhpmax && moves - wailmsg > 50) {
39161f28255Scgd wailmsg = moves;
39261f28255Scgd if (u.uhp == 1)
39361f28255Scgd pline("You hear the wailing of the Banshee...");
39461f28255Scgd else
39561f28255Scgd pline("You hear the howling of the CwnAnnwn...");
39661f28255Scgd }
39761f28255Scgd if (u.uhp < u.uhpmax) {
39861f28255Scgd if (u.ulevel > 9) {
39961f28255Scgd if (Regeneration || !(moves % 3)) {
40061f28255Scgd flags.botl = 1;
40161f28255Scgd u.uhp += rnd((int) u.ulevel - 9);
40261f28255Scgd if (u.uhp > u.uhpmax)
40361f28255Scgd u.uhp = u.uhpmax;
40461f28255Scgd }
40561f28255Scgd } else if (Regeneration ||
40661f28255Scgd (!(moves % (22 - u.ulevel * 2)))) {
40761f28255Scgd flags.botl = 1;
40861f28255Scgd u.uhp++;
40961f28255Scgd }
41061f28255Scgd }
4113ea4a95cSchristos if (Teleportation && !rn2(85))
4123ea4a95cSchristos tele();
4133ea4a95cSchristos if (Searching && multi >= 0)
4143ea4a95cSchristos (void) dosearch();
41561f28255Scgd gethungry();
41661f28255Scgd invault();
41761f28255Scgd amulet();
41861f28255Scgd }
41961f28255Scgd if (multi < 0) {
42061f28255Scgd if (!++multi) {
42157c13365Sjoerg if (nomovemsg)
42257c13365Sjoerg pline("%s", nomovemsg);
42357c13365Sjoerg else
42457c13365Sjoerg pline("You can move again.");
42561f28255Scgd nomovemsg = 0;
4263ea4a95cSchristos if (afternmv)
4273ea4a95cSchristos (*afternmv) ();
42861f28255Scgd afternmv = 0;
42961f28255Scgd }
43061f28255Scgd }
43161f28255Scgd find_ac();
43261f28255Scgd #ifndef QUEST
43361f28255Scgd if (!flags.mv || Blind)
43461f28255Scgd #endif
43561f28255Scgd {
43661f28255Scgd seeobjs();
43761f28255Scgd seemons();
43861f28255Scgd nscr();
43961f28255Scgd }
4403ea4a95cSchristos if (flags.botl || flags.botlx)
4413ea4a95cSchristos bot();
44261f28255Scgd
44361f28255Scgd flags.move = 1;
44461f28255Scgd
44561f28255Scgd if (multi >= 0 && occupation) {
44661f28255Scgd if (monster_nearby())
44761f28255Scgd stop_occupation();
44861f28255Scgd else if ((*occupation) () == 0)
44961f28255Scgd occupation = 0;
45061f28255Scgd continue;
45161f28255Scgd }
45261f28255Scgd if (multi > 0) {
45361f28255Scgd #ifdef QUEST
4543ea4a95cSchristos if (flags.run >= 4)
4553ea4a95cSchristos finddir();
45661f28255Scgd #endif
45761f28255Scgd lookaround();
45861f28255Scgd if (!multi) { /* lookaround may clear multi */
45961f28255Scgd flags.move = 0;
46061f28255Scgd continue;
46161f28255Scgd }
46261f28255Scgd if (flags.mv) {
46361f28255Scgd if (multi < COLNO && !--multi)
46461f28255Scgd flags.mv = flags.run = 0;
46561f28255Scgd domove();
46661f28255Scgd } else {
46761f28255Scgd --multi;
46861f28255Scgd rhack(save_cm);
46961f28255Scgd }
47061f28255Scgd } else if (multi == 0) {
47161f28255Scgd #ifdef MAIL
47261f28255Scgd ckmailstatus();
47361f28255Scgd #endif
474*2c0ecb1aSdholland rhack(NULL);
47561f28255Scgd }
47661f28255Scgd if (multi && multi % 7 == 0)
47761f28255Scgd (void) fflush(stdout);
47861f28255Scgd }
47961f28255Scgd }
48061f28255Scgd
4813ea4a95cSchristos void
glo(int foo)4821fa8a9a6Sdholland glo(int foo)
48361f28255Scgd {
48461f28255Scgd /* construct the string xlock.n */
485165c915bSdholland size_t pos;
48661f28255Scgd
487165c915bSdholland pos = 0;
488165c915bSdholland while (lock[pos] && lock[pos] != '.')
489165c915bSdholland pos++;
490165c915bSdholland (void) snprintf(lock + pos, sizeof(lock) - pos, ".%d", foo);
49161f28255Scgd }
49261f28255Scgd
49361f28255Scgd /*
49461f28255Scgd * plname is filled either by an option (-u Player or -uPlayer) or
49561f28255Scgd * explicitly (-w implies wizard) or by askname.
49661f28255Scgd * It may still contain a suffix denoting pl_character.
49761f28255Scgd */
4983ea4a95cSchristos void
askname(void)4991fa8a9a6Sdholland askname(void)
5003ea4a95cSchristos {
5013ea4a95cSchristos int c, ct;
50261f28255Scgd printf("\nWho are you? ");
50361f28255Scgd (void) fflush(stdout);
50461f28255Scgd ct = 0;
50561f28255Scgd while ((c = getchar()) != '\n') {
5063ea4a95cSchristos if (c == EOF)
5073ea4a95cSchristos error("End of input\n");
50861f28255Scgd /* some people get confused when their erase char is not ^H */
50961f28255Scgd if (c == '\010') {
5103ea4a95cSchristos if (ct)
5113ea4a95cSchristos ct--;
51261f28255Scgd continue;
51361f28255Scgd }
51461f28255Scgd if (c != '-')
5153ea4a95cSchristos if (c < 'A' || (c > 'Z' && c < 'a') || c > 'z')
5163ea4a95cSchristos c = '_';
5173c439f43Sdholland if (ct < (int)sizeof(plname) - 1)
5183ea4a95cSchristos plname[ct++] = c;
51961f28255Scgd }
52061f28255Scgd plname[ct] = 0;
5213ea4a95cSchristos if (ct == 0)
5223ea4a95cSchristos askname();
52361f28255Scgd }
52461f28255Scgd
52561f28255Scgd /* VARARGS1 */
5263ea4a95cSchristos void
impossible(const char * s,...)5273ea4a95cSchristos impossible(const char *s, ...)
52861f28255Scgd {
5293ea4a95cSchristos va_list ap;
5303ea4a95cSchristos
5313ea4a95cSchristos va_start(ap, s);
5323ea4a95cSchristos vpline(s, ap);
5333ea4a95cSchristos va_end(ap);
53461f28255Scgd pline("Program in disorder - perhaps you'd better Quit.");
53561f28255Scgd }
53661f28255Scgd
53761f28255Scgd #ifdef CHDIR
53861f28255Scgd static void
chdirx(const char * dir,boolean wr)5391fa8a9a6Sdholland chdirx(const char *dir, boolean wr)
54061f28255Scgd {
54161f28255Scgd
54261f28255Scgd #ifdef SECURE
54361f28255Scgd if (dir /* User specified directory? */
54461f28255Scgd #ifdef HACKDIR
54561f28255Scgd && strcmp(dir, HACKDIR) /* and not the default? */
54661f28255Scgd #endif
54761f28255Scgd ) {
54861f28255Scgd (void) setuid(getuid()); /* Ron Wessels */
54961f28255Scgd (void) setgid(getgid());
55061f28255Scgd }
55161f28255Scgd #endif
55261f28255Scgd
55361f28255Scgd #ifdef HACKDIR
55461f28255Scgd if (dir == NULL)
55561f28255Scgd dir = HACKDIR;
55661f28255Scgd #endif
55761f28255Scgd
55861f28255Scgd if (dir && chdir(dir) < 0) {
55961f28255Scgd perror(dir);
56061f28255Scgd error("Cannot chdir to %s.", dir);
56161f28255Scgd }
56261f28255Scgd /* warn the player if he cannot write the record file */
56361f28255Scgd /* perhaps we should also test whether . is writable */
56461f28255Scgd /* unfortunately the access systemcall is worthless */
56561f28255Scgd if (wr) {
5663ea4a95cSchristos int fd;
56761f28255Scgd
56861f28255Scgd if (dir == NULL)
56961f28255Scgd dir = ".";
570ab8b6343Sjsm if ((fd = open(RECORD, O_RDWR)) < 0) {
57161f28255Scgd printf("Warning: cannot write %s/%s", dir, RECORD);
57261f28255Scgd getret();
57361f28255Scgd } else
57461f28255Scgd (void) close(fd);
57561f28255Scgd }
57661f28255Scgd }
57761f28255Scgd #endif
57861f28255Scgd
5793ea4a95cSchristos void
stop_occupation(void)5801fa8a9a6Sdholland stop_occupation(void)
58161f28255Scgd {
58261f28255Scgd if (occupation) {
58361f28255Scgd pline("You stop %s.", occtxt);
58461f28255Scgd occupation = 0;
58561f28255Scgd }
58661f28255Scgd }
587