Mercurial > hg > early-roguelike
comparison rogue5/mach_dep.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
| author | elwin |
|---|---|
| date | Mon, 24 May 2010 20:10:59 +0000 |
| parents | |
| children | 655c317b6237 |
comparison
equal
deleted
inserted
replaced
| 32:2dcd75e6a736 | 33:f502bf60e6e4 |
|---|---|
| 1 /* | |
| 2 * Various installation dependent routines | |
| 3 * | |
| 4 * @(#)mach_dep.c 4.37 (Berkeley) 05/23/83 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman | |
| 8 * All rights reserved. | |
| 9 * | |
| 10 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 11 */ | |
| 12 | |
| 13 /* | |
| 14 * The various tuneable defines are: | |
| 15 * | |
| 16 * SCOREFILE Where/if the score file should live. | |
| 17 * ALLSCORES Score file is top ten scores, not top ten | |
| 18 * players. This is only useful when only a few | |
| 19 * people will be playing; otherwise the score file | |
| 20 * gets hogged by just a few people. | |
| 21 * NUMSCORES Number of scores in the score file (default 10). | |
| 22 * NUMNAME String version of NUMSCORES (first character | |
| 23 * should be capitalized) (default "Ten"). | |
| 24 * MAXLOAD What (if any) the maximum load average should be | |
| 25 * when people are playing. Since it is divided | |
| 26 * by 10, to specify a load limit of 4.0, MAXLOAD | |
| 27 * should be "40". If defined, then | |
| 28 * LOADAV Should it use it's own routine to get | |
| 29 * the load average? | |
| 30 * NAMELIST If so, where does the system namelist | |
| 31 * hide? | |
| 32 * MAXUSERS What (if any) the maximum user count should be | |
| 33 * when people are playing. If defined, then | |
| 34 * UCOUNT Should it use it's own routine to count | |
| 35 * users? | |
| 36 * UTMP If so, where does the user list hide? | |
| 37 * CHECKTIME How often/if it should check during the game | |
| 38 * for high load average. | |
| 39 */ | |
| 40 | |
| 41 #include <signal.h> | |
| 42 #include <sys/types.h> | |
| 43 #include <sys/stat.h> | |
| 44 #include <limits.h> | |
| 45 #include <string.h> | |
| 46 #include <fcntl.h> | |
| 47 #include <errno.h> | |
| 48 #include <time.h> | |
| 49 #include <curses.h> | |
| 50 #include "extern.h" | |
| 51 | |
| 52 #define NOOP(x) (x += 0) | |
| 53 | |
| 54 # ifndef NUMSCORES | |
| 55 # define NUMSCORES 10 | |
| 56 # define NUMNAME "Ten" | |
| 57 # endif | |
| 58 | |
| 59 #ifdef CHECKTIME | |
| 60 static int num_checks = 0; /* times we've gone over in checkout() */ | |
| 61 #endif /* CHECKTIME */ | |
| 62 | |
| 63 /* | |
| 64 * init_check: | |
| 65 * Check out too see if it is proper to play the game now | |
| 66 */ | |
| 67 | |
| 68 void | |
| 69 init_check(void) | |
| 70 { | |
| 71 #if defined(MAXLOAD) || defined(MAXUSERS) | |
| 72 if (too_much()) | |
| 73 { | |
| 74 printf("Sorry, %s, but the system is too loaded now.\n", whoami); | |
| 75 printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", | |
| 76 vowelstr(fruit), fruit); | |
| 77 if (author()) | |
| 78 printf("However, since you're a good guy, it's up to you\n"); | |
| 79 else | |
| 80 exit(1); | |
| 81 } | |
| 82 #endif | |
| 83 } | |
| 84 | |
| 85 /* | |
| 86 * open_score: | |
| 87 * Open up the score file for future use | |
| 88 */ | |
| 89 | |
| 90 void | |
| 91 open_score(void) | |
| 92 { | |
| 93 #ifdef SCOREFILE | |
| 94 char *scorefile = SCOREFILE; | |
| 95 | |
| 96 numscores = NUMSCORES; | |
| 97 Numname = NUMNAME; | |
| 98 | |
| 99 #ifdef ALLSCORES | |
| 100 allscore = TRUE; | |
| 101 #else /* ALLSCORES */ | |
| 102 allscore = FALSE; | |
| 103 #endif /* ALLSCORES */ | |
| 104 | |
| 105 /* | |
| 106 * We drop setgid privileges after opening the score file, so subsequent | |
| 107 * open()'s will fail. Just reuse the earlier filehandle. | |
| 108 */ | |
| 109 | |
| 110 if (scoreboard != NULL) { | |
| 111 rewind(scoreboard); | |
| 112 return; | |
| 113 } | |
| 114 | |
| 115 scoreboard = fopen(scorefile, "r+"); | |
| 116 | |
| 117 if ((scoreboard == NULL) && (errno == ENOENT)) | |
| 118 { | |
| 119 scoreboard = fopen(scorefile, "w+"); | |
| 120 md_chmod(scorefile,0664); | |
| 121 } | |
| 122 | |
| 123 if (scoreboard == NULL) { | |
| 124 fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno)); | |
| 125 fflush(stderr); | |
| 126 } | |
| 127 #else | |
| 128 scoreboard = NULL; | |
| 129 #endif | |
| 130 } | |
| 131 | |
| 132 /* | |
| 133 * getltchars: | |
| 134 * Get the local tty chars for later use | |
| 135 */ | |
| 136 | |
| 137 void | |
| 138 getltchars(void) | |
| 139 { | |
| 140 got_ltc = TRUE; | |
| 141 orig_dsusp = md_dsuspchar(); | |
| 142 md_setdsuspchar( md_suspchar() ); | |
| 143 } | |
| 144 | |
| 145 /* | |
| 146 * setup: | |
| 147 * Get starting setup for all games | |
| 148 */ | |
| 149 | |
| 150 void | |
| 151 setup(void) | |
| 152 { | |
| 153 #ifdef DUMP | |
| 154 md_onsignal_autosave(); | |
| 155 #else | |
| 156 md_onsignal_default(); | |
| 157 #endif | |
| 158 | |
| 159 #ifdef CHECKTIME | |
| 160 md_start_checkout_timer(CHECKTIME*60); | |
| 161 num_checks = 0; | |
| 162 #endif | |
| 163 | |
| 164 raw(); /* Raw mode */ | |
| 165 noecho(); /* Echo off */ | |
| 166 keypad(stdscr,1); | |
| 167 getltchars(); /* get the local tty chars */ | |
| 168 } | |
| 169 | |
| 170 /* | |
| 171 * resetltchars: | |
| 172 * Reset the local tty chars to original values. | |
| 173 */ | |
| 174 void | |
| 175 resetltchars(void) | |
| 176 { | |
| 177 if (got_ltc) { | |
| 178 md_setdsuspchar(orig_dsusp); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 /* | |
| 183 * playltchars: | |
| 184 * Set local tty chars to the values we use when playing. | |
| 185 */ | |
| 186 void | |
| 187 playltchars(void) | |
| 188 { | |
| 189 if (got_ltc) { | |
| 190 md_setdsuspchar( md_suspchar() ); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 /* | |
| 195 * start_score: | |
| 196 * Start the scoring sequence | |
| 197 */ | |
| 198 | |
| 199 void | |
| 200 start_score(void) | |
| 201 { | |
| 202 #ifdef CHECKTIME | |
| 203 md_stop_checkout_timer(); | |
| 204 #endif | |
| 205 } | |
| 206 | |
| 207 /* | |
| 208 * is_symlink: | |
| 209 * See if the file has a symbolic link | |
| 210 */ | |
| 211 int | |
| 212 is_symlink(char *sp) | |
| 213 { | |
| 214 #ifdef S_IFLNK | |
| 215 struct stat sbuf2; | |
| 216 | |
| 217 if (lstat(sp, &sbuf2) < 0) | |
| 218 return FALSE; | |
| 219 else | |
| 220 return ((sbuf2.st_mode & S_IFMT) != S_IFREG); | |
| 221 #else | |
| 222 NOOP(sp); | |
| 223 return FALSE; | |
| 224 #endif | |
| 225 } | |
| 226 | |
| 227 #if defined(MAXLOAD) || defined(MAXUSERS) | |
| 228 /* | |
| 229 * too_much: | |
| 230 * See if the system is being used too much for this game | |
| 231 */ | |
| 232 int | |
| 233 too_much(void) | |
| 234 { | |
| 235 #ifdef MAXLOAD | |
| 236 double avec[3]; | |
| 237 #else | |
| 238 int cnt; | |
| 239 #endif | |
| 240 | |
| 241 #ifdef MAXLOAD | |
| 242 md_loadav(avec); | |
| 243 if (avec[1] > (MAXLOAD / 10.0)) | |
| 244 return TRUE; | |
| 245 #endif | |
| 246 #ifdef MAXUSERS | |
| 247 if (ucount() > MAXUSERS) | |
| 248 return TRUE; | |
| 249 #endif | |
| 250 return FALSE; | |
| 251 } | |
| 252 | |
| 253 /* | |
| 254 * author: | |
| 255 * See if a user is an author of the program | |
| 256 */ | |
| 257 int | |
| 258 author(void) | |
| 259 { | |
| 260 #ifdef MASTER | |
| 261 if (wizard) | |
| 262 return TRUE; | |
| 263 #endif | |
| 264 switch (md_getuid()) | |
| 265 { | |
| 266 case -1: | |
| 267 return TRUE; | |
| 268 default: | |
| 269 return FALSE; | |
| 270 } | |
| 271 } | |
| 272 #endif | |
| 273 | |
| 274 #ifdef CHECKTIME | |
| 275 /* | |
| 276 * checkout: | |
| 277 * Check each CHECKTIME seconds to see if the load is too high | |
| 278 */ | |
| 279 | |
| 280 checkout(int sig) | |
| 281 { | |
| 282 char *msgs[] = { | |
| 283 "The load is too high to be playing. Please leave in %0.1f minutes", | |
| 284 "Please save your game. You have %0.1f minutes", | |
| 285 "Last warning. You have %0.1f minutes to leave", | |
| 286 }; | |
| 287 int checktime; | |
| 288 | |
| 289 if (too_much()) | |
| 290 { | |
| 291 if (author()) | |
| 292 { | |
| 293 num_checks = 1; | |
| 294 chmsg("The load is rather high, O exaulted one"); | |
| 295 } | |
| 296 else if (num_checks++ == 3) | |
| 297 fatal("Sorry. You took too long. You are dead\n"); | |
| 298 checktime = (CHECKTIME * 60) / num_checks; | |
| 299 chmsg(msgs[num_checks - 1], ((double) checktime / 60.0)); | |
| 300 } | |
| 301 else | |
| 302 { | |
| 303 if (num_checks) | |
| 304 { | |
| 305 num_checks = 0; | |
| 306 chmsg("The load has dropped back down. You have a reprieve"); | |
| 307 } | |
| 308 checktime = (CHECKTIME * 60); | |
| 309 } | |
| 310 | |
| 311 md_start_checkout_timer(checktime); | |
| 312 } | |
| 313 | |
| 314 /* | |
| 315 * chmsg: | |
| 316 * checkout()'s version of msg. If we are in the middle of a | |
| 317 * shell, do a printf instead of a msg to a the refresh. | |
| 318 */ | |
| 319 /* VARARGS1 */ | |
| 320 | |
| 321 chmsg(char *fmt, int arg) | |
| 322 { | |
| 323 if (!in_shell) | |
| 324 msg(fmt, arg); | |
| 325 else | |
| 326 { | |
| 327 printf(fmt, arg); | |
| 328 putchar('\n'); | |
| 329 fflush(stdout); | |
| 330 } | |
| 331 } | |
| 332 #endif | |
| 333 | |
| 334 #ifdef UCOUNT | |
| 335 /* | |
| 336 * ucount: | |
| 337 * count number of users on the system | |
| 338 */ | |
| 339 #include <utmp.h> | |
| 340 | |
| 341 struct utmp buf; | |
| 342 | |
| 343 int | |
| 344 ucount(void) | |
| 345 { | |
| 346 struct utmp *up; | |
| 347 FILE *utmp; | |
| 348 int count; | |
| 349 | |
| 350 if ((utmp = fopen(UTMP, "r")) == NULL) | |
| 351 return 0; | |
| 352 | |
| 353 up = &buf; | |
| 354 count = 0; | |
| 355 | |
| 356 while (fread(up, 1, sizeof (*up), utmp) > 0) | |
| 357 if (buf.ut_name[0] != '\0') | |
| 358 count++; | |
| 359 fclose(utmp); | |
| 360 return count; | |
| 361 } | |
| 362 #endif | |
| 363 | |
| 364 /* | |
| 365 * lock_sc: | |
| 366 * lock the score file. If it takes too long, ask the user if | |
| 367 * they care to wait. Return TRUE if the lock is successful. | |
| 368 */ | |
| 369 static FILE *lfd = NULL; | |
| 370 int | |
| 371 lock_sc(void) | |
| 372 { | |
| 373 #if defined(SCOREFILE) && defined(LOCKFILE) | |
| 374 int cnt; | |
| 375 struct stat sbuf; | |
| 376 char *lockfile = LOCKFILE; | |
| 377 | |
| 378 over: | |
| 379 if ((lfd=fopen(lockfile, "w+")) != NULL) | |
| 380 return TRUE; | |
| 381 for (cnt = 0; cnt < 5; cnt++) | |
| 382 { | |
| 383 md_sleep(1); | |
| 384 if ((lfd=fopen(lockfile, "w+")) != NULL) | |
| 385 return TRUE; | |
| 386 } | |
| 387 if (stat(lockfile, &sbuf) < 0) | |
| 388 { | |
| 389 lfd=fopen(lockfile, "w+"); | |
| 390 return TRUE; | |
| 391 } |
