Mercurial > ~darius > hgwebdir.cgi > paradise_client
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.c Sat Dec 06 05:41:29 1997 +0000 @@ -0,0 +1,865 @@ +/* $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\ +"); +}