Mercurial > ~darius > hgwebdir.cgi > paradise_server
view src/main.c @ 7:814de70c9f67
Initial revision
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:04 +0000 |
parents | aa38447a4b21 |
children |
line wrap: on
line source
/*-------------------------------------------------------------------------- NETREK II -- Paradise Permission to use, copy, modify, and distribute this software and its documentation, or any derivative works thereof, for any NON-COMMERCIAL purpose and without fee is hereby granted, provided that this copyright notice appear in all copies. No representations are made about the suitability of this software for any purpose. This software is provided "as is" without express or implied warranty. Xtrek Copyright 1986 Chris Guthrie Netrek (Xtrek II) Copyright 1989 Kevin P. Smith Scott Silvey Paradise II (Netrek II) Copyright 1993 Larry Denys Kurt Olsen Brandon Gillespie --------------------------------------------------------------------------*/ char binary[] = "@(#)ntserv"; #include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <signal.h> #include <setjmp.h> #include <pwd.h> #include <sys/time.h> #include <sys/wait.h> #include <sys/resource.h> #include <unistd.h> #include "defs.h" #include "struct.h" #include "data.h" #include "packets.h" #include "shmem.h" #include "path.h" #if 0 #define D(s) do { s } while(0) #else #define D(s) #endif #if 0 jmp_buf env; #endif int startTkills, startTlosses, startTarms, startTplanets, startTticks; char start_login[16]; /* change 1/25/91 TC */ char start_name[16]; /* change 1/25/91 TC */ int goAway = 0; /* change 4/14/91 TC */ int ignored[MAXPLAYER]; /* change 7/24/91 TC */ int overload = 0; /* global 7/31/91 TC */ /* overload indicates a request for a reserved slot */ int indie = 0; /* always be indie 8/28/91 TC */ extern void load_time_access(); void printntservUsage(); extern pid_t getpid(); extern int connectToClient(); extern int checkSocket(); extern int initClientData(); extern int socketPause(); extern int readFromClient(); extern int checkVersion(); extern int findslot(); extern void updateSelf(); extern void updateShips(); extern void updatePlanets(); extern void updateTerrain(); extern void flushSockBuf(); extern int getname(); extern int sendShipCap(); extern int logEntry(); extern int getEntry(); void printStats(); void exitGame(); #if defined(sparc) && !defined(SVR4) int atexitfunc( /* int, caddr_t */ ); #else void atexitfunc(); #endif extern void (*r_signal()) (); extern int enter(); extern int input(); extern int setitimer(); extern int pmessage2(); extern int savestats(); extern void move_player(); extern int sendMotdLine(); extern int time_access(); void doMotdPics(); extern int numPlanets(); extern int sendMotdPic(); extern int ParseXbmFile(); int main(argc, argv) int argc; char **argv; { int intrupt(); char *getenv(); int team, s_type; int pno; int usage = 0; /* Flag saying tell usage */ int errorc = 0; /* Error count */ char *errorv[5]; /* Error Vector (cannot have more than 5) */ char *name, *ptr; int reaper(); int callHost = 0; long starttime; enum HomeAway homeaway = NEITHER; int observer = 0; argv0 = argv[0]; pno = time(NULL); /* load_time_acess - read in the hours file, Larry's. */ load_time_access(); name = *argv++; argc--; if ((ptr = strrchr(name, '/')) != NULL) name = ptr + 1; while (*argv) { if (**argv == '-') ++* argv; else break; argc--; ptr = *argv++; while (*ptr) { switch (*ptr) { case 'u': /* for old times sake */ case '-': /* this will help the --help people */ case 'h': usage++; break; case 'i': indie++; break; /* 8/28/91 TC */ case 'R': if (getuid() == geteuid()) overload++; break; case 's': xtrekPort = atoi(*argv); callHost = 1; argv++; argc--; break; case 'M': blk_metaserver = 1; break; case 'd': host = *argv; argc--; argv++; break; /* netrek league stuff */ case 'O': observer = 1; break; case 'H': homeaway = HOME; break; case 'A': homeaway = AWAY; break; default: { char buffer[100]; sprintf(buffer, "Unknown option '%c'\n", *ptr); errorv[errorc++] = buffer; break; } } if (usage) break; ptr++; } } if (usage || errorc) { int x; char message[][255] = { "\n\t'%s [options] -s <socket number> <display address>'\n\n", "Options:\n", "\t-h Help (this usage message)\n", "\t-i Team independant\n", "\t-R Reserved slot\n", "\t-s Socket number\n", "\t-M Metaserver\n", "\t-d Display\n", "\t-O Observer\n", "\t-H Home (League Play)\n", "\t-A Away (League Play)\n", "\nNOTE: %s is designed to be launched by the startup process\n\n", "\0" }; fprintf(stderr, "-- NetrekII (Paradise), %s --\n", PARAVERS); for (x = 0; x < errorc; x++) fprintf(stderr, "\n%s: %s", argv0, errorv[x]); for (x = 0; *message[x] != '\0'; x++) fprintf(stderr, message[x], argv0); exit(1); } openmem(1, homeaway != NEITHER); /* compatability */ if (argc > 0) host = argv[0]; srand48(getpid() + time((time_t *) 0)); /* this finds the shared memory information */ #if 0 if (blk_metaserver) { FILE *ptr; char *buf; buf = build_path("logs/metaserver.log"); ptr = fopen(buf, "a"); fprintf(ptr, "Connection from meta-server\n"); fclose(ptr); } #endif me = NULL; /* UDP fix (?) */ if (callHost) { if (!connectToClient(host, xtrekPort)) { exit(0); } } else { sock = 0; /* Because we were forked by inetd! */ checkSocket(); initClientData(); /* "normally" called by connectToClient() */ } starttime = time(NULL); while (userVersion == 0) { /* * Waiting for user to send his version number. We give him ten seconds * to do so... */ if (starttime + 10 < time(NULL)) { exit(1); } socketPause(); readFromClient(); } if (!checkVersion()) exit(1); pno = findslot(overload, homeaway); if (pno < 0) { /* print some appropriate message */ exit(1); } #if defined(sparc) && !defined(SVR4) on_exit(atexitfunc, (caddr_t) 0); #else atexit(atexitfunc); /* register a function to execute at exit */ #endif me = &players[pno]; me->p_no = pno; me->p_team = NOBODY; me->p_stats.st_royal = 0; #ifdef RC_DISTRESS me->gen_distress = 0; /* default to RCD off */ #endif me->p_ntspid = getpid(); myship = &me->p_ship; mystats = &me->p_stats; lastm = mctl->mc_current; me->p_lastrefit = -1; me->p_spyable = 1; me->p_teamspy = ~0; #if 0 me->p_planfrac = 0; /* reset fractional parts */ me->p_bombfrac = 0; /* reset fractional parts */ #endif /* --------------------------[ CLUECHECK stuff ]-------------------------- */ #ifdef CLUECHECK1 me->p_cluedelay = 10; me->p_cluecountdown = 0; #endif #ifdef CLUECHECK2 me->p_cluedelay = lrand48() % 1000; /* so it doesn't ask them immediately */ me->p_cluecountdown = 0; #endif /* ----------------------------------------------------------------------- */ #ifndef AUTHORIZE strcpy(RSA_client_type, "server doesn't support RSA"); #endif (void) r_signal(SIGINT, SIG_IGN); (void) r_signal(SIGCHLD, reaper); /* * We set these so we won't bother updating him on the location of the * other players in the galaxy which he is not near. There is no real harm * to doing this, except that he would then get more information than he * deserves. It is kind of a hack, but should be harmless. */ me->p_x = -100000; me->p_y = -100000; me->p_homeaway = homeaway; me->p_observer = observer; #if 0 updateGameparams(); #endif updateSelf(); /* so he gets info on who he is */ updateShips(); /* put this back so maybe something will work */ /* with Andy's meta-server */ if (!blk_metaserver) { updateStatus(); updatePlanets(); updateTerrain(); } #if 1 updateGameparams(); #endif flushSockBuf(); /* Get login name */ #if 0 if ((pwent = getpwuid(getuid())) != NULL) (void) strncpy(login, pwent->pw_name, sizeof(login)); else #endif (void) strncpy(login, "Bozo", sizeof(login)); login[sizeof(login) - 1] = '\0'; strcpy(pseudo, "Guest"); strcpy(me->p_name, pseudo); me->p_team = ALLTEAM; getname(); if (me->p_stats.st_rank >= NUMRANKS) me->p_stats.st_rank = NUMRANKS - 1; if (me->p_stats.st_royal >= NUMROYALRANKS) me->p_stats.st_royal = NUMROYALRANKS - 1; strcpy(pseudo, me->p_name); strcpy(start_name, me->p_name); /* change 1/25/91 TC */ sendShipCap(); /* KAO 1/25/93 */ keeppeace = (me->p_stats.st_flags & ST_KEEPPEACE) == ST_KEEPPEACE; /* * Set p_hostile to hostile, so if keeppeace is on, the guy starts off * hating everyone (like a good fighter should) */ me->p_hostile = (FED | ROM | KLI | ORI); s_type = CRUISER; me->p_planets = 0; me->p_armsbomb = 0; me->p_dooshes = 0; me->p_resbomb = 0; /* Set up a reasonable default */ me->p_whydead = KQUIT; (void) strncpy(me->p_login, login, sizeof(me->p_login)); me->p_login[sizeof(me->p_login) - 1] = '\0'; strcpy(start_login, login); /* change 1/25/91 TC */ { int i; for (i = 0; i < MAXPLAYER; i++) ignored[i] = 0; } (void) strncpy(me->p_monitor, host, sizeof(me->p_monitor)); me->p_monitor[sizeof(me->p_monitor) - 1] = '\0'; /* assume this is only place p_monitor is set, and mirror accordingly */ /* 4/13/92 TC */ (void) strncpy(me->p_full_hostname, host, sizeof(me->p_full_hostname)); me->p_full_hostname[sizeof(me->p_full_hostname) - 1] = '\0'; logEntry(); /* moved down to get login/monitor 2/12/92 * TMC */ me->p_avrt = -1; /* ping stats */ me->p_stdv = -1; me->p_pkls = -1; startTkills = me->p_stats.st_tkills; startTlosses = me->p_stats.st_tlosses; startTarms = me->p_stats.st_tarmsbomb; startTplanets = me->p_stats.st_tplanets; startTticks = me->p_stats.st_tticks; r_signal(SIGHUP, exitGame); /* allows use of HUP to force a clean exit */ me->p_status = POUTFIT; repCount = 0; while (1) { switch (me->p_status) { case POUTFIT: case PTQUEUE: /* give the player the motd and find out which team he wants */ if (me->p_status != PALIVE) { me->p_x = -100000; me->p_y = -100000; updateSelf(); updateShips(); teamPick = -1; flushSockBuf(); getEntry(&team, &s_type); } if (goAway) { /* change 4/14/91 TC */ printStats(); exit(0); } if (team == -1) { exitGame(); } if (indie) team = 4; /* force to independent 8/28/91 TC */ inputMask = -1; /* Allow all input now */ enter(team, 0, pno, s_type, -1); /* for (i = 0; i < NSIG; i++) { r_signal(i, SIG_IGN); } */ me->p_status = me->p_observer ? POBSERVE : PALIVE; /* Put player in game */ me->p_ghostbuster = 0; break; case PALIVE: case PEXPLODE: case PDEAD: case POBSERVE: /* Get input until the player quits or dies */ input(); break; default: if (tmpPick != PATROL) { printf("player status = %d. exiting\n", me->p_status); exitGame(); } } } /* NOTREACHED */ return 1; } extern int setflag(); /* input.c */ int interrupting = 0; void stop_interruptor() { struct itimerval udt; if (!interrupting) return; r_signal(SIGALRM, SIG_IGN); /* set up signals */ udt.it_interval.tv_sec = 0; udt.it_interval.tv_usec = 0; udt.it_value.tv_sec = 0; udt.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &udt, 0); interrupting = 0; } void start_interruptor() { struct itimerval udt; if (interrupting) return; { int min_delay = me->p_observer ? configvals->min_observer_upd_delay : configvals->min_upd_delay; if (timerDelay < min_delay) timerDelay = min_delay; } r_signal(SIGALRM, SIG_IGN); /* set up signals */ udt.it_interval.tv_sec = 0; udt.it_interval.tv_usec = timerDelay; udt.it_value.tv_sec = 0; udt.it_value.tv_usec = timerDelay; setitimer(ITIMER_REAL, &udt, 0); r_signal(SIGALRM, setflag); interrupting = 1; } #if 0 /* * this is TOTALLY untested. It probably doesn't belong in this file, * either. When I figure out all the mechanisms, this will replace the while * loop in main(). RF */ void inputloop() { static int switching = -1; /* is the player changing teams? */ int status = me->p_status; while (1) { switch (status) { case PFREE: status = me->p_status = PDEAD; me->p_explode = 600; stop_interruptor(); break; case POUTFIT: case PTQUEUE: updateSelf(); updateShips(); sendMaskPacket(tournamentMask(me->p_team)); briefUpdateClient(); teamPick = -1; socketPause(); break; case PEXPLODE: case PDEAD: inputMask = 0; case PALIVE: socketWait(); delay_interrupt(); /* don't let client read be interrupted by * the interval timer */ /* * ^-- won't work.. delay_interrupt doesn't stop ALRMs from happening * (HAK 9/21) */ break; } /* me->p_status could change in here. */ readFromClient(); if (isClientDead()) { if (!reconnect()) { /* me->p_status=PFREE; should this be done? RF */ exit(0); } } switch (status) { case POUTFIT: case PTQUEUE: if (teamPick == -1) break; if (teamPick < 0 || teamPick > 3 /* XXX */ ) { warning("That is not a valid team."); sendPickokPacket(0); } else if (!(tournamentMask(me->p_team) & (1 << teamPick))) { warning("I cannot allow that. Pick another team"); sendPickokPacket(0); } else if (((1 << teamPick) != me->p_team) && (me->p_team != ALLTEAM) && switching != teamPick && me->p_whydead != KGENOCIDE) { /* switching teams */ switching = teamPick; warning("Please confirm change of teams. Select the new team again."); sendPickokPacket(0); } else if (shipPick < 0 || shipPick >= NUM_TYPES) { /* His team choice is ok. */ warning("That is an illegal ship type. Try again."); sendPickokPacket(0); } else if (!allowed_ship(1 << teamPick, mystats->st_rank, mystats->st_royal, shipPick)) { sendPickokPacket(0); } else { if (goAway) { /* what does this do ? */ printStats(); exit(0); } if (indie) me->p_team = 4; inputMask = -1; enter(teamPick, 0, me->p_no, shipPick, -1); status = me->p_status = me->p_observer ? POBSERVER : PALIVE; start_interruptor(); /* since we're alive, we need regular * interrupts now */ me->p_ghostbuster = 0; repCount = 0; } break; case PALIVE: case PEXPLODE: case PDEAD: if (0 /* sendflag */ ) { /* this is still busted, ugh */ check_authentication(); if (me->p_status == PFREE) { me->p_ghostbuster = 0; me->p_status = PDEAD; } if ((me->p_status == PDEAD || me->p_status == POUTFIT) && (me->p_ntorp <= 0) && (me->p_nplasmatorp <= 0)) { stop_interruptor(); death(); status = POUTFIT; } auto_features(); updateClient(); /* sendflag=0; ugh, broke */ } reenable_interrupt(); } } } #endif void exitGame() { char buf[80]; char addrbuf[20]; if (me != NULL && me->p_team != ALLTEAM) { sprintf(buf, "%s %s (%s) leaving game (%.16s@%.32s)", ((me->p_stats.st_royal) ? royal[me->p_stats.st_royal].name : ranks[me->p_stats.st_rank].name), me->p_name, twoletters(me), me->p_login, me->p_full_hostname ); sprintf(addrbuf, " %s->ALL", twoletters(me)); pmessage2(buf, 0, MALL | MLEAVE, addrbuf, me->p_no); me->p_stats.st_flags &= ~ST_CYBORG; /* clear this flag 8/27/91 TC */ savestats(); printStats(); } me->p_status = PFREE; move_player(me->p_no, -1, -1, 1); exit(0); } #if defined(sparc) && !defined(SVR4) int atexitfunc(status, arg) int status; caddr_t arg; #else void atexitfunc() #endif { me->p_ntspid = 0; me->p_status = PFREE; } #define PLURAL(n) (((n)==1)?"":"s") static char *weapon_types[WP_MAX] = { "Plasma torpedos", "Tractors", "Missiles", "Fighters", }; void sendSysDefs() { char buf[200], buf2[200]; int i; sendMotdLine("\t@@@"); if (!time_access()) { sendMotdLine("** WE ARE CLOSED, CHECK HOURS **"); sendMotdLine(""); } sendMotdLine("Available ship types:"); buf[0] = 0; for (i = 0; i < NUM_TYPES; i++) { struct ship *s = &shipvals[i]; if (!shipsallowed[i]) continue; sprintf(buf2, " %c) %s/%c%c", s->s_letter, s->s_name, s->s_desig1, s->s_desig2); if (strlen(buf) + strlen(buf2) > 80) { sendMotdLine(buf); strcpy(buf, buf2); } else { strcat(buf, buf2); } } /* guaranteed to have stuff here */ sendMotdLine(buf); sendMotdLine(""); sendMotdLine( "SHIP REQUIRED RANK BUILD TIME LIMIT NUM PLYRS NUM PLNTS"); for (i = 0; i < NUM_TYPES; i++) { struct ship *s = &shipvals[i]; if (!shipsallowed[i]) continue; buf2[0] = 0; if (s->s_rank > 0 || s->s_timer > 0 || s->s_maxnum < 16 || s->s_numdefn || s->s_numplan) { sprintf(buf2, "%-13s%-16s", s->s_name, s->s_rank ? ranks[s->s_rank].name : "none"); if (s->s_timer > 0) sprintf(buf, "%d minutes", s->s_timer); else strcpy(buf, "none"); sprintf(buf2 + strlen(buf2), "%-14s", buf); if (s->s_maxnum < 16) sprintf(buf, "%d/team", s->s_maxnum); else strcpy(buf, "none"); sprintf(buf2 + strlen(buf2), "%-12s %-3d %-3d", buf, s->s_numdefn, s->s_numplan); sendMotdLine(buf2); } } sendMotdLine(""); buf2[0] = 0; for (i = 0; i < WP_MAX; i++) { if (weaponsallowed[i]) { if (buf2[0]) strcat(buf2, ", "); strcat(buf2, weapon_types[i]); } } sprintf(buf, "Special weapons enabled: %s", buf2[0] ? buf2 : "none"); sendMotdLine(buf); if (weaponsallowed[WP_PLASMA]) { sprintf(buf, "You need %.1f kill%s to get plasma torpedos", configvals->plkills, PLURAL(configvals->plkills)); sendMotdLine(buf); } if (weaponsallowed[WP_MISSILE]) { sprintf(buf, "You need %.1f kill%s to get missiles", configvals->mskills, PLURAL(configvals->mskills)); sendMotdLine(buf); } sendMotdLine(""); sprintf(buf, "Tournament mode requires %d player%s per team", configvals->tournplayers, PLURAL(configvals->tournplayers)); sendMotdLine(buf); /* sendMotdLine(""); */ /* We don't blab about newturn */ #if 0 sendMotdLine(configvals->hiddenenemy ? "Visibility is restricted during T-mode" : "Visibility is unlimited all the time"); #endif sendMotdLine(configvals->binconfirm ? "Only authorized binaries are allowed" : "Non-authorized binaries are detected but not rejected"); if (configvals->planetlimittype) { sprintf(buf, "Independent planets may be taken if your team has fewer than %d planets", configvals->planetsinplay); sendMotdLine(buf); } else { sprintf(buf, "Only %d planets can be in play at once", configvals->planetsinplay); sendMotdLine(buf); } if (configvals->planupdspd == 0) { sendMotdLine("Planets do not orbit their stars"); } else { sprintf(buf, "Planets orbit their stars at a rate of %g", configvals->planupdspd); sendMotdLine(buf); } sendMotdLine(configvals->warpdecel ? "New warp deceleration code is in effect" : "Old-style instant warp deceleration is in effect"); sprintf(buf, "The next galaxy will be generated using method #%d", configvals->galaxygenerator); sendMotdLine(buf); sendMotdLine (configvals->affect_shiptimers_outside_T ? "Ship deaths outside tournament mode affect construction timers" : "Construction timers are not affected by ship deaths outside tournament mode"); sprintf(buf, "Cloaking during warp prep is %sallowed", configvals->cloakduringwarpprep ? "" : "not "); sendMotdLine(buf); sprintf(buf, "Cloaking during warp is %sallowed", configvals->cloakwhilewarping ? "" : "not "); sendMotdLine(buf); sprintf(buf, "Variable warp speed is %sabled", configvals->variable_warp ? "en" : "dis"); sendMotdLine(buf); sprintf(buf, "Warp prep suspension is %sallowed", configvals->warpprep_suspendable ? "" : "not "); sendMotdLine(buf); switch (configvals->warpprepstyle) { case WPS_NOTRACT: sendMotdLine("Tractors do not affect warp prep"); break; case WPS_TABORT: sendMotdLine("Tractors make warp fail to engage"); break; case WPS_TPREVENT: sendMotdLine("Tractors prevent entering warp"); break; case WPS_TABORTNOW: sendMotdLine("Tractors abort warp prep countdown"); break; case WPS_TSUSPEND: sendMotdLine("Tractors suspend warp prep countdown"); break; } sprintf(buf, "There is a %d%% chance that you'll orbit a planet CCW", (int) ((1.0 - configvals->orbitdirprob) * 100)); sendMotdLine(buf); sprintf(buf, "Army growth: %d. Pop choice: %d. Pop speed: %d%%.", configvals->popscheme, configvals->popchoice, configvals->popspeed); sendMotdLine(buf); if (configvals->warpzone) { sprintf(buf, "Warp zones are enabled with radius %d.", configvals->warpzone); } else { sprintf(buf, "Warp zones are disabled."); } sendMotdLine(buf); } void sendMotd() { FILE *motd; char buf[100], buf2[30]; /* big enough... */ char *paths; time_t curtime; struct tm *tmstruct; int hour, tacc; time(&curtime); tmstruct = localtime(&curtime); if (!(hour = tmstruct->tm_hour % 12)) hour = 12; sprintf(buf, "Netrek II (Paradise) server %s, connection established at %d:%02d%s.", PARAVERS, hour, tmstruct->tm_min, tmstruct->tm_hour >= 12 ? "pm" : "am"); /* * if (!(tacc = time_access())) strcat(buf, " WE'RE CLOSED, CHECK HOURS"); */ sendMotdLine(buf); sendMotdLine(" "); if (!blk_flag) { paths = build_path(WCMOTD); /* Wrong client message */ if ((motd = fopen(paths, "r")) != NULL) { while (fgets(buf, sizeof(buf), motd) != NULL) { buf[strlen(buf) - 1] = '\0'; sendMotdLine(buf); } fclose(motd); } else { /* default message */ sendMotdLine(" "); sendMotdLine( " ****************************************************************"); sendMotdLine(" "); sendMotdLine( " This is a Paradise server; you need a Paradise client to play!"); sendMotdLine(" "); sendMotdLine( " Paradise clients can be had from"); sendMotdLine( " ftp.cis.ufl.edu pub/netrek.paradise/"); sendMotdLine( " ftp.reed.edu mirrors/netrek.paradise/"); sendMotdLine(" "); sendMotdLine( " ****************************************************************"); } return; } /* if (blk_flag) */ { /* added 1/19/93 KAO */ int i, first = 1; strcpy(buf, "BLK: REFIT "); for (i = 0; i < NUM_TYPES; i++) { struct ship *s = &shipvals[i]; if (!shipsallowed[i]) continue; if (!first) strcat(buf, ", "); else first = 0; sprintf(buf2, "%c) %c%c", s->s_letter, s->s_desig1, s->s_desig2); strcat(buf, buf2); } sendMotdLine(buf); } /* the following will read a motd */ if (!time_access()) { paths = build_path(CLOSEDMOTD); if ((motd = fopen(paths, "r")) == NULL) { paths = build_path(MOTD); motd = fopen(paths, "r"); } } else { paths = build_path(MOTD); motd = fopen(paths, "r"); } if (motd != NULL) { #ifdef CLUECHECK1 init_motdbuf(paths); #endif while (fgets(buf, sizeof(buf), motd) != NULL) { buf[strlen(buf) - 1] = '\0'; sendMotdLine(buf); } (void) fclose(motd); } sendSysDefs(); /* wait till the end for the pictures */ if (!blk_metaserver) doMotdPics(); } int reaper(sig) int sig; { #ifndef SVR4 while (wait3((union wait *) 0, WNOHANG, (struct rusage *) 0) > 0); #else while (waitpid(0, NULL, WNOHANG) > 0); #endif /* SVR4 */ return 0; } void printStats() { FILE *logfile; #if defined(SVR4) || defined(sparc) time_t curtime; #else int curtime; #endif /* SVR4 */ char *paths; /* added 1/18/93 KAO */ paths = build_path(LOGFILENAME); logfile = fopen(paths, "a"); if (!logfile) return; curtime = time(NULL); #ifdef LOG_LONG_INFO /*-[ Long info printed to logfiles and startup.log ]-*/ fprintf(logfile, "Leaving: %-16s (%s) %3dP %3dA %3dW/%3dL %3dmin %drtt %dsdv %dls %dplan <%s@%s> %s", me->p_name, twoletters(me), me->p_stats.st_tplanets - startTplanets, me->p_stats.st_tarmsbomb - startTarms, me->p_stats.st_tkills - startTkills, me->p_stats.st_tlosses - startTlosses, (me->p_stats.st_tticks - startTticks) / 600, me->p_avrt, me->p_stdv, me->p_pkls, numPlanets(me->p_team), #else fprintf(logfile, "Leaving: %s <%s@%s> %s", me->p_name, #endif me->p_login, me->p_full_hostname, ctime(&curtime)); /* #endif /*-[ LOG_LONG_INFO ]- */ if (goAway) fprintf(logfile, "^^^ 2 players/1 slot. was %s (%s)\n", start_name, start_login); fclose(logfile); } /* * .pics file format: * * name x y page name x y page etc */ void doMotdPics() { FILE *ptr, *ftemp; char buf[128], fname[128]; unsigned char *bits; char *result; int x, y, page, w, h; int bytesperline; /* pad the width to a byte */ int linesperblock; /* how many lines in 1016 bytes? */ int i; char *paths; paths = build_path(PICS); ptr = fopen(paths, "r"); if (ptr == NULL) return; while (1) { result = fgets(fname, 125, ptr); if (result == NULL) /* must fclose ptr */ break; if (fname[strlen(fname) - 1] == '\n') fname[strlen(fname) - 1] = 0; paths = build_path(fname); ftemp = fopen(paths, "r"); bits = 0; if (ftemp == 0) { fprintf(stderr, "ntserv: couldn't open file %s. skipping\n", paths); } else { ParseXbmFile(ftemp, &w, &h, &bits); /* parsexbm.c */ bytesperline = (w - 1) / 8 + 1; linesperblock = 1016 /* packets.h */ / bytesperline; } fgets(buf, 125, ptr); if (3 != sscanf(buf, "%d %d %d", &x, &y, &page)) { printf("Format error in .pics file\n"); if (bits) free(bits); bits = NULL; } if (bits) { if (me != 0 && (me->p_stats.st_flags & ST_NOBITMAPS)) { sendMotdNopic(x, y, page, w, h); } else for (i = 0; i * linesperblock < h; i++) { int nlines; if ((i + 1) * linesperblock > h) nlines = h - i * linesperblock; else nlines = linesperblock; #if 0 printf("Sending MotdPics: %s %d %d %d %d %d\n", fname, x, y + i * linesperblock, page, w, nlines); #endif sendMotdPic(x, y + i * linesperblock, bits + bytesperline * linesperblock * i, page, w, nlines); } free(bits); } } fclose(ptr); } #undef D