1*25fdf802Sjsg /* $OpenBSD: hack.main.c,v 1.26 2023/09/06 11:53:56 jsg 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/stat.h>
65dc14b708Sbentley #include <errno.h>
66aed906e4Smestre
67df930be7Sderaadt #include <stdio.h>
68aed906e4Smestre #include <stdlib.h>
69df930be7Sderaadt #include <signal.h>
704a5fbbc4Spjanzen #include <unistd.h>
71aed906e4Smestre
72df930be7Sderaadt #include "hack.h"
73df930be7Sderaadt
74df930be7Sderaadt #ifdef QUEST
75df930be7Sderaadt #define gamename "quest"
76df930be7Sderaadt #else
77df930be7Sderaadt #define gamename "hack"
78df930be7Sderaadt #endif
79df930be7Sderaadt
80df930be7Sderaadt extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
81df930be7Sderaadt extern struct permonst mons[CMNUM+2];
82846311fcStdeval extern char genocided[60], fut_geno[60];
83df930be7Sderaadt
844a5fbbc4Spjanzen void (*afternmv)(void);
854a5fbbc4Spjanzen int (*occupation)(void);
86df930be7Sderaadt char *occtxt; /* defined when occupation != NULL */
87df930be7Sderaadt
88df930be7Sderaadt int hackpid; /* current pid */
89df930be7Sderaadt int locknum; /* max num of players */
90df930be7Sderaadt #ifdef DEF_PAGER
91df930be7Sderaadt char *catmore; /* default pager */
92df930be7Sderaadt #endif
93df930be7Sderaadt char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */
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
main(int argc,char ** argv)1044a5fbbc4Spjanzen main(int argc, char **argv)
105df930be7Sderaadt {
1064a5fbbc4Spjanzen int fd;
107df930be7Sderaadt #ifdef CHDIR
1084a5fbbc4Spjanzen char *dir;
109df930be7Sderaadt #endif
110df930be7Sderaadt
111df930be7Sderaadt hackpid = getpid();
112df930be7Sderaadt
113df930be7Sderaadt #ifdef CHDIR /* otherwise no chdir() */
114df930be7Sderaadt /*
115df930be7Sderaadt * See if we must change directory to the playground.
116df930be7Sderaadt * (Perhaps hack runs suid and playground is inaccessible
117df930be7Sderaadt * for the player.)
118df930be7Sderaadt * The environment variable HACKDIR is overridden by a
119df930be7Sderaadt * -d command line option (must be the first option given)
120df930be7Sderaadt */
121df930be7Sderaadt
122df930be7Sderaadt dir = getenv("HACKDIR");
123df930be7Sderaadt if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
124df930be7Sderaadt argc--;
125df930be7Sderaadt argv++;
126df930be7Sderaadt dir = argv[0]+2;
127df930be7Sderaadt if(*dir == '=' || *dir == ':') dir++;
128df930be7Sderaadt if(!*dir && argc > 1) {
129df930be7Sderaadt argc--;
130df930be7Sderaadt argv++;
131df930be7Sderaadt dir = argv[0];
132df930be7Sderaadt }
133df930be7Sderaadt if(!*dir)
134df930be7Sderaadt error("Flag -d must be followed by a directory name.");
135df930be7Sderaadt }
136df930be7Sderaadt #endif
137df930be7Sderaadt
138df930be7Sderaadt /*
139df930be7Sderaadt * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
140c7b2accbSmillert * 2. Use $LOGNAME or $USER (if 1. fails)
141df930be7Sderaadt * 3. Use getlogin() (if 2. fails)
142df930be7Sderaadt * The resulting name is overridden by command line options.
143df930be7Sderaadt * If everything fails, or if the resulting name is some generic
144df930be7Sderaadt * account like "games", "play", "player", "hack" then eventually
145df930be7Sderaadt * we'll ask him.
146df930be7Sderaadt * Note that we trust him here; it is possible to play under
147df930be7Sderaadt * somebody else's name.
148df930be7Sderaadt */
1494a5fbbc4Spjanzen { char *s;
150df930be7Sderaadt
151df930be7Sderaadt initoptions();
152df930be7Sderaadt if(!*plname && (s = getenv("LOGNAME")))
153479daa62Savsm (void) strlcpy(plname, s, sizeof(plname));
154c7b2accbSmillert if(!*plname && (s = getenv("USER")))
155479daa62Savsm (void) strlcpy(plname, s, sizeof(plname));
156df930be7Sderaadt if(!*plname && (s = getlogin()))
157479daa62Savsm (void) strlcpy(plname, s, sizeof(plname));
158df930be7Sderaadt }
159df930be7Sderaadt
160df930be7Sderaadt /*
161df930be7Sderaadt * Now we know the directory containing 'record' and
162df930be7Sderaadt * may do a prscore().
163df930be7Sderaadt */
164df930be7Sderaadt if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
165df930be7Sderaadt #ifdef CHDIR
166df930be7Sderaadt chdirx(dir,0);
167df930be7Sderaadt #endif
168df930be7Sderaadt prscore(argc, argv);
16917641e31Stb return 0;
170df930be7Sderaadt }
171df930be7Sderaadt
172df930be7Sderaadt /*
173df930be7Sderaadt * It seems he really wants to play.
174df930be7Sderaadt * Remember tty modes, to be restored on exit.
175df930be7Sderaadt */
176df930be7Sderaadt gettty();
17733206277Stedu setvbuf(stdout, obuf, _IOFBF, sizeof obuf);
178a7a85d61Stholo umask(007);
179df930be7Sderaadt startup();
180df930be7Sderaadt cls();
181df930be7Sderaadt u.uhp = 1; /* prevent RIP on early quits */
182df930be7Sderaadt u.ux = FAR; /* prevent nscr() */
1834a5fbbc4Spjanzen (void) signal(SIGHUP, hackhangup);
184df930be7Sderaadt
185df930be7Sderaadt #ifdef CHDIR
186df930be7Sderaadt chdirx(dir,1);
187df930be7Sderaadt #endif
188df930be7Sderaadt
189df930be7Sderaadt /*
190df930be7Sderaadt * Process options.
191df930be7Sderaadt */
192df930be7Sderaadt while(argc > 1 && argv[1][0] == '-'){
193df930be7Sderaadt argv++;
194df930be7Sderaadt argc--;
195df930be7Sderaadt switch(argv[0][1]){
196df930be7Sderaadt #ifdef WIZARD
197df930be7Sderaadt case 'D':
198df930be7Sderaadt /* if(!strcmp(getlogin(), WIZARD)) */
199df930be7Sderaadt wizard = TRUE;
200df930be7Sderaadt /* else
201df930be7Sderaadt printf("Sorry.\n"); */
202df930be7Sderaadt break;
203df930be7Sderaadt #endif
204df930be7Sderaadt #ifdef NEWS
205df930be7Sderaadt case 'n':
206df930be7Sderaadt flags.nonews = TRUE;
207df930be7Sderaadt break;
208df930be7Sderaadt #endif
209df930be7Sderaadt case 'u':
210c7b2accbSmillert if(argv[0][2]) {
211479daa62Savsm (void) strlcpy(plname, argv[0]+2, sizeof(plname));
212c7b2accbSmillert } else if(argc > 1) {
213df930be7Sderaadt argc--;
214df930be7Sderaadt argv++;
215479daa62Savsm (void) strlcpy(plname, argv[0], sizeof(plname));
216df930be7Sderaadt } else
217df930be7Sderaadt printf("Player name expected after -u\n");
218df930be7Sderaadt break;
219df930be7Sderaadt default:
220df930be7Sderaadt /* allow -T for Tourist, etc. */
221479daa62Savsm (void) strlcpy(pl_character, argv[0]+1, sizeof(pl_character));
222df930be7Sderaadt /* printf("Unknown option: %s\n", *argv); */
223df930be7Sderaadt }
224df930be7Sderaadt }
225df930be7Sderaadt
226df930be7Sderaadt if(argc > 1)
227df930be7Sderaadt locknum = atoi(argv[1]);
228df930be7Sderaadt #ifdef MAX_NR_OF_PLAYERS
229df930be7Sderaadt if(!locknum || locknum > MAX_NR_OF_PLAYERS)
230df930be7Sderaadt locknum = MAX_NR_OF_PLAYERS;
231df930be7Sderaadt #endif
232df930be7Sderaadt #ifdef DEF_PAGER
233df930be7Sderaadt if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
234df930be7Sderaadt catmore = DEF_PAGER;
235df930be7Sderaadt #endif
236df930be7Sderaadt #ifdef MAIL
237df930be7Sderaadt getmailstatus();
238df930be7Sderaadt #endif
239df930be7Sderaadt #ifdef WIZARD
24042ceebb3Sderaadt if(wizard) (void) strlcpy(plname, "wizard", sizeof plname); else
241df930be7Sderaadt #endif
242df930be7Sderaadt if(!*plname || !strncmp(plname, "player", 4)
243df930be7Sderaadt || !strncmp(plname, "games", 4))
244df930be7Sderaadt askname();
245df930be7Sderaadt plnamesuffix(); /* strip suffix from name; calls askname() */
246df930be7Sderaadt /* again if suffix was whole name */
247df930be7Sderaadt /* accepts any suffix */
248df930be7Sderaadt #ifdef WIZARD
249df930be7Sderaadt if(!wizard) {
250df930be7Sderaadt #endif
251df930be7Sderaadt /*
252df930be7Sderaadt * check for multiple games under the same name
253df930be7Sderaadt * (if !locknum) or check max nr of players (otherwise)
254df930be7Sderaadt */
255df930be7Sderaadt (void) signal(SIGQUIT,SIG_IGN);
256df930be7Sderaadt (void) signal(SIGINT,SIG_IGN);
257df930be7Sderaadt if(!locknum)
258846311fcStdeval (void) strlcpy(lock,plname,sizeof lock);
259df930be7Sderaadt getlock(); /* sets lock if locknum != 0 */
260df930be7Sderaadt #ifdef WIZARD
261df930be7Sderaadt } else {
2624a5fbbc4Spjanzen char *sfoo;
263846311fcStdeval (void) strlcpy(lock,plname,sizeof lock);
2644a5fbbc4Spjanzen if ((sfoo = getenv("MAGIC")))
265df930be7Sderaadt while(*sfoo) {
266df930be7Sderaadt switch(*sfoo++) {
267f84032edSderaadt case 'n': (void) srandom_deterministic(*sfoo++);
268df930be7Sderaadt break;
269df930be7Sderaadt }
270df930be7Sderaadt }
2714a5fbbc4Spjanzen if ((sfoo = getenv("GENOCIDED"))) {
272df930be7Sderaadt if(*sfoo == '!'){
2734a5fbbc4Spjanzen struct permonst *pm = mons;
2744a5fbbc4Spjanzen char *gp = genocided;
275df930be7Sderaadt
276df930be7Sderaadt while(pm < mons+CMNUM+2){
277180acc8fSmillert if(!strchr(sfoo, pm->mlet))
278df930be7Sderaadt *gp++ = pm->mlet;
279df930be7Sderaadt pm++;
280df930be7Sderaadt }
281df930be7Sderaadt *gp = 0;
282df930be7Sderaadt } else
283846311fcStdeval strlcpy(genocided, sfoo, sizeof genocided);
284846311fcStdeval strlcpy(fut_geno, genocided, sizeof fut_geno);
285df930be7Sderaadt }
286df930be7Sderaadt }
287df930be7Sderaadt #endif
288df930be7Sderaadt setftty();
28942ceebb3Sderaadt (void) snprintf(SAVEF, sizeof SAVEF, "save/%u%s", getuid(), plname);
290df930be7Sderaadt regularize(SAVEF+5); /* avoid . or / in name */
29177f90040Sop if((fd = open(SAVEF, O_RDONLY)) >= 0) {
292df930be7Sderaadt (void) signal(SIGINT,done1);
293df930be7Sderaadt pline("Restoring old save file...");
294df930be7Sderaadt (void) fflush(stdout);
295df930be7Sderaadt if(!dorecover(fd))
296df930be7Sderaadt goto not_recovered;
297df930be7Sderaadt pline("Hello %s, welcome to %s!", plname, gamename);
298df930be7Sderaadt flags.move = 0;
299df930be7Sderaadt } else {
300df930be7Sderaadt not_recovered:
301df930be7Sderaadt fobj = fcobj = invent = 0;
302df930be7Sderaadt fmon = fallen_down = 0;
303df930be7Sderaadt ftrap = 0;
304df930be7Sderaadt fgold = 0;
305df930be7Sderaadt flags.ident = 1;
306df930be7Sderaadt init_objects();
307df930be7Sderaadt u_init();
308df930be7Sderaadt
309df930be7Sderaadt (void) signal(SIGINT,done1);
310df930be7Sderaadt mklev();
311df930be7Sderaadt u.ux = xupstair;
312df930be7Sderaadt u.uy = yupstair;
313df930be7Sderaadt (void) inshop();
314df930be7Sderaadt setsee();
315df930be7Sderaadt flags.botlx = 1;
316df930be7Sderaadt makedog();
3174a5fbbc4Spjanzen { struct monst *mtmp;
3184a5fbbc4Spjanzen if ((mtmp = m_at(u.ux, u.uy)))
3194a5fbbc4Spjanzen mnexto(mtmp); /* riv05!a3 */
320df930be7Sderaadt }
321df930be7Sderaadt seemons();
322df930be7Sderaadt #ifdef NEWS
323df930be7Sderaadt if(flags.nonews || !readnews())
324df930be7Sderaadt /* after reading news we did docrt() already */
325df930be7Sderaadt #endif
326df930be7Sderaadt docrt();
327df930be7Sderaadt
328df930be7Sderaadt /* give welcome message before pickup messages */
329df930be7Sderaadt pline("Hello %s, welcome to %s!", plname, gamename);
330df930be7Sderaadt
331df930be7Sderaadt pickup(1);
332df930be7Sderaadt read_engr_at(u.ux,u.uy);
333df930be7Sderaadt flags.move = 1;
334df930be7Sderaadt }
335df930be7Sderaadt
336df930be7Sderaadt flags.moonphase = phase_of_the_moon();
337df930be7Sderaadt if(flags.moonphase == FULL_MOON) {
338df930be7Sderaadt pline("You are lucky! Full moon tonight.");
339df930be7Sderaadt u.uluck++;
340df930be7Sderaadt } else if(flags.moonphase == NEW_MOON) {
341df930be7Sderaadt pline("Be careful! New moon tonight.");
342df930be7Sderaadt }
343df930be7Sderaadt
344df930be7Sderaadt initrack();
345df930be7Sderaadt
346df930be7Sderaadt for(;;) {
347df930be7Sderaadt if(flags.move) { /* actual time passed */
348df930be7Sderaadt
349df930be7Sderaadt settrack();
350df930be7Sderaadt
351df930be7Sderaadt if(moves%2 == 0 ||
352df930be7Sderaadt (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
353df930be7Sderaadt movemon();
354df930be7Sderaadt if(!rn2(70))
355df930be7Sderaadt (void) makemon((struct permonst *)0, 0, 0);
356df930be7Sderaadt }
357df930be7Sderaadt if(Glib) glibr();
3584a5fbbc4Spjanzen hacktimeout();
359df930be7Sderaadt ++moves;
360df930be7Sderaadt if(flags.time) flags.botl = 1;
361df930be7Sderaadt if(u.uhp < 1) {
362df930be7Sderaadt pline("You die...");
363df930be7Sderaadt done("died");
364df930be7Sderaadt }
365df930be7Sderaadt if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
366df930be7Sderaadt wailmsg = moves;
367df930be7Sderaadt if(u.uhp == 1)
368df930be7Sderaadt pline("You hear the wailing of the Banshee...");
369df930be7Sderaadt else
370df930be7Sderaadt pline("You hear the howling of the CwnAnnwn...");
371df930be7Sderaadt }
372df930be7Sderaadt if(u.uhp < u.uhpmax) {
373df930be7Sderaadt if(u.ulevel > 9) {
374df930be7Sderaadt if(Regeneration || !(moves%3)) {
375df930be7Sderaadt flags.botl = 1;
376df930be7Sderaadt u.uhp += rnd((int) u.ulevel-9);
377df930be7Sderaadt if(u.uhp > u.uhpmax)
378df930be7Sderaadt u.uhp = u.uhpmax;
379df930be7Sderaadt }
380df930be7Sderaadt } else if(Regeneration ||
381df930be7Sderaadt (!(moves%(22-u.ulevel*2)))) {
382df930be7Sderaadt flags.botl = 1;
383df930be7Sderaadt u.uhp++;
384df930be7Sderaadt }
385df930be7Sderaadt }
386df930be7Sderaadt if(Teleportation && !rn2(85)) tele();
387df930be7Sderaadt if(Searching && multi >= 0) (void) dosearch();
388df930be7Sderaadt gethungry();
389df930be7Sderaadt invault();
390df930be7Sderaadt amulet();
391df930be7Sderaadt }
392df930be7Sderaadt if(multi < 0) {
393df930be7Sderaadt if(!++multi){
394911134d2Sguenther pline("%s", nomovemsg ? nomovemsg :
395df930be7Sderaadt "You can move again.");
396df930be7Sderaadt nomovemsg = 0;
397df930be7Sderaadt if(afternmv) (*afternmv)();
398df930be7Sderaadt afternmv = 0;
399df930be7Sderaadt }
400df930be7Sderaadt }
401df930be7Sderaadt
402df930be7Sderaadt find_ac();
403df930be7Sderaadt #ifndef QUEST
404df930be7Sderaadt if(!flags.mv || Blind)
405df930be7Sderaadt #endif
406df930be7Sderaadt {
407df930be7Sderaadt seeobjs();
408df930be7Sderaadt seemons();
409df930be7Sderaadt nscr();
410df930be7Sderaadt }
411df930be7Sderaadt if(flags.botl || flags.botlx) bot();
412df930be7Sderaadt
413df930be7Sderaadt flags.move = 1;
414df930be7Sderaadt
415df930be7Sderaadt if(multi >= 0 && occupation) {
416df930be7Sderaadt if(monster_nearby())
417df930be7Sderaadt stop_occupation();
418df930be7Sderaadt else if ((*occupation)() == 0)
419df930be7Sderaadt occupation = 0;
420df930be7Sderaadt continue;
421df930be7Sderaadt }
422df930be7Sderaadt
423df930be7Sderaadt if(multi > 0) {
424df930be7Sderaadt #ifdef QUEST
425df930be7Sderaadt if(flags.run >= 4) finddir();
426df930be7Sderaadt #endif
427df930be7Sderaadt lookaround();
428df930be7Sderaadt if(!multi) { /* lookaround may clear multi */
429df930be7Sderaadt flags.move = 0;
430df930be7Sderaadt continue;
431df930be7Sderaadt }
432df930be7Sderaadt if(flags.mv) {
433df930be7Sderaadt if(multi < COLNO && !--multi)
434df930be7Sderaadt flags.mv = flags.run = 0;
435df930be7Sderaadt domove();
436df930be7Sderaadt } else {
437df930be7Sderaadt --multi;
438df930be7Sderaadt rhack(save_cm);
439df930be7Sderaadt }
440df930be7Sderaadt } else if(multi == 0) {
441df930be7Sderaadt #ifdef MAIL
442df930be7Sderaadt ckmailstatus();
443df930be7Sderaadt #endif
4446acf840eSmestre rhack(NULL);
445df930be7Sderaadt }
446df930be7Sderaadt if(multi && multi%7 == 0)
447df930be7Sderaadt (void) fflush(stdout);
448df930be7Sderaadt }
449df930be7Sderaadt }
450df930be7Sderaadt
4514a5fbbc4Spjanzen void
glo(int foo)4524a5fbbc4Spjanzen glo(int foo)
453df930be7Sderaadt {
454df930be7Sderaadt /* construct the string xlock.n */
4554a5fbbc4Spjanzen char *tf;
456df930be7Sderaadt
457df930be7Sderaadt tf = lock;
458df930be7Sderaadt while(*tf && *tf != '.') tf++;
459846311fcStdeval (void) snprintf(tf, lock + sizeof lock - tf, ".%d", foo);
460df930be7Sderaadt }
461df930be7Sderaadt
462df930be7Sderaadt /*
463df930be7Sderaadt * plname is filled either by an option (-u Player or -uPlayer) or
464df930be7Sderaadt * explicitly (-w implies wizard) or by askname.
465df930be7Sderaadt * It may still contain a suffix denoting pl_character.
466df930be7Sderaadt */
4674a5fbbc4Spjanzen void
askname(void)468aed906e4Smestre askname(void)
4694a5fbbc4Spjanzen {
4704a5fbbc4Spjanzen int c,ct;
4714a5fbbc4Spjanzen
472df930be7Sderaadt printf("\nWho are you? ");
473df930be7Sderaadt (void) fflush(stdout);
474df930be7Sderaadt ct = 0;
475df930be7Sderaadt while((c = getchar()) != '\n'){
476df930be7Sderaadt if(c == EOF) error("End of input\n");
477df930be7Sderaadt /* some people get confused when their erase char is not ^H */
478df930be7Sderaadt if(c == '\010') {
479df930be7Sderaadt if(ct) ct--;
480df930be7Sderaadt continue;
481df930be7Sderaadt }
482df930be7Sderaadt if(c != '-')
483df930be7Sderaadt if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
484df930be7Sderaadt if(ct < sizeof(plname)-1) plname[ct++] = c;
485df930be7Sderaadt }
486df930be7Sderaadt plname[ct] = 0;
487df930be7Sderaadt if(ct == 0) askname();
488df930be7Sderaadt }
489df930be7Sderaadt
4904a5fbbc4Spjanzen void
impossible(const char * s,...)491911134d2Sguenther impossible(const char *s, ...)
492df930be7Sderaadt {
4934a5fbbc4Spjanzen va_list ap;
4944a5fbbc4Spjanzen
4954a5fbbc4Spjanzen va_start(ap, s);
496911134d2Sguenther vpline(s, ap);
4974a5fbbc4Spjanzen va_end(ap);
498df930be7Sderaadt pline("Program in disorder - perhaps you'd better Quit.");
499df930be7Sderaadt }
500df930be7Sderaadt
501df930be7Sderaadt #ifdef CHDIR
502df930be7Sderaadt static void
chdirx(char * dir,boolean wr)5034a5fbbc4Spjanzen chdirx(char *dir, boolean wr)
504df930be7Sderaadt {
505f4878ebaSdjm gid_t gid;
506df930be7Sderaadt
507df930be7Sderaadt #ifdef SECURE
508df930be7Sderaadt if(dir /* User specified directory? */
509df930be7Sderaadt #ifdef HACKDIR
510df930be7Sderaadt && strcmp(dir, HACKDIR) /* and not the default? */
511df930be7Sderaadt #endif
512df930be7Sderaadt ) {
513f4878ebaSdjm /* revoke privs */
514f4878ebaSdjm gid = getgid();
515f4878ebaSdjm setresgid(gid, gid, gid);
516df930be7Sderaadt }
517df930be7Sderaadt #endif
518df930be7Sderaadt
519df930be7Sderaadt #ifdef HACKDIR
520df930be7Sderaadt if(dir == NULL)
521df930be7Sderaadt dir = HACKDIR;
522df930be7Sderaadt #endif
523df930be7Sderaadt
524df69c215Sderaadt if(dir && chdir(dir) == -1) {
525df930be7Sderaadt perror(dir);
526df930be7Sderaadt error("Cannot chdir to %s.", dir);
527df930be7Sderaadt }
528df930be7Sderaadt
529df930be7Sderaadt /* warn the player if he cannot write the record file */
530dc14b708Sbentley /* warn the player if he cannot read the permanent lock file */
531dc14b708Sbentley /* warn the player if he cannot create the save directory */
532df930be7Sderaadt /* perhaps we should also test whether . is writable */
533df930be7Sderaadt /* unfortunately the access systemcall is worthless */
534df930be7Sderaadt if(wr) {
5354a5fbbc4Spjanzen int fd;
536df930be7Sderaadt
537df930be7Sderaadt if(dir == NULL)
538df930be7Sderaadt dir = ".";
539df69c215Sderaadt if((fd = open(RECORD, O_RDWR | O_CREAT, FMASK)) == -1) {
540df930be7Sderaadt printf("Warning: cannot write %s/%s", dir, RECORD);
541df930be7Sderaadt getret();
542df930be7Sderaadt } else
543df930be7Sderaadt (void) close(fd);
544df69c215Sderaadt if((fd = open(HLOCK, O_RDONLY | O_CREAT, FMASK)) == -1) {
545dc14b708Sbentley printf("Warning: cannot read %s/%s", dir, HLOCK);
546dc14b708Sbentley getret();
547dc14b708Sbentley } else
548dc14b708Sbentley (void) close(fd);
549dc14b708Sbentley if(mkdir("save", 0770) && errno != EEXIST) {
550dc14b708Sbentley printf("Warning: cannot create %s/save", dir);
551dc14b708Sbentley getret();
552dc14b708Sbentley }
553df930be7Sderaadt }
554df930be7Sderaadt }
555df930be7Sderaadt #endif
556df930be7Sderaadt
5574a5fbbc4Spjanzen void
stop_occupation(void)558aed906e4Smestre stop_occupation(void)
559df930be7Sderaadt {
560df930be7Sderaadt if(occupation) {
561df930be7Sderaadt pline("You stop %s.", occtxt);
562df930be7Sderaadt occupation = 0;
563df930be7Sderaadt }
564df930be7Sderaadt }
565