OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / sys / unix / unixunix.c
1 /*      SCCS Id: @(#)unixunix.c 3.4     1994/11/07      */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* This file collects some Unix dependencies */
6
7 #include "hack.h"       /* mainly for index() which depends on BSD */
8
9 #include <errno.h>
10 #include <sys/stat.h>
11 #if defined(NO_FILE_LINKS) || defined(SUNOS4) || defined(POSIX_TYPES)
12 #include <fcntl.h>
13 #endif
14 #include <signal.h>
15
16 #ifdef _M_UNIX
17 extern void NDECL(sco_mapon);
18 extern void NDECL(sco_mapoff);
19 #endif
20 #ifdef __linux__
21 extern void NDECL(linux_mapon);
22 extern void NDECL(linux_mapoff);
23 #endif
24
25 #ifndef NHSTDC
26 extern int errno;
27 #endif
28
29 static struct stat buf;
30
31 /* see whether we should throw away this xlock file */
32 static int
33 veryold(fd)
34 int fd;
35 {
36         time_t date;
37
38         if(fstat(fd, &buf)) return(0);                  /* cannot get status */
39 #ifndef INSURANCE
40         if(buf.st_size != sizeof(int)) return(0);       /* not an xlock file */
41 #endif
42 #if defined(BSD) && !defined(POSIX_TYPES)
43         (void) time((long *)(&date));
44 #else
45         (void) time(&date);
46 #endif
47         if(date - buf.st_mtime < 3L*24L*60L*60L) {      /* recent */
48                 int lockedpid;  /* should be the same size as hackpid */
49
50                 if(read(fd, (genericptr_t)&lockedpid, sizeof(lockedpid)) !=
51                         sizeof(lockedpid))
52                         /* strange ... */
53                         return(0);
54
55                 /* From: Rick Adams <seismo!rick> */
56                 /* This will work on 4.1cbsd, 4.2bsd and system 3? & 5. */
57                 /* It will do nothing on V7 or 4.1bsd. */
58 #ifndef NETWORK
59                 /* It will do a VERY BAD THING if the playground is shared
60                    by more than one machine! -pem */
61                 if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
62 #endif
63                         return(0);
64         }
65         (void) close(fd);
66         return(1);
67 }
68
69 static int
70 eraseoldlocks()
71 {
72         register int i;
73
74         /* cannot use maxledgerno() here, because we need to find a lock name
75          * before starting everything (including the dungeon initialization
76          * that sets astral_level, needed for maxledgerno()) up
77          */
78         for(i = 1; i <= MAXDUNGEON*MAXLEVEL + 1; i++) {
79                 /* try to remove all */
80                 set_levelfile_name(lock, i);
81                 (void) unlink(fqname(lock, LEVELPREFIX, 0));
82         }
83         set_levelfile_name(lock, 0);
84         if (unlink(fqname(lock, LEVELPREFIX, 0)))
85                 return(0);                              /* cannot remove it */
86         return(1);                                      /* success! */
87 }
88
89 void
90 getlock()
91 {
92         register int i = 0, fd, c;
93         const char *fq_lock;
94
95 #ifdef TTY_GRAPHICS
96         /* idea from rpick%ucqais@uccba.uc.edu
97          * prevent automated rerolling of characters
98          * test input (fd0) so that tee'ing output to get a screen dump still
99          * works
100          * also incidentally prevents development of any hack-o-matic programs
101          */
102         /* added check for window-system type -dlc */
103         if (!strcmp(windowprocs.name, "tty"))
104             if (!isatty(0))
105                 error("You must play from a terminal.");
106 #endif
107
108         /* we ignore QUIT and INT at this point */
109         if (!lock_file(HLOCK, LOCKPREFIX, 10)) {
110                 wait_synch();
111                 error("%s", "");
112         }
113
114         regularize(lock);
115         set_levelfile_name(lock, 0);
116
117         if(locknum) {
118                 if(locknum > 25) locknum = 25;
119
120                 do {
121                         lock[0] = 'a' + i++;
122                         fq_lock = fqname(lock, LEVELPREFIX, 0);
123
124                         if((fd = open(fq_lock, 0)) == -1) {
125                             if(errno == ENOENT) goto gotlock; /* no such file */
126                             perror(fq_lock);
127                             unlock_file(HLOCK);
128                             error("Cannot open %s", fq_lock);
129                         }
130
131                         if(veryold(fd) /* closes fd if true */
132                                                         && eraseoldlocks())
133                                 goto gotlock;
134                         (void) close(fd);
135                 } while(i < locknum);
136
137                 unlock_file(HLOCK);
138                 error("Too many hacks running now.");
139         } else {
140                 fq_lock = fqname(lock, LEVELPREFIX, 0);
141                 if((fd = open(fq_lock, 0)) == -1) {
142                         if(errno == ENOENT) goto gotlock;    /* no such file */
143                         perror(fq_lock);
144                         unlock_file(HLOCK);
145                         error("Cannot open %s", fq_lock);
146                 }
147
148                 if(veryold(fd) /* closes fd if true */ && eraseoldlocks())
149                         goto gotlock;
150                 (void) close(fd);
151
152                 if(iflags.window_inited) {
153                     c = yn("There is already a game in progress under your name.  Destroy old game?");
154                 } else {
155                     (void) printf("\nThere is already a game in progress under your name.");
156                     (void) printf("  Destroy old game? [yn] ");
157                     (void) fflush(stdout);
158                     c = getchar();
159                     (void) putchar(c);
160                     (void) fflush(stdout);
161                     while (getchar() != '\n') ; /* eat rest of line and newline */
162                 }
163                 if(c == 'y' || c == 'Y')
164                         if(eraseoldlocks())
165                                 goto gotlock;
166                         else {
167                                 unlock_file(HLOCK);
168                                 error("Couldn't destroy old game.");
169                         }
170                 else {
171                         unlock_file(HLOCK);
172                         error("%s", "");
173                 }
174         }
175
176 gotlock:
177         fd = creat(fq_lock, FCMASK);
178         unlock_file(HLOCK);
179         if(fd == -1) {
180                 error("cannot creat lock file (%s).", fq_lock);
181         } else {
182                 if(write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
183                     != sizeof(hackpid)){
184                         error("cannot write lock (%s)", fq_lock);
185                 }
186                 if(close(fd) == -1) {
187                         error("cannot close lock (%s)", fq_lock);
188                 }
189         }
190 }
191
192 void
193 regularize(s)   /* normalize file name - we don't like .'s, /'s, spaces */
194 register char *s;
195 {
196         register char *lp;
197
198         while((lp=index(s, '.')) || (lp=index(s, '/')) || (lp=index(s,' ')))
199                 *lp = '_';
200 #if defined(SYSV) && !defined(AIX_31) && !defined(SVR4) && !defined(LINUX) && !defined(__APPLE__)
201         /* avoid problems with 14 character file name limit */
202 # ifdef COMPRESS
203         /* leave room for .e from error and .Z from compress appended to
204          * save files */
205         {
206 #  ifdef COMPRESS_EXTENSION
207             int i = 12 - strlen(COMPRESS_EXTENSION);
208 #  else
209             int i = 10;         /* should never happen... */
210 #  endif
211             if(strlen(s) > i)
212                 s[i] = '\0';
213         }
214 # else
215         if(strlen(s) > 11)
216                 /* leave room for .nn appended to level files */
217                 s[11] = '\0';
218 # endif
219 #endif
220 }
221
222 #if defined(TIMED_DELAY) && !defined(msleep) && defined(SYSV)
223 #include <poll.h>
224
225 void
226 msleep(msec)
227 unsigned msec;                          /* milliseconds */
228 {
229         struct pollfd unused;
230         int msecs = msec;               /* poll API is signed */
231
232         if (msecs < 0) msecs = 0;       /* avoid infinite sleep */
233         (void) poll(&unused, (unsigned long)0, msecs);
234 }
235 #endif /* TIMED_DELAY for SYSV */
236
237 #ifdef SHELL
238 int
239 dosh()
240 {
241         register char *str;
242         if(child(0)) {
243                 if((str = getenv("SHELL")) != (char*)0)
244                         (void) execl(str, str, (char *)0);
245                 else
246                         (void) execl("/bin/sh", "sh", (char *)0);
247                 raw_print("sh: cannot execute.");
248                 exit(EXIT_FAILURE);
249         }
250         return 0;
251 }
252 #endif /* SHELL */
253
254 #if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
255 int
256 child(wt)
257 int wt;
258 {
259         register int f;
260         suspend_nhwindows((char *)0);   /* also calls end_screen() */
261 #ifdef _M_UNIX
262         sco_mapon();
263 #endif
264 #ifdef __linux__
265         linux_mapon();
266 #endif
267         if((f = fork()) == 0){          /* child */
268                 (void) setgid(getgid());
269                 (void) setuid(getuid());
270 #ifdef CHDIR
271                 (void) chdir(getenv("HOME"));
272 #endif
273                 return(1);
274         }
275         if(f == -1) {   /* cannot fork */
276                 pline("Fork failed.  Try again.");
277                 return(0);
278         }
279         /* fork succeeded; wait for child to exit */
280         (void) signal(SIGINT,SIG_IGN);
281         (void) signal(SIGQUIT,SIG_IGN);
282         (void) wait( (int *) 0);
283 #ifdef _M_UNIX
284         sco_mapoff();
285 #endif
286 #ifdef __linux__
287         linux_mapoff();
288 #endif
289         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
290 #ifdef WIZARD
291         if(wizard) (void) signal(SIGQUIT,SIG_DFL);
292 #endif
293         if(wt) {
294                 raw_print("");
295                 wait_synch();
296         }
297         resume_nhwindows();
298         return(0);
299 }
300 #endif
301
302 #ifdef GETRES_SUPPORT
303
304 extern int FDECL(nh_getresuid, (uid_t *, uid_t *, uid_t *));
305 extern uid_t NDECL(nh_getuid);
306 extern uid_t NDECL(nh_geteuid);
307 extern int FDECL(nh_getresgid, (gid_t *, gid_t *, gid_t *));
308 extern gid_t NDECL(nh_getgid);
309 extern gid_t NDECL(nh_getegid);
310
311 int
312 (getresuid)(ruid, euid, suid)
313 uid_t *ruid, *euid, *suid;
314 {
315     return nh_getresuid(ruid, euid, suid);
316 }
317
318 uid_t
319 (getuid)()
320 {
321     return nh_getuid();
322 }
323
324 uid_t
325 (geteuid)()
326 {
327     return nh_geteuid();
328 }
329
330 int
331 (getresgid)(rgid, egid, sgid)
332 gid_t *rgid, *egid, *sgid;
333 {
334     return nh_getresgid(rgid, egid, sgid);
335 }
336
337 gid_t
338 (getgid)()
339 {
340     return nh_getgid();
341 }
342
343 gid_t
344 (getegid)()
345 {
346     return nh_getegid();
347 }
348
349 #endif  /* GETRES_SUPPORT */