Mercurial > hg > early-roguelike
view arogue7/main.c @ 173:78fa1d0e5d25
srogue: open the score and log files when the program starts.
Super-Rogue can now use the same privilege-dropping scheme as the other
games.
author | John "Elwin" Edwards |
---|---|
date | Sat, 01 Aug 2015 15:12:11 -0400 |
parents | cadff8f047a1 |
children | f9ef86cf22b2 |
line wrap: on
line source
/* * main.c - setup code * * Advanced Rogue * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T * All rights reserved. * * Based on "Rogue: Exploring the Dungeons of Doom" * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include "curses.h" #include <stdlib.h> #include <string.h> #include <signal.h> #ifdef BSD #include <sys/time.h> #else #include <time.h> #endif #include "mach_dep.h" #include "network.h" #include "rogue.h" #ifdef PC7300 #include "sys/window.h" #include <ctype.h> extern struct uwdata wdata, oldwin; extern char oldtext[WTXTNUM][WTXTLEN]; #endif void open_records(void); main(argc, argv, envp) char **argv; char **envp; { register char *env; int lowtime; time_t now; #ifdef PC7300 int hardwindow; /* Do we have a hardware window? */ #endif md_init(); /* * get home and options from environment */ strncpy(home, md_gethomedir(), LINELEN); /* Get default save file */ strcpy(file_name, home); strcat(file_name, "arogue77.sav"); /* Get default score file */ #ifdef SCOREFILE strncpy(score_file, SCOREFILE, LINELEN); score_file[LINELEN-1] = '\0'; #else strcpy(score_file, md_getroguedir()); if (*score_file) strcat(score_file,"/"); strcat(score_file,"arogue77.scr"); #endif #ifdef SAVEDIR /* Check for common save location */ if (argc >= 3 && strcmp(argv[1], "-n") == 0) { strncpy(whoami, argv[2], 79); whoami[79] = '\0'; use_savedir = TRUE; if (LINELEN <= snprintf(file_name, LINELEN, "%s/%d-%s.ar7sav", SAVEDIR, md_getuid(), whoami)) { strcpy(file_name, "xrogue.sav"); use_savedir = FALSE; } } #endif if ((env = getenv("ROGUEOPTS")) != NULL) parse_opts(env); if (whoami[0] == '\0') strucpy(whoami, md_getusername(), strlen(md_getusername())); open_records(); /* * check for print-score option */ if (argc == 2 && strcmp(argv[1], "-s") == 0) { waswizard = TRUE; score(0, SCOREIT, 0); exit(0); } #ifdef NUMNET /* * Check for a network update */ if (argc == 2 && strcmp(argv[1], "-u") == 0) { unsigned long netread(); int errcheck, errors = 0; unsigned long amount; short monster; /* Read in the amount and monster values to pass to score */ amount = netread(&errcheck, sizeof(unsigned long), stdin); if (errcheck) errors++; monster = (short) netread(&errcheck, sizeof(short), stdin); if (errcheck) errors++; /* Now do the update if there were no errors */ if (errors) exit(1); else { score(amount, UPDATE, monster); exit(0); } } #endif #ifdef WIZARD /* * Check to see if he is a wizard */ if (argc >= 2 && argv[1][0] == '\0') if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "mT")) == 0) { wizard = TRUE; argv++; argc--; } #endif if (!wizard && !author() && !holiday()) { printf("Sorry, %s, but you can't play during working hours.\n", whoami); printf("Try again later.\n"); exit(1); } if (!wizard && !author() && too_much()) { printf("Sorry, %s, but the system is too loaded now.\n", whoami); printf("Try again later.\n"); exit(1); } #if NICE if (!wizard) nice(19); /* nice the max amount */ #endif if (use_savedir) { if (!restore(file_name, envp)) exit(1); } else { md_normaluser(); } if (argc == 2) if (!restore(argv[1], envp)) /* Note: restore will never return */ exit(1); lowtime = (int) time(&now); dnum = (wizard && getenv("SEED") != NULL ? atoi(getenv("SEED")) : lowtime + getpid()); if (wizard) printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum); else printf("Hello %s, just a moment while I dig the dungeon...\n", whoami); fflush(stdout); seed = dnum; md_srand(seed); #ifdef PC7300 /* Store static window parameters */ hardwindow = ioctl(0, WIOCGETD, &wdata); if (hardwindow >= 0) { /* We have a hardware window */ extern char **environ; /* Make sure our window is the right size */ oldwin = wdata; if ((wdata.uw_height / wdata.uw_vs) < 23 || (wdata.uw_width / wdata.uw_hs) < 75) { wdata.uw_width = 80 * wdata.uw_hs; wdata.uw_height = 24 * wdata.uw_vs; wdata.uw_x = 0; wdata.uw_y = wdata.uw_vs; wdata.uw_uflags = NBORDER; /* Make the change */ if (ioctl(1, WIOCSETD, &wdata) >= 0 && environ) { char **eptr, *tptr, *nptr, *newenv, *lptr = 0, *cptr = 0; int i, nlines = -1, ncols = -1, nlindig = 0, ncoldig = 0; struct utdata labelbuf; /* Save and change window-associated text */ for (i=0; i<WTXTNUM; i++) { labelbuf.ut_num = i; ioctl(1, WIOCGETTEXT, &labelbuf); strncpy(oldtext[i], labelbuf.ut_text, WTXTLEN - 1); if (*labelbuf.ut_text) { *labelbuf.ut_text = '\0'; ioctl(1, WIOCSETTEXT, &labelbuf); } } labelbuf.ut_num = WTXTLABEL; strcpy(labelbuf.ut_text, "Advanced Rogue"); ioctl(1, WIOCSETTEXT, &labelbuf); /* We have to change the TERMCAP entry */ eptr = environ; while (*eptr) { if (strncmp(*eptr, "TERMCAP=", 8) == 0) break; else eptr++; } /* We found a TERMCAP entry */ if (*eptr) { /* Search for li# and co# */ tptr = *eptr; while (*tptr) { switch (*tptr) { case 'l': if (nlines == -1 && strncmp(tptr, "li#", 3) == 0) { tptr += 3; lptr = tptr; lines = atoi(tptr); while (isdigit(*tptr)) { nlindig++;; tptr++; } } else tptr++; break; case 'c': if (ncols == -1 && strncmp(tptr, "co#", 3) == 0) { tptr += 3; cptr = tptr; cols = atoi(tptr); while (isdigit(*tptr)) { ncoldig++; tptr++; } } else tptr++; break; default: tptr++; } } /* Change the entry */ if (ncoldig != 2 || nlindig != 2) { int length; /* Add in difference in num lengths plus NULL */ length = strlen(*eptr) - ncoldig - nlindig + 5; if (ncoldig == 0) length += 4; /* For :co# */ if (nlindig == 0) length += 4; /* For :li# */ newenv = malloc(length); tptr = *eptr; nptr = newenv; if (nlindig == 0 || ncoldig == 0) { /* Copy up to the first : */ while (*tptr && *tptr != ':') *nptr++ = *tptr++; /* Do we have to add a field? */ if (nlindig == 0) { strcpy(nptr, ":li#24"); nptr += 6; } if (ncoldig == 0) { strcpy(nptr, ":co#80"); nptr += 6; } } while (*tptr) { if (tptr == lptr) { strcpy(nptr, "24"); nptr += 2; tptr += nlindig; } else if (tptr == cptr) { strcpy(nptr, "80"); nptr += 2; tptr += ncoldig; } else *nptr++ = *tptr++; } *nptr = '\0'; /* Replace the old one */ free(*eptr); *eptr = newenv; } else { /* Just overwrite the old numbers */ *lptr++ = '2'; *lptr = '4'; *cptr++ = '8'; *cptr = '0'; } } } } } #endif init_things(); /* Set up probabilities of things */ init_colors(); /* Set up colors of potions */ init_stones(); /* Set up stone settings of rings */ init_materials(); /* Set up materials of wands */ initscr(); /* Start up cursor package */ init_names(); /* Set up names of scrolls */ init_misc(); /* Set up miscellaneous magic */ init_foods(); /* set up the food table */ cols = COLS; lines = LINES; if (cols > 85) cols = 85; if (lines > 24) lines = 24; if (lines < 23 || cols < 75) { /* give player a break if larger font used */ printf("\nERROR: screen size too small for rogue\n"); byebye(0); } /* * Now that we have cols and lines, we can update our window * structure for non-hardware windows. */ #ifdef PC7300 if (hardwindow < 0) { wdata.uw_x = 0; wdata.uw_y = 0; wdata.uw_width = COLS; wdata.uw_height = LINES; wdata.uw_uflags = 0; wdata.uw_hs = 1; wdata.uw_vs = 1; wdata.uw_baseline = 0; } #endif setup(); /* * Set up windows */ cw = newwin(lines, cols, 0, 0); mw = newwin(lines, cols, 0, 0); hw = newwin(lines, cols, 0, 0); msgw = newwin(4, cols, 0, 0); keypad(cw,TRUE); keypad(msgw,TRUE); init_player(); /* Roll up the rogue */ waswizard = wizard; #ifdef WIZARD /* A super wizard doesn't have to get equipped */ if (wizard && strcmp(getenv("SUPER"),"YES") == 0) { level = 1; new_level(NORMLEV); } else #endif new_level(STARTLEV); /* Draw current level */ /* * Start up daemons and fuses */ start_daemon(doctor, &player, AFTER); fuse(swander, 0, WANDERTIME, AFTER); if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER) fuse(spell_recovery, 0, SPELLTIME, AFTER); if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER) fuse(chant_recovery, 0, SPELLTIME, AFTER); if (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) fuse(prayer_recovery, 0, SPELLTIME, AFTER); start_daemon(stomach, 0, AFTER); if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN || player.t_ctype == C_MONK) start_daemon(trap_look, 0, AFTER); /* Does this character have any special knowledge? */ switch (player.t_ctype) { case C_ASSASIN: /* Assassins automatically recognize poison */ p_know[P_POISON] = TRUE; } /* Choose a quest item */ quest_item = rnd(MAXRELIC); draw(cw); msg("You have been quested to retrieve the %s....", rel_magic[quest_item].mi_name); mpos = 0; playit(); } /* * endit: * Exit the program abnormally. */ void endit(sig) int sig; { fatal("Ok, if you want to exit that badly, I'll have to allow it\n"); } /* * fatal: * Exit the program, printing a message. */ fatal(s) char *s; { clear(); move(lines-2, 0); printw("%s", s); draw(stdscr); endwin(); #ifdef PC7300 endhardwin(); #endif printf("\n"); /* So the curser doesn't stop at the end of the line */ exit(0); } /* * rnd: * Pick a very random number. */ rnd(range) register int range; { return(range <= 0 ? 0 : md_rand() % range); } /* * roll: * roll a number of dice */ roll(number, sides) register int number, sides; { register int dtotal = 0; while(number--) dtotal += rnd(sides)+1; return dtotal; } # ifdef SIGTSTP /* * handle stop and start signals */ void tstp(sig) int sig; { mvcur(0, cols - 1, lines - 1, 0); endwin(); fflush(stdout); kill(0, SIGTSTP); signal(SIGTSTP, tstp); raw(); noecho(); keypad(cw,1); keypad(msgw,1); clearok(curscr, TRUE); touchwin(cw); draw(cw); md_flushinp(); } # endif setup() { #ifdef CHECKTIME int checkout(); if (!author()) { signal(SIGALRM, checkout); alarm(CHECKTIME * 60); } #endif /* #ifndef DUMP signal(SIGILL, bugkill); #ifdef SIGTRAP signal(SIGTRAP, bugkill); #endif #ifdef SIGIOT signal(SIGIOT, bugkill); #endif #ifdef SIGEMT signal(SIGEMT, bugkill); #endif signal(SIGFPE, bugkill); #ifdef SIGBUS signal(SIGBUS, bugkill); #endif signal(SIGSEGV, bugkill); #ifdef SIGSYS signal(SIGSYS, bugkill); #endif #ifdef SIGPIPE signal(SIGPIPE, bugkill); #endif #endif */ #ifdef SIGTSTP signal(SIGTSTP, tstp); #endif #ifdef SIGHUP signal(SIGHUP, auto_save); #endif signal(SIGTERM, auto_save); signal(SIGINT, quit); #ifdef SIGQUIT signal(SIGQUIT, endit); #endif raw(); /* Cbreak mode */ noecho(); /* Echo off */ nonl(); } void open_records(void) { if (scorefd == -1) md_reopen_score(); #ifdef LOGFILE if (logfile == NULL) logfile = fopen(LOGFILE, "a"); #endif return; } /* * playit: * The main loop of the program. Loop until the game is over, * refreshing things and looking at the proper times. */ playit() { register char *opts; /* * parse environment declaration of options */ if ((opts = getenv("ROGUEOPTS")) != NULL) parse_opts(opts); player.t_oldpos = hero; oldrp = roomin(&hero); after = TRUE; command(); /* Command execution */ endit(0); } /* * see if the system is being used too much for this game */ too_much() { #if MAXPROCESSES if (loadav() > MAXPROCESSES) return(TRUE); #endif #if MAXUSERS if (ucount() > MAXUSERS) return(TRUE); #endif return(FALSE); } /* * author: * See if a user is an author of the program */ author() { switch (md_getuid()) { #if AUTHOR case AUTHOR: #endif case 0: /* always OK for root to play */ return TRUE; default: return FALSE; } } #if CHECKTIME static int num_checks = 0; /* times we've gone over in checkout() */ checkout() { static char *msgs[] = { "The system is too loaded for games. Please leave in %d minutes", "Please save your game. You have %d minutes", "This is your last chance. You had better leave in %d minutes", }; int checktime; signal(SIGALRM, checkout); if (!holiday() && !author()) { msg("Game time is over. Your game is being saved.\n\n"); auto_save(); /* NO RETURN */ } if (too_much()) { if (num_checks >= 3) fatal("You didn't listen, so now you are DEAD !!\n"); checktime = CHECKTIME / (num_checks + 1); chmsg(msgs[num_checks++], checktime); alarm(checktime * 60); } else { if (num_checks) { chmsg("The load has dropped. You have a reprieve."); num_checks = 0; } alarm(CHECKTIME * 60); } } /* * checkout()'s version of msg. If we are in the middle of a shell, do a * printf instead of a msg to avoid the refresh. */ chmsg(fmt, arg) char *fmt; int arg; { if (in_shell) { printf(fmt, arg); putchar('\n'); fflush(stdout); } else msg(fmt, arg); } #endif #ifdef MAXPROCESSES #include <fcntl.h> loadav() { char *sarcmd = "sar -v | cut -c17-20 | tail -2"; char *gettycmd = "grep getty /etc/inittab | wc -l"; char sysbuffer[BUFSIZ]; char tempfile[50]; char inbuf[BUFSIZ]; int fd, nprocess, ngetty; sprintf(tempfile, "/tmp/rg%d", getpid()); sprintf(sysbuffer, "%s > %s", sarcmd, tempfile); if (system(sysbuffer) != 0) { debug ("system() call failed"); return (MAXPROCESSES - 1); } if ((fd = open(tempfile, O_RDONLY)) == -1) { debug ("open() call failed"); return (MAXPROCESSES - 1); } if (read(fd, inbuf, BUFSIZ) == -1) { debug ("read() call failed"); return (MAXPROCESSES - 1); } close(fd); sscanf(inbuf, "%d", &nprocess); sprintf(sysbuffer, "%s > %s", gettycmd, tempfile); if (system(sysbuffer) != 0) { debug ("system() call failed"); return (MAXPROCESSES - 1); } if ((fd = open(tempfile, O_RDONLY)) == -1) { debug ("open() call failed"); return (MAXPROCESSES - 1); } if (read(fd, inbuf, BUFSIZ) == -1) { debug ("read() call failed"); return (MAXPROCESSES - 1); } close(fd); sscanf(inbuf, "%d", &ngetty); unlink(tempfile); return(nprocess - ngetty); } #endif #ifdef MAXUSERS /* * ucount: * Count the number of people on the system */ #include <sys/types.h> #include <utmp.h> struct utmp buf; ucount() { reg struct utmp *up; reg FILE *utmp; reg int count; if ((utmp = fopen(UTMP, "r")) == NULL) return 0; up = &buf; count = 0; while (fread(up, 1, sizeof (*up), utmp) > 0) #ifdef BSD if (buf.ut_line[0] == 't') /* On a tty */ #else if (buf.ut_type == USER_PROCESS) #endif count++; fclose(utmp); return count; } #endif /* * holiday: * Returns TRUE when it is a good time to play rogue */ holiday() { #ifdef CHECKTIME long now; struct tm *localtime(); reg struct tm *ntime; time(&now); /* get the current time */ ntime = localtime(&now); if(ntime->tm_wday == 0 || ntime->tm_wday == 6) return TRUE; /* OK on Sat & Sun */ if(ntime->tm_hour < 8 || ntime->tm_hour >= 18) return TRUE; /* OK before 8AM & after 6PM */ if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350) return TRUE; /* OK during Christmas */ return FALSE; /* All other times are bad */ #else return TRUE; #endif }