1*33206277Stedu /* $OpenBSD: hack.main.c,v 1.18 2015/11/04 21:22:10 tedu Exp $ */ 2d0b779f3Sniklas 3df930be7Sderaadt /* 4d25013f2Scamield * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5d25013f2Scamield * Amsterdam 6d25013f2Scamield * All rights reserved. 7d25013f2Scamield * 8d25013f2Scamield * Redistribution and use in source and binary forms, with or without 9d25013f2Scamield * modification, are permitted provided that the following conditions are 10d25013f2Scamield * met: 11d25013f2Scamield * 12d25013f2Scamield * - Redistributions of source code must retain the above copyright notice, 13d25013f2Scamield * this list of conditions and the following disclaimer. 14d25013f2Scamield * 15d25013f2Scamield * - Redistributions in binary form must reproduce the above copyright 16d25013f2Scamield * notice, this list of conditions and the following disclaimer in the 17d25013f2Scamield * documentation and/or other materials provided with the distribution. 18d25013f2Scamield * 19d25013f2Scamield * - Neither the name of the Stichting Centrum voor Wiskunde en 20d25013f2Scamield * Informatica, nor the names of its contributors may be used to endorse or 21d25013f2Scamield * promote products derived from this software without specific prior 22d25013f2Scamield * written permission. 23d25013f2Scamield * 24d25013f2Scamield * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25d25013f2Scamield * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26d25013f2Scamield * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27d25013f2Scamield * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28d25013f2Scamield * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31d25013f2Scamield * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32d25013f2Scamield * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33d25013f2Scamield * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34d25013f2Scamield * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35d25013f2Scamield */ 36d25013f2Scamield 37d25013f2Scamield /* 38d25013f2Scamield * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> 39d25013f2Scamield * All rights reserved. 40d25013f2Scamield * 41d25013f2Scamield * Redistribution and use in source and binary forms, with or without 42d25013f2Scamield * modification, are permitted provided that the following conditions 43d25013f2Scamield * are met: 44d25013f2Scamield * 1. Redistributions of source code must retain the above copyright 45d25013f2Scamield * notice, this list of conditions and the following disclaimer. 46d25013f2Scamield * 2. Redistributions in binary form must reproduce the above copyright 47d25013f2Scamield * notice, this list of conditions and the following disclaimer in the 48d25013f2Scamield * documentation and/or other materials provided with the distribution. 49d25013f2Scamield * 3. The name of the author may not be used to endorse or promote products 50d25013f2Scamield * derived from this software without specific prior written permission. 51d25013f2Scamield * 52d25013f2Scamield * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53d25013f2Scamield * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54d25013f2Scamield * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55d25013f2Scamield * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58d25013f2Scamield * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59d25013f2Scamield * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60d25013f2Scamield * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61d25013f2Scamield * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62df930be7Sderaadt */ 63df930be7Sderaadt 644a5fbbc4Spjanzen #include <sys/types.h> 654a5fbbc4Spjanzen #include <sys/stat.h> 664a5fbbc4Spjanzen #include <stdlib.h> 67df930be7Sderaadt #include <stdio.h> 684a5fbbc4Spjanzen #include <stdarg.h> 69df930be7Sderaadt #include <signal.h> 704a5fbbc4Spjanzen #include <unistd.h> 71df930be7Sderaadt #include "hack.h" 72df930be7Sderaadt 73df930be7Sderaadt #ifdef QUEST 74df930be7Sderaadt #define gamename "quest" 75df930be7Sderaadt #else 76df930be7Sderaadt #define gamename "hack" 77df930be7Sderaadt #endif 78df930be7Sderaadt 79df930be7Sderaadt extern char plname[PL_NSIZ], pl_character[PL_CSIZ]; 80df930be7Sderaadt extern struct permonst mons[CMNUM+2]; 81846311fcStdeval extern char genocided[60], fut_geno[60]; 82df930be7Sderaadt 834a5fbbc4Spjanzen void (*afternmv)(void); 844a5fbbc4Spjanzen int (*occupation)(void); 85df930be7Sderaadt char *occtxt; /* defined when occupation != NULL */ 86df930be7Sderaadt 87df930be7Sderaadt int hackpid; /* current pid */ 88df930be7Sderaadt int locknum; /* max num of players */ 89df930be7Sderaadt #ifdef DEF_PAGER 90df930be7Sderaadt char *catmore; /* default pager */ 91df930be7Sderaadt #endif 92df930be7Sderaadt char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */ 93df930be7Sderaadt char *hname; /* name of the game (argv[0] of call) */ 94df930be7Sderaadt char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ 95df930be7Sderaadt 96df930be7Sderaadt extern char *nomovemsg; 97df930be7Sderaadt extern long wailmsg; 98df930be7Sderaadt 99df930be7Sderaadt #ifdef CHDIR 1004a5fbbc4Spjanzen static void chdirx(char *, boolean); 101df930be7Sderaadt #endif 102df930be7Sderaadt 1034a5fbbc4Spjanzen int 1044a5fbbc4Spjanzen main(int argc, char **argv) 105df930be7Sderaadt { 1064a5fbbc4Spjanzen int fd; 107df930be7Sderaadt #ifdef CHDIR 1084a5fbbc4Spjanzen char *dir; 109df930be7Sderaadt #endif 110df930be7Sderaadt 111df930be7Sderaadt hname = argv[0]; 112df930be7Sderaadt hackpid = getpid(); 113df930be7Sderaadt 114df930be7Sderaadt #ifdef CHDIR /* otherwise no chdir() */ 115df930be7Sderaadt /* 116df930be7Sderaadt * See if we must change directory to the playground. 117df930be7Sderaadt * (Perhaps hack runs suid and playground is inaccessible 118df930be7Sderaadt * for the player.) 119df930be7Sderaadt * The environment variable HACKDIR is overridden by a 120df930be7Sderaadt * -d command line option (must be the first option given) 121df930be7Sderaadt */ 122df930be7Sderaadt 123df930be7Sderaadt dir = getenv("HACKDIR"); 124df930be7Sderaadt if(argc > 1 && !strncmp(argv[1], "-d", 2)) { 125df930be7Sderaadt argc--; 126df930be7Sderaadt argv++; 127df930be7Sderaadt dir = argv[0]+2; 128df930be7Sderaadt if(*dir == '=' || *dir == ':') dir++; 129df930be7Sderaadt if(!*dir && argc > 1) { 130df930be7Sderaadt argc--; 131df930be7Sderaadt argv++; 132df930be7Sderaadt dir = argv[0]; 133df930be7Sderaadt } 134df930be7Sderaadt if(!*dir) 135df930be7Sderaadt error("Flag -d must be followed by a directory name."); 136df930be7Sderaadt } 137df930be7Sderaadt #endif 138df930be7Sderaadt 139df930be7Sderaadt /* 140df930be7Sderaadt * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS 141c7b2accbSmillert * 2. Use $LOGNAME or $USER (if 1. fails) 142df930be7Sderaadt * 3. Use getlogin() (if 2. fails) 143df930be7Sderaadt * The resulting name is overridden by command line options. 144df930be7Sderaadt * If everything fails, or if the resulting name is some generic 145df930be7Sderaadt * account like "games", "play", "player", "hack" then eventually 146df930be7Sderaadt * we'll ask him. 147df930be7Sderaadt * Note that we trust him here; it is possible to play under 148df930be7Sderaadt * somebody else's name. 149df930be7Sderaadt */ 1504a5fbbc4Spjanzen { char *s; 151df930be7Sderaadt 152df930be7Sderaadt initoptions(); 153df930be7Sderaadt if(!*plname && (s = getenv("LOGNAME"))) 154479daa62Savsm (void) strlcpy(plname, s, sizeof(plname)); 155c7b2accbSmillert if(!*plname && (s = getenv("USER"))) 156479daa62Savsm (void) strlcpy(plname, s, sizeof(plname)); 157df930be7Sderaadt if(!*plname && (s = getlogin())) 158479daa62Savsm (void) strlcpy(plname, s, sizeof(plname)); 159df930be7Sderaadt } 160df930be7Sderaadt 161df930be7Sderaadt /* 162df930be7Sderaadt * Now we know the directory containing 'record' and 163df930be7Sderaadt * may do a prscore(). 164df930be7Sderaadt */ 165df930be7Sderaadt if(argc > 1 && !strncmp(argv[1], "-s", 2)) { 166df930be7Sderaadt #ifdef CHDIR 167df930be7Sderaadt chdirx(dir,0); 168df930be7Sderaadt #endif 169df930be7Sderaadt prscore(argc, argv); 170df930be7Sderaadt exit(0); 171df930be7Sderaadt } 172df930be7Sderaadt 173df930be7Sderaadt /* 174df930be7Sderaadt * It seems he really wants to play. 175df930be7Sderaadt * Remember tty modes, to be restored on exit. 176df930be7Sderaadt */ 177df930be7Sderaadt gettty(); 178*33206277Stedu setvbuf(stdout, obuf, _IOFBF, sizeof obuf); 179a7a85d61Stholo umask(007); 180df930be7Sderaadt startup(); 181df930be7Sderaadt cls(); 182df930be7Sderaadt u.uhp = 1; /* prevent RIP on early quits */ 183df930be7Sderaadt u.ux = FAR; /* prevent nscr() */ 1844a5fbbc4Spjanzen (void) signal(SIGHUP, hackhangup); 185df930be7Sderaadt 186df930be7Sderaadt /* 187df930be7Sderaadt * Find the creation date of this game, 188df930be7Sderaadt * so as to avoid restoring outdated savefiles. 189df930be7Sderaadt */ 190df930be7Sderaadt gethdate(hname); 191df930be7Sderaadt 192df930be7Sderaadt /* 193df930be7Sderaadt * We cannot do chdir earlier, otherwise gethdate will fail. 194df930be7Sderaadt */ 195df930be7Sderaadt #ifdef CHDIR 196df930be7Sderaadt chdirx(dir,1); 197df930be7Sderaadt #endif 198df930be7Sderaadt 199df930be7Sderaadt /* 200df930be7Sderaadt * Process options. 201df930be7Sderaadt */ 202df930be7Sderaadt while(argc > 1 && argv[1][0] == '-'){ 203df930be7Sderaadt argv++; 204df930be7Sderaadt argc--; 205df930be7Sderaadt switch(argv[0][1]){ 206df930be7Sderaadt #ifdef WIZARD 207df930be7Sderaadt case 'D': 208df930be7Sderaadt /* if(!strcmp(getlogin(), WIZARD)) */ 209df930be7Sderaadt wizard = TRUE; 210df930be7Sderaadt /* else 211df930be7Sderaadt printf("Sorry.\n"); */ 212df930be7Sderaadt break; 213df930be7Sderaadt #endif 214df930be7Sderaadt #ifdef NEWS 215df930be7Sderaadt case 'n': 216df930be7Sderaadt flags.nonews = TRUE; 217df930be7Sderaadt break; 218df930be7Sderaadt #endif 219df930be7Sderaadt case 'u': 220c7b2accbSmillert if(argv[0][2]) { 221479daa62Savsm (void) strlcpy(plname, argv[0]+2, sizeof(plname)); 222c7b2accbSmillert } else if(argc > 1) { 223df930be7Sderaadt argc--; 224df930be7Sderaadt argv++; 225479daa62Savsm (void) strlcpy(plname, argv[0], sizeof(plname)); 226df930be7Sderaadt } else 227df930be7Sderaadt printf("Player name expected after -u\n"); 228df930be7Sderaadt break; 229df930be7Sderaadt default: 230df930be7Sderaadt /* allow -T for Tourist, etc. */ 231479daa62Savsm (void) strlcpy(pl_character, argv[0]+1, sizeof(pl_character)); 232df930be7Sderaadt /* printf("Unknown option: %s\n", *argv); */ 233df930be7Sderaadt } 234df930be7Sderaadt } 235df930be7Sderaadt 236df930be7Sderaadt if(argc > 1) 237df930be7Sderaadt locknum = atoi(argv[1]); 238df930be7Sderaadt #ifdef MAX_NR_OF_PLAYERS 239df930be7Sderaadt if(!locknum || locknum > MAX_NR_OF_PLAYERS) 240df930be7Sderaadt locknum = MAX_NR_OF_PLAYERS; 241df930be7Sderaadt #endif 242df930be7Sderaadt #ifdef DEF_PAGER 243df930be7Sderaadt if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) 244df930be7Sderaadt catmore = DEF_PAGER; 245df930be7Sderaadt #endif 246df930be7Sderaadt #ifdef MAIL 247df930be7Sderaadt getmailstatus(); 248df930be7Sderaadt #endif 249df930be7Sderaadt #ifdef WIZARD 25042ceebb3Sderaadt if(wizard) (void) strlcpy(plname, "wizard", sizeof plname); else 251df930be7Sderaadt #endif 252df930be7Sderaadt if(!*plname || !strncmp(plname, "player", 4) 253df930be7Sderaadt || !strncmp(plname, "games", 4)) 254df930be7Sderaadt askname(); 255df930be7Sderaadt plnamesuffix(); /* strip suffix from name; calls askname() */ 256df930be7Sderaadt /* again if suffix was whole name */ 257df930be7Sderaadt /* accepts any suffix */ 258df930be7Sderaadt #ifdef WIZARD 259df930be7Sderaadt if(!wizard) { 260df930be7Sderaadt #endif 261df930be7Sderaadt /* 262df930be7Sderaadt * check for multiple games under the same name 263df930be7Sderaadt * (if !locknum) or check max nr of players (otherwise) 264df930be7Sderaadt */ 265df930be7Sderaadt (void) signal(SIGQUIT,SIG_IGN); 266df930be7Sderaadt (void) signal(SIGINT,SIG_IGN); 267df930be7Sderaadt if(!locknum) 268846311fcStdeval (void) strlcpy(lock,plname,sizeof lock); 269df930be7Sderaadt getlock(); /* sets lock if locknum != 0 */ 270df930be7Sderaadt #ifdef WIZARD 271df930be7Sderaadt } else { 2724a5fbbc4Spjanzen char *sfoo; 273846311fcStdeval (void) strlcpy(lock,plname,sizeof lock); 2744a5fbbc4Spjanzen if ((sfoo = getenv("MAGIC"))) 275df930be7Sderaadt while(*sfoo) { 276df930be7Sderaadt switch(*sfoo++) { 277f84032edSderaadt case 'n': (void) srandom_deterministic(*sfoo++); 278df930be7Sderaadt break; 279df930be7Sderaadt } 280df930be7Sderaadt } 2814a5fbbc4Spjanzen if ((sfoo = getenv("GENOCIDED"))) { 282df930be7Sderaadt if(*sfoo == '!'){ 2834a5fbbc4Spjanzen struct permonst *pm = mons; 2844a5fbbc4Spjanzen char *gp = genocided; 285df930be7Sderaadt 286df930be7Sderaadt while(pm < mons+CMNUM+2){ 287180acc8fSmillert if(!strchr(sfoo, pm->mlet)) 288df930be7Sderaadt *gp++ = pm->mlet; 289df930be7Sderaadt pm++; 290df930be7Sderaadt } 291df930be7Sderaadt *gp = 0; 292df930be7Sderaadt } else 293846311fcStdeval strlcpy(genocided, sfoo, sizeof genocided); 294846311fcStdeval strlcpy(fut_geno, genocided, sizeof fut_geno); 295df930be7Sderaadt } 296df930be7Sderaadt } 297df930be7Sderaadt #endif 298df930be7Sderaadt setftty(); 29942ceebb3Sderaadt (void) snprintf(SAVEF, sizeof SAVEF, "save/%u%s", getuid(), plname); 300df930be7Sderaadt regularize(SAVEF+5); /* avoid . or / in name */ 3016cd28e42Smillert if((fd = open(SAVEF, O_RDONLY)) >= 0 && 302df930be7Sderaadt (uptodate(fd) || unlink(SAVEF) == 666)) { 303df930be7Sderaadt (void) signal(SIGINT,done1); 304df930be7Sderaadt pline("Restoring old save file..."); 305df930be7Sderaadt (void) fflush(stdout); 306df930be7Sderaadt if(!dorecover(fd)) 307df930be7Sderaadt goto not_recovered; 308df930be7Sderaadt pline("Hello %s, welcome to %s!", plname, gamename); 309df930be7Sderaadt flags.move = 0; 310df930be7Sderaadt } else { 311df930be7Sderaadt not_recovered: 312df930be7Sderaadt fobj = fcobj = invent = 0; 313df930be7Sderaadt fmon = fallen_down = 0; 314df930be7Sderaadt ftrap = 0; 315df930be7Sderaadt fgold = 0; 316df930be7Sderaadt flags.ident = 1; 317df930be7Sderaadt init_objects(); 318df930be7Sderaadt u_init(); 319df930be7Sderaadt 320df930be7Sderaadt (void) signal(SIGINT,done1); 321df930be7Sderaadt mklev(); 322df930be7Sderaadt u.ux = xupstair; 323df930be7Sderaadt u.uy = yupstair; 324df930be7Sderaadt (void) inshop(); 325df930be7Sderaadt setsee(); 326df930be7Sderaadt flags.botlx = 1; 327df930be7Sderaadt makedog(); 3284a5fbbc4Spjanzen { struct monst *mtmp; 3294a5fbbc4Spjanzen if ((mtmp = m_at(u.ux, u.uy))) 3304a5fbbc4Spjanzen mnexto(mtmp); /* riv05!a3 */ 331df930be7Sderaadt } 332df930be7Sderaadt seemons(); 333df930be7Sderaadt #ifdef NEWS 334df930be7Sderaadt if(flags.nonews || !readnews()) 335df930be7Sderaadt /* after reading news we did docrt() already */ 336df930be7Sderaadt #endif 337df930be7Sderaadt docrt(); 338df930be7Sderaadt 339df930be7Sderaadt /* give welcome message before pickup messages */ 340df930be7Sderaadt pline("Hello %s, welcome to %s!", plname, gamename); 341df930be7Sderaadt 342df930be7Sderaadt pickup(1); 343df930be7Sderaadt read_engr_at(u.ux,u.uy); 344df930be7Sderaadt flags.move = 1; 345df930be7Sderaadt } 346df930be7Sderaadt 347df930be7Sderaadt flags.moonphase = phase_of_the_moon(); 348df930be7Sderaadt if(flags.moonphase == FULL_MOON) { 349df930be7Sderaadt pline("You are lucky! Full moon tonight."); 350df930be7Sderaadt u.uluck++; 351df930be7Sderaadt } else if(flags.moonphase == NEW_MOON) { 352df930be7Sderaadt pline("Be careful! New moon tonight."); 353df930be7Sderaadt } 354df930be7Sderaadt 355df930be7Sderaadt initrack(); 356df930be7Sderaadt 357df930be7Sderaadt for(;;) { 358df930be7Sderaadt if(flags.move) { /* actual time passed */ 359df930be7Sderaadt 360df930be7Sderaadt settrack(); 361df930be7Sderaadt 362df930be7Sderaadt if(moves%2 == 0 || 363df930be7Sderaadt (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { 364df930be7Sderaadt extern struct monst *makemon(); 365df930be7Sderaadt movemon(); 366df930be7Sderaadt if(!rn2(70)) 367df930be7Sderaadt (void) makemon((struct permonst *)0, 0, 0); 368df930be7Sderaadt } 369df930be7Sderaadt if(Glib) glibr(); 3704a5fbbc4Spjanzen hacktimeout(); 371df930be7Sderaadt ++moves; 372df930be7Sderaadt if(flags.time) flags.botl = 1; 373df930be7Sderaadt if(u.uhp < 1) { 374df930be7Sderaadt pline("You die..."); 375df930be7Sderaadt done("died"); 376df930be7Sderaadt } 377df930be7Sderaadt if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ 378df930be7Sderaadt wailmsg = moves; 379df930be7Sderaadt if(u.uhp == 1) 380df930be7Sderaadt pline("You hear the wailing of the Banshee..."); 381df930be7Sderaadt else 382df930be7Sderaadt pline("You hear the howling of the CwnAnnwn..."); 383df930be7Sderaadt } 384df930be7Sderaadt if(u.uhp < u.uhpmax) { 385df930be7Sderaadt if(u.ulevel > 9) { 386df930be7Sderaadt if(Regeneration || !(moves%3)) { 387df930be7Sderaadt flags.botl = 1; 388df930be7Sderaadt u.uhp += rnd((int) u.ulevel-9); 389df930be7Sderaadt if(u.uhp > u.uhpmax) 390df930be7Sderaadt u.uhp = u.uhpmax; 391df930be7Sderaadt } 392df930be7Sderaadt } else if(Regeneration || 393df930be7Sderaadt (!(moves%(22-u.ulevel*2)))) { 394df930be7Sderaadt flags.botl = 1; 395df930be7Sderaadt u.uhp++; 396df930be7Sderaadt } 397df930be7Sderaadt } 398df930be7Sderaadt if(Teleportation && !rn2(85)) tele(); 399df930be7Sderaadt if(Searching && multi >= 0) (void) dosearch(); 400df930be7Sderaadt gethungry(); 401df930be7Sderaadt invault(); 402df930be7Sderaadt amulet(); 403df930be7Sderaadt } 404df930be7Sderaadt if(multi < 0) { 405df930be7Sderaadt if(!++multi){ 406911134d2Sguenther pline("%s", nomovemsg ? nomovemsg : 407df930be7Sderaadt "You can move again."); 408df930be7Sderaadt nomovemsg = 0; 409df930be7Sderaadt if(afternmv) (*afternmv)(); 410df930be7Sderaadt afternmv = 0; 411df930be7Sderaadt } 412df930be7Sderaadt } 413df930be7Sderaadt 414df930be7Sderaadt find_ac(); 415df930be7Sderaadt #ifndef QUEST 416df930be7Sderaadt if(!flags.mv || Blind) 417df930be7Sderaadt #endif 418df930be7Sderaadt { 419df930be7Sderaadt seeobjs(); 420df930be7Sderaadt seemons(); 421df930be7Sderaadt nscr(); 422df930be7Sderaadt } 423df930be7Sderaadt if(flags.botl || flags.botlx) bot(); 424df930be7Sderaadt 425df930be7Sderaadt flags.move = 1; 426df930be7Sderaadt 427df930be7Sderaadt if(multi >= 0 && occupation) { 428df930be7Sderaadt if(monster_nearby()) 429df930be7Sderaadt stop_occupation(); 430df930be7Sderaadt else if ((*occupation)() == 0) 431df930be7Sderaadt occupation = 0; 432df930be7Sderaadt continue; 433df930be7Sderaadt } 434df930be7Sderaadt 435df930be7Sderaadt if(multi > 0) { 436df930be7Sderaadt #ifdef QUEST 437df930be7Sderaadt if(flags.run >= 4) finddir(); 438df930be7Sderaadt #endif 439df930be7Sderaadt lookaround(); 440df930be7Sderaadt if(!multi) { /* lookaround may clear multi */ 441df930be7Sderaadt flags.move = 0; 442df930be7Sderaadt continue; 443df930be7Sderaadt } 444df930be7Sderaadt if(flags.mv) { 445df930be7Sderaadt if(multi < COLNO && !--multi) 446df930be7Sderaadt flags.mv = flags.run = 0; 447df930be7Sderaadt domove(); 448df930be7Sderaadt } else { 449df930be7Sderaadt --multi; 450df930be7Sderaadt rhack(save_cm); 451df930be7Sderaadt } 452df930be7Sderaadt } else if(multi == 0) { 453df930be7Sderaadt #ifdef MAIL 454df930be7Sderaadt ckmailstatus(); 455df930be7Sderaadt #endif 456df930be7Sderaadt rhack((char *) 0); 457df930be7Sderaadt } 458df930be7Sderaadt if(multi && multi%7 == 0) 459df930be7Sderaadt (void) fflush(stdout); 460df930be7Sderaadt } 461df930be7Sderaadt } 462df930be7Sderaadt 4634a5fbbc4Spjanzen void 4644a5fbbc4Spjanzen glo(int foo) 465df930be7Sderaadt { 466df930be7Sderaadt /* construct the string xlock.n */ 4674a5fbbc4Spjanzen char *tf; 468df930be7Sderaadt 469df930be7Sderaadt tf = lock; 470df930be7Sderaadt while(*tf && *tf != '.') tf++; 471846311fcStdeval (void) snprintf(tf, lock + sizeof lock - tf, ".%d", foo); 472df930be7Sderaadt } 473df930be7Sderaadt 474df930be7Sderaadt /* 475df930be7Sderaadt * plname is filled either by an option (-u Player or -uPlayer) or 476df930be7Sderaadt * explicitly (-w implies wizard) or by askname. 477df930be7Sderaadt * It may still contain a suffix denoting pl_character. 478df930be7Sderaadt */ 4794a5fbbc4Spjanzen void 4804a5fbbc4Spjanzen askname() 4814a5fbbc4Spjanzen { 4824a5fbbc4Spjanzen int c,ct; 4834a5fbbc4Spjanzen 484df930be7Sderaadt printf("\nWho are you? "); 485df930be7Sderaadt (void) fflush(stdout); 486df930be7Sderaadt ct = 0; 487df930be7Sderaadt while((c = getchar()) != '\n'){ 488df930be7Sderaadt if(c == EOF) error("End of input\n"); 489df930be7Sderaadt /* some people get confused when their erase char is not ^H */ 490df930be7Sderaadt if(c == '\010') { 491df930be7Sderaadt if(ct) ct--; 492df930be7Sderaadt continue; 493df930be7Sderaadt } 494df930be7Sderaadt if(c != '-') 495df930be7Sderaadt if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; 496df930be7Sderaadt if(ct < sizeof(plname)-1) plname[ct++] = c; 497df930be7Sderaadt } 498df930be7Sderaadt plname[ct] = 0; 499df930be7Sderaadt if(ct == 0) askname(); 500df930be7Sderaadt } 501df930be7Sderaadt 5024a5fbbc4Spjanzen void 503911134d2Sguenther impossible(const char *s, ...) 504df930be7Sderaadt { 5054a5fbbc4Spjanzen va_list ap; 5064a5fbbc4Spjanzen 5074a5fbbc4Spjanzen va_start(ap, s); 508911134d2Sguenther vpline(s, ap); 5094a5fbbc4Spjanzen va_end(ap); 510df930be7Sderaadt pline("Program in disorder - perhaps you'd better Quit."); 511df930be7Sderaadt } 512df930be7Sderaadt 513df930be7Sderaadt #ifdef CHDIR 514df930be7Sderaadt static void 5154a5fbbc4Spjanzen chdirx(char *dir, boolean wr) 516df930be7Sderaadt { 517f4878ebaSdjm gid_t gid; 518df930be7Sderaadt 519df930be7Sderaadt #ifdef SECURE 520df930be7Sderaadt if(dir /* User specified directory? */ 521df930be7Sderaadt #ifdef HACKDIR 522df930be7Sderaadt && strcmp(dir, HACKDIR) /* and not the default? */ 523df930be7Sderaadt #endif 524df930be7Sderaadt ) { 525f4878ebaSdjm /* revoke privs */ 526f4878ebaSdjm gid = getgid(); 527f4878ebaSdjm setresgid(gid, gid, gid); 528df930be7Sderaadt } 529df930be7Sderaadt #endif 530df930be7Sderaadt 531df930be7Sderaadt #ifdef HACKDIR 532df930be7Sderaadt if(dir == NULL) 533df930be7Sderaadt dir = HACKDIR; 534df930be7Sderaadt #endif 535df930be7Sderaadt 536df930be7Sderaadt if(dir && chdir(dir) < 0) { 537df930be7Sderaadt perror(dir); 538df930be7Sderaadt error("Cannot chdir to %s.", dir); 539df930be7Sderaadt } 540df930be7Sderaadt 541df930be7Sderaadt /* warn the player if he cannot write the record file */ 542df930be7Sderaadt /* perhaps we should also test whether . is writable */ 543df930be7Sderaadt /* unfortunately the access systemcall is worthless */ 544df930be7Sderaadt if(wr) { 5454a5fbbc4Spjanzen int fd; 546df930be7Sderaadt 547df930be7Sderaadt if(dir == NULL) 548df930be7Sderaadt dir = "."; 5496cd28e42Smillert if((fd = open(RECORD, O_RDWR)) < 0) { 550df930be7Sderaadt printf("Warning: cannot write %s/%s", dir, RECORD); 551df930be7Sderaadt getret(); 552df930be7Sderaadt } else 553df930be7Sderaadt (void) close(fd); 554df930be7Sderaadt } 555df930be7Sderaadt } 556df930be7Sderaadt #endif 557df930be7Sderaadt 5584a5fbbc4Spjanzen void 559df930be7Sderaadt stop_occupation() 560df930be7Sderaadt { 561df930be7Sderaadt if(occupation) { 562df930be7Sderaadt pline("You stop %s.", occtxt); 563df930be7Sderaadt occupation = 0; 564df930be7Sderaadt } 565df930be7Sderaadt } 566