view main.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
line wrap: on
line source

/* $Id: main.c,v 1.1.1.1 1997/12/06 05:41:29 darius Exp $ */

/*
 * main.c
 */
#include "copyright.h"

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <pwd.h>
#ifdef hpux
#include <time.h>
#else
#include <sys/time.h>
#include <sys/wait.h>
#endif				/* hpux */
#include "Wlib.h"
#include "defs.h"
#include "struct.h"
#include "data.h"
#include "packets.h"
#include "proto.h"
#include "gameconf.h"
#ifdef SOUND
#include "Slib.h"
#endif
#include "sound.h"

jmp_buf env;

#ifdef AMIGA
/* needed for metafork... implemented by running a whole new copy
   don't honestly know why I bothered ;-) */
char **command_line;
int global_argc;
#endif

#ifdef GATEWAY
#define DEFAULT_GATEWAY		"atlgw"	/* for Quar */

static char *get_gw P((void));
static unsigned long mkaddr P((char *m));
static void getUdpPort P((void));
#endif

extern int UdpLocalPort;
/* Prototypes */
static void printUsage P((char *prog));
static void show_credits ();

int
main(argc, argv)
    int     argc;
    char  **argv;
{
    int     intrupt();
    int     team, s_type;
    char   *dpyname = NULL;
    int     usage = 0;
    int     err = 0;
    char   *name, *ptr, *cp;
#if !defined(NeXT) && !defined(RS6K) && !defined(SVR4)
    char   *rindex();
#endif
    struct passwd *pwent;
    int     passive = 0;
#ifdef METASERVER
    int     usemeta = 0;
#endif				/* METASERVER */
/*    char *defaultsFile=NULL;*/

    pseudo[0] = defpasswd[0] = '\0';

#ifdef AMIGA
    command_line = argv;
    global_argc=argc;
#endif

    name = *argv++;
    argc--;
    if ((ptr = rindex(name, '/')) != NULL)
	name = ptr + 1;
#ifdef GATEWAY
    netaddr = -1;		/* special NULL address */
    serverName = get_gw();	/* default machine is gw */
#endif
    while (*argv) {
	if (**argv != '-') {
	    serverName = *argv;	/* don't abort argument processing */
	    argv++;
	    argc--;
	} else {
	    ++*argv;

	    argc--;
	    ptr = *argv++;
	    while (*ptr) {
		switch (*ptr) {
		case 'C':	/* character name */
		    (void) strncpy(pseudo, *argv, sizeof(pseudo));
		    argv++;
		    argc--;
		    break;

		case 'c':	/* Credits */
		    show_credits();
		    exit (0);
		    break;

		case 'P':	/* authorization password */
		    (void) strncpy(defpasswd, *argv, sizeof(defpasswd));
		    {
			int     i;
			for (i = 0; (*argv)[i]; i++)
			    (*argv)[i] = 0;
		    }
		    argv++;
		    argc--;
		    break;

		case 'u':
		    usage++;
		    break;
		case 's':
		    if (*argv) {
			xtrekPort = atoi(*argv);
			passive = 1;
			argv++;
			argc--;
		    }
		    break;
		case 'p':
		    if (*argv) {
			xtrekPort = atoi(*argv);
			argv++;
			argc--;
		    }
		    break;
		case 'd':
		    dpyname = *argv;
		    argc--;
		    argv++;
		    break;
#ifdef METASERVER
		case 'm':
		    usemeta = 1;
		    break;
#endif				/* METASERVER */
		case 'h':
		    serverName = *argv;
		    if (!serverName)
			err++;
#ifdef GATEWAY
		    gw_mach = *argv;
#endif
		    argc--;
		    argv++;
		    break;
#ifdef GATEWAY
		case 'H':
		    netaddr = mkaddr(*argv);
		    argc--;
		    argv++;
		    break;
#endif

		case 't':
		    title = *argv;
		    argc--;
		    argv++;
		    break;
		case 'r':
		    defaultsFile = *argv;
		    argv++;
		    argc--;
		    break;
#ifdef AUTHORIZE
		case 'o':
		    RSA_Client = -1;
		    break;
		case 'R':
		    RSA_Client = -2;
		    break;
#else
		case 'o':
		case 'R':
		    printf("This client does not have binary authorization.\n");
		    break;
#endif
		case 'e':
#ifdef AUTHORIZE
		    checkExpire(1);
#else
		    printf("This client does not RSA verify and will not expire.\n");
#endif
		    exit(0);
		    break;
		case 'f':	/* list ftp sites */
		    fprintf(stderr, "\n\
The newest version of the Paradise client can be found at:\n\
      ftp.pnetrek.org in /pub/paradise/bin/\n\
or    ftp.cs.umn.edu  in /users/glamm/paradise/bin/\n\
\n\
Quick ftp instructions:\n\
This assumes you are bob@school.edu and are using a Sun workstation\n\
('sparc' architecture).  Modify with your mailing address and architecture.\n\
Type:\n\
   ftp ftp.cs.umn.edu\n\
   (at name prompt) anonymous\n\
   (at password prompt) bob@school.edu\n\
   (at ftp> prompt) cd users/glamm/paradise/bin\n\
   (at ftp> prompt) binary\n\
   (at ftp> prompt) dir\n\
   (lots of files printed - pick out the latest release for your architecture.\n\
    all the client binaries begin with 'netrek'.)\n\
   (at ftp> prompt) get netrek.Sparc-SunOS-static\n\
   (note: static and dynamic are functionally the same.\n\
  (at ftp> prompt) bye\n\
\n\
That's it!\n");
		    exit(0);
		case 'G':
		    if (*argv) {
			ghoststart++;
			ghost_pno = atoi(*argv);
			printf("Emergency restart being attempted...\n");
			argv++;
			argc--;
		    }
		    break;
		case '2':	/* force paradise */
		    paradise = 1;
		    break;
#ifdef RECORDER
		case 'F':	/* File playback */
		    if (*argv) {
			playFile = strdup(*argv);
			playback = 1;
			argv++;
			argc--;
		    }
		    break;
#endif
		case 'U':
		    if(*argv == NULL || (UdpLocalPort = atoi(*argv)) <= 0) {
			fprintf(stderr, "Error: -U requires a port number\n");
			usage++;
			break;
		    }
		    argc--;
		    argv++;
		    break;
		default:
		    fprintf(stderr, "%s: unknown option '%c'\n", name, *ptr);
		    err++;
		    break;
		}
		ptr++;
	    }
	}
    }
#ifdef GATEWAY
    if (netaddr == -1) {
	fprintf(stderr,
		"netrek: no remote address set (-H).  Restricted server will not work.\n");
    }
#endif



    inittrigtables();

    initStars();		/* moved from redraw.c at KAO\'s suggestion */

    if (usage || err) {
	printUsage(name);
#ifdef AUTHORIZE
	checkExpire(1);
#endif
	exit(0);
	/* exit(err); Exits from checkExpire */
    }
    defaultsFile = initDefaults(defaultsFile);

#ifdef AUTHORIZE
    if (RSA_Client != -1)
	checkExpire(0);
#endif

    /* compatability */
    if (argc > 0)
	serverName = argv[0];

    srandom(getpid() + time((long *) 0));

#ifdef RECORDER
    if(playback || booleanDefault("playback",0)) {
        defNickName = "playback";
	usemeta=0;
        serverName = "playback";
    } else
#endif
    {
        if (serverName) {
	    char    temp[80], *s;
	    sprintf(temp, "server.%s", serverName);
	    if ((s = getdefault(temp))) {
		s=strdup(s);
		printf("Using nickname \"%s\" for server %s\n", serverName, s);
		defNickName = serverName;
		serverName = s;
		defFlavor = getdefault("flavor");
		if(defFlavor) 
                    defFlavor=strdup(defFlavor);
	    }
	}
	if (!serverName) {
	    if(serverName = getdefault("server"))
		serverName = strdup(serverName);
        }
	if (!serverName && !passive) {
	    serverName = DEFAULT_SERVER;
#ifdef METASERVER
	    usemeta = 1;		/* no server specified, show the menu */
#endif
	}
	if (passive)
	    serverName = "passive";	/* newwin gets a wrong title otherwise */

	if (xtrekPort < 0)
	    xtrekPort = intDefault("port", -1);
	if (xtrekPort < 0)
	    xtrekPort = DEFAULT_PORT;
#if 0
#ifdef AUTHORIZE
	if (RSA_Client >= 0)
	    RSA_Client = booleanDefault("useRSA", RSA_Client);
	else
	    RSA_Client = (RSA_Client == -2);
#endif
#endif				/* 0 */

    } /* playback */
    build_default_configuration();

#ifdef METASERVER
    metaserverAddress = stringDefault("metaserver",
				      "metaserver.ecst.csuchico.edu");
    if (usemeta)
	parsemeta();
#endif				/* METASERVER */

    W_Initialize(dpyname);
#ifdef SOUND
    S_Initialize();
#endif


#ifdef METASERVER
    metaFork = booleanDefault("metaFork", metaFork);
    /* do the metawindow thang */
    if (usemeta) {
	metawindow();
	metainput();
	if (metaFork)
	    W_Initialize(dpyname);
	newwin(dpyname, name);
    } else
#endif				/* METASERVER */

	/* this creates the necessary x windows for the game */
	newwin(dpyname, name);

#ifdef TIMELORD
    start_timelord();
#endif

    /* open memory...? */
    openmem();
#ifdef RECORDER
    if (!startPlayback())
#endif
    {
	if (!passive) {
	    callServer(xtrekPort, serverName);
	} else {
	    connectToServer(xtrekPort);
	}
    }
#ifdef FEATURE
    sendFeature("FEATURE_PACKETS", 'S', 1, 0, 0);
#endif

    timeStart = time(NULL);
    findslot();

    /* sets all the settings from defaults file (.xtrekrc probably) */
    resetDefaults();

#ifdef UNIX_SOUND
    init_sound();
    play_sound(SND_PARADISE);
#endif

    mapAll();
/*    signal(SIGINT, SIG_IGN);*/
    signal(SIGCHLD, (void (*) ()) reaper);

    /* Get login name */
    if ((pwent = getpwuid(getuid())) != NULL)
	(void) strncpy(login, pwent->pw_name, sizeof(login));
    else
	(void) strncpy(login, "Bozo", sizeof(login));
    login[sizeof(login) - 1] = '\0';

    if (pseudo[0] == '\0') {
	if ((cp = getdefault("name")) != 0)
	    (void) strncpy(pseudo, cp, sizeof(pseudo));
	else
	    (void) strncpy(pseudo, login, sizeof(pseudo));
    }
    pseudo[sizeof(pseudo) - 1] = '\0';

    if (defpasswd[0] == '\0') {
	char buf[100], buf2[100];  /* added password by character name -JR */
	sprintf(buf,"password.%s",pseudo);
        if (serverName)         /* password by server name -TH */
            sprintf(buf2, "password.%s", serverName);
	if((cp = getdefault(buf)) || (cp = getdefault(buf2)) ||
 		(cp = getdefault("password")))
	    (void) strncpy(defpasswd, cp, sizeof(defpasswd));
    }
    defpasswd[sizeof(defpasswd) - 1] = '\0';

    /*
       sendLoginReq("Gray Lensman", "hh", "sfd", 0); loginAccept = -1; while
       (loginAccept == -1) { socketPause(1,0); readFromServer(); }
    */
    getname(pseudo, defpasswd);
    loggedIn = 1;
#ifdef TIMER
    timeBank[T_SERVER] = timeStart;
    timeBank[T_DAY] = 0;
#endif				/* TIMER */


#ifdef AUTOKEY
    /* autokey.c */
    autoKeyDefaults();
#endif				/* AUTOKEY */

    /*
       Set p_hostile to hostile, so if keeppeace is on, the guy starts off
       hating everyone (like a good fighter should)
    */
    me->p_hostile = (1 << number_of_teams) - 1;

    redrawTstats();

    me->p_planets = 0;
    me->p_genoplanets = 0;
    me->p_armsbomb = 0;
    me->p_genoarmsbomb = 0;
    /* Set up a reasonable default */
    me->p_whydead = KQUIT;
    me->p_teami = -1;
    s_type = defaultShip(CRUISER);	/* from rlb7h 11/15/91 TC */

    if (booleanDefault("netStats", 1))
	startPing();		/* tell the server that we support pings */

#ifdef AUTOKEY
    if (autoKey) {
	/* XX: changes entire state of display */
	W_AutoRepeatOff();
    }
#endif
    /*
       hack to make galaxy class ships work.  This could be more elegant, but
       the configuration code would have to be modified quite a bit, since
       the client doesn't know if it's on a paradise server until after it
       connects, and it needs the configuration info before it connects.
    */
    init_galaxy_class();

    initkeymap(-1);		/* needs to have ship types initialized -JR */

    setjmp(env);		/* Reentry point of game */

    if (ghoststart) {
	int     i;

	ghoststart = 0;

	for (i = -1; i < 5; i++)
	    if (teaminfo[i].letter == me->p_mapchars[0])
		break;

	me->p_teami = i;

	if (me->p_damage > me->p_ship->s_maxdamage) {
	    me->p_status = POUTFIT;
	} else
	    me->p_status = PALIVE;
    } else
	me->p_status = POUTFIT;

    while (1) {
	switch (me->p_status) {
	case POUTFIT:
	case PTQUEUE:
	    /* give the player the motd and find out which team he wants */
#if 1
	    new_entrywindow(&team, &s_type);
#else
	    entrywindow(&team, &s_type);
#endif
	    allowPlayerlist = 1;
	    if (W_IsMapped(playerw))
		playerlist();

#ifdef RECORDER
	    if (!playback)
#endif
		if (team == -1) {
		    W_DestroyWindow(w);
#ifdef AUTOKEY
		    if (autoKey)
			W_AutoRepeatOn();
#endif
		    sendByeReq();
		    sleep(1);
		    printf("OK, bye!\n");
		    EXIT(0);
		}
	    sendVersion();
	    myship = getship(myship->s_type);

	    currentship = myship->s_type;

	    /*
	       sendOptionsPacket(); /* this would totally blast any flags you
	       had on the server
	    */

	    redrawall = 1;
	    enter();
	    calibrate_stats();
	    W_ClearWindow(w);
	    /*
	       for (i = 0; i < NSIG; i++) { signal(i, SIG_IGN); }
	    */

	    me->p_status = PALIVE;	/* Put player in game */

#ifdef UNIX_SOUND
            kill_sound ();
#endif
            
#ifdef HOCKEY
	    hockeyInit();
#endif /*HOCKEY*/

#ifdef TIMER
	    timeBank[T_SHIP] = time(NULL);
#endif				/* TIMER */

	    if (showStats)	/* Default showstats are on. */
		W_MapWindow(statwin);

#ifdef GATEWAY
	    /* pick a nice set of UDP ports */
	    getUdpPort();
#endif

#if ATM
	    if (tryUdp && commMode != COMM_UDP) {
		sendUdpReq(COMM_UDP);
	    }
#endif				/* ATM */
#ifdef SHORT_PACKETS
	    if (tryShort) {
		sendShortReq(SPK_VON);
		tryShort = 0;	/* only try it once */
	    }
#endif	/* SHORT_PACKETS */
	    /* Send request for a full update */
	    if (askforUpdate) {
		if(recv_short)
		    sendShortReq(SPK_SALL);
		else
		    sendUdpReq(COMM_UPDATE);
	    }
	    sendUpdatePacket(1000000 / updateSpeed);

	    W_Deiconify(baseWin);

	    break;
	case PALIVE:
	case PEXPLODE:
	case PDEAD:
	case POBSERVE:

#ifdef TIMELORD
	    /* reading the MOTD doesn't count against your playing time */
	    update_timelord_notcount();
#endif

	    /* Get input until the player quits or dies */
	    input();
	    W_ClearWindow(mapw);
#ifdef TIMELORD
	    /* get any fractional minutes we missed */
	    update_timelord(1);
#endif
	    break;
	default:
	    printf("client has p_status=%d.  how strange\n", me->p_status);
	    me->p_status = POUTFIT;
	}
    }

    /* NOTREACHED */
}

static void
printUsage(prog)
    char   *prog;
{
    fprintf(stderr, "Usage:\n  %s [ options ] [ ntserv-host ]\n\
Where options are\n\
    [-h] host          server host name\n\
    [-p] port          server port number\n\
    [-r] xtrekrc       defaults file to replace ~/.xtrekrc\n\
    [-t] title         window manager title\n\
    [-d] display       set Xwindows display\n\
    [-C] name          netrek pseudonym\n\
    [-P] passwd        passwd to use to attempt autologin\n\
    [-R]               use RSA authorization (default)\n\
    [-o]               use old (non-RSA) authorization\n\
    [-s] port          wait for connection from ntserv on a port (debugging)\n\
%s\
%s\
    [-U] port          specify base local UDP port number to use\n\
    [-e]               check the expire time on the client\n\
    [-f]               how to get the newest client\n\
    [-u]               print usage\n\
    [-c]               Paradise credits\n\
  For emergency restart:\n\
    [-2]               force paradise - use if you were on a paradise server\n\
    [-G] playernum     specify player number to use\n\
    [-s] port          specify socket number to use\n\
Paradise Client %s\n\
For more information on how to play Paradise, use Netscape or Internet\n\
Explorer and connect to:\n\
    http://www.pnetrek.org/               OR\n\
    http://www.cs.umn.edu/users/glamm/paradise/\n\n", prog,
#ifdef METASERVER
	    "    [-m]               check metaserver for active servers\n",
#else
	    "",
#endif				/* METASERVER */
#ifdef RECORDER
	    "    [-F] file          Replay from file instead of connecting\n",
#else
	    "",
#endif
	    CLIENTVERS);
}

void
reaper()
{
#if defined(hpux) || defined(SVR4) || defined(AMIGA)
    wait((int *) 0);
#else
    /* well, hell, just use NULL, it works for everything else anyway */
/*    while (wait3((union wait *) 0, WNOHANG, NULL) > 0);*/
    while(wait3(NULL, WNOHANG, NULL) > 0);
#endif				/* hpux */
}

#ifdef GATEWAY
static struct udpmap_t {
    int     uid;
    int     serv_port;
    int     port;
    int     local_port;
}       udpmap[] = {
    /* 5000, 5001, 5000 *//* generic */
    {
	1290, 5010, 5011, 5010
    },				/* fadden */
    {
	757, 5020, 5021, 5020
    },				/* user2 */
};
#define MAPSIZE (sizeof(udpmap) / sizeof(struct udpmap_t))

static void
getUdpPort()
{
    int     i;
    uid_t   uid;
    char   *gw_m, *gw_p, *gw_lp, *gw_sp, *err, *getenv();

    /* should always be set prior, but in case not .. */
    if (!gw_mach) {
	gw_m = getenv("GW_MACH");
	if (gw_m)
	    gw_mach = gw_m;
	else
	    gw_mach = DEFAULT_GATEWAY;
    }
    uid = getuid();

    for (i = 0; i < MAPSIZE; i++) {
	if (uid == udpmap[i].uid) {
	    gw_serv_port = udpmap[i].serv_port;
	    gw_port = udpmap[i].port;
	    gw_local_port = udpmap[i].local_port;
	    return;
	}
    }

    gw_p = getenv("GW_PORT");
    gw_sp = getenv("GW_SPORT");
    gw_lp = getenv("GW_LPORT");

    if (gw_p) {
	gw_port = strtol(gw_p, &err, 10);
	if (err == gw_p) {
	    fprintf(stderr, "netrek: malformed integer for GW_PORT: %s\n",
		    gw_p);
	    /* let something else complain about port 0 */
	}
    } else
	gw_port = 5001;
    if (gw_sp) {
	gw_serv_port = strtol(gw_sp, &err, 10);
	if (err == gw_sp) {
	    fprintf(stderr, "netrek: malformed integer for GW_SPORT: %s\n",
		    gw_sp);
	    /* let something else complain about port 0 */
	}
    } else
	gw_serv_port = 5000;

    if (gw_lp) {
	gw_local_port = strtol(gw_lp, &err, 10);
	if (err == gw_lp) {
	    fprintf(stderr, "netrek: malformed integer for GW_LPORT: %s\n",
		    gw_lp);
	    /* let something else complain about port 0 */
	}
    } else
	gw_local_port = 5000;

    /*
       printf("gw_mach: \'%s\'\n", gw_mach); printf("gw_local_port: %d\n",
       gw_local_port); printf("gw_serv_port: %d\n", gw_serv_port);
       printf("gw_port: %d\n", gw_port);
    */
}

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

/*
 * In the event of problems assiocated with the above include files the
 * following routine can be alternately used to convert a string
 * ("xxx.xxx.xxx.xxx") to an internet address number.
 *
 * (author: Andy McFadden)
 */

#ifdef notneeded
unsigned long
dotAddrToNetAddr(str)
    char   *str;
{
    char   *t;
    unsigned long answer = 0;
    t = str;
    for (i = 0; i < 4; i++) {
	answer = (answer << 8) | atoi(t);
	while (*t && *t != '.')
	    t++;
	if (*t)
	    t++;
    }
    return answer;
}
#endif

/*
 * More network "correct" routine
 */

static unsigned long
mkaddr(m)
    char   *m;
{
    struct in_addr ad;
    struct hostent *hp;

    hp = gethostbyname(m);
    if (!hp) {
	ad.s_addr = inet_addr(m);
	if (ad.s_addr == -1) {
	    fprintf(stderr, "netrek: unknown host \'%s\'\n", m);
	    exit(1);
	}
    } else
	bcopy(hp->h_addr, (char *) &ad, hp->h_length);

    return ad.s_addr;
}

static char *
get_gw()
{
    char   *gw_m;

    gw_m = getenv("GW_MACH");
    if (gw_m)
	gw_mach = gw_m;
    else
	gw_mach = DEFAULT_GATEWAY;

    return gw_mach;
}

#endif

void
show_credits()
{
	printf ("Paradise Netrek\n\
\n\
Copyright (c) 1986	Chris Guthrie\n\
Copyright (c) 1989	Kevin P. Smith\n\
Copyright (c) 1993	Larry Denys, Kurt Olsen, Brandon Gillespie, and\n\
			Robert Forsman\n\
Copyright (c)		Eric Mehlaff, Sujal Patel, Robert Glamm, \n\
			Lars Bernhardsson, Kurt Siegl, Nick Trown\n\
\n\
Paradise Developers\n\
  Larry Deny                       Robert Forsman\n\
  Brandon Gillespie                Kurt Olsen\n\
\n\
Paradise Contributors (In alphabetical order):\n\
  Terence Chang                    Mike McGrath\n\
  Bill Dyess                       Matthew Mead\n\
  Jerry Frain                      Gary Parnes\n\
  Robert Glamm                     Sujal Patel\n\
  T. Hadley                        Joe Rumsey\n\
  Heath A. Kehoe                   Rado Smiljanic\n\
  Andy McFadden                    Joe Young\n\
");
}