Mercurial > ~darius > hgwebdir.cgi > paradise_server
diff src/main.c @ 4:aa38447a4b21
First entry of Paradise Server 2.9 patch 10 Beta
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:03 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.c Sat Dec 06 04:37:03 1997 +0000 @@ -0,0 +1,1211 @@ +/*-------------------------------------------------------------------------- +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