qstat-2.11/0000777002404400000620000000000010523107301007562 500000000000000qstat-2.11/info/0000777002404400000620000000000010523107301010515 500000000000000qstat-2.11/info/Makefile.am0000644002404400000620000000003710140661715012476 00000000000000EXTRA_DIST = $(wildcard *.txt) qstat-2.11/info/Makefile.in0000644002404400000620000001720510523107225012510 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = info DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnuconfig.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = $(wildcard *.txt) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign info/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign info/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: qstat-2.11/info/UT2003.txt0000644002404400000620000000374207606672315012061 00000000000000Unreal Tournament 2003 servers can be queried with the Gamespy style protocol (-gps) or with the native UT2003 protocol (-ut2s). The query port offset for Gamespy is usually 10. The query port offset for the native UT2003 protocol is always 1. The gamespy response returns a team name for each player, the UT2S response does not. Don't be concerned because the team name is the same for all players, and seems to be map name followed by the string ".xTeamRoster" Probably a bug in the UT2003 gamespy support. The UT2S response includes a player global statistics id. The gamespy response does not. However, this id is zero for all players on both demo and retail servers. I guess they don't have global stats implemented. The protocols return similar but different servers rules. In UT2S the rule names are all lower-case. In gamespy, they are mixed-case. Some of the rules overlap, but each returns info not available from the other protocol. In the UT2S response, the "Mutator" rule (the only one with mixed-case) may appear multiple times. If you use $(RULE:Mutator) only the value of the first Mutator will be output. UT2003 servers frequently do not return information for all of the players. I don't know why. UT2003 master server lists are available from Epic Games. Here's the description from the Unreal Technology page: --------------------- We have made server lists available via HTTP for both demo and full version UT2003 servers so that 3rd party server query tools can add UT2003 support. http://ut2003master.epicgames.com/serverlist/full-all.txt http://ut2003master.epicgames.com/serverlist/demo-all.txt These URLs contain a tab-separated list of server IP, game port and query port for all servers in our master server. The query port is the port number the server is listening on for UDP queries. The query format and response is exactly the same as UT 1. The source code to the game server's query responder is in the UdpGameSpyQuery UnrealScript class. --------------------- qstat-2.11/info/GhostRecon.txt0000644002404400000620000001435507564605624013303 00000000000000Ghost Recon - QStat notes ------------------------- The following Server Stats are pulled from the Ghost Recon Server - NOTE many other stats continue to work as normal due to the base qstat program. $SERVERNAME The name of the GR Server. $PLAYERS The number of Players that are playing, oberving or in the Lobby (note the ignoreserverplayer Argument above) $MAXPLAYERS The maximum players that the server will allow playing, oberving or in the Lobby (note the ignoreserverplayer Argument above) $MAP The Name of the MAP that is being used (NOTE not the Mission) $GAME The Mods that the server is running. Ex: mp1; is the Desert Seige Mod $(RULE:error) If an error occured there may be some detail here. IF the problm occurred very early in the interpretation then $SERVERNAME will hold the details. $(RULE:mission) The name of the Mission that the server is running. $(RULE:gamemode) What is the Game Mode that the server is in. Known values are COOP, TEAM and SOLO $(RULE:missiontype) What is the Mission Type. Known Values are: Mission, Firefight, Recon, Hamburger Hill, Last Man Standing, Sharpshooter, Search And Rescue, Domination, and Seige. $(RULE:dedicated) Is this server Dedicated; Yes or No. $(RULE:status) What is the Playing Status of the Server, values are Playing, Joining or Debrief. $(RULE:gametime) What is the Time limit for the Game. Values are 00:00, 05:00, 10:00, 15:00 20:00, 25:00, 30:00, 45:00 and 60:00. The 00:00 is for an unlimited game. The format of this uses the -ts, -tc and -tsw command line options. $(RULE:timeplayed) How long has this game been playing. The format of this uses the -ts, -tc and -tsw command line options. $(RULE:remainingtime) How much time is left in this game. The format of this uses the -ts, -tc and -tsw command line options. $(RULE:version) What is the Version number reported by the server. Patch 1.2 = 10.1010A, Patch 1.3 = 11.101A $(RULE:spawntype) What type of spawn is in use. Known Values are None, Infinite, Individual and Team. $(RULE:spawncount) How many spawns are allowed. Enhancment possibility to add $(IF:SPAWN) to filter out when spawntype is none. $(RULE:restrict) What Weapon restrictions are in force for the server. $(RULE:password) Does the Server have a join password defined Yes or No. $(RULE:ti) Is the server using the Threat Indicator. $(RULE:motd) What is the Message Of The Day - Note these can be quite big. $(RULE:patch) What is the patch level of the GR Server. $(RULE:usestarttime) Is the server configured to start a game after "starttimeset" (Yes) OR does everyone need to click on ready (no). $(RULE:starttimeset) What time is configured to automatically start the next round. $(RULE:debrieftime) How long does the server wait at the Debrief screen after a mission. $(RULE:respawnmin) How long must a dead player wait before he can repawn. $(RULE:respawnmax) What is the longest time that a user has to respawn. $(RULE:respawnsafe) How long after respawn is a player invulnerable/cannot damage others. $(RULE:allowobservers) Does the server allow observers? Yes or No $(RULE:startwait) How long untill the automatic start timer forces the next game to start. $(RULE:iff) What Identification - Friend or Foe is configured. None, Reticule or Names $PLAYERNAME What is the Players Name. $TEAMNUM What Team Number is the Player On. Known Values are 1,2,3,4,5. 1 is Team BLUE, 2 is Team Read, 3 is Team Yellow, 4 is Team Green, 5 is Unassigned (observer or in lobby) $TEAMNAME What is the Name of the Team, see above. $DEATHS What is the health of this player. 0 Alive, 1 Dead. Note if the player has spawns remaining this can change from 1 back to 0. Enhancement possibility to add $HEALTH or $(RULE:health). Hopefully RSE/UBI will add the Deaths, Frags, and Ping to the availible information. If this happens then it would be better to have a $HEALTH $(IF:DEATHS) and $(IFNOT:DEATHS) A Test to see if the player is dead. Usefull in this constuct: $(IF:DEATHS)Dead$(ENDIF)$(IFNOT:DEATHS)Alive$(ENDIF) Ghost Recon communicates on two UDP ports and one TCP stream. Normally TCP is on port 2346 and carries the game dialog. This is the port number that is mentioned in the game so we use it and apply an offset to get the port number for status queries. Port 2347 gives some high level server stats and 2348 gives fairly low level server stats. QStat is designed around a single port per server so the 2348 port is used. One down side to this is the lack of many meaningful detail player stats (Deaths, frags, hit percentage, ping etc.). I imagines that some of these are availible in the TCP stream but that would be difficult to add to a program like QStat. The Ghost Recon packets are variable structures with a lot of string lengths. This requires fairly defensive programming as Red Storm Entertainment is not forthcoming with any details. This release adds support for the GhostRecon game. Number one note is that Red Storm and UBI do not provide the information that many Quake based users expect. Specifically they do not make Frags, Deaths Connect Time or Pings availible - at least not as far as I can tell. That said there are quite a few things that are availible and allow a server administrator to make the status of his or her server available to the public via the web. This change uses all undocumented interfaces to the Ghost Recon server so will most likely break when you install a patch. It has been tested against the Desert Seige update and several public servers. It should work against the 1.2, 1.3, and 1.4 patches and Island Thunder add-on to Ghost Recon. The Ghost Recon game type is GRS. For command-line queries, use -grs There is one query argument to this server, ignoreserverplayer. This option controls whether the first player is ignored. Ghost Recon requires that the dedicated server program take up one of the player slots (always the first slot). The ignoreserverplayer option defaults to 'yes', so the "server player" will normally not be seen. If you are running a non-dedicated server, then set ignoreserverplayer to 'no' like this: -grs,ignoreserverplayer=no Otherwise you would not be able to display your own stats. Ghost Recon support provided by Bob Marriott. qstat-2.11/info/a2s.txt0000644002404400000620000001231610221402151011656 00000000000000Server Queries The Source engine allows you to query information from a running game server using UDP/IP packets. This document describes the packet formats and protocol to access this data. Basic Data Types All server queries consist of 5 basic types of data packed together into a data stream. All types are little endian. Name Description byte 8 bit character short 16 bit signed integer long 32 bit signed integer float 32 bit float value string variable length byte field, terminated by 0x00 Query Types The server responds to 4 queries: • A2S_SERVERQUERY_GETCHALLENGE - Returns a challenge number for use in the player and rules query. • A2S_INFO - Basic information about the server. • A2S_PLAYER - Details about each player on the server. • A2S_RULES - The rules the server is using. Queries should be sent in UDP packets to the listen port of the server, which is typically port 27015. A2S_SERVERQUERY_GETCHALLENGE Request format Challenge values are required for A2S_PLAYER and A2S_RULES requests, you can use this request to get one. Note: You can also send A2S_PLAYER and A2S_RULES queries with a challenge value of -1 (0xFF FF FF FF FF FF FF FF) and they will respond with a challenge value to use (using the reply format below). FF FF FF FF 57 Reply format Data Type Comment Type byte Should be equal to 'A' (0x41) Challenge long The challenge number to use Example reply: FF FF FF FF FF 41 32 42 59 45 53 93 43 71 A2S_INFO Request format Server info can be requested by sending the following byte values in a UDP packet to the server. FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 6E 65 20 51 75 65 72 79 00 Reply format Data Type Comment Type byte Should be equal to 'I' (0x49) Version byte Network version Hostname string The Servers name Map string The current map being played Game Directory string The Game type Game string A friendly string name for the game type Description AppID short Steam Application number (currently always set to 0) Num players byte The number of players currently on the server Max players byte Maximum allowed players for the server Num of bots byte Number of bot players currently on the server Dedicated byte Set to 1 for dedicated servers OS byte 'l' for Linux, 'w' for Windows Password byte If set to 1 a password is required to join this server Secure byte If set to 1 this server is running VAC Game Version string The version of the game Example reply: FF FF FF FF 49 02 67 61 6D 65 32 78 73 2E 63 6F ....I.game2xs.co 6D 20 43 6F 75 6E 74 65 72 2D 53 74 72 69 6B 65 m.Counter-Strike 20 53 6F 75 72 63 65 20 23 31 00 64 65 5F 64 75 .Source.#1.de_du 73 74 00 63 73 74 72 69 6B 65 00 43 6F 75 6E 74 st.cstrike.Count 65 72 2D 53 74 72 69 6B 65 00 00 00 0B 28 00 64 er-Strike....(.d 6C 00 00 31 2e 31 2e 30 2e 31 36 00 l..1.1.0.16 A2S_PLAYER Request format FF FF FF FF 55 <4 byte challenge number> The challenge number can either be set to -1 (0xFF FF FF FF FF FF FF FF) to have the server reply with S2C_CHALLENGE, or use the value from a previous A2S_SERVERQUERY_GETCHALLENGE request. Reply format The players response has two sections, the initial header: Data Type Comment Type byte Should be equal to 'D' (0x44) Num Players byte The number of players reported in this response Then for each player the following fields are sent: Data Type Comment Index byte The index into [0.. Num Players] for this entry Player Name string Player's name Kills long Number of kills this player has Time connected float The time in seconds this player has been connected A2S_RULES Request format FF FF FF FF 56 <4 byte challenge number> The challenge number can either be set to -1 (0xFF FF FF FF FF FF FF FF) to have the server reply with S2C_CHALLENGE, or use the value from a previous A2S_SERVERQUERY_GETCHALLENGE request. Reply format The rules response has two sections, the initial header: Data Type Comment Type byte Should be equal to 'E' (0x45) Num Rules short The number of rules reported in this response Then for each rule the following fields are sent: Data Type Comment Rule Name string The name of the rule Rule Value string The rules value ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (C) 2004 Valve Corporation. All rights reserved. Valve, the Valve logo, Half-Life, the Half-Life logo, the Lambda logo, Steam, the Steam logo, Team Fortress, the Team Fortress logo, Opposing Force, Day of Defeat, the Day of Defeat logo, Counter-Strike, the Counter-Strike logo, Source, the Source logo, Hammer and Counter-Strike: Condition Zero are trademarks and/or registered trademarks of Valve Corporation. Microsoft and Visual Studio are trademarks and/or registered trademarks of Microsoft Corporation. All other trademarks are property of their respective owners. qstat-2.11/tm.c0000644002404400000620000001772210470043631010301 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Gamespy query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #include #endif #include #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" void send_tm_request_packet( struct qserver *server ) { char buf[2048]; char *xmlp = buf + 8; unsigned int len; if ( ! server->protocol_version ) { // No seen the version yet wait // register_send here to ensure that timeouts function correctly register_send( server ); return; } if ( get_player_info ) { server->flags |= TF_PLAYER_QUERY|TF_RULES_QUERY; // TODO: add more calls to get full player info? strcpy( xmlp, "\n\nsystem.multicall\n\nmethodNameGetServerOptionsparams\nmethodNameGetCurrentChallengeInfoparams\nmethodNameGetPlayerListparams1000\n\n" ); } else { server->flags |= TF_STATUS_QUERY; strcpy( xmlp, "\n\nsystem.multicall\n\nmethodNameGetServerOptionsparams\nmethodNameGetCurrentChallengeInfoparams\nmethodNameGetPlayerListparams1000\n\n" ); } // First 4 bytes is the length of the request len = strlen( xmlp ); memcpy( buf, &len, 4 ); // Second 4 bytes is the handle identifier ( id ) memcpy( buf+4, &server->challenge, 4 ); // prep the details we need for multi packet responses // we expect at least 1 packet response server->saved_data.pkt_max = 1; send_packet( server, buf, len + 8 ); } void deal_with_tm_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *s, *end; char *key = NULL, *value = NULL, *tmpp = NULL; char fullname[256]; struct player *player = NULL; int pkt_max = server->saved_data.pkt_max; unsigned total_len, expected_len; int method_response = 1; debug( 2, "processing..." ); s = rawpkt; if ( 4 == pktlen && 0 == memcmp( rawpkt, "\x0b\x00\x00\x00", 4 ) ) { // setup handle identifier // greater 2^31 = XML-RPC, less = callback server->challenge = 0x80000001; return; } else if ( 10 < pktlen && 1 == sscanf( rawpkt, "GBXRemote %d", &server->protocol_version ) ) { // Got protocol version send request send_tm_request_packet( server ); return; } else if ( 8 <= pktlen && 0 == memcmp( rawpkt+4, &server->challenge, 4 ) ) { // first 4 bytes = the length // Note: We use pkt_id to store the length of the expected packet // this could cause loss but very unlikely unsigned long len; memcpy( &len, rawpkt, 4 ); // second 4 bytes = handle identifier we sent in the request if ( 8 == pktlen ) { // split packet // we have at least one more packet coming if ( ! add_packet( server, len, 0, 2, pktlen, rawpkt, 1 ) ) { // fatal error e.g. out of memory return; } return; } else { // ensure the length is stored server->saved_data.pkt_id = (int)len; s += 8; } } total_len = combined_length( server, server->saved_data.pkt_id ); expected_len = server->saved_data.pkt_id; if ( total_len < expected_len + 8 ) { // we dont have a complete response add the packet int last, new_max; if ( total_len + pktlen >= expected_len + 8 ) { last = 1; new_max = pkt_max; } else { last = 0; new_max = pkt_max + 1; } if ( ! add_packet( server, server->saved_data.pkt_id, pkt_max - 1, new_max, pktlen, rawpkt, 1 ) ) { // fatal error e.g. out of memory return; } if ( last ) { // we are the last packet run combine to call us back combine_packets( server ); } return; } server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL); } rawpkt[pktlen]= '\0'; end = &rawpkt[pktlen]; //fprintf( stderr, "S=%s\n", s ); s = strtok( s, "\015\012" ); while ( NULL != s ) { //fprintf( stderr, "S=%s\n", s ); if ( 0 == strncmp( s, "", 14 ) ) { key = s + 14; tmpp = strstr( key, "" ); if ( NULL != tmpp ) { *tmpp = '\0'; } s = strtok( NULL, "\015\012" ); value = NULL; continue; } else if ( 0 == strncmp( s, "", 7 ) ) { // value s += 7; if ( 0 == strncmp( s, "", 8 ) ) { // String value = s+8; tmpp = strstr( s, "" ); } else if ( 0 == strncmp( s, "", 4 ) ) { // Int value = s+4; tmpp = strstr( s, "" ); } else if ( 0 == strncmp( s, "", 9 ) ) { // Boolean value = s+9; tmpp = strstr( s, "" ); } else if ( 0 == strncmp( s, "", 8 ) ) { // Double value = s+8; tmpp = strstr( s, "" ); } // also have struct and array but not interested in those if ( NULL != tmpp ) { *tmpp = '\0'; } if ( NULL != value ) { debug( 4, "%s = %s\n", key, value ); } } else if ( 0 == strncmp( s, "", 9 ) && 3 > method_response ) { // end of method response method_response++; } if ( NULL != value ) { switch( method_response ) { case 1: // GetServerOptions response if ( 0 == strcmp( "Name", key ) ) { server->server_name = strdup( value ); } else if ( 0 == strcmp( "CurrentMaxPlayers", key ) ) { server->max_players = atoi( value ); } else { sprintf( fullname, "server.%s", key ); add_rule( server, fullname, value, NO_FLAGS); } break; case 2: // GetCurrentChallengeInfo response if ( 0 == strcmp( "Name", key ) ) { server->map_name = strdup( value ); } else { sprintf( fullname, "challenge.%s", key ); add_rule( server, fullname, value, NO_FLAGS); } break; case 3: // GetPlayerList response // Player info if ( 0 == strcmp( "Login", key ) ) { player = add_player( server, server->n_player_info ); server->num_players++; } else if ( NULL != player ) { if ( 0 == strcmp( "NickName", key ) ) { player->name = strdup( value ); } else if ( 0 == strcmp( "PlayerId", key ) ) { //player->number = atoi( value ); } else if ( 0 == strcmp( "TeamId", key ) ) { player->team = atoi( value ); } else if ( 0 == strcmp( "IsSpectator", key ) ) { player->flags = player->flags & 1; } else if ( 0 == strcmp( "IsInOfficialMode", key ) ) { player->flags = player->flags & 2; } else if ( 0 == strcmp( "LadderRanking", key ) ) { player->score = atoi( value ); } } break; } value = NULL; } s = strtok( NULL, "\015\012" ); } if ( 0 == strncmp( rawpkt + pktlen - 19, "", 17 ) ) { // last packet seen cleanup_qserver( server, 1 ); } } qstat-2.11/tm.h0000644002404400000620000000063210464730441010303 00000000000000/* * qstat 2.8 * by Steve Jankowski * * TrackMania protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_GPS_H #define QSTAT_GPS_H #include "qserver.h" // Packet processing methods void deal_with_tm_packet( struct qserver *server, char *pkt, int pktlen ); void send_tm_request_packet( struct qserver *server ); #endif qstat-2.11/debug.c0000644002404400000620000000520010435066370010741 00000000000000/* * qstat 2.6 * by Steve Jankowski * * debug helper functions * Copyright 2004 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include "debug.h" #include #include #ifndef _WIN32 #include #include #endif #include #include #include #include #include #include #include #ifdef DEBUG void _debug(const char* file, int line, const char* function, int level, const char* fmt, ...) { va_list ap; char buf[9]; time_t now; now = time(NULL); strftime(buf,9,"%T",localtime(&now)); fprintf(stderr, "debug(%d) %s %s:%d %s() - ", level, buf, file, line, function); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if ( '\n' != fmt[strlen(fmt)-1] ) { fputs("\n", stderr); } return; } #endif static int debug_level = 0; void set_debug_level (int level) { debug_level = level; } int get_debug_level (void) { return (debug_level); } void malformed_packet(const struct qserver* server, const char* fmt, ...) { va_list ap; if(!show_errors) return; fputs("malformed packet", stderr); if(server) { fprintf(stderr, " from %d.%d.%d.%d:%hu", server->ipaddr&0xff, (server->ipaddr>>8)&0xff, (server->ipaddr>>16)&0xff, (server->ipaddr>>24)&0xff, server->port); } fputs(": ", stderr); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if(*fmt && fmt[strlen(fmt)-1] != '\n') { fputc('\n',stderr); } } #ifdef ENABLE_DUMP static unsigned count = 0; #endif void dump_packet(const char* buf, int buflen) { #ifdef ENABLE_DUMP char fn[PATH_MAX] = {0}; int fd; sprintf(fn, "dump%03u", count++); fprintf(stderr, "dumping to %s\n", fn); fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0644); if(fd == -1) { perror("open"); return; } if(write(fd, buf, buflen) == -1) perror("write"); close(fd); #endif } void print_packet( struct qserver *server, const char *buf, int buflen) { static char *hex= "0123456789abcdef"; unsigned char *p= (unsigned char*)buf; int i, h, a, b, astart, offset= 0; char line[256]; if ( server != NULL) fprintf( stderr, "FROM %s len %d\n", server->arg, buflen ); for ( i= buflen; i ; offset+= 16) { memset( line, ' ', 256); h= 0; h+= sprintf( line, "%5d:", offset); a= astart = h + 16*2 + 16/4 + 2; for ( b=16; b && i; b--, i--, p++) { if ( (b & 3) == 0) line[h++]= ' '; line[h++]= hex[*p >> 4]; line[h++]= hex[*p & 0xf]; if ( isprint( *p)) line[a++]= *p; else line[a++]= '.'; if((a-astart)==8) line[a++] = ' '; } line[a]= '\0'; fputs( line, stderr); fputs( "\n", stderr); } fputs( "\n", stderr); } qstat-2.11/debug.h0000644002404400000620000000176310435066370010760 00000000000000/* * qstat 2.6 * by Steve Jankowski * * debug helper functions * Copyright 2004 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_DEBUG_H #define QSTAT_DEBUG_H #include "qstat.h" // NOTE: Windows doesn't support debugging ATM #ifdef _WIN32 #define debug 0 && #else #ifdef DEBUG #include void _debug(const char* file, int line, const char* function, int level, const char* fmt, ...) GCC_FORMAT_PRINTF(5, 6); #define debug(level,fmt,rem...) \ if( level <= get_debug_level() ) \ _debug(__FILE__,__LINE__,__FUNCTION__,level,fmt,##rem) #else #define debug(...) #endif #endif void dump_packet(const char* buf, int buflen); /** report a packet decoding error to stderr */ void malformed_packet(const struct qserver* server, const char* fmt, ...) GCC_FORMAT_PRINTF(2, 3); int get_debug_level (void); void set_debug_level (int level); void print_packet( struct qserver *server, const char *buf, int buflen ); #endif qstat-2.11/depcomp0000755002404400000620000003710010422550571011065 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2005-07-09.11 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mecanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: qstat-2.11/a2s.c0000644002404400000620000003137110436307026010345 00000000000000/* * qstat 2.8 * by Steve Jankowski * * New Half-Life2 query protocol * Copyright 2005 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #endif #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" #define A2S_GETCHALLENGE "\xFF\xFF\xFF\xFF\x57" #define A2S_CHALLENGERESPONSE 0x41 #define A2S_INFO "\xFF\xFF\xFF\xFF\x54Source Engine Query" #define A2S_INFORESPONSE_HL1 0x6D #define A2S_INFORESPONSE_HL2 0x49 #define A2S_PLAYER "\xFF\xFF\xFF\xFF\x55" #define A2S_PLAYERRESPONSE 0x44 #define A2S_RULES "\xFF\xFF\xFF\xFF\x56" #define A2S_RULESRESPONSE 0x45 struct a2s_status { unsigned sent_challenge : 1; unsigned have_challenge : 1; unsigned sent_info : 1; unsigned have_info : 1; unsigned sent_player : 1; unsigned have_player : 1; unsigned sent_rules : 1; unsigned have_rules : 1; unsigned challenge; unsigned char type; }; void send_a2s_request_packet(struct qserver *server) { struct a2s_status* status = (struct a2s_status*)server->master_query_tag; if(qserver_send_initial(server, A2S_INFO, sizeof(A2S_INFO)) == -1) goto error; status->sent_info = 1; status->type = 0; if(get_server_rules || get_player_info) server->next_rule = ""; // trigger calling send_a2s_rule_request_packet return; error: cleanup_qserver(server, 1); } void send_a2s_rule_request_packet(struct qserver *server) { struct a2s_status* status = (struct a2s_status*)server->master_query_tag; if(!get_server_rules && !get_player_info) { goto error; } do { if(!status->have_challenge) { debug(3, "sending challenge"); if(qserver_send_initial(server, A2S_GETCHALLENGE, sizeof(A2S_GETCHALLENGE)-1) == -1) goto error; status->sent_challenge = 1; break; } else if(get_server_rules && !status->have_rules) { char buf[sizeof(A2S_RULES)-1+4] = A2S_RULES; memcpy(buf+sizeof(A2S_RULES)-1, &status->challenge, 4); debug(3, "sending rule query"); if(qserver_send_initial(server, buf, sizeof(buf)) == -1) goto error; status->sent_rules = 1; break; } else if(get_player_info && !status->have_player) { char buf[sizeof(A2S_PLAYER)-1+4] = A2S_PLAYER; memcpy(buf+sizeof(A2S_PLAYER)-1, &status->challenge, 4); debug(3, "sending player query"); if(qserver_send_initial(server, buf, sizeof(buf)) == -1) goto error; status->sent_player = 1; break; } else { debug(3, "timeout"); // we are probably called due to timeout, restart. status->have_challenge = 0; status->have_rules = 0; } } while(1); return; error: cleanup_qserver(server, 1); } void deal_with_a2s_packet(struct qserver *server, char *rawpkt, int pktlen) { struct a2s_status* status = (struct a2s_status*)server->master_query_tag; char* pkt = rawpkt; char buf[16]; char* str; unsigned cnt; if(server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); server->n_requests++; } if(pktlen < 5) goto out_too_short; if( 0 == memcmp(pkt, "\xFE\xFF\xFF\xFF", 4) ) { // fragmented packet unsigned char pkt_index, pkt_max; unsigned int pkt_id = 1; SavedData *sdata; if(pktlen < 9) goto out_too_short; pkt += 4; // format: // int sequenceNumber // byte packetId // packetId format: // bits 0 - 3 = packets position in the sequence ( 0 .. N - 1 ) // bits 4 - 7 = total number of packets // sequenceId memcpy( &pkt_id, pkt, 4 ); debug( 3, "sequenceId: %d", pkt_id ); pkt += 4; // packetId if ( 1 == status->type ) { // HL2 format // The lower four bits represent the number of packets (2 to 15) and // the upper four bits represent the current packet starting with 0 pkt_max = ((unsigned char)*pkt) & 15; pkt_index = ((unsigned char)*pkt) >> 4; debug( 3, "packetid: 0x%hhx => idx: %hhu, max: %hhu", *pkt, pkt_index, pkt_max ); pkt++; pktlen -= 9; } else if ( 2 == status->type ) { // HL2 format // The next two bytes are: // 1. the max packets sent // 2. the index of this packet starting from 0 if(pktlen < 10) goto out_too_short; pkt_max = ((unsigned char)*pkt); pkt_index = ((unsigned char)*(pkt+1)); debug( 3, "packetid: 0x%hhx => idx: %hhu, max: %hhu", *pkt, pkt_index, pkt_max ); pkt+=2; pktlen -= 10; } else { malformed_packet( server, "Unable to determine packet format" ); cleanup_qserver( server, 1 ); return; } // pkt_max is the total number of packets expected // pkt_index is a bit mask of the packets received. if ( server->saved_data.data == NULL ) { sdata = &server->saved_data; } else { sdata = (SavedData*) calloc( 1, sizeof(SavedData)); sdata->next = server->saved_data.next; server->saved_data.next = sdata; } sdata->pkt_index = pkt_index; sdata->pkt_max = pkt_max; sdata->pkt_id = pkt_id; sdata->datalen = pktlen; sdata->data= (char*) malloc( sdata->datalen); if ( NULL == sdata->data ) { malformed_packet(server, "Out of memory"); cleanup_qserver( server, 1 ); return; } memcpy( sdata->data, pkt, sdata->datalen); // combine_packets will call us recursively combine_packets( server ); return; } else if( 0 != memcmp(pkt, "\xFF\xFF\xFF\xFF", 4) ) { malformed_packet(server, "invalid packet header"); goto out_error; } pkt += 4; pktlen -= 4; pktlen -= 1; switch(*pkt++) { case A2S_CHALLENGERESPONSE: if(pktlen < 4) goto out_too_short; memcpy(&status->challenge, pkt, 4); // do not count challenge as retry if(!status->have_challenge && server->retry1 != n_retries) { ++server->retry1; if(server->n_retries) { --server->n_retries; } } status->have_challenge = 1; debug(3, "challenge %x", status->challenge); break; case A2S_INFORESPONSE_HL1: if(pktlen < 28) goto out_too_short; status->type = 1; // ip:port str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; //server->server_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // server name str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->server_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // map str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->map_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // mod dir str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->game = strdup(pkt); add_rule(server, "gamedir", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // mod description str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "gamename", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; if( pktlen < 7 ) goto out_too_short; // num players server->num_players = (unsigned char)pkt[0]; // max players server->max_players = (unsigned char)pkt[1]; // version sprintf( buf, "%hhu", pkt[2] ); add_rule( server, "version", buf, 0 ); // dedicated add_rule( server, "dedicated", pkt[3] == 'd' ? "1" : "0", 0 ); // os switch( pkt[4] ) { case 'l': add_rule(server, "sv_os", "linux", 0); break; case 'w': add_rule(server, "sv_os", "windows", 0); break; default: buf[0] = pkt[4]; buf[1] = '\0'; add_rule(server, "sv_os", buf, 0); } // password add_rule(server, "password", pkt[5] ? "1" : "0" , 0); pkt += 6; pktlen -= 6; // mod info if ( pkt[0] ) { pkt++; pktlen--; // mod URL str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "mod_url", strdup( pkt ), 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // mod DL str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "mod_dl", strdup( pkt ), 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // mod Empty str = memchr(pkt, '\0', pktlen); pktlen -= str-pkt+1; pkt += str-pkt+1; if( pktlen < 10 ) goto out_too_short; // mod version sprintf( buf, "%u", swap_long_from_little(pkt)); add_rule( server, "mod_ver", buf, 0 ); pkt += 4; pktlen -= 4; // mod size sprintf( buf, "%u", swap_long_from_little(pkt)); add_rule( server, "mod_size", buf, 0 ); pkt += 4; pktlen -= 4; // svonly add_rule( server, "mod_svonly", ( *pkt ) ? "1" : "0" , 0 ); pkt++; pktlen--; // cldll add_rule( server, "mod_cldll", ( *pkt ) ? "1" : "0" , 0 ); pkt++; pktlen--; } if( pktlen < 2 ) goto out_too_short; // Secure add_rule( server, "secure", *pkt ? "1" : "0" , 0 ); pkt++; pktlen--; // Bots sprintf( buf, "%hhu", *pkt ); add_rule( server, "bots", buf, 0 ); pkt++; pktlen--; status->have_info = 1; server->retry1 = n_retries; server->next_player_info = server->num_players; break; case A2S_INFORESPONSE_HL2: if(pktlen < 1) goto out_too_short; status->type = 2; snprintf(buf, sizeof(buf), "%hhX", *pkt); add_rule(server, "protocol", buf, 0); ++pkt; --pktlen; // server name str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->server_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // map str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->map_name = strdup(pkt); pktlen -= str-pkt+1; pkt += str-pkt+1; // mod str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; server->game = strdup(pkt); add_rule(server, "gamedir", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; // description str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "gamename", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; if(pktlen < 9) goto out_too_short; // pkt[0], pkt[1] steam id unused server->num_players = (unsigned char)pkt[2]; server->max_players = (unsigned char)pkt[3]; // pkt[4] number of bots add_rule(server, "dedicated", pkt[5]?"1":"0", 0); if(pkt[6] == 'l') { add_rule(server, "sv_os", "linux", 0); } else if(pkt[6] == 'w') { add_rule(server, "sv_os", "windows", 0); } else { buf[0] = pkt[6]; buf[1] = '\0'; add_rule(server, "sv_os", buf, 0); } if(pkt[7]) { snprintf(buf, sizeof(buf), "%hhu", (unsigned char)pkt[7]); add_rule(server, "password", buf, 0); } if(pkt[8]) { snprintf(buf, sizeof(buf), "%hhu", (unsigned char)pkt[8]); add_rule(server, "secure", buf, 0); } pkt += 9; pktlen -= 9; // version str = memchr(pkt, '\0', pktlen); if(!str) goto out_too_short; add_rule(server, "version", pkt, 0); pktlen -= str-pkt+1; pkt += str-pkt+1; status->have_info = 1; server->retry1 = n_retries; server->next_player_info = server->num_players; break; case A2S_RULESRESPONSE: if(pktlen < 2) goto out_too_short; cnt = (unsigned char)pkt[0] + ((unsigned char)pkt[1]<<8); pktlen -= 2; pkt += 2; debug(3, "num_rules: %d", cnt); for(;cnt && pktlen > 0; --cnt) { char* key, *value; str = memchr(pkt, '\0', pktlen); if(!str) break; key = pkt; pktlen -= str-pkt+1; pkt += str-pkt+1; str = memchr(pkt, '\0', pktlen); if(!str) break; value = pkt; pktlen -= str-pkt+1; pkt += str-pkt+1; add_rule(server, key, value, NO_FLAGS); } if(cnt) { malformed_packet(server, "packet contains too few rules, missing %d", cnt); server->missing_rules = 1; } if(pktlen) malformed_packet(server, "garbage at end of rules, %d bytes left", pktlen); status->have_rules = 1; server->retry1 = n_retries; break; case A2S_PLAYERRESPONSE: if(pktlen < 1) goto out_too_short; cnt = (unsigned char)pkt[0]; pktlen -= 1; pkt += 1; debug(3, "num_players: %d", cnt); for(;cnt && pktlen > 0; --cnt) { unsigned idx; const char* name; struct player* p; idx = *pkt++; --pktlen; str = memchr(pkt, '\0', pktlen); if(!str) break; name = pkt; pktlen -= str-pkt+1; pkt += str-pkt+1; if(pktlen < 8) goto out_too_short; debug(3, "player index %d", idx); p = add_player(server, server->n_player_info); if(p) { p->name = strdup(name); p->frags = swap_long_from_little(pkt); p->connect_time = swap_float_from_little(pkt+4); } pktlen -= 8; pkt += 8; } #if 0 // seems to be a rather normal condition if(cnt) { malformed_packet(server, "packet contains too few players, missing %d", cnt); } #endif if(pktlen) malformed_packet(server, "garbage at end of player info, %d bytes left", pktlen); status->have_player = 1; server->retry1 = n_retries; break; default: malformed_packet(server, "invalid packet id %hhx", *--pkt); goto out_error; } if( (!get_player_info || (get_player_info && status->have_player)) && (!get_server_rules || (get_server_rules && status->have_rules)) ) { server->next_rule = NULL; } cleanup_qserver(server, 0); return; out_too_short: malformed_packet(server, "packet too short"); out_error: cleanup_qserver(server, 1); } // vim: sw=4 ts=8 noet qstat-2.11/a2s.h0000644002404400000620000000070010252737147010351 00000000000000/* * qstat 2.8 * by Steve Jankowski * * New Half-Life2 query protocol * Copyright 2005 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_A2S_H #define QSTAT_A2S_H #include "qserver.h" void send_a2s_request_packet(struct qserver *server); void send_a2s_rule_request_packet(struct qserver *server); void deal_with_a2s_packet(struct qserver *server, char *rawpkt, int pktlen); #endif qstat-2.11/aclocal.m40000644002404400000620000007546210520647402011364 00000000000000# generated automatically by aclocal 1.9.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.9.6])]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 7 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE]) AC_SUBST([$1_FALSE]) if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH]) ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 12 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.58])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $1 | $1:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"$am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. # # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories # created by `make install' are always world readable, even if the # installer happens to have an overly restrictive umask (e.g. 077). # This was a mistake. There are at least two reasons why we must not # use `-m 0755': # - it causes special bits like SGID to be ignored, # - it may be too restrictive (some setups expect 775 directories). # # Do not use -m 0755 and let people choose whatever they expect by # setting umask. # # We cannot accept any implementation of `mkdir' that recognizes `-p'. # Some implementations (such as Solaris 8's) are not thread-safe: if a # parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' # concurrently, both version can detect that a/ is missing, but only # one can create it and the other will error out. Consequently we # restrict ourselves to GNU make (using the --version option ensures # this.) AC_DEFUN([AM_PROG_MKDIR_P], [if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi AC_SUBST([mkdir_p])]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR qstat-2.11/gs2.c0000644002404400000620000002016010473372551010353 00000000000000/* * qstat 2.8 * by Steve Jankowski * * New Gamespy v2 query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #endif #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" void send_gs2_request_packet( struct qserver *server ) { // The below should work but seems to make no difference to what some // servers send if ( get_player_info ) { server->type->status_packet[8] = 0xff; server->type->status_packet[9] = 0xff; } else { server->type->status_packet[8] = 0x00; server->type->status_packet[9] = 0x00; } send_packet( server, server->type->status_packet, server->type->status_len ); } // See the following for protocol details: // http://dev.kquery.com/index.php?article=42 void deal_with_gs2_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *ptr = rawpkt; char *end = rawpkt + pktlen; unsigned char type = 0; unsigned char no_players = 0; unsigned char total_players = 0; unsigned char no_teams = 0; unsigned char total_teams = 0; unsigned char no_headers = 0; char **headers = NULL; debug( 2, "processing packet..." ); if ( pktlen < 15 ) { // invalid packet? cleanup_qserver( server, 1); return; } server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL); } // Could check the header here should // match the 4 byte id sent ptr += 5; while ( 0 == type && ptr < end ) { // server info: // name value pairs null seperated // empty name && value signifies the end of section char *var, *val; int var_len, val_len; var = ptr; var_len = strlen( var ); if ( ptr + var_len + 2 > end ) { if ( 0 != var_len ) { malformed_packet( server, "no rule value" ); } else if ( get_player_info ) { malformed_packet( server, "no player headers" ); } cleanup_qserver( server, 1); return; } ptr += var_len + 1; val = ptr; val_len = strlen( val ); ptr += val_len + 1; debug( 2, "var:%s (%d)=%s (%d)\n", var, var_len, val, val_len ); // Lets see what we've got if ( 0 == strcmp( var, "hostname" ) ) { server->server_name = strdup( val ); } else if( 0 == strcmp( var, "game_id" ) ) { server->game = strdup( val ); } else if( 0 == strcmp( var, "gamever" ) ) { // format: // v1.0 server->protocol_version = atoi( val+1 ); add_rule( server, var, val, NO_FLAGS ); } else if( 0 == strcmp( var, "mapname" ) ) { server->map_name = strdup( val ); } else if( 0 == strcmp( var, "maxplayers" ) ) { server->max_players = atoi( val ); } else if( 0 == strcmp( var, "numplayers" ) ) { server->num_players = no_players = atoi( val ); } else if( 0 == strcmp( var, "hostport" ) ) { change_server_port( server, atoi( val ), 0 ); } else if ( 0 == var_len ) { // check for end of section type = 1; } else { add_rule( server, var, val, NO_FLAGS ); } } if ( 1 != type ) { // no more info should be player headers here as we // requested it malformed_packet( server, "no player headers" ); cleanup_qserver( server, 1); return; } // player info header // format: // first byte = player count // followed by null seperated header no_players = (unsigned char)*ptr; debug( 2, "No Players:%d\n", no_players ); ptr++; if ( ptr >= end ) { malformed_packet( server, "no player headers" ); cleanup_qserver( server, 1); return; } while ( 1 == type && ptr < end ) { // first we have the headers null seperated char **tmpp; char *head = ptr; int head_len = strlen( head ); no_headers++; tmpp = (char**)realloc( headers, no_headers * sizeof( char* ) ); if ( NULL == tmpp ) { debug( 0, "Failed to realloc memory for headers\n" ); if ( NULL != headers ) { free( headers ); } cleanup_qserver( server, 1); return; } headers = tmpp; headers[no_headers-1] = head; ptr += head_len + 1; // end of headers check if ( 0x00 == *ptr ) { type = 2; ptr++; } debug( 2, "player header[%d] = '%s'", no_headers-1, head ); } if ( 2 != type ) { // no more info should be player info here as we // requested it malformed_packet( server, "no players" ); cleanup_qserver( server, 1); return; } while( 2 == type && ptr < end ) { // now each player details // add the player if ( 0x00 == *ptr ) { // no players if ( 0 != no_players ) { malformed_packet( server, "no players" ); cleanup_qserver( server, 1); return; } } else { struct player *player = add_player( server, total_players ); int i; for ( i = 0; i < no_headers; i++ ) { char *header = headers[i]; char *val; int val_len; if ( ptr >= end ) { malformed_packet( server, "short player detail" ); cleanup_qserver( server, 1); return; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; // lets see what we got if ( 0 == strcmp( header, "player_" ) ) { player->name = strdup( val ); } else if ( 0 == strcmp( header, "score_" ) ) { player->score = atoi( val ); } else if ( 0 == strcmp( header, "deaths_" ) ) { player->deaths = atoi( val ); } else if ( 0 == strcmp( header, "ping_" ) ) { player->ping = atoi( val ); } else if ( 0 == strcmp( header, "kills_" ) ) { player->frags = atoi( val ); } else if ( 0 == strcmp( header, "team_" ) ) { player->team = atoi( val ); } else { int len = strlen( header ); if ( '_' == header[len-1] ) { header[len-1] = '\0'; } player_add_info( player, header, val, NO_FLAGS ); } debug( 2, "Player[%d][%s]=%s\n", total_players, headers[i], val ); } total_players++; } if ( total_players > no_players ) { malformed_packet( server, "to many players %d > %d", total_players, no_players ); cleanup_qserver( server, 1); return; } // check for end of player info if ( 0x00 == *ptr ) { if ( total_players != no_players ) { malformed_packet( server, "bad number of players %d != %d", total_players, no_players ); cleanup_qserver( server, 1); return; } type = 3; ptr++; } } if ( 3 != type ) { // no more info should be team info here as we // requested it malformed_packet( server, "no teams" ); cleanup_qserver( server, 1 ); return; } no_teams = (unsigned char)*ptr; ptr++; debug( 2, "No teams:%d\n", no_teams ); no_headers = 0; while ( 3 == type && ptr < end ) { // first we have the headers null seperated char **tmpp; char *head = ptr; int head_len = strlen( head ); no_headers++; tmpp = (char**)realloc( headers, no_headers * sizeof( char* ) ); if ( NULL == tmpp ) { debug( 0, "Failed to realloc memory for headers\n" ); if ( NULL != headers ) { free( headers ); } cleanup_qserver( server, 1); return; } headers = tmpp; headers[no_headers-1] = head; ptr += head_len + 1; // end of headers check if ( 0x00 == *ptr ) { type = 4; ptr++; } } if ( 4 != type ) { // no more info should be team info here as we // requested it malformed_packet( server, "no teams" ); cleanup_qserver( server, 1); return; } while( 4 == type && ptr < end ) { // now each teams details int i; for ( i = 0; i < no_headers; i++ ) { char *val; int val_len; if ( ptr >= end ) { malformed_packet( server, "short team detail" ); cleanup_qserver( server, 1); return; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; // lets see what we got if ( 0 == strcmp( headers[i], "team_t" ) ) { // BF being stupid again teams 1 based instead of 0 players_set_teamname( server, total_teams + 1, val ); } debug( 2, "Team[%d][%s]=%s\n", total_teams, headers[i], val ); } total_teams++; if ( total_teams > no_teams ) { malformed_packet( server, "to many teams" ); cleanup_qserver( server, 1); return; } } cleanup_qserver( server, 1); return; } qstat-2.11/gs2.h0000644002404400000620000000064610253026620010354 00000000000000/* * qstat 2.8 * by Steve Jankowski * * New Gamespy v2 query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_GS2_H #define QSTAT_GS2_H #include "qserver.h" // Packet processing methods void deal_with_gs2_packet( struct qserver *server, char *pkt, int pktlen ); void send_gs2_request_packet( struct qserver *server ); #endif qstat-2.11/gs3.c0000644002404400000620000003247410470421276010363 00000000000000/* * qstat 2.8 * by Steve Jankowski * * New Gamespy v3 query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #include #endif #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" int process_gs3_packet( struct qserver *server ); // Player headers #define PLAYER_NAME_HEADER 1 #define PLAYER_SCORE_HEADER 2 #define PLAYER_DEATHS_HEADER 3 #define PLAYER_PING_HEADER 4 #define PLAYER_KILLS_HEADER 5 #define PLAYER_TEAM_HEADER 6 #define PLAYER_OTHER_HEADER 7 // Team headers #define TEAM_NAME_HEADER 1 #define TEAM_OTHER_HEADER 2 // Challenge response algorithum // Before sending a qr2 query (type 0x00) the client must first send a // challenge request (type 0x09). The host will respond with the same // packet type containing a string signed integer. // // Once the challenge is received the client should convert the string to a // network byte order integer and embed it in the keys query. // // Example: // // challenge request: [0xFE][0xFD][0x09][0x.. 4-byte-instance] // challenge response: [0x09][0x.. 4-byte-instance]["-1287574694"] // query: [0xFE][0xFD][0x00][0x.. 4-byte-instance][0xb3412b5a "-1287574694"] // void deal_with_gs3_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *ptr = rawpkt; unsigned int pkt_id; int pkt_index; unsigned char flag; unsigned int pkti, final; debug( 2, "packet..." ); if ( pktlen < 12 ) { // invalid packet? malformed_packet( server, "too short" ); cleanup_qserver( server, 1 ); return; } if ( 0x09 == *ptr ) { // challenge response // Could check the header here should // match the 4 byte id sent ptr++; memcpy( &pkt_id, ptr, 4 ); ptr += 4; server->challenge = atoi( ptr ); // Correct the stats due to two phase protocol server->retry1++; server->n_packets--; if ( server->retry1 == n_retries || server->flags & FLAG_BROADCAST ) { server->n_requests--; } else { server->n_retries--; } send_gs3_request_packet( server ); return; } if ( 0x00 != *ptr ) { malformed_packet( server, "bad initial byte '%hhx'", *ptr ); cleanup_qserver( server, 1 ); return; } ptr++; server->n_servers++; if ( server->server_name == NULL ) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL); } // Could check the header here should // match the 4 byte id sent memcpy( &pkt_id, ptr, 4 ); ptr += 4; // Next we have the splitnum details if ( 0 != strncmp( ptr, "splitnum", 8 ) ) { if ( server->flags & TF_STATUS_QUERY ) { // we have the status response deal_with_gs3_status( server, ptr, pktlen - ( ptr - rawpkt ) ); return; } else { malformed_packet( server, "missing splitnum" ); cleanup_qserver( server, 1 ); return; } } ptr += 9; pkt_index = ((unsigned char)*ptr) & 127; final = ((unsigned char)*ptr) >> 7; flag = *ptr++; pkti = *ptr++; debug( 1, "splitnum: flag = 0x%hhx, index = %d, final = %d, %d", flag, pkt_index, final, pkti ); if ( 0xFF != flag ) { // not a single packet response or a callback int pkt_max = pkt_index + 1; if ( ! final ) { // Guess that we have more to come pkt_max++; debug( 2, "more to come 0x%hxx 0x%hhx 0x%hhx", rawpkt[pktlen-3], rawpkt[pktlen-2], rawpkt[pktlen-1] ); } debug( 2, "pkt_max %d", pkt_max ); if ( 0 == pkt_index ) { // to prevent reprocessing when we get the call back // override the packet flag so it looks like a single // packet response rawpkt[14] = 0xFF; } // add the packet recalcing maxes if ( ! add_packet( server, pkt_id, pkt_index, pkt_max, pktlen, rawpkt, 1 ) ) { // fatal error e.g. out of memory return; } // combine_packets will call us recursively combine_packets( server ); return; } // if we get here we have what should be a full packet process_gs3_packet( server ); return; } void deal_with_gs3_status( struct qserver *server, char *rawpkt, int pktlen ) { char *pkt = rawpkt; debug( 1, "status packet" ); // Server name server->server_name = strdup( pkt ); pkt += strlen( pkt ) + 1; // gametype add_rule( server, "gametype", pkt, NO_FLAGS ); pkt += strlen( pkt ) + 1; // map server->map_name = strdup( pkt ); pkt += strlen( pkt ) + 1; // num players server->num_players = atoi( pkt ); pkt += strlen( pkt ) + 1; // max_players server->max_players = atoi( pkt ); pkt += strlen( pkt ) + 1; // hostport change_server_port( server, atoi( pkt ), 0 ); pkt += strlen( pkt ) + 1; cleanup_qserver( server, 1 ); } int process_gs3_packet( struct qserver *server ) { unsigned char state = 0; unsigned char no_players = 0; unsigned char total_players = 0; unsigned char no_teams = 0; unsigned char total_teams = 0; int pkt_index = 0; SavedData *fragment; debug( 2, "processing packet..." ); while ( NULL != ( fragment = get_packet_fragment( pkt_index++ ) ) ) { int pktlen = fragment->datalen; char *ptr = fragment->data; char *end = ptr + pktlen; debug( 2, "processing fragment[%d]...", fragment->pkt_index ); // check we have a full header if ( pktlen < 16 ) { // invalid packet? malformed_packet( server, "too short" ); cleanup_qserver( server, 1 ); return 0; } // skip over the header ptr += 16; while ( 0 == state && ptr < end ) { // server info: // name value pairs null seperated // empty name && value signifies the end of section char *var, *val; int var_len, val_len; if ( 0x00 == ptr[0] && 0x01 == ptr[1] ) { // not quite sure of the significance of these bytes // but we use them as a check for end of section state = 1; ptr += 2; break; } var = ptr; var_len = strlen( var ); ptr += var_len + 1; if ( ptr + 1 > end ) { malformed_packet( server, "no rule value" ); cleanup_qserver( server, 1); return 0; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; debug( 2, "var:%s (%d)=%s (%d)\n", var, var_len, val, val_len ); // Lets see what we've got if ( 0 == strcmp( var, "hostname" ) ) { server->server_name = strdup( val ); } else if( 0 == strcmp( var, "game_id" ) ) { server->game = strdup( val ); add_rule( server, var, val, NO_FLAGS ); } else if( 0 == strcmp( var, "gamever" ) ) { // format: // v1.0 server->protocol_version = atoi( val+1 ); add_rule( server, var, val, NO_FLAGS ); } else if( 0 == strcmp( var, "mapname" ) ) { server->map_name = strdup( val ); } else if( 0 == strcmp( var, "maxplayers" ) ) { server->max_players = atoi( val ); } else if( 0 == strcmp( var, "numplayers" ) ) { server->num_players = no_players = atoi( val ); } else if( 0 == strcmp( var, "hostport" ) ) { change_server_port( server, atoi( val ), 0 ); add_rule( server, var, val, NO_FLAGS ); } else { add_rule( server, var, val, NO_FLAGS ); } } while ( 1 == state && ptr < end ) { // first we have the header char *header = ptr; int head_len = strlen( header ); int header_type; ptr += head_len + 1; if ( 0 == head_len ) { // no more info debug( 3, "All done" ); cleanup_qserver( server, 1 ); return 1; } debug( 2, "player header '%s'", header ); if ( ptr > end ) { malformed_packet( server, "no details for header '%s'", header ); cleanup_qserver( server, 1 ); return 0; } // the next byte is the starting number total_players = *ptr++; if ( 0 == strcmp( header, "player_" ) ) { header_type = PLAYER_NAME_HEADER; } else if ( 0 == strcmp( header, "score_" ) ) { header_type = PLAYER_SCORE_HEADER; } else if ( 0 == strcmp( header, "deaths_" ) ) { header_type = PLAYER_DEATHS_HEADER; } else if ( 0 == strcmp( header, "ping_" ) ) { header_type = PLAYER_PING_HEADER; } else if ( 0 == strcmp( header, "kills_" ) ) { header_type = PLAYER_KILLS_HEADER; } else if ( 0 == strcmp( header, "team_" ) ) { header_type = PLAYER_TEAM_HEADER; } else { header_type = PLAYER_OTHER_HEADER; } while( ptr < end ) { // now each player details // add the player struct player *player; char *val; int val_len; // check for end of this headers player info if ( 0x00 == *ptr ) { debug( 3, "end of '%s' detail", header ); ptr++; // Note: can't check ( total_players != no_players ) here as we may have more packets if ( ptr < end && 0x00 == *ptr ) { debug( 3, "end of players" ); // end of all player headers / detail state = 2; ptr++; } break; } player = get_player_by_number( server, total_players ); if ( NULL == player ) { player = add_player( server, total_players ); } if ( ptr >= end ) { malformed_packet( server, "short player detail" ); cleanup_qserver( server, 1); return 0; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; debug( 2, "Player[%d][%s]=%s\n", total_players, header, val ); // lets see what we got switch( header_type ) { case PLAYER_NAME_HEADER: player->name = strdup( val ); break; case PLAYER_SCORE_HEADER: player->score = atoi( val ); break; case PLAYER_DEATHS_HEADER: player->deaths = atoi( val ); break; case PLAYER_PING_HEADER: player->ping = atoi( val ); break; case PLAYER_KILLS_HEADER: player->frags = atoi( val ); break; case PLAYER_TEAM_HEADER: player->team = atoi( val ); break; case PLAYER_OTHER_HEADER: default: if ( '_' == header[head_len-1] ) { header[head_len-1] = '\0'; player_add_info( player, header, val, NO_FLAGS ); header[head_len-1] = '_'; } else { player_add_info( player, header, val, NO_FLAGS ); } break; } total_players++; if ( total_players > no_players ) { malformed_packet( server, "to many players %d > %d", total_players, no_players ); cleanup_qserver( server, 1 ); return 0; } } } if ( 2 == state ) { no_teams = (unsigned char)*ptr; ptr++; debug( 2, "No teams:%d\n", no_teams ); state = 3; } while ( 3 == state && ptr < end ) { // first we have the header char *header = ptr; int head_len = strlen( header ); int header_type; ptr += head_len + 1; if ( 0 == head_len ) { // no more info debug( 3, "All done" ); cleanup_qserver( server, 1 ); return 1; } debug( 2, "team header '%s'", header ); if ( 0 == strcmp( header, "team_t" ) ) { header_type = TEAM_NAME_HEADER; } else { header_type = TEAM_OTHER_HEADER; } // the next byte is the starting number total_teams = *ptr++; while( ptr < end ) { // now each teams details char *val; int val_len; char rule[512]; if ( ptr >= end ) { malformed_packet( server, "short team detail" ); cleanup_qserver( server, 1); return 0; } val = ptr; val_len = strlen( val ); ptr += val_len + 1; debug( 2, "Team[%d][%s]=%s\n", total_teams, header, val ); // lets see what we got switch ( header_type ) { case TEAM_NAME_HEADER: // BF being stupid again teams 1 based instead of 0 players_set_teamname( server, total_teams + 1, val ); // N.B. yes no break case TEAM_OTHER_HEADER: default: // add as a server rule sprintf( rule, "%s%d", header, total_teams ); add_rule( server, rule, val, NO_FLAGS ); break; } total_teams++; if ( 0x00 == *ptr ) { // end of this headers teams ptr++; break; } } } } cleanup_qserver( server, 1 ); return 1; } void send_gs3_request_packet( struct qserver *server ) { char *packet; char query_buf[128]; int len; // In the old v3 protocol the doesnt seems to make a difference // to what the servers sends but in the challenge version it definitely does if ( get_player_info || get_server_rules ) { server->flags |= TF_PLAYER_QUERY|TF_RULES_QUERY; if ( server->challenge ) { // we've recieved a challenge response, send the query + challenge id len = sprintf( query_buf, "\xfe\xfd%c\x10\x20\x30\x40%c%c%c%c\xff\xff\xff\x01", 0x00, (unsigned char)(server->challenge >> 24), (unsigned char)(server->challenge >> 16), (unsigned char)(server->challenge >> 8), (unsigned char)(server->challenge >> 0) ); packet = query_buf; } else { // Either basic v3 protocol or challenge request packet = server->type->player_packet; len = server->type->player_len; } } else { server->flags |= TF_STATUS_QUERY; if ( server->challenge ) { // we've recieved a challenge response, send the query + challenge id len = sprintf( query_buf, "\xfe\xfd%c\x10\x20\x30\x40%c%c%c%c\x06\x01\x06\x05\x08\x0a\x04%c%c", 0x00, (unsigned char)(server->challenge >> 24), (unsigned char)(server->challenge >> 16), (unsigned char)(server->challenge >> 8), (unsigned char)(server->challenge >> 0), 0x00, 0x00 ); packet = query_buf; } else { // Either basic v3 protocol or challenge request packet = server->type->status_packet; len = server->type->status_len; } } send_packet( server, packet, len ); } qstat-2.11/gs3.h0000644002404400000620000000076410266352104010361 00000000000000/* * qstat 2.8 * by Steve Jankowski * * New Gamespy v3 query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_GS3_H #define QSTAT_GS3_H #include "qserver.h" // Packet processing methods void deal_with_gs3_packet( struct qserver *server, char *pkt, int pktlen ); void deal_with_gs3_status( struct qserver *server, char *rawpkt, int pktlen ); void send_gs3_request_packet( struct qserver *server ); #endif qstat-2.11/gps.c0000644002404400000620000002426110442312003010435 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Gamespy query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #endif #include #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" int gps_max_players( struct qserver *server ) { struct player *player; int no_players = 0; if ( 0 == server->num_players ) { return 0; } for ( player= server->players; player; player= player->next) { no_players++; } return ( no_players < server->num_players ) ? 1 : 0; } int gps_player_info_key( char *s, char *end) { static char *keys[] = { "frags_", "team_", "ping_", "species_", "race_", "deaths_", "score_", "enemy_", "player_", "keyhash_", "teamname_", "playername_", "keyhash_", "kills_", "queryid" }; int i; for ( i= 0; i < sizeof(keys)/sizeof(char*); i++) { int len= strlen(keys[i]); if ( s+len < end && strncmp( s, keys[i], len) == 0) { return len; } } return 0; } void send_gps_request_packet( struct qserver *server ) { send_packet( server, server->type->status_packet, server->type->status_len ); } void deal_with_gps_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *s, *key, *value, *end; struct player *player = NULL; int id_major=0, id_minor=0, final=0, player_num; char tmp[256]; debug( 2, "processing..." ); server->n_servers++; if ( server->server_name == NULL ) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL ); } /* // We're using the saved_data a bit differently here to track received // packets. // pkt_id is the id_major from the \queryid\ // pkt_max is the total number of packets expected // pkt_index is a bit mask of the packets received. The id_minor of // \queryid\ provides packet numbers (1 through pkt_max). */ if ( server->saved_data.pkt_index == -1) { server->saved_data.pkt_index= 0; } rawpkt[pktlen]= '\0'; end= &rawpkt[pktlen]; s= rawpkt; while ( *s) { // find the '\' while ( *s && *s == '\\') { s++; } if ( !*s ) { // out of packet break; } // Start of key key = s; // while we still have data and its not a '\' while ( *s && *s != '\\') { s++; } if ( !*s ) { // out of packet break; } // Terminate the key *s++= '\0'; // Now for the value value = s; // while we still have data and its not a '\' while ( *s && *s != '\\') { s++; } if ( s[0] && s[1] ) { //fprintf( stderr, "%s = %s\n", key, value ); if ( ! isalpha((unsigned char)s[1]) ) { // escape char? s++; // while we still have data and its not a '\' while ( *s && *s != '\\') { s++; } } else if ( isalpha((unsigned char)s[1]) && 0 == strncmp( key, "player_", 7 ) && 0 != strcmp( key, "player_flags" ) ) { // possible '\' in player name if ( ! gps_player_info_key( s+1, end ) ) { // yep there was an escape in the player name s++; // while we still have data and its not a '\' while ( *s && *s != '\\') { s++; } } } } if ( *s) { *s++= '\0'; } //fprintf( stderr, "%s = %s\n", key, value ); if ( *value == '\0') { if ( strcmp( key, "final" ) == 0 ) { final= 1; if ( id_minor > server->saved_data.pkt_max ) { server->saved_data.pkt_max = id_minor; } continue; } } /* This must be done before looking for player info because "queryid" is a valid according to gps_player_info_key(). */ if ( strcmp( key, "queryid") == 0) { sscanf( value, "%d.%d", &id_major, &id_minor); if ( server->saved_data.pkt_id == 0) { server->saved_data.pkt_id = id_major; } if ( id_major == server->saved_data.pkt_id) { if ( id_minor > 0) { // pkt_index is bitmask of packets recieved server->saved_data.pkt_index |= 1 << (id_minor-1); } if ( final && id_minor > server->saved_data.pkt_max) { server->saved_data.pkt_max = id_minor; } } continue; } if ( player == NULL ) { int len = gps_player_info_key( key, end); if ( len ) { // We have player info int player_number = atoi( key + len ); player = get_player_by_number( server, player_number); // && gps_max_players( server ) due to bf1942 issue // where the actual no players is correct but more player // details are returned if ( player == NULL && gps_max_players( server ) ) { player = add_player( server, player_number ); if ( player ) { // init to -1 so we can tell if // we have team info player->team = -1; player->deaths = -999; } } } } if ( strcmp( key, "mapname") == 0 && !server->map_name) { server->map_name= strdup( value ); } else if ( strcmp( key, "hostname") == 0 && !server->server_name) { server->server_name= strdup( value ); } else if ( strcmp( key, "hostport") == 0) { change_server_port( server, atoi( value), 0 ); } else if ( strcmp( key, "maxplayers") == 0) { server->max_players= atoi( value ); } else if ( strcmp( key, "numplayers") == 0) { server->num_players= atoi( value); } else if ( strcmp( key, server->type->game_rule) == 0 && !server->game) { server->game= strdup( value ); add_rule( server, key, value, NO_FLAGS); } else if ( strcmp( key, "final") == 0) { final= 1; if ( id_minor > server->saved_data.pkt_max) { server->saved_data.pkt_max = id_minor; } continue; } else if ( strncmp( key, "player_", 7) == 0 || strncmp( key, "playername_", 11) == 0 ) { int no; if ( strncmp( key, "player_", 7) == 0 ) { no = atoi(key+7); } else { no = atoi(key+11); } if ( player && player->number == no ) { player->name = strdup( value); player = NULL; } else if ( NULL != ( player = get_player_by_number( server, no ) ) ) { player->name = strdup( value); player = NULL; } else if ( gps_max_players( server ) ) { // gps_max_players( server ) due to bf1942 issue // where the actual no players is correct but more player // details are returned player = add_player( server, no ); if ( player ) { player->name= strdup( value); // init to -1 so we can tell if // we have team info player->team = -1; player->deaths = -999; } } } else if ( strncmp( key, "teamname_", 9) == 0 ) { // Yes plus 1 BF1942 is a silly players_set_teamname( server, atoi( key+9 ) + 1, value ); } else if ( strncmp( key, "team_t", 6) == 0 ) { players_set_teamname( server, atoi( key+6 ), value ); } else if ( strncmp( key, "frags_", 6) == 0 ) { player = get_player_by_number( server, atoi( key+6 ) ); if ( NULL != player ) { player->frags= atoi( value ); } } else if ( strncmp( key, "kills_", 6) == 0 ) { player = get_player_by_number( server, atoi( key+6 ) ); if ( NULL != player ) { player->frags= atoi( value ); } } else if ( strncmp( key, "team_", 5) == 0 ) { player = get_player_by_number( server, atoi( key+5 ) ); if ( NULL != player ) { if ( ! isdigit( (unsigned char)*value ) ) { player->team_name= strdup(value); } else { player->team= atoi( value); } server->flags|= FLAG_PLAYER_TEAMS; } } else if ( strncmp( key, "skin_", 5) == 0 ) { player = get_player_by_number( server, atoi( key+5 ) ); if ( NULL != player ) { player->skin= strdup( value); } } else if ( strncmp( key, "mesh_", 5) == 0 ) { player = get_player_by_number( server, atoi( key+5 ) ); if ( NULL != player ) { player->mesh = strdup( value); } } else if ( strncmp( key, "ping_", 5) == 0 ) { player = get_player_by_number( server, atoi( key+5 ) ); if ( NULL != player ) { player->ping= atoi( value); } } else if ( strncmp( key, "face_", 5) == 0 ) { player = get_player_by_number( server, atoi( key+5 ) ); if ( NULL != player ) { player->face= strdup( value); } } else if ( strncmp( key, "deaths_", 7) == 0 ) { player = get_player_by_number( server, atoi( key+7 ) ); if ( NULL != player ) { player->deaths= atoi( value ); } } // isnum( key[6] ) as halo uses score_tX for team scores else if ( strncmp( key, "score_", 6) == 0 && isdigit( (unsigned char)key[6] ) ) { player = get_player_by_number( server, atoi( key+6 ) ); if ( NULL != player ) { player->score = atoi( value ); } } else if ( player && strncmp( key, "playertype", 10) == 0) { player->team_name= strdup( value ); } else if ( player && strncmp( key, "charactername", 13) == 0) { player->face = strdup( value ); } else if ( player && strncmp( key, "characterlevel", 14) == 0) { player->ship= atoi( value ); } else if ( strncmp( key, "keyhash_", 8) == 0) { // Ensure these dont make it into the rules } else if ( 2 == sscanf( key, "%255[^_]_%d", tmp, &player_num ) ) { // arbitary player info player = get_player_by_number( server, player_num ); if ( NULL != player ) { player_add_info( player, tmp, value, NO_FLAGS ); } else if ( gps_max_players( server ) ) { // gps_max_players( server ) due to bf1942 issue // where the actual no players is correct but more player // details are returned player = add_player( server, player_num ); if ( player ) { player->name = NULL; // init to -1 so we can tell if // we have team info player->team = -1; player->deaths = -999; } player_add_info( player, tmp, value, NO_FLAGS ); } } else { player = NULL; add_rule( server, key, value, NO_FLAGS); } } debug( 2, "final %d\n", final ); debug( 2, "pkt_id %d\n", server->saved_data.pkt_id ); debug( 2, "pkt_max %d\n", server->saved_data.pkt_max ); debug( 2, "pkt_index %x\n", server->saved_data.pkt_index ); if ( ( final && server->saved_data.pkt_id == 0 ) || ( server->saved_data.pkt_max && server->saved_data.pkt_index >= ((1<<(server->saved_data.pkt_max))-1) ) || ( server->num_players < 0 && id_minor >= 3) ) { cleanup_qserver( server, 1); } } qstat-2.11/gps.h0000644002404400000620000000063710255535002010453 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Gamespy query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_GPS_H #define QSTAT_GPS_H #include "qserver.h" // Packet processing methods void deal_with_gps_packet( struct qserver *server, char *pkt, int pktlen ); void send_gps_request_packet( struct qserver *server ); #endif qstat-2.11/md5.c0000644002404400000620000003022210134554420010334 00000000000000/* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: md5.c,v 1.1 2004/10/17 20:41:52 l-n Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order either statically or dynamically; added missing #include in library. 2002-03-11 lpd Corrected argument list for main(), and added int return type, in test program and T value program. 2002-02-21 lpd Added missing #include in test program. 2000-07-03 lpd Patched to eliminate warnings about "constant is unsigned in ANSI C, signed in traditional"; made test program self-checking. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #include "md5.h" #include #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #ifdef ARCH_IS_BIG_ENDIAN # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) #else # define BYTE_ORDER 0 #endif #define T_MASK ((md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 0x242070db #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) #define T6 0x4787c62a #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) #define T9 0x698098d8 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) #define T13 0x6b901122 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) #define T16 0x49b40821 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) #define T19 0x265e5a51 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) #define T22 0x02441453 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) #define T25 0x21e1cde6 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) #define T28 0x455a14ed #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) #define T31 0x676f02d9 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) #define T35 0x6d9d6122 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) #define T38 0x4bdecfa9 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) #define T41 0x289b7ec6 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) #define T44 0x04881d05 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) #define T47 0x1fa27cf8 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) #define T50 0x432aff97 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) #define T53 0x655b59c3 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) #define T57 0x6fa87e4f #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) #define T60 0x4e0811a1 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) #define T63 0x2ad7d2bb #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ md5_word_t xbuf[16]; const md5_word_t *X; #endif { #if BYTE_ORDER == 0 /* * Determine dynamically whether this is a big-endian or * little-endian machine, since we can use a more efficient * algorithm on the latter. */ static const int w = 1; if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { /* * On little-endian machines, we can process properly aligned * data without copying it. */ if (!((data - (const md5_byte_t *)0) & 3)) { /* data are properly aligned */ X = (const md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } } #endif #if BYTE_ORDER == 0 else /* dynamic big-endian */ #endif #if BYTE_ORDER >= 0 /* big-endian */ { /* * On big-endian machines, we must arrange the bytes in the * right order. */ const md5_byte_t *xp = data; int i; # if BYTE_ORDER == 0 X = xbuf; /* (dynamic only) */ # else # define xbuf X /* (static only) */ # endif for (i = 0; i < 16; ++i, xp += 4) xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); } #endif } #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; pms->abcd[3] = 0x10325476; } void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) { const md5_byte_t *p = data; int left = nbytes; int offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } qstat-2.11/md5.h0000644002404400000620000000650010134554421010344 00000000000000/* Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: md5.h,v 1.1 2004/10/17 20:41:53 l-n Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.h is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed references to Ghostscript; clarified derivation from RFC 1321; now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); added conditionalization for C++ compilation from Martin Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED # define md5_INCLUDED /* * This package supports both compile-time and run-time determination of CPU * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is * defined as non-zero, the code will be compiled to run only on big-endian * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to * run on either big- or little-endian CPUs, but will run slightly less * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. */ typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; #ifdef __cplusplus extern "C" { #endif /* Initialize the algorithm. */ void md5_init(md5_state_t *pms); /* Append a string to the message. */ void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); /* Finish the message and return the digest. */ void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* md5_INCLUDED */ qstat-2.11/qstat.c0000644002404400000620000100617210520647376011027 00000000000000/* * qstat 2.8 * by Steve Jankowski * steve@qstat.org * http://www.qstat.org * * Thanks to Per Hammer for the OS/2 patches (per@mindbend.demon.co.uk) * Thanks to John Ross Hunt for the OpenVMS Alpha patches (bigboote@ais.net) * Thanks to Scott MacFiggen for the quicksort code (smf@webmethods.com) * Thanks to Simon Garner for the XML patch (sgarner@gameplanet.co.nz) * Thanks to Bob Marriott for the Ghost Recon code (bmarriott@speakeasy.net) * * Inspired by QuakePing by Len Norton * * Copyright 1996,1997,1998,1999,2000,2001,2002,2003,2004 by Steve Jankowski * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifdef HAVE_CONFIG_H # include "gnuconfig.h" #else # ifndef VERSION # define VERSION "2.11" # endif #endif char *qstat_version= VERSION; /* OS/2 defines */ #ifdef __OS2__ #define BSD_SELECT #endif #include #include #include #include #include #include #include #include #define QUERY_PACKETS #include "qstat.h" #include "packet_manip.h" #include "config.h" #ifndef _WIN32 #include #include #include #ifndef VMS #include #endif #include #include #include #include #include #ifndef F_SETFL #include #endif #ifdef __hpux extern int h_errno; #define STATIC static #else #define STATIC #endif #define INVALID_SOCKET -1 #ifndef INADDR_NONE #define INADDR_NONE ~0 #endif #define sockerr() errno #endif /* _WIN32 */ #ifdef __OS2__ #include #include #include #include #include #include #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #define close(a) soclose(a) #endif /* __OS2__ */ #ifndef FD_SETSIZE #define FD_SETSIZE 64 #endif /* Figure out whether to use poll() or select() */ #ifndef USE_POLL #ifndef USE_SELECT #ifdef sun #define USE_POLL #endif #ifdef linux #define USE_POLL #include #endif #ifdef __linux__ #define USE_POLL #include #endif #ifdef __linux #define USE_POLL #include #endif #ifdef __hpux #define USE_POLL #include #endif #ifdef __OpenBSD__ #define USE_POLL #include #endif #ifdef _AIX #define USE_POLL #include #endif #ifdef _WIN32 #define USE_SELECT #endif #ifdef __EMX__ #define USE_SELECT #endif #endif /* USE_SELECT */ #endif /* USE_POLL */ /* If did not chose, then use select() */ #ifndef USE_POLL #ifndef USE_SELECT #define USE_SELECT #endif #endif #ifdef ENABLE_DUMP #ifndef _WIN32 #include #include #endif #include #include static int do_dump; #endif #include "debug.h" server_type *types; int n_server_types; /* * Values set by command-line arguments */ int hostname_lookup= 0; /* set if -H was specified */ int new_style= 1; /* unset if -old was specified */ int n_retries= DEFAULT_RETRIES; int retry_interval= DEFAULT_RETRY_INTERVAL; int master_retry_interval= DEFAULT_RETRY_INTERVAL*4; int get_player_info= 0; int get_server_rules= 0; int up_servers_only= 0; int no_full_servers= 0; int no_empty_servers= 0; int no_header_display= 0; int raw_display= 0; char *raw_delimiter= "\t"; char *multi_delimiter = "|"; int player_address= 0; int hex_player_names= 0; int hex_server_names= 0; int name_xforms= 1; int strip_carets= 1; int max_simultaneous= MAXFD_DEFAULT; int sendinterval = 5; int html_names= -1; extern int html_mode; int raw_arg= 0; int show_game_in_raw= 0; int progress= 0; int num_servers_total= 0; int num_players_total= 0; int max_players_total= 0; int num_servers_returned= 0; int num_servers_timed_out= 0; int num_servers_down= 0; server_type* default_server_type= NULL; FILE *OF; /* output file */ unsigned int source_ip= INADDR_ANY; unsigned short source_port_low= 0; unsigned short source_port_high= 0; unsigned short source_port= 0; int show_game_port = 0; int no_port_offset = 0; #define ENCODING_LATIN_1 1 #define ENCODING_UTF_8 8 int xml_display= 0; int xml_encoding= ENCODING_LATIN_1; #define SUPPORTED_SERVER_SORT "pgihn" #define SUPPORTED_PLAYER_SORT "PFTNS" #define SUPPORTED_SORT_KEYS "l" SUPPORTED_SERVER_SORT SUPPORTED_PLAYER_SORT char sort_keys[32]; int player_sort= 0; int server_sort= 0; void quicksort( void **array, int i, int j, int (*compare)(void*,void*)); int qpartition( void **array, int i, int j, int (*compare)(void*,void*)); void sort_servers( struct qserver **array, int size); void sort_players( struct qserver *server); int server_compare( struct qserver *one, struct qserver *two); int player_compare( struct player *one, struct player *two); int type_option_compare( server_type *one, server_type *two ); int type_string_compare( server_type *one, server_type *two ); STATIC int u2xmp_html_color( short color, char *dest, int *font_tag ); STATIC int ut2k4_html_color( const unsigned char *color, char *dest, int *font_tag ); int show_errors= 0; static int noserverdups = 1; #define DEFAULT_COLOR_NAMES_RAW 0 #define DEFAULT_COLOR_NAMES_DISPLAY 1 int color_names= -1; #define SECONDS 0 #define CLOCK_TIME 1 #define STOPWATCH_TIME 2 #define DEFAULT_TIME_FMT_RAW SECONDS #define DEFAULT_TIME_FMT_DISPLAY CLOCK_TIME int time_format= -1; struct qserver *servers= NULL; struct qserver **last_server= &servers; struct qserver **connmap= NULL; int max_connmap; struct qserver *last_server_bind= NULL; struct qserver *first_server_bind= NULL; int connected= 0; time_t run_timeout= 0; time_t start_time; int waiting_for_masters; #define ADDRESS_HASH_LENGTH 2999 static unsigned num_servers; /* current number of servers in memory */ static struct qserver **server_hash[ADDRESS_HASH_LENGTH]; static unsigned int server_hash_len[ADDRESS_HASH_LENGTH]; static void free_server_hash(); static void xml_display_player_info_info(struct player* player); char *DOWN= "DOWN"; char *SYSERROR= "SYSERROR"; char *TIMEOUT= "TIMEOUT"; char *MASTER= "MASTER"; char *SERVERERROR= "ERROR"; char *HOSTNOTFOUND= "HOSTNOTFOUND"; char *BFRIS_SERVER_NAME= "BFRIS Server"; char *GAMESPY_MASTER_NAME= "Gamespy Master"; int display_prefix= 0; char *current_filename; int current_fileline; int count_bits( int n); static int qserver_get_timeout(struct qserver* server, struct timeval* now); static int wait_for_timeout( unsigned int ms); static void finish_output(); static void decode_stefmaster_packet( struct qserver *server, char *pkt, int pktlen); static void decode_q3master_packet( struct qserver *server, char *pkt, int pktlen); char * ut2003_strdup( const char *string, const char *end, char **next ); int html_entity( const char c, char *dest ); static const char * unreal_colors[] = { "AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black", "BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue", "DarkCyan", "DarkGoldenrod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "DarkOrange", "DarkOrchid", "DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DodgerBlue", "FireBrick", "FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "Goldenrod", "Gray", "Green", "GreenYellow", "Honeydew", "HotPink", "IndianRed", "Indigo", "Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue", "LightCoral", "LightCyan", "LightGoldenrodYellow", "LightGreen", "LightGrey", "LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon", "MediumAquamarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenrod", "PaleGreen", "PaleTurquoise", "PaleVioletRed", "PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "Seashell", "Sienna", "Silver", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", "Tan", "Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "White", "WhiteSmoke", "Yellow", "YellowGreen", }; static const char *unreal_rgb_colors[] = { "#F0F8FF", "#FAEBD7", "#00FFFF", "#7FFFD4", "#F0FFFF", "#F5F5DC", "#FFE4C4", "#000000", "#FFEBCD", "#0000FF", "#8A2BE2", "#A52A2A", "#DEB887", "#5F9EA0", "#7FFF00", "#D2691E", "#FF7F50", "#6495ED", "#FFF8DC", "#DC143C", "#00FFFF", "#00008B", "#008B8B", "#B8860B", "#A9A9A9", "#006400", "#BDB76B", "#8B008B", "#556B2F", "#FF8C00", "#9932CC", "#8B0000", "#E9967A", "#8FBC8F", "#483D8B", "#2F4F4F", "#00CED1", "#9400D3", "#FF1493", "#00BFFF", "#696969", "#1E90FF", "#B22222", "#FFFAF0", "#228B22", "#FF00FF", "#DCDCDC", "#F8F8FF", "#FFD700", "#DAA520", "#808080", "#008000", "#ADFF2F", "#F0FFF0", "#FF69B4", "#CD5C5C", "#4B0082", "#FFFFF0", "#F0E68C", "#E6E6FA", "#FFF0F5", "#7CFC00", "#FFFACD", "#ADD8E6", "#F08080", "#E0FFFF", "#FAFAD2", "#90EE90", "#D3D3D3", "#FFB6C1", "#FFA07A", "#20B2AA", "#87CEFA", "#778899", "#B0C4DE", "#FFFFE0", "#00FF00", "#32CD32", "#FAF0E6", "#FF00FF", "#800000", "#66CDAA", "#0000CD", "#BA55D3", "#9370DB", "#3CB371", "#7B68EE", "#00FA9A", "#48D1CC", "#C71585", "#191970", "#F5FFFA", "#FFE4E1", "#FFE4B5", "#FFDEAD", "#000080", "#FDF5E6", "#808000", "#6B8E23", "#FFA500", "#FF4500", "#DA70D6", "#EEE8AA", "#98FB98", "#AFEEEE", "#DB7093", "#FFEFD5", "#FFDAB9", "#CD853F", "#FFC0CB", "#DDA0DD", "#B0E0E6", "#800080", "#FF0000", "#BC8F8F", "#4169E1", "#8B4513", "#FA8072", "#F4A460", "#2E8B57", "#FFF5EE", "#A0522D", "#C0C0C0", "#87CEEB", "#6A5ACD", "#708090", "#FFFAFA", "#00FF7F", "#4682B4", "#D2B48C", "#008080", "#D8BFD8", "#FF6347", "#40E0D0", "#EE82EE", "#F5DEB3", "#FFFFFF", "#F5F5F5", "#FFFF00", "#9ACD32", }; void free_server( struct qserver *server); void free_player( struct player *player); void free_rule( struct rule *rule); void standard_display_server( struct qserver *server); /* MODIFY HERE * Change these functions to display however you want */ void display_server( struct qserver *server) { if ( player_sort) sort_players( server); if ( raw_display) raw_display_server( server); else if ( xml_display) xml_display_server( server); else if ( have_server_template()) template_display_server( server); else standard_display_server( server); free_server( server); } void standard_display_server( struct qserver *server) { char prefix[64]; if ( display_prefix) sprintf( prefix, "%-4s ", server->type->type_prefix); else prefix[0]='\0'; if ( server->server_name == DOWN) { if ( ! up_servers_only) fprintf( OF, "%s%-16s %10s\n", prefix, (hostname_lookup) ? server->host_name : server->arg, DOWN); return; } if ( server->server_name == TIMEOUT) { if ( server->flags & FLAG_BROADCAST && server->n_servers) fprintf( OF, "%s%-16s %d servers\n", prefix, server->arg, server->n_servers); else if ( ! up_servers_only) fprintf( OF, "%s%-16s no response\n", prefix, (hostname_lookup) ? server->host_name : server->arg); return; } if ( server->type->master) { display_qwmaster(server); return; } if ( no_full_servers && server->num_players >= server->max_players) return; if ( no_empty_servers && server->num_players == 0) return; if ( server->error != NULL) { fprintf( OF, "%s%-21s ERROR <%s>\n", prefix, (hostname_lookup) ? server->host_name : server->arg, server->error); return; } if ( new_style) { char *game= get_qw_game( server); int map_name_width= 8, game_width=0; switch( server->type->id) { case QW_SERVER: case Q2_SERVER: case Q3_SERVER: game_width= 9; break; case TRIBES2_SERVER: map_name_width= 14; game_width= 8; break; case GHOSTRECON_SERVER: map_name_width= 15; game_width= 15; break; case HL_SERVER: map_name_width= 12; break; default: break; } fprintf( OF, "%s%-21s %2d/%2d %*s %6d / %1d %*s %s\n", prefix, (hostname_lookup) ? server->host_name : server->arg, server->num_players, server->max_players, map_name_width, (server->map_name) ? server->map_name : "?", server->n_requests ? server->ping_total/server->n_requests : 999, server->n_retries, game_width, game, xform_name(server->server_name, server)); if ( get_server_rules) server->type->display_rule_func( server); if ( get_player_info) server->type->display_player_func( server); } else { char name[512]; sprintf( name, "\"%s\"", server->server_name); fprintf( OF, "%-16s %10s map %s at %22s %d/%d players %d ms\n", (hostname_lookup) ? server->host_name : server->arg, name, server->map_name, server->address, server->num_players, server->max_players, server->n_requests ? server->ping_total/server->n_requests : 999); } } void display_qwmaster( struct qserver *server) { char *prefix; prefix= server->type->type_prefix; if ( server->error != NULL) fprintf( OF, "%s %-17s ERROR <%s>\n", prefix, (hostname_lookup) ? server->host_name : server->arg, server->error); else fprintf( OF, "%s %-17s %d servers %6d / %1d\n", prefix, (hostname_lookup) ? server->host_name : server->arg, server->n_servers, server->n_requests ? server->ping_total/server->n_requests : 999, server->n_retries); } void display_header() { if ( ! no_header_display) fprintf( OF, "%-16s %8s %8s %15s %s\n", "ADDRESS", "PLAYERS", "MAP", "RESPONSE TIME", "NAME"); } void display_server_rules( struct qserver *server) { struct rule *rule; int printed= 0; rule= server->rules; for ( ; rule != NULL; rule= rule->next) { if ( (server->type->id != Q_SERVER && server->type->id != H2_SERVER) || ! is_default_rule( rule)) { fprintf( OF, "%c%s=%s", (printed)?',':'\t', rule->name, rule->value); printed++; } } if ( printed) fputs( "\n", OF); } void display_q_player_info( struct qserver *server) { char fmt[128]; struct player *player; strcpy( fmt, "\t#%-2d %3d frags %9s "); if ( color_names) strcat( fmt, "%9s:%-9s "); else strcat( fmt, "%2s:%-2s "); if ( player_address) strcat( fmt, "%22s "); else strcat( fmt, "%s"); strcat( fmt, "%s\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, player->number, player->frags, play_time(player->connect_time,1), quake_color(player->shirt_color), quake_color(player->pants_color), (player_address)?player->address:"", xform_name( player->name, server)); } } void display_qw_player_info( struct qserver *server) { char fmt[128]; struct player *player; strcpy( fmt, "\t#%-6d %3d frags %6s@%-5s %8s"); if ( color_names) strcat( fmt, "%9s:%-9s "); else strcat( fmt, "%2s:%-2s "); strcat( fmt, "%s\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, player->number, player->frags, play_time(player->connect_time,0), ping_time(player->ping), player->skin ? player->skin : "", quake_color(player->shirt_color), quake_color(player->pants_color), xform_name( player->name, server)); } } void display_q2_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( server->flags & FLAG_PLAYER_TEAMS) fprintf( OF, "\t%3d frags team#%d %8s %s\n", player->frags, player->team, ping_time(player->ping), xform_name( player->name, server)); else fprintf( OF, "\t%3d frags %8s %s\n", player->frags, ping_time(player->ping), xform_name( player->name, server)); } } void display_unreal_player_info( struct qserver *server) { struct player *player; static const char * fmt_team_number= "\t%3d frags team#%-3d %7s %s\n"; static const char * fmt_team_name= "\t%3d frags %8s %7s %s\n"; static const char * fmt_no_team= "\t%3d frags %8s %s\n"; player= server->players; for ( ; player != NULL; player= player->next) { if ( server->flags & FLAG_PLAYER_TEAMS) { // we use (player->score) ? player->score : player->frags, // so we get details from halo if ( player->team_name) { fprintf( OF, fmt_team_name, (player->score && NA_INT != player->score ) ? player->score : player->frags, player->team_name, ping_time(player->ping), xform_name( player->name, server) ); } else { fprintf( OF, fmt_team_number, (player->score && NA_INT != player->score ) ? player->score : player->frags, player->team, ping_time(player->ping), xform_name( player->name, server) ); } } else { fprintf( OF, fmt_no_team, player->frags, ping_time(player->ping), xform_name( player->name, server) ); } } } void display_shogo_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t%3d frags %8s %s\n", player->frags, ping_time(player->ping), xform_name( player->name, server)); } } void display_halflife_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t%3d frags %8s %s\n", player->frags, play_time( player->connect_time,1), xform_name( player->name, server)); } } void display_tribes_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t%4d score team#%d %8s %s\n", player->frags, player->team, ping_time( player->ping), xform_name( player->name, server)); } } void display_tribes2_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\tscore %4d %14s %s\n", player->frags, player->team_name ? player->team_name : (player->number == TRIBES_TEAM ? "TEAM" : "?"), xform_name( player->name, server)); } } void display_bfris_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\ttid: %d, ship: %d, team: %s, ping: %d, score: %d, kills: %d, name: %s\n", player->number, player->ship, player->team_name, player->ping, player->score, player->frags, xform_name( player->name, server)); } } void display_descent3_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t%3d frags %3d deaths team#%-3d %7s %s\n", player->frags, player->deaths, player->team, ping_time(player->ping), xform_name( player->name, server)); } } void display_ghostrecon_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\tdead=%3d team#%-3d %s\n", player->deaths, player->team, xform_name( player->name, server)); } } void display_eye_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->team_name) fprintf( OF, "\tscore %4d %6s team %12s %s\n", player->score, ping_time(player->ping), player->team_name, xform_name( player->name, server)); else fprintf( OF, "\tscore %4d %6s team#%d %s\n", player->score, ping_time(player->ping), player->team, xform_name( player->name, server)); } } int calculate_armyops_score( struct player *player) { /* Calculates a player's score for ArmyOps from the basic components */ int score = 0; int kill_score = 0; struct info *info; for ( info = player->info; info; info = info->next ) { if ( 0 == strcmp( info->name, "leader") || 0 == strcmp( info->name, "goal") || 0 == strcmp( info->name, "roe") ) score += atoi( info->value ); else if ( 0 == strcmp( info->name, "kia") || 0 == strcmp( info->name, "enemy") ) kill_score += atoi( info->value ); } if ( kill_score > 0 ) score += kill_score; return score; } void display_gs2_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->team_name) fprintf( OF, "\tscore %4d %6s team %12s %s\n", player->score, ping_time(player->ping), player->team_name, xform_name( player->name, server)); else fprintf( OF, "\tscore %4d %6s team#%d %s\n", player->score, ping_time(player->ping), player->team, xform_name( player->name, server)); } } void display_armyops_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { player->score = calculate_armyops_score( player ); } display_gs2_player_info(server); } void display_ts2_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t%6s %s\n", ping_time(player->ping), xform_name( player->name, server) ); } } void display_tm_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t%6s %s\n", ping_time(player->ping), xform_name( player->name, server) ); } } void display_doom3_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->tribe_tag) fprintf( OF, "\t#%-4d score %4d %6s team %12s %s\n", player->number, player->score, ping_time(player->ping), player->tribe_tag, xform_name( player->name, server)); else fprintf( OF, "\t#%-4d score %4d %6s team#%d %s\n", player->number, player->score, ping_time(player->ping), player->team, xform_name( player->name, server)); } } void display_hl2_player_info( struct qserver *server ) { // ATM this looks like halflife player info display_halflife_player_info( server ); } void display_ravenshield_player_info( struct qserver *server) { struct player *player = server->players; for ( ; player != NULL; player = player->next ) { fprintf( OF, "\t%3d frags %8s %s\n", player->frags, play_time( player->connect_time,1), xform_name( player->name, server)); } } void display_savage_player_info( struct qserver *server) { struct player *player = server->players; for ( ; player != NULL; player = player->next ) { fprintf( OF, "\t%3d frags %8s %s\n", player->frags, play_time( player->connect_time,1), xform_name( player->name, server)); } } void display_farcry_player_info( struct qserver *server) { struct player *player = server->players; for ( ; player != NULL; player = player->next ) { fprintf( OF, "\t%3d frags %8s %s\n", player->frags, play_time( player->connect_time,1), xform_name( player->name, server)); } } char * get_qw_game( struct qserver *server) { struct rule *rule; if ( server->type->game_rule == NULL || *server->type->game_rule == '\0') { return ""; } rule = server->rules; for ( ; rule != NULL; rule = rule->next) { if ( strcmp( rule->name, server->type->game_rule) == 0) { if ( server->type->id == Q3_SERVER && strcmp( rule->value, "baseq3") == 0) { return ""; } return rule->value; } } rule= server->rules; for ( ; rule != NULL; rule = rule->next) { if ( strcmp( rule->name, "game" ) == 0) { return rule->value; } } return ""; } /* Raw output for web master types */ #define RD raw_delimiter void raw_display_server( struct qserver *server) { char *prefix; int ping_time; prefix= server->type->type_prefix; if ( server->n_requests) ping_time= server->ping_total/server->n_requests; else ping_time= 999; if ( server->server_name == DOWN) { if ( ! up_servers_only) fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s\n\n", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup)?server->host_name:server->arg, RD, DOWN); return; } if ( server->server_name == TIMEOUT) { if ( server->flags & FLAG_BROADCAST && server->n_servers) fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%d\n", prefix, raw_arg, RD, raw_arg, server->arg, RD, server->arg, RD, server->n_servers); else if ( ! up_servers_only) fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s\n\n", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup)?server->host_name:server->arg, RD, TIMEOUT); return; } if ( server->error != NULL) { fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s" "%s%s", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup) ? server->host_name : server->arg, RD, "ERROR", RD, server->error); } else if ( server->type->flags & TF_RAW_STYLE_QUAKE) { fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s" "%s%s" "%s%d" "%s%s" "%s%d" "%s%d" "%s%d" "%s%d" "%s%s", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup) ? server->host_name : server->arg, RD, xform_name( server->server_name, server), RD, server->address, RD, server->protocol_version, RD, server->map_name, RD, server->max_players, RD, server->num_players, RD, ping_time, RD, server->n_retries, show_game_in_raw ? RD : "", show_game_in_raw ? get_qw_game(server) : "" ); } else if ( server->type->flags & TF_RAW_STYLE_TRIBES) { fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s" "%s%s" "%s%d" "%s%d", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup) ? server->host_name : server->arg, RD, xform_name( server->server_name, server), RD, (server->map_name) ? server->map_name : "?", RD, server->num_players, RD, server->max_players ); } else if ( server->type->flags & TF_RAW_STYLE_GHOSTRECON) { fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s" "%s%s" "%s%d" "%s%d", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup) ? server->host_name : server->arg, RD, xform_name( server->server_name, server), RD, (server->map_name) ? server->map_name : "?", RD, server->num_players, RD, server->max_players ); } else if ( server->type->master) { fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%d", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup) ? server->host_name : server->arg, RD, server->n_servers ); } else { fprintf( OF, "%s" "%.*s%.*s" "%s%s" "%s%s" "%s%s" "%s%d" "%s%d" "%s%d" "%s%d" "%s%s", prefix, raw_arg, RD, raw_arg, server->arg, RD, (hostname_lookup) ? server->host_name : server->arg, RD, xform_name( server->server_name, server), RD, (server->map_name) ? server->map_name : "?", RD, server->max_players, RD, server->num_players, RD, ping_time, RD, server->n_retries, show_game_in_raw ? RD : "", show_game_in_raw ? get_qw_game(server) : "" ); } fputs( "\n", OF); if ( server->type->master || server->error != NULL) { fputs( "\n", OF); return; } if ( get_server_rules) server->type->display_raw_rule_func( server); if ( get_player_info) server->type->display_raw_player_func( server); fputs( "\n", OF); } void raw_display_server_rules( struct qserver *server) { struct rule *rule; int printed= 0; rule= server->rules; for ( ; rule != NULL; rule= rule->next) { if ( server->type->id == TRIBES2_SERVER) { char *v; for ( v= rule->value; *v; v++) if ( *v == '\n') *v= ' '; } fprintf( OF, "%s%s=%s", (printed)?RD:"", rule->name, rule->value); printed++; } if ( server->missing_rules) fprintf( OF, "%s?", (printed)?RD:""); fputs( "\n", OF); } void raw_display_q_player_info( struct qserver *server) { char fmt[] = "%d" "%s%s" "%s%s" "%s%d" "%s%s" "%s%s" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, player->number, RD, xform_name( player->name, server), RD, player->address, RD, player->frags, RD, play_time(player->connect_time,1), RD, quake_color(player->shirt_color), RD, quake_color(player->pants_color) ); fputs( "\n", OF); } } void raw_display_qw_player_info( struct qserver *server) { char fmt[128]; struct player *player; strcpy( fmt, "%d" "%s%s" "%s%d" "%s%s" "%s%s" "%s%s"); strcat( fmt, "%s%d" "%s%s"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, player->number, RD, xform_name( player->name, server), RD, player->frags, RD, play_time(player->connect_time,1), RD, quake_color(player->shirt_color), RD, quake_color(player->pants_color), RD, player->ping, RD, player->skin ? player->skin : "" ); fputs( "\n", OF); } } void raw_display_q2_player_info( struct qserver *server) { static const char *fmt = "%s" "%s%d" "%s%d"; static const char *fmt_team = "%s" "%s%d" "%s%d" "%s%d"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( server->flags & FLAG_PLAYER_TEAMS) fprintf( OF, fmt_team, xform_name( player->name, server), RD, player->frags, RD, player->ping, RD, player->team ); else fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, player->ping ); fputs( "\n", OF); } } void raw_display_unreal_player_info( struct qserver *server) { static const char *fmt= "%s" "%s%d" "%s%d" "%s%d" "%s%s" "%s%s" "%s%s"; static const char *fmt_team_name= "%s" "%s%d" "%s%d" "%s%s" "%s%s" "%s%s" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->team_name) fprintf( OF, fmt_team_name, xform_name( player->name, server), RD, player->frags, RD, player->ping, RD, player->team_name, RD, player->skin ? player->skin : "", RD, player->mesh ? player->mesh : "", RD, player->face ? player->face : "" ); else fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, player->ping, RD, player->team, RD, player->skin ? player->skin : "", RD, player->mesh ? player->mesh : "", RD, player->face ? player->face : "" ); fputs( "\n", OF); } } void raw_display_halflife_player_info( struct qserver *server) { static char fmt[24]= "%s" "%s%d" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, play_time( player->connect_time,1) ); fputs( "\n", OF); } } void raw_display_tribes_player_info( struct qserver *server) { static char fmt[24]= "%s" "%s%d" "%s%d" "%s%d" "%s%d"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, player->ping, RD, player->team, RD, player->packet_loss ); fputs( "\n", OF); } } void raw_display_tribes2_player_info( struct qserver *server) { static char fmt[]= "%s" "%s%d" "%s%d" "%s%s" "%s%s" "%s%s"; struct player *player; char *type; player= server->players; for ( ; player != NULL; player= player->next) { switch( player->type_flag) { case PLAYER_TYPE_BOT: type= "Bot"; break; case PLAYER_TYPE_ALIAS: type= "Alias"; break; default: type= ""; break; } fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, player->team, RD, player->team_name ? player->team_name : "TEAM", RD, type, RD, player->tribe_tag ? xform_name(player->tribe_tag,server) : "" ); fputs( "\n", OF); } } void raw_display_bfris_player_info( struct qserver *server) { static char fmt[] = "%d" "%s%d" "%s%s" "%s%d" "%s%d" "%s%d" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, player->number, RD, player->ship, RD, player->team_name, RD, player->ping, RD, player->score, RD, player->frags, RD, xform_name( player->name, server) ); fputs( "\n", OF); } } void raw_display_descent3_player_info( struct qserver *server) { static char fmt[]= "%s" "%s%d" "%s%d" "%s%d" "%s%d"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, player->deaths, RD, player->ping, RD, player->team ); fputs( "\n", OF); } } void raw_display_ghostrecon_player_info( struct qserver *server) { static char fmt[28]= "%s" "%s%d" "%s%d"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->deaths, RD, player->team ); fputs( "\n", OF); } } void raw_display_eye_player_info( struct qserver *server) { static const char *fmt= "%s" "%s%d" "%s%d" "%s%d" "%s%s" "%s%s"; static const char *fmt_team_name= "%s" "%s%d" "%s%d" "%s%s" "%s%s" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->team_name) fprintf( OF, fmt_team_name, xform_name( player->name, server), RD, player->score, RD, player->ping, RD, player->team_name, RD, player->skin ? player->skin : "", RD, play_time( player->connect_time,1) ); else fprintf( OF, fmt, xform_name( player->name, server), RD, player->score, RD, player->ping, RD, player->team, RD, player->skin ? player->skin : "", RD, play_time( player->connect_time,1) ); fputs( "\n", OF); } } void raw_display_doom3_player_info( struct qserver *server) { static const char *fmt= "%s" "%s%d" "%s%d" "%s%d" "%s%u"; static const char *fmt_team_name= "%s" "%s%d" "%s%d" "%s%s" "%s%u"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->tribe_tag) fprintf( OF, fmt_team_name, xform_name( player->name, server), RD, player->score, RD, player->ping, RD, player->tribe_tag, RD, player->number ); else fprintf( OF, fmt, xform_name( player->name, server), RD, player->score, RD, player->ping, RD, player->team, RD, player->number ); fputs( "\n", OF); } } void raw_display_hl2_player_info( struct qserver *server ) { // ATM this looks like halflife player info raw_display_halflife_player_info( server ); } void raw_display_gs2_player_info( struct qserver *server) { static const char *fmt= "%s" "%s%d" "%s%d" "%s%d" "%s%s" "%s%s"; static const char *fmt_team_name= "%s" "%s%d" "%s%d" "%s%s" "%s%s" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { if ( player->team_name) fprintf( OF, fmt_team_name, xform_name( player->name, server), RD, player->score, RD, player->ping, RD, player->team_name, RD, player->skin ? player->skin : "", RD, play_time( player->connect_time,1) ); else fprintf( OF, fmt, xform_name( player->name, server), RD, player->score, RD, player->ping, RD, player->team, RD, player->skin ? player->skin : "", RD, play_time( player->connect_time,1) ); fputs( "\n", OF); } } void raw_display_armyops_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { player->score = calculate_armyops_score( player ); } raw_display_gs2_player_info(server); } void raw_display_ts2_player_info( struct qserver *server) { static const char *fmt= "%s" "%s%d" "%s%s" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->ping, RD, player->skin ? player->skin : "", RD, play_time( player->connect_time, 1 ) ); fputs( "\n", OF); } } void raw_display_tm_player_info( struct qserver *server) { static const char *fmt= "%s" "%s%d" "%s%s" "%s%s"; struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->ping, RD, player->skin ? player->skin : "", RD, play_time( player->connect_time, 1 ) ); fputs( "\n", OF); } } void raw_display_ravenshield_player_info( struct qserver *server) { static char fmt[24]= "%s" "%s%d" "%s%s"; struct player *player = server->players; for ( ; player != NULL; player= player->next ) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, play_time( player->connect_time,1) ); fputs( "\n", OF); } } void raw_display_savage_player_info( struct qserver *server) { static char fmt[24]= "%s" "%s%d" "%s%s"; struct player *player = server->players; for ( ; player != NULL; player= player->next ) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, play_time( player->connect_time,1) ); fputs( "\n", OF); } } void raw_display_farcry_player_info( struct qserver *server) { static char fmt[24]= "%s" "%s%d" "%s%s"; struct player *player = server->players; for ( ; player != NULL; player= player->next ) { fprintf( OF, fmt, xform_name( player->name, server), RD, player->frags, RD, play_time( player->connect_time,1) ); fputs( "\n", OF); } } /* XML output * Contributed by :-) */ void xml_display_server( struct qserver *server) { char *prefix; prefix= server->type->type_prefix; if ( server->server_name == DOWN) { if ( ! up_servers_only) { fprintf( OF, "\t\n", xml_escape(prefix), xml_escape(server->arg), xml_escape(DOWN)); fprintf( OF, "\t\t%s\n", xml_escape((hostname_lookup)?server->host_name:server->arg)); fprintf( OF, "\t\n"); } return; } if ( server->server_name == TIMEOUT) { if ( server->flags & FLAG_BROADCAST && server->n_servers) { fprintf( OF, "\t\n", xml_escape(prefix), xml_escape(server->arg), xml_escape(TIMEOUT), server->n_servers); fprintf( OF, "\t\n"); } else if ( ! up_servers_only) { fprintf( OF, "\t\n", xml_escape(prefix), xml_escape(server->arg), xml_escape(TIMEOUT)); fprintf( OF, "\t\t%s\n", xml_escape((hostname_lookup)?server->host_name:server->arg)); fprintf( OF, "\t\n"); } return; } if ( server->error != NULL) { fprintf( OF, "\t\n", xml_escape(prefix), xml_escape(server->arg), "ERROR"); fprintf( OF, "\t\t%s\n", xml_escape((hostname_lookup)?server->host_name:server->arg)); fprintf( OF, "\t\t%s\n", xml_escape(server->error)); } else if ( server->type->master) { fprintf( OF, "\t\n", xml_escape(prefix), xml_escape(server->arg), "UP", server->n_servers); } else { fprintf( OF, "\t\n", xml_escape(prefix), xml_escape(server->arg), "UP"); fprintf( OF, "\t\t%s\n", xml_escape((hostname_lookup)?server->host_name:server->arg)); fprintf( OF, "\t\t%s\n", xml_escape(xform_name( server->server_name, server))); fprintf( OF, "\t\t%s\n", xml_escape(get_qw_game(server))); fprintf( OF, "\t\t%s\n", xml_escape(server->map_name)); fprintf( OF, "\t\t%d\n", server->num_players); fprintf( OF, "\t\t%d\n", server->max_players); if ( !(server->type->flags & TF_RAW_STYLE_TRIBES)) { fprintf( OF, "\t\t%d\n", server->n_requests ? server->ping_total/server->n_requests : 999); fprintf( OF, "\t\t%d\n", server->n_retries); } if ( server->type->flags & TF_RAW_STYLE_QUAKE) { fprintf( OF, "\t\t
%s
\n", xml_escape(server->address)); fprintf( OF, "\t\t%d\n", server->protocol_version); } } if ( ! server->type->master && server->error == NULL) { if ( get_server_rules) server->type->display_xml_rule_func( server); if ( get_player_info) server->type->display_xml_player_func( server); } fprintf( OF, "\t
\n"); } void xml_header() { fprintf( OF, "\n\n", xml_encoding == ENCODING_LATIN_1 ? "iso-8859-1" : "UTF-8"); } void xml_footer() { fprintf( OF, "\n"); } void xml_display_server_rules( struct qserver *server) { struct rule *rule; rule= server->rules; fprintf( OF, "\t\t\n"); for ( ; rule != NULL; rule= rule->next) { fprintf( OF, "\t\t\t%s\n", xml_escape(rule->name), xml_escape(rule->value)); } fprintf( OF, "\t\t\n"); } void xml_display_q_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n", player->number); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t
%s
\n", xml_escape(player->address)); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t\n", xml_escape(play_time(player->connect_time,1))); if ( color_names) { fprintf( OF, "\t\t\t\t%s\n", xml_escape(quake_color(player->shirt_color))); fprintf( OF, "\t\t\t\t%s\n", xml_escape(quake_color(player->pants_color))); } else { fprintf( OF, "\t\t\t\t%s\n", quake_color(player->shirt_color)); fprintf( OF, "\t\t\t\t%s\n", quake_color(player->pants_color)); } fprintf( OF, "\t\t\t
\n"); } fprintf( OF, "\t\t
\n"); } void xml_display_qw_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n", player->number); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t\n", xml_escape(play_time(player->connect_time,1))); if ( color_names) { fprintf( OF, "\t\t\t\t%s\n", xml_escape(quake_color(player->shirt_color))); fprintf( OF, "\t\t\t\t%s\n", xml_escape(quake_color(player->pants_color))); } else { fprintf( OF, "\t\t\t\t%s\n", quake_color(player->shirt_color)); fprintf( OF, "\t\t\t\t%s\n", quake_color(player->pants_color)); } fprintf( OF, "\t\t\t\t%d\n", player->ping); fprintf( OF, "\t\t\t\t%s\n", player->skin ? xml_escape(player->skin) : ""); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_q2_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); if ( server->flags & FLAG_PLAYER_TEAMS) fprintf( OF, "\t\t\t\t%d\n", player->team); fprintf( OF, "\t\t\t\t%d\n", player->ping); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_player_info_info(struct player* player) { struct info *info; for (info = player->info; info; info = info->next ) { if ( info->name ) { char *name = xml_escape( info->name ); char *value = xml_escape( info->value ); fprintf( OF, "\t\t\t\t<%s>%s\n", name, value, name ); } } } void xml_display_unreal_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); if ( -999 != player->deaths ) { fprintf( OF, "\t\t\t\t%d\n", player->deaths); } fprintf( OF, "\t\t\t\t%d\n", player->ping); if ( player->team_name) { fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->team_name)); } else if ( -1 != player->team ) { fprintf( OF, "\t\t\t\t%d\n", player->team); } // Some games dont provide // so only display if they do if ( player->skin ) { fprintf( OF, "\t\t\t\t%s\n", player->skin ? xml_escape(player->skin) : ""); } if ( player->mesh ) { fprintf( OF, "\t\t\t\t%s\n", player->mesh ? xml_escape(player->mesh) : ""); } if ( player->face ) { fprintf( OF, "\t\t\t\t%s\n", player->face ? xml_escape(player->face) : ""); } xml_display_player_info_info(player); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_halflife_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_tribes_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t%d\n", player->team); fprintf( OF, "\t\t\t\t%d\n", player->ping); fprintf( OF, "\t\t\t\t%d\n", player->packet_loss); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_tribes2_player_info( struct qserver *server) { struct player *player; char *type; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { if ( player->team_name) { switch( player->type_flag) { case PLAYER_TYPE_BOT: type= "Bot"; break; case PLAYER_TYPE_ALIAS: type= "Alias"; break; default: type= ""; break; } fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t%s\n", player->team, xml_escape(player->team_name)); fprintf( OF, "\t\t\t\t%s\n", xml_escape(type)); fprintf( OF, "\t\t\t\t%s\n", player->tribe_tag ? xml_escape(xform_name(player->tribe_tag,server)) : ""); fprintf( OF, "\t\t\t\n"); } } fprintf( OF, "\t\t\n"); } void xml_display_bfris_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n", player->number); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->score); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->team_name)); fprintf( OF, "\t\t\t\t%d\n", player->ping); fprintf( OF, "\t\t\t\t%d\n", player->ship); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_descent3_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t%d\n", player->deaths); fprintf( OF, "\t\t\t\t%d\n", player->ping); fprintf( OF, "\t\t\t\t%d\n", player->team); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_ravenshield_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_ghostrecon_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->deaths); fprintf( OF, "\t\t\t\t%d\n", player->team); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_eye_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->score); fprintf( OF, "\t\t\t\t%d\n", player->ping); if ( player->team_name) fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->team_name)); else fprintf( OF, "\t\t\t\t%d\n", player->team); if ( player->skin) fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->skin)); if ( player->connect_time) fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_doom3_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%u\n", player->number); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->score); fprintf( OF, "\t\t\t\t%d\n", player->ping); if ( player->tribe_tag) fprintf( OF, "\t\t\t\t%s\n", player->tribe_tag ? xml_escape(xform_name(player->tribe_tag,server)) : ""); else fprintf( OF, "\t\t\t\t%d\n", player->team); if ( player->skin) fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->skin)); if ( player->connect_time) fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); xml_display_player_info_info(player); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_hl2_player_info( struct qserver *server ) { // ATM this looks like halflife player info xml_display_halflife_player_info( server ); } void xml_display_gs2_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->ping); if ( NA_INT != player->score ) { fprintf( OF, "\t\t\t\t%d\n", player->score); } if ( NA_INT != player->deaths ) { fprintf( OF, "\t\t\t\t%d\n", player->deaths); } if ( NA_INT != player->frags ) { fprintf( OF, "\t\t\t\t%d\n", player->frags); } if ( player->team_name ) { fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->team_name)); } else { fprintf( OF, "\t\t\t\t%d\n",player->team); } if ( player->skin) { fprintf( OF, "\t\t\t\t%s\n", xml_escape(player->skin)); } if ( player->connect_time) { fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); } xml_display_player_info_info(player); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_armyops_player_info( struct qserver *server) { struct player *player; player= server->players; for ( ; player != NULL; player= player->next) { player->score = calculate_armyops_score( player ); } xml_display_gs2_player_info(server); } void xml_display_ts2_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->ping); if ( player->connect_time ) { fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); } xml_display_player_info_info(player); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_tm_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->ping); if ( player->connect_time ) { fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); } xml_display_player_info_info(player); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_savage_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void xml_display_farcry_player_info( struct qserver *server) { struct player *player; fprintf( OF, "\t\t\n"); player= server->players; for ( ; player != NULL; player= player->next) { fprintf( OF, "\t\t\t\n"); fprintf( OF, "\t\t\t\t%s\n", xml_escape(xform_name( player->name, server))); fprintf( OF, "\t\t\t\t%d\n", player->frags); fprintf( OF, "\t\t\t\t\n", xml_escape(play_time( player->connect_time,1))); fprintf( OF, "\t\t\t\n"); } fprintf( OF, "\t\t\n"); } void display_progress() { static struct timeval rate_start= {0,0}; char rate[32]; struct timeval now; gettimeofday( &now, NULL); if ( ! rate_start.tv_sec) { rate_start= now; rate[0]='\0'; } else { int delta= time_delta( &now, &rate_start); if ( delta > 1500 ) sprintf( rate, " %d servers/sec ", (num_servers_returned+num_servers_timed_out)*1000 / delta); else rate[0]='\0'; } // only print out every 'progress' number of servers. if ( 0 != num_servers_returned+num_servers_timed_out && ( progress == 1 || (num_servers_returned+num_servers_timed_out) % progress == 0 ) ) { fprintf( stderr, "\r%d/%d (%d timed out, %d down)%s", num_servers_returned+num_servers_timed_out, num_servers_total, num_servers_timed_out, num_servers_down, rate ); } } /* ----- END MODIFICATION ----- Don't need to change anything below here. */ void set_non_blocking( int fd); int set_fds( fd_set *fds); void get_next_timeout( struct timeval *timeout); void set_file_descriptors(); int wait_for_file_descriptors( struct timeval *timeout); struct qserver * get_next_ready_server(); /* Misc flags */ struct timeval packet_recv_time; int one_server_type_id= ~ MASTER_SERVER; static int one= 1; static int little_endian; static int big_endian; unsigned int swap_long( void *); unsigned short swap_short( void *); float swap_float_from_little( void *f); char * strndup( const char *string, size_t len); #define FORCE 1 /* Print an error message and the program usage notes */ void usage( char *msg, char **argv, char *a1) { int i; server_type *type; server_type **sorted_types; if ( msg) fprintf( stderr, msg, a1); printf( "Usage: %s [options ...]\n", argv[0]); printf( "\t[-default server-type] [-cfg file] [-f file] [host[:port]] ...\n"); printf( "Where host is an IP address or host name\n"); sorted_types = (server_type **) malloc( sizeof(server_type *) * n_server_types ); type = &types[0]; for ( i = 0; type->id != Q_UNKNOWN_TYPE; type++, i++ ) { sorted_types[i] = type; } quicksort( (void**)sorted_types, 0, n_server_types-1, (int (*)(void*,void*)) type_option_compare ); for ( i = 0; i < n_server_types; i++ ) { type = sorted_types[i]; printf( "%s\t\tquery %s server\n", type->type_option, type->game_name ); } quicksort( (void**)sorted_types, 0, n_server_types-1, (int (*)(void*,void*)) type_string_compare ); printf( "-default\tset default server type:"); for ( i = 0; i < n_server_types; type++, i++ ) { type = sorted_types[i]; printf( " %s", type->type_string ); } puts(""); printf( "-nocfg\t\tIgnore qstat configuration loaded from any default location. Must be the first option on the command-line.\n" ); printf( "-cfg\t\tread the extended types from given file not the default one\n"); printf( "-f\t\tread hosts from file\n"); printf( "-R\t\tfetch and display server rules\n"); printf( "-P\t\tfetch and display player info\n"); printf( "-sort\t\tsort servers and/or players\n"); printf( "-u\t\tonly display servers that are up\n"); printf( "-nf\t\tdo not display full servers\n"); printf( "-ne\t\tdo not display empty servers\n"); printf( "-nh\t\tdo not display header line.\n" ); printf( "-cn\t\tdisplay color names instead of numbers\n"); printf( "-ncn\t\tdisplay color numbers instead of names\n"); printf( "-hc\t\tdisplay colors in #rrggbb format\n"); printf( "-tc\t\tdisplay time in clock format (DhDDmDDs)\n"); printf( "-tsw\t\tdisplay time in stop-watch format (DD:DD:DD)\n"); printf( "-ts\t\tdisplay time in seconds\n"); printf( "-pa\t\tdisplay player address\n"); printf( "-hpn\t\tdisplay player names in hex\n"); printf( "-hsn\t\tdisplay server names in hex\n"); printf( "-nh\t\tdo not display header\n"); printf( "-old\t\told style display\n"); printf( "-progress\tdisplay progress meter (text only)\n"); printf( "-retry\t\tnumber of retries, default is %d\n", DEFAULT_RETRIES); printf( "-interval\tinterval between retries, default is %.2f seconds\n", DEFAULT_RETRY_INTERVAL / 1000.0); printf( "-mi\t\tinterval between master server retries, default is %.2f seconds\n", (DEFAULT_RETRY_INTERVAL*4) / 1000.0); printf( "-timeout\ttotal time in seconds before giving up\n"); printf( "-maxsim\t\tset maximum simultaneous queries\n"); printf( "-sendinterval\t\tset time in ms between sending packets, default %u\n", sendinterval); printf( "-errors\t\tdisplay errors\n"); printf( "-allowserverdups\t\tallow adding multiple servers with same ip:port (needed for ts2)\n"); printf( "-of\t\toutput file\n"); printf( "-af\t\tLike -of, but append to the file\n" ); printf( "-raw \toutput in raw format using as delimiter\n"); printf( "-mdelim \tFor rules with multi values use as delimiter\n"); printf( "-xml\t\toutput status data as an XML document\n"); printf( "-Th,-Ts,-Tpt\toutput templates: header, server and player\n"); printf( "-Tr,-Tt\t\toutput templates: rule, and trailer\n"); printf( "-srcport \tSend packets from these network ports\n"); printf( "-srcip \tSend packets using this IP address\n"); printf( "-H\t\tresolve host names\n"); printf( "-Hcache\t\thost name cache file\n"); printf( "-carets\t\tDisplay carets in Quake 3 player names\n" ); printf( "-d\t\tEnable debug options. Specify multiple times to increase debug level.\n"); #ifdef ENABLE_DUMP printf( "-dump\t\twrite received raw packets to dumpNNN files which must not exist before\n"); printf( "-pkt \tuse file as server reply instead of quering the server. Works only with TF_SINGLE_QUERY servers\n"); #endif printf( "-htmlmode\tConvert <, >, and & to the equivalent HTML entities\n" ); printf( "-htmlnames\tColorize Quake 3 and Tribes 2 player names using html font tags\n" ); printf( "-nohtmlnames\tDo not colorize Quake 3 and Tribes 2 player names even if $HTML is used in an output template.\n" ); printf( "-showgameport\tAlways display the game port in QStat output.\n" ); printf( "-noportoffset\tDont use builtin status port offsets ( assume query port was specified ).\n" ); printf( "-raw-arg\tWhen used with -raw, always display the server address as it appeared in a file or on the command-line.\n" ); printf( "-utf8\t\tUse the UTF-8 character encoding for XML output.\n" ); #ifdef _WIN32 printf( "-noconsole\t\tFree the console\n" ); #endif printf( "\n"); printf( "Sort keys:\n"); printf( " servers: p=by-ping, g=by-game, i=by-IP-address, h=by-hostname, n=by-#-players, l=by-list-order\n"); printf( " players: P=by-ping, F=by-frags, T=by-team, N=by-name\n"); printf( "\nqstat version %s\n", VERSION); exit(0); } struct server_arg { int type_id; server_type *type; char *arg; char *outfilename; char *query_arg; }; server_type* find_server_type_id( int type_id) { server_type *type= &types[0]; for ( ; type->id != Q_UNKNOWN_TYPE; type++) if ( type->id == type_id) return type; return NULL; } server_type* find_server_type_string( char* type_string) { server_type *type= &types[0]; char *t= type_string; for ( ; *t; t++) *t= tolower( *t); for ( ; type->id != Q_UNKNOWN_TYPE; type++) if ( strcmp( type->type_string, type_string) == 0) return type; return NULL; } server_type* find_server_type_option( char* option) { server_type *type= &types[0]; for ( ; type->id != Q_UNKNOWN_TYPE; type++) if ( strcmp( type->type_option, option) == 0) return type; return NULL; } server_type* parse_server_type_option( char* option, int *outfile, char **query_arg) { server_type *type= &types[0]; char *comma, *arg; int len; *outfile= 0; *query_arg= 0; comma= strchr( option, ','); if ( comma) *comma++= '\0'; for ( ; type->id != Q_UNKNOWN_TYPE; type++) if ( strcmp( type->type_option, option) == 0) break; if ( type->id == Q_UNKNOWN_TYPE) return NULL; if ( ! comma) return type; if ( strcmp( comma, "outfile") == 0) { *outfile= 1; comma= strchr( comma, ','); if ( ! comma) return type; *comma++= '\0'; } *query_arg= strdup(comma); arg= comma; do { comma= strchr( arg, ','); if (comma) len= comma-arg; else len= strlen( arg); if ( strncmp( arg, "outfile", len) == 0) *outfile= 1; arg= comma+1; } while ( comma); return type; } void add_server_arg( char *arg, int type, char *outfilename, char *query_arg, struct server_arg **args, int *n, int *max) { if ( *n == *max) { if ( *max == 0) { *max= 4; *args= (struct server_arg*)malloc(sizeof(struct server_arg) * (*max)); } else { (*max)*= 2; *args= (struct server_arg*) realloc( *args, sizeof(struct server_arg) * (*max)); } } (*args)[*n].type_id= type; /* (*args)[*n].type= find_server_type_id( type); */ (*args)[*n].type= NULL; (*args)[*n].arg= arg; (*args)[*n].outfilename= outfilename; (*args)[*n].query_arg= query_arg; (*n)++; } void add_query_param( struct qserver *server, char *arg) { char *equal; struct query_param *param; equal= strchr( arg, '='); *equal++= '\0'; param= (struct query_param *) malloc( sizeof(struct query_param)); param->key= arg; param->value= equal; sscanf( equal, "%i", ¶m->i_value); sscanf( equal, "%i", ¶m->ui_value); param->next= server->params; server->params= param; } char * get_param_value( struct qserver *server, const char *key, char *default_value) { struct query_param *p= server->params; for ( ; p; p= p->next) if ( strcasecmp( key, p->key) == 0) return p->value; return default_value; } int get_param_i_value( struct qserver *server, char *key, int default_value) { struct query_param *p= server->params; for ( ; p; p= p->next) if ( strcasecmp( key, p->key) == 0) return p->i_value; return default_value; } unsigned int get_param_ui_value( struct qserver *server, char *key, unsigned int default_value) { struct query_param *p= server->params; for ( ; p; p= p->next) if ( strcasecmp( key, p->key) == 0) return p->ui_value; return default_value; } int parse_source_address( char *addr, unsigned int *ip, unsigned short *port) { char *colon; colon= strchr( addr, ':'); if ( colon) { *colon= '\0'; *port= atoi( colon+1); if ( colon == addr) return 0; } else *port= 0; *ip= inet_addr( addr); if ( *ip == INADDR_NONE && !isdigit( (unsigned char)*ip)) *ip= hcache_lookup_hostname( addr); if ( *ip == INADDR_NONE) { fprintf( stderr, "%s: Not an IP address or unknown host name\n", addr); return -1; } *ip= ntohl( *ip); return 0; } int parse_source_port( char *port, unsigned short *low, unsigned short *high) { char *dash; *low= atoi( port); dash= strchr( port, '-'); *high= 0; if ( dash) *high= atoi( dash+1); if ( *high == 0) *high= *low; if ( *high < *low) { fprintf( stderr, "%s: Invalid port range\n", port); return -1; } return 0; } void add_config_server_types() { int n_config_types, n_builtin_types, i; server_type **config_types; server_type *new_types, *type; config_types= qsc_get_config_server_types( &n_config_types); if ( n_config_types == 0) return; n_builtin_types= (sizeof( builtin_types) / sizeof(server_type)) - 1; new_types= (server_type*) malloc( sizeof(server_type) * (n_builtin_types + n_config_types + 1)); memcpy( new_types, &builtin_types[0], n_builtin_types*sizeof(server_type)); type= &new_types[n_builtin_types]; for ( i= n_config_types; i; i--, config_types++, type++) *type= **config_types; n_server_types= n_builtin_types + n_config_types; new_types[n_server_types].id= Q_UNKNOWN_TYPE; if ( types != &builtin_types[0]) free( types); types= new_types; } void revert_server_types() { if ( types != &builtin_types[0]) free( types); n_server_types= (sizeof( builtin_types) / sizeof(server_type)) - 1; types= &builtin_types[0]; } #ifdef ENABLE_DUMP unsigned pkt_dump_pos = 0; const char* pkt_dumps[64] = {0}; static void add_pkt_from_file(const char* file) { if(pkt_dump_pos >= sizeof(pkt_dumps)/sizeof(pkt_dumps[0])) return; pkt_dumps[pkt_dump_pos++] = file; } static void replay_pkt_dumps() { struct qserver* server = servers; char* pkt = NULL; int fd; int bytes_read = 0; // should be ssize_t but for ease with win32 int i; struct stat statbuf; gettimeofday( &packet_recv_time, NULL); for ( i = 0; i < pkt_dump_pos; i++ ) { if((fd = open(pkt_dumps[i], O_RDONLY)) == -1) { goto err; } if( fstat( fd, &statbuf) == -1 ) { goto err; } pkt = malloc( statbuf.st_size ); if ( NULL == pkt ) { goto err; } bytes_read = read( fd, pkt, statbuf.st_size ); if ( bytes_read != statbuf.st_size ) { fprintf( stderr, "Failed to read entire packet from disk got %d of %ld bytes\n", bytes_read, (long)statbuf.st_size ); goto err; } server->type->packet_func( server, pkt, statbuf.st_size); close(fd); fd = 0; } goto out; err: perror(__FUNCTION__); close(fd); out: fd = 0; // NOP } #endif // ENABLE_DUMP struct rcv_pkt { struct qserver* server; struct sockaddr_in addr; struct timeval recv_time; char data[PACKET_LEN]; int len; int _errno; }; void do_work(void) { int pktlen, rc, fd; char *pkt= NULL; int bind_retry= 0; struct timeval timeout; struct rcv_pkt* buffer; unsigned buffill = 0, i = 0; unsigned bufsize = max_simultaneous*2; struct timeval t,ts; gettimeofday(&t, NULL); ts = t; buffer = malloc(sizeof(struct rcv_pkt) * bufsize); if(!buffer) return; #ifdef ENABLE_DUMP if(pkt_dump_pos) { replay_pkt_dumps(); } else #endif { bind_retry = bind_sockets(); } send_packets(); debug(2, "connected: %d", connected); while ( connected || (!connected && bind_retry==-2)) { if ( ! connected && bind_retry==-2) { rc= wait_for_timeout( 60); bind_retry= bind_sockets(); continue; } bind_retry= 0; set_file_descriptors(); if ( progress) display_progress(); get_next_timeout( &timeout); rc= wait_for_file_descriptors( &timeout); debug(2, "rc %d", rc); if ( rc == SOCKET_ERROR) { #ifndef _WIN32 if ( errno == EINTR) continue; #endif perror("select"); break; } fd= 0; for ( ; rc && buffill < bufsize; rc--) { int addrlen= sizeof(buffer[buffill].addr); struct qserver* server= get_next_ready_server(); if ( server == NULL) break; gettimeofday( &buffer[buffill].recv_time, NULL); pktlen = recvfrom( server->fd, buffer[buffill].data, sizeof(buffer[buffill].data), 0, (struct sockaddr*)&buffer[buffill].addr, (void*)&addrlen); if ( pktlen == SOCKET_ERROR) { if(errno == EAGAIN) { malformed_packet(server, "EAGAIN on UDP socket, probably incorrect checksum"); } else if ( connection_refused()) { server->server_name= DOWN; num_servers_down++; cleanup_qserver( server, 1); } continue; } debug(1, "recv %3d %3d %d.%d.%d.%d:%hu\n", time_delta(&buffer[buffill].recv_time, &ts), time_delta(&buffer[buffill].recv_time, &t), server->ipaddr&0xff, (server->ipaddr>>8)&0xff, (server->ipaddr>>16)&0xff, (server->ipaddr>>24)&0xff, server->port); t = buffer[buffill].recv_time; buffer[buffill].server = server; buffer[buffill].len = pktlen; ++buffill; } for(i = 0; i < buffill; ++i) { struct qserver* server = buffer[i].server; pkt = buffer[i].data; pktlen = buffer[i].len; memcpy(&packet_recv_time, &buffer[i].recv_time, sizeof(packet_recv_time)); if ( get_debug_level() > 0 ) print_packet( server, pkt, pktlen); #ifdef ENABLE_DUMP if (do_dump) dump_packet(pkt, pktlen); #endif if ( server->flags & FLAG_BROADCAST) { struct qserver *broadcast= server; unsigned short port= ntohs(buffer[i].addr.sin_port); /* create new server and init */ if ( ! (no_port_offset || server->flags & TF_NO_PORT_OFFSET)) { port-= server->type->port_offset; } server= add_qserver_byaddr( ntohl(buffer[i].addr.sin_addr.s_addr), port, server->type, NULL); if ( server == NULL) { server= find_server_by_address( buffer[i].addr.sin_addr.s_addr, ntohs(buffer[i].addr.sin_port)); if ( server == NULL) { continue; } /* if ( show_errors) { fprintf(stderr, "duplicate or invalid packet received from 0x%08x:%hu\n", ntohl(buffer[i].addr.sin_addr.s_addr), ntohs(buffer[i].addr.sin_port)); print_packet( NULL, pkt, pktlen); } continue; */ } else { server->packet_time1= broadcast->packet_time1; server->packet_time2= broadcast->packet_time2; server->ping_total= broadcast->ping_total; server->n_requests= broadcast->n_requests; server->n_packets= broadcast->n_packets; broadcast->n_servers++; } } debug(2, "connected: %d", connected); server->type->packet_func( server, pkt, pktlen); debug(2, "connected: %d", connected); } buffill = 0; if ( run_timeout && time(0)-start_time >= run_timeout) { debug(2, "run timeout reached"); break; } send_packets(); if ( connected < max_simultaneous) bind_retry= bind_sockets(); debug(2, "connected: %d", connected); } free(buffer); } #ifndef _WIN32 void sigpipe( int sig ) { fprintf( stderr, "SIG: %d\n", sig ); } #endif int main( int argc, char *argv[]) { int arg, n_files, i; char **files, *outfilename, *query_arg; struct server_arg *server_args= NULL; int n_server_args= 0, max_server_args= 0; int default_server_type_id; #ifdef _WIN32 WORD version= MAKEWORD(1,1); WSADATA wsa_data; if ( WSAStartup(version,&wsa_data) != 0) { fprintf( stderr, "Could not open winsock\n"); exit(1); } #else signal( SIGPIPE, &sigpipe ); #endif types= &builtin_types[0]; n_server_types= (sizeof( builtin_types) / sizeof(server_type)) - 1; i= qsc_load_default_config_files(); if ( i == -1) return 1; else if ( i == 0) add_config_server_types(); if ( argc == 1) usage(NULL,argv,NULL); OF= stdout; files= (char **) malloc( sizeof(char*) * (argc/2)); n_files= 0; default_server_type_id= Q_SERVER; little_endian= ((char*)&one)[0]; big_endian= !little_endian; for ( arg= 1; arg < argc; arg++) { if ( argv[arg][0] != '-') break; outfilename= NULL; if ( strcmp( argv[arg], "-nocfg") == 0 && arg == 1) { revert_server_types(); } else if ( strcmp( argv[arg], "--help") == 0) { usage(NULL,argv,NULL); } else if ( strcmp( argv[arg], "-f") == 0) { arg++; if ( arg >= argc) usage( "missing argument for -f\n", argv,NULL); files[n_files++]= argv[arg]; } else if ( strcmp( argv[arg], "-retry") == 0) { arg++; if ( arg >= argc) usage( "missing argument for -retry\n", argv,NULL); n_retries= atoi( argv[arg]); if ( n_retries <= 0) { fprintf( stderr, "retries must be greater than zero\n"); exit(1); } } else if ( strcmp( argv[arg], "-interval") == 0) { double value= 0.0; arg++; if ( arg >= argc) usage( "missing argument for -interval\n", argv,NULL); sscanf( argv[arg], "%lf", &value); if ( value < 0.1) { fprintf( stderr, "retry interval must be greater than 0.1\n"); exit(1); } retry_interval= (int)(value * 1000); } else if ( strcmp( argv[arg], "-mi") == 0) { double value= 0.0; arg++; if ( arg >= argc) usage( "missing argument for -mi\n", argv,NULL); sscanf( argv[arg], "%lf", &value); if ( value < 0.1) { fprintf( stderr, "interval must be greater than 0.1\n"); exit(1); } master_retry_interval= (int)(value * 1000); } else if ( strcmp( argv[arg], "-H") == 0) hostname_lookup= 1; else if ( strcmp( argv[arg], "-u") == 0) up_servers_only= 1; else if ( strcmp( argv[arg], "-nf") == 0) no_full_servers= 1; else if ( strcmp( argv[arg], "-ne") == 0) no_empty_servers= 1; else if ( strcmp( argv[arg], "-nh") == 0) no_header_display= 1; else if ( strcmp( argv[arg], "-old") == 0) new_style= 0; else if ( strcmp( argv[arg], "-P") == 0) get_player_info= 1; else if ( strcmp( argv[arg], "-R") == 0) get_server_rules= 1; else if ( strncmp( argv[arg], "-raw", 4) == 0) { if ( argv[arg][4] == ',') { if ( strcmp( &argv[arg][5], "game") == 0) { show_game_in_raw= 1; } else { usage( "Unknown -raw option\n", argv, NULL); } } arg++; if ( arg >= argc) { usage( "missing argument for -raw\n", argv,NULL); } raw_delimiter= argv[arg]; // Check the multi rule delimiter isnt the same // If it is fix to maintain backwards compatibility if ( 0 == strcmp( raw_delimiter, multi_delimiter ) && 0 == strcmp( raw_delimiter, "|" ) ) { multi_delimiter = ":"; } raw_display= 1; } else if ( strcmp( argv[arg], "-mdelim" ) == 0 ) { arg++; if ( arg >= argc) { usage( "missing argument for -mdelim\n", argv,NULL); } multi_delimiter = argv[arg]; } else if ( strcmp( argv[arg], "-xml") == 0) { xml_display= 1; if (raw_display == 1) usage( "cannot specify both -raw and -xml\n", argv,NULL); } else if ( strcmp( argv[arg], "-utf8") == 0) { xml_encoding= ENCODING_UTF_8; name_xforms= 0; } else if ( strcmp( argv[arg], "-ncn") == 0) { color_names= 0; } else if ( strcmp( argv[arg], "-cn") == 0) { color_names= 1; } else if ( strcmp( argv[arg], "-hc") == 0) { color_names= 2; } else if ( strcmp( argv[arg], "-nx") == 0) { name_xforms= 1; } else if ( strcmp( argv[arg], "-nnx") == 0) { name_xforms= 0; } else if ( strcmp( argv[arg], "-tc") == 0) { time_format= CLOCK_TIME; } else if ( strcmp( argv[arg], "-tsw") == 0) { time_format= STOPWATCH_TIME; } else if ( strcmp( argv[arg], "-ts") == 0) { time_format= SECONDS; } else if ( strcmp( argv[arg], "-pa") == 0) { player_address= 1; } else if ( strcmp( argv[arg], "-hpn") == 0) { hex_player_names= 1; } else if ( strcmp( argv[arg], "-hsn") == 0) { hex_server_names= 1; } else if ( strncmp( argv[arg], "-maxsimultaneous", 7) == 0) { arg++; if ( arg >= argc) usage( "missing argument for -maxsimultaneous\n", argv,NULL); max_simultaneous= atoi(argv[arg]); if ( max_simultaneous <= 0) usage( "value for -maxsimultaneous must be > 0\n", argv,NULL); if ( max_simultaneous > FD_SETSIZE) max_simultaneous= FD_SETSIZE; } else if ( strcmp( argv[arg], "-sendinterval") == 0) { arg++; if ( arg >= argc) usage( "missing argument for -sendinterval\n", argv,NULL); sendinterval= atoi(argv[arg]); if ( sendinterval < 0) usage( "value for -sendinterval must be >= 0\n", argv,NULL); } else if ( strcmp( argv[arg], "-raw-arg") == 0) { raw_arg= 1000; } else if ( strcmp( argv[arg], "-timeout") == 0) { arg++; if ( arg >= argc) usage( "missing argument for -timeout\n", argv,NULL); run_timeout= atoi( argv[arg]); if ( run_timeout <= 0) usage( "value for -timeout must be > 0\n", argv,NULL); } else if ( strncmp(argv[arg], "-progress", sizeof("-progress")-1) == 0) { char *p= argv[arg] + sizeof("-progress")-1; progress= 1; if ( *p == ',') progress= atoi(p+1); } else if ( strcmp( argv[arg], "-Hcache") == 0) { arg++; if ( arg >= argc) usage( "missing argument for -Hcache\n", argv,NULL); if ( hcache_open( argv[arg], 0) == -1) return 1; } else if ( strcmp( argv[arg], "-default") == 0) { arg++; if ( arg >= argc) usage( "missing argument for -default\n", argv,NULL); default_server_type= find_server_type_string( argv[arg]); if ( default_server_type == NULL) { char opt[256], *o= &opt[0]; sprintf( opt, "-%s", argv[arg]); for ( ; *o; o++) *o= tolower(*o); default_server_type= find_server_type_option( opt); } if ( default_server_type == NULL) { fprintf( stderr, "unknown server type \"%s\"\n", argv[arg]); usage( NULL, argv,NULL); } default_server_type_id= default_server_type->id; default_server_type= NULL; } else if ( strncmp( argv[arg], "-Tserver", 3) == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( read_qserver_template( argv[arg]) == -1) return 1; } else if ( strncmp( argv[arg], "-Trule", 3) == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( read_rule_template( argv[arg]) == -1) return 1; } else if ( strncmp( argv[arg], "-Theader", 3) == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( read_header_template( argv[arg]) == -1) return 1; } else if ( strncmp( argv[arg], "-Ttrailer", 3) == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( read_trailer_template( argv[arg]) == -1) return 1; } else if ( strncmp( argv[arg], "-Tplayer", 3) == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( read_player_template( argv[arg]) == -1) return 1; } else if ( strcmp( argv[arg], "-sort") == 0) { size_t pos; arg++; if ( arg >= argc) usage( "missing argument for -sort\n", argv, NULL); strncpy( sort_keys, argv[arg], sizeof(sort_keys)-1); pos= strspn( sort_keys, SUPPORTED_SORT_KEYS); if ( pos != strlen( sort_keys)) { fprintf( stderr, "Unknown sort key \"%c\", valid keys are \"%s\"\n", sort_keys[pos], SUPPORTED_SORT_KEYS); return 1; } server_sort= strpbrk( sort_keys, SUPPORTED_SERVER_SORT) != NULL; if ( strchr( sort_keys, 'l')) server_sort= 1; player_sort= strpbrk( sort_keys, SUPPORTED_PLAYER_SORT) != NULL; } else if ( strcmp( argv[arg], "-errors") == 0) { show_errors++; } else if ( strcmp( argv[arg], "-of") == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( argv[arg][0] == '-' && argv[arg][1] == '\0') OF= stdout; else OF= fopen( argv[arg], "w"); if ( OF == NULL) { perror( argv[arg]); return 1; } } else if ( strcmp( argv[arg], "-af") == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( argv[arg][0] == '-' && argv[arg][1] == '\0') OF= stdout; else OF= fopen( argv[arg], "a"); if ( OF == NULL) { perror( argv[arg]); return 1; } } else if ( strcmp( argv[arg], "-htmlnames") == 0) { html_names= 1; } else if ( strcmp( argv[arg], "-nohtmlnames") == 0) { html_names= 0; } else if ( strcmp( argv[arg], "-htmlmode") == 0) { html_mode= 1; } else if ( strcmp( argv[arg], "-carets") == 0) { strip_carets= 0; } else if ( strcmp( argv[arg], "-d") == 0) { set_debug_level(get_debug_level() + 1); } else if ( strcmp( argv[arg], "-showgameport") == 0) { show_game_port= 1; } else if ( strcmp( argv[arg], "-noportoffset") == 0) { no_port_offset= 1; } else if ( strcmp( argv[arg], "-srcip") == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( parse_source_address( argv[arg], &source_ip, &source_port) == -1) return 1; if ( source_port) { source_port_low= source_port; source_port_high= source_port; } } else if ( strcmp( argv[arg], "-srcport") == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( parse_source_port( argv[arg], &source_port_low, &source_port_high) == -1) return 1; source_port= source_port_low; } else if ( strcmp( argv[arg], "-cfg") == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); if ( qsc_load_config_file( argv[arg]) == -1) return 1; add_config_server_types(); } else if ( strcmp( argv[arg], "-allowserverdups") == 0) { noserverdups = 0; } #ifdef ENABLE_DUMP else if ( strcmp( argv[arg], "-dump") == 0) { do_dump = 1; } else if ( strcmp( argv[arg], "-pkt") == 0) { arg++; if ( arg >= argc) usage( "missing argument for %s\n", argv, argv[arg-1]); add_pkt_from_file(argv[arg]); } #endif #ifdef _WIN32 else if ( strcmp( argv[arg], "-noconsole") == 0) { FreeConsole(); } #endif else { int outfile; server_type *type; arg++; if ( arg >= argc) { fprintf( stderr, "missing argument for \"%s\"\n", argv[arg-1]); return 1; } type= parse_server_type_option( argv[arg-1], &outfile, &query_arg); if ( type == NULL) { fprintf( stderr, "unknown option \"%s\"\n", argv[arg-1]); return 1; } outfilename= NULL; if ( outfile) { outfilename= strchr( argv[arg], ','); if ( outfilename == NULL) { fprintf( stderr, "missing file name for \"%s,outfile\"\n", argv[arg-1]); return 1; } *outfilename++= '\0'; } /* if ( query_arg && !(type->flags & TF_QUERY_ARG)) { fprintf( stderr, "option flag \"%s\" not allowed for this server type\n", query_arg); return 1; } */ if ( type->flags & TF_QUERY_ARG_REQUIRED && !query_arg) { fprintf( stderr, "option flag missing for server type \"%s\"\n", argv[arg-1]); return 1; } add_server_arg( argv[arg], type->id, outfilename, query_arg, &server_args, &n_server_args, &max_server_args); } } start_time= time(0); default_server_type= find_server_type_id( default_server_type_id); for ( i= 0; i < n_files; i++) add_file( files[i]); for ( ; arg < argc; arg++) add_qserver( argv[arg], default_server_type, NULL, NULL); for ( i= 0; i < n_server_args; i++) { server_type *server_type= find_server_type_id( server_args[i].type_id); add_qserver( server_args[i].arg, server_type, server_args[i].outfilename, server_args[i].query_arg); } free( server_args); if ( servers == NULL) exit(1); max_connmap= max_simultaneous + 10; connmap= (struct qserver**) calloc( 1, sizeof(struct qserver*) * max_connmap); if ( color_names == -1) color_names= ( raw_display) ? DEFAULT_COLOR_NAMES_RAW : DEFAULT_COLOR_NAMES_DISPLAY; if ( time_format == -1) time_format= ( raw_display) ? DEFAULT_TIME_FMT_RAW : DEFAULT_TIME_FMT_DISPLAY; if ( (one_server_type_id & MASTER_SERVER) || one_server_type_id == 0) display_prefix= 1; if ( xml_display) xml_header(); else if ( new_style && ! raw_display && ! have_server_template()) display_header(); else if ( have_header_template()) template_display_header(); q_serverinfo.length= htons( q_serverinfo.length); h2_serverinfo.length= htons( h2_serverinfo.length); q_player.length= htons( q_player.length); do_work(); finish_output(); free_server_hash(); free(files); free(connmap); return 0; } void finish_output() { int i; hcache_update_file(); if ( progress) { display_progress(); fputs( "\n", stderr); } if ( server_sort) { struct qserver **array, *server, *next_server; if ( strchr( sort_keys, 'l') && strpbrk( sort_keys, SUPPORTED_SERVER_SORT) == NULL) { server= servers; for ( ; server; server= next_server) { next_server= server->next; display_server( server); } } else { array= (struct qserver **) malloc( sizeof(struct qserver *) * num_servers_total); server= servers; for ( i= 0; server != NULL; i++) { array[i]= server; server= server->next; } sort_servers( array, num_servers_total); if ( progress) fprintf( stderr, "\n"); for ( i= 0; i < num_servers_total; i++) display_server( array[i]); free( array); } } else { struct qserver *server, *next_server; server= servers; for ( ; server; server= next_server) { next_server= server->next; if ( server->server_name == HOSTNOTFOUND) display_server( server); } } if ( xml_display) xml_footer(); else if ( have_trailer_template()) template_display_trailer(); if ( OF != stdout) fclose( OF); } void add_file( char *filename) { FILE *file; char name[200], *comma, *query_arg = NULL; server_type* type; if ( strcmp( filename, "-") == 0) { file= stdin; current_filename= NULL; } else { file= fopen( filename, "r"); current_filename= filename; } current_fileline= 1; if ( file == NULL) { perror( filename); return; } for ( ; fscanf( file, "%s", name) == 1; current_fileline++) { comma= strchr( name, ','); if ( comma) { *comma++= '\0'; query_arg= strdup( comma); } type = find_server_type_string( name); if ( type == NULL) { add_qserver( name, default_server_type, NULL, NULL); } else if ( fscanf( file, "%s", name) == 1) { if ( type->flags & TF_QUERY_ARG && comma && *query_arg) { add_qserver( name, type, NULL, query_arg ); } else { add_qserver( name, type, NULL, NULL ); } } } if ( file != stdin) fclose(file); current_fileline= 0; } void print_file_location() { if ( current_fileline != 0) fprintf( stderr, "%s:%d: ", current_filename?current_filename:"", current_fileline); } void parse_query_params( struct qserver *server, char *params) { char *comma, *arg= params; do { comma= strchr(arg,','); if ( comma) *comma= '\0'; if ( strchr( arg, '=')) add_query_param( server, arg); else if ( strcmp( arg, "noportoffset") == 0 || strcmp( arg, "qp") == 0) server->flags |= TF_NO_PORT_OFFSET; else if ( strcmp( arg, "showgameport") == 0 || strcmp( arg, "gp") == 0) server->flags |= TF_SHOW_GAME_PORT; arg= comma+1; } while ( comma); } int add_qserver( char *arg, server_type* type, char *outfilename, char *query_arg) { struct qserver *server, *prev_server; int flags= 0; char *colon= NULL, *arg_copy, *hostname= NULL; unsigned int ipaddr; unsigned short port, port_max; int portrange = 0; unsigned colonpos = 0; if ( run_timeout && time(0)-start_time >= run_timeout) { finish_output(); exit(0); } port = port_max = type->default_port; if ( outfilename && strcmp( outfilename, "-") != 0) { FILE *outfile= fopen( outfilename, "r+"); if ( outfile == NULL && (errno == EACCES || errno == EISDIR || errno == ENOSPC || errno == ENOTDIR)) { perror( outfilename); return -1; } if ( outfile) { fclose(outfile); } } arg_copy= strdup(arg); colon= strchr( arg, ':'); if ( colon != NULL) { if(sscanf( colon+1, "%hu-%hu", &port, &port_max) == 2) { portrange = 1; } else { port_max = port; } *colon= '\0'; colonpos = colon-arg; } if ( *arg == '+') { flags|= FLAG_BROADCAST; arg++; } ipaddr= inet_addr(arg); if ( ipaddr == INADDR_NONE) { if ( strcmp( arg, "255.255.255.255") != 0) { ipaddr= htonl( hcache_lookup_hostname(arg)); } } else if ( hostname_lookup && !(flags&FLAG_BROADCAST)) { hostname= hcache_lookup_ipaddr( ntohl(ipaddr)); } if ( (ipaddr == INADDR_NONE || ipaddr == 0) && strcmp( arg, "255.255.255.255") != 0) { print_file_location(); fprintf( stderr, "%s: %s\n", arg, strherror(h_errno)); server= (struct qserver *) calloc( 1, sizeof( struct qserver)); for(;port <= port_max; ++port) { init_qserver( server, type); if(portrange) { server->arg = ( port==port_max ) ? arg_copy : strdup(arg_copy); } if(portrange) { sprintf(server->arg+colonpos+1, "%hu", port); } server->server_name= HOSTNOTFOUND; server->error= strdup( strherror(h_errno)); server->query_port = server->port= port; if ( last_server != &servers) { prev_server= (struct qserver*) ((char*)last_server - ((char*)&server->next - (char*)server)); server->prev= prev_server; } *last_server= server; last_server= & server->next; if ( one_server_type_id == ~MASTER_SERVER) { one_server_type_id= type->id; } else if ( one_server_type_id != type->id) { one_server_type_id= 0; } } return -1; } for(; port > 0 && port <= port_max; ++port) { if ( noserverdups && find_server_by_address( ipaddr, port) != NULL) { continue; } server= (struct qserver *) calloc( 1, sizeof( struct qserver)); server->arg= port==port_max?arg_copy:strdup(arg_copy); if(portrange) { sprintf(server->arg+colonpos+1, "%hu", port); } if ( hostname && colon) { server->host_name= (char*)malloc( strlen(hostname) + 5 +2); sprintf( server->host_name, "%s:%hu", hostname, port); } else { server->host_name= strdup((hostname)?hostname:arg); } server->ipaddr= ipaddr; server->query_port = server->port = port; server->type= type; server->outfilename= outfilename; server->flags= flags; if (query_arg) { server->query_arg = ( port == port_max ) ? query_arg : strdup(query_arg); parse_query_params( server, server->query_arg); } else { server->query_arg = NULL; } init_qserver( server, type); if ( server->type->master) { waiting_for_masters++; } if ( num_servers_total % 10 == 0) { hcache_update_file(); } if ( last_server != &servers ) { prev_server= (struct qserver*) ((char*)last_server - ((char*)&server->next - (char*)server)); server->prev= prev_server; } *last_server= server; last_server= &server->next; add_server_to_hash( server ); if ( one_server_type_id == ~MASTER_SERVER) { one_server_type_id= type->id; } else if ( one_server_type_id != type->id) { one_server_type_id= 0; } ++num_servers; } return 0; } struct qserver * add_qserver_byaddr( unsigned int ipaddr, unsigned short port, server_type* type, int *new_server) { char arg[36]; struct qserver *server, *prev_server; char *hostname= NULL; if ( run_timeout && time(0)-start_time >= run_timeout) { finish_output(); exit(0); } if ( new_server) { *new_server= 0; } ipaddr= htonl(ipaddr); if ( ipaddr == 0) { return 0; } // TODO: this prevents servers with the same ip:port being queried // and hence breaks virtual servers support e.g. Teamspeak 2 if ( find_server_by_address( ipaddr, port) != NULL) { return 0; } if ( new_server) { *new_server= 1; } server= (struct qserver *) calloc( 1, sizeof( struct qserver)); server->ipaddr= ipaddr; ipaddr= ntohl(ipaddr); sprintf( arg, "%d.%d.%d.%d:%hu", ipaddr>>24, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, port); server->arg= strdup(arg); if ( hostname_lookup) { hostname= hcache_lookup_ipaddr( ipaddr); } if ( hostname) { server->host_name= (char*)malloc( strlen(hostname) + 6 + 2); sprintf( server->host_name, "%s:%hu", hostname, port); } else { server->host_name= strdup( arg); } server->query_port = server->port = port; init_qserver( server, type); if ( num_servers_total % 10 == 0) { hcache_update_file(); } if ( last_server != &servers) { prev_server= (struct qserver*) ((char*)last_server - ((char*)&server->next - (char*)server)); server->prev= prev_server; } *last_server= server; last_server= & server->next; add_server_to_hash( server); ++num_servers; return server; } void add_servers_from_masters() { struct qserver *server; unsigned int ipaddr, i; unsigned short port; int n_servers, new_server, port_adjust= 0; char *pkt; server_type* server_type; FILE *outfile; for ( server= servers; server != NULL; server= server->next) { if ( !server->type->master || server->master_pkt == NULL) continue; pkt= server->master_pkt; if ( server->query_arg && server->type->id == GAMESPY_MASTER) { server_type= find_server_type_string( server->query_arg); if ( server_type == NULL) server_type= find_server_type_id( server->type->master); } else server_type= find_server_type_id( server->type->master); if ( server->type->id == GAMESPY_MASTER && server_type) { if ( server_type->id == UN_SERVER) port_adjust= -1; else if ( server_type->id == KINGPIN_SERVER) port_adjust= 10; } outfile= NULL; if ( server->outfilename) { if ( strcmp( server->outfilename, "-") == 0) outfile= stdout; else outfile= fopen( server->outfilename, "w"); if ( outfile == NULL) { perror( server->outfilename); continue; } } n_servers= 0; for ( i= 0; i < server->master_pkt_len; i+= 6) { memcpy( &ipaddr, &pkt[i], 4); memcpy( &port, &pkt[i+4], 2); ipaddr= ntohl( ipaddr); port= ntohs( port) + port_adjust; new_server= 1; if ( outfile) fprintf( outfile, "%s %d.%d.%d.%d:%hu\n", server_type ? server_type->type_string : "", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, port); else if ( server_type == NULL) fprintf( OF, "%d.%d.%d.%d:%hu\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, port); else add_qserver_byaddr( ipaddr, port, server_type, &new_server); n_servers+= new_server; } free( server->master_pkt); server->master_pkt= NULL; server->master_pkt_len= 0; server->n_servers= n_servers; if ( outfile) fclose( outfile); } if ( hostname_lookup) hcache_update_file(); bind_sockets(); } void init_qserver( struct qserver *server, server_type* type) { server->server_name= NULL; server->map_name= NULL; server->game= NULL; server->num_players= 0; server->fd= -1; if ( server->flags & FLAG_BROADCAST) { server->retry1= 1; server->retry2= 1; } else { server->retry1= n_retries; server->retry2= n_retries; } server->n_retries= 0; server->ping_total= 0; server->n_packets= 0; server->n_requests= 0; server->n_servers= 0; server->master_pkt_len= 0; server->master_pkt= NULL; server->error= NULL; server->saved_data.data= NULL; server->saved_data.datalen= 0; server->saved_data.pkt_index= -1; server->saved_data.pkt_max= 0; server->saved_data.next= NULL; server->type = type; server->next_rule= (get_server_rules) ? "" : NO_SERVER_RULES; server->next_player_info= (get_player_info && type->player_packet) ? 0 : NO_PLAYER_INFO; server->n_player_info= 0; server->players= NULL; server->n_rules= 0; server->rules= NULL; server->last_rule= &server->rules; server->missing_rules= 0; num_servers_total++; } // ipaddr should be network byte-order // port should be host byte-order struct qserver * find_server_by_address( unsigned int ipaddr, unsigned short port) { struct qserver **hashed; unsigned int hash, i; hash= (ipaddr + port) % ADDRESS_HASH_LENGTH; if ( ipaddr == 0) { for ( hash= 0; hash < ADDRESS_HASH_LENGTH; hash++) printf( "%3d %d\n", hash, server_hash_len[hash]); return NULL; } hashed = server_hash[hash]; for ( i= server_hash_len[hash]; i; i--, hashed++) if ( *hashed && (*hashed)->ipaddr == ipaddr && (*hashed)->port == port) return *hashed; return NULL; } void add_server_to_hash( struct qserver *server) { unsigned int hash; hash = (server->ipaddr + server->port) % ADDRESS_HASH_LENGTH; if ( server_hash_len[hash] % 16 == 0) { server_hash[hash]= (struct qserver**) realloc( server_hash[hash], sizeof( struct qserver **) * (server_hash_len[hash]+16)); memset( &server_hash[hash][server_hash_len[hash]], 0, sizeof( struct qserver **) * 16); } server_hash[hash][server_hash_len[hash]]= server; server_hash_len[hash]++; } void remove_server_from_hash( struct qserver *server) { struct qserver **hashed; unsigned int hash, i, ipaddr; unsigned short port; hash= (server->ipaddr + server->port) % ADDRESS_HASH_LENGTH; ipaddr= server->ipaddr; port= server->port; hashed= server_hash[hash]; for ( i= server_hash_len[hash]; i; i--, hashed++) if ( *hashed && (*hashed)->ipaddr == ipaddr && (*hashed)->port == port) { *hashed= NULL; break; } } void free_server_hash() { int i; for ( i= 0; i < ADDRESS_HASH_LENGTH; i++) if ( server_hash[i]) free( server_hash[i]); } /* Functions for binding sockets to Quake servers */ int bind_qserver( struct qserver *server) { struct sockaddr_in addr; static int one= 1; if ( server->type->flags & TF_TCP_CONNECT) server->fd= socket( AF_INET, SOCK_STREAM, 0); else server->fd= socket( AF_INET, SOCK_DGRAM, 0); if ( server->fd == INVALID_SOCKET) { if ( sockerr() == EMFILE) { server->fd= -1; return -2; } perror( "socket" ); server->server_name= SYSERROR; return -1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl( source_ip); if ( server->type->id == Q2_MASTER) addr.sin_port= htons(26500); else if ( source_port == 0) addr.sin_port= 0; else { addr.sin_port= htons( source_port); source_port++; if ( source_port > source_port_high) source_port= source_port_low; } memset( &(addr.sin_zero), 0, sizeof(addr.sin_zero) ); if ( bind( server->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == SOCKET_ERROR) { if ( sockerr() != EADDRINUSE) { perror( "bind" ); server->server_name= SYSERROR; } close(server->fd); server->fd= -1; return -1; } if ( server->flags & FLAG_BROADCAST) setsockopt( server->fd, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one)); if ( server->type->id != Q2_MASTER && !(server->flags & FLAG_BROADCAST)) { addr.sin_family= AF_INET; if ( no_port_offset || server->flags & TF_NO_PORT_OFFSET) addr.sin_port= htons(server->port); else addr.sin_port= htons( (unsigned short)( server->port + server->type->port_offset ) ); addr.sin_addr.s_addr= server->ipaddr; memset( &(addr.sin_zero), 0, sizeof(addr.sin_zero) ); if ( connect( server->fd, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) { char error[50]; if ( server->type->id == UN_MASTER) { if ( connection_refused()) { /* server->fd= -2; */ /* set up for connect retry */ } } sprintf( error, "connect:%s:%u", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) ); perror( error ); server->server_name= SYSERROR; close(server->fd); server->fd= -1; return -1; } } // we need nonblocking always. poll on an udp socket would wake // up and recv blocks if a packet with incorrect checksum is // received set_non_blocking( server->fd); if ( server->type->flags & TF_TCP_CONNECT) { int one= 1; setsockopt( server->fd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one)); } #ifndef _WIN32 if ( server->fd >= max_connmap) { int old_max= max_connmap; max_connmap= server->fd + 32; connmap= (struct qserver **) realloc( connmap, max_connmap * sizeof( struct qserver *)); memset( &connmap[old_max], 0, (max_connmap - old_max) * sizeof( struct qserver *)); } connmap[server->fd]= server; #endif #ifdef _WIN32 { int i; for ( i= 0; i < max_connmap; i++) { if ( connmap[i] == NULL) { connmap[i]= server; break; } } if ( i >= max_connmap) printf( "could not put server in connmap\n"); } #endif return 0; } static struct timeval t_lastsend = {0,0}; int bind_sockets() { struct qserver *server; struct timeval now; int rc, retry_count= 0;; gettimeofday(&now, NULL); if(connected && sendinterval && time_delta(&now, &t_lastsend) < sendinterval) { server = NULL; } else if ( !waiting_for_masters) { if ( last_server_bind == NULL) { last_server_bind= servers; } server= last_server_bind; } else { server= servers; } for ( ; server != NULL && connected < max_simultaneous; server= server->next) { if ( server->server_name == NULL && server->fd == -1) { if ( waiting_for_masters && !server->type->master) { continue; } if ( (rc= bind_qserver( server)) == 0) { debug(1, "send %d.%d.%d.%d:%hu\n", server->ipaddr&0xff, (server->ipaddr>>8)&0xff, (server->ipaddr>>16)&0xff, (server->ipaddr>>24)&0xff, server->port); gettimeofday(&t_lastsend, NULL); server->type->status_query_func( server); connected++; if ( !waiting_for_masters) { last_server_bind= server; } break; } else if ( rc == -2 && ++retry_count > 2) { return -2; } } } if ( ! connected && retry_count) { return -2; } return 0; } /* * Functions for sending packets */ // this is so broken, someone please rewrite the timeout handling void send_packets() { struct qserver *server; struct timeval now; int interval, n_sent=0, prev_n_sent; unsigned i; debug( 3, "processing..." ); gettimeofday( &now, NULL); if(!t_lastsend.tv_sec) { // nothing } else if(connected && sendinterval && time_delta(&now, &t_lastsend) < sendinterval) { return; } for ( i = 0; i < max_connmap; ++i ) { server = connmap[i]; if( ! server ) { continue; } if(server->fd == -1) { debug(0, "invalid entry in connmap\n"); } if ( server->type->id & MASTER_SERVER) { interval = master_retry_interval; } else { interval = retry_interval; } debug(2, "server %p, name %s, retry1 %d, next_rule %p, next_player_info %d, num_players %d, n_retries %d", server, server->server_name, server->retry1, server->next_rule, server->next_player_info, server->num_players, n_retries); prev_n_sent = n_sent; if ( server->server_name == NULL ) { // We havent seen the server yet? if ( server->retry1 != n_retries && time_delta( &now, &server->packet_time1) < (interval*(n_retries-server->retry1+1)) ) { continue; } if ( ! server->retry1 ) { // No more retries cleanup_qserver( server, 1); continue; } if( qserver_get_timeout(server, &now) <= 0 ) { // Query status debug(2, "calling status_query_func for %p", server); server->type->status_query_func( server); gettimeofday(&t_lastsend, NULL); n_sent++; continue; } } if ( server->next_rule != NO_SERVER_RULES ) { // We want server rules if ( server->retry1 != n_retries && time_delta( &now, &server->packet_time1) < (interval*(n_retries-server->retry1+1)) ) { continue; } if ( ! server->retry1 ) { // no more retries server->next_rule= NULL; server->missing_rules = 1; cleanup_qserver( server, 0); continue; } send_rule_request_packet( server); gettimeofday(&t_lastsend, NULL); n_sent++; } if ( server->next_player_info < server->num_players) { // Expecting player details if ( server->retry2 != n_retries && time_delta( &now, &server->packet_time2) < (interval*(n_retries-server->retry2+1)) ) { continue; } if ( ! server->retry2 ) { server->next_player_info++; if ( server->next_player_info >= server->num_players ) { // no more retries cleanup_qserver( server, 0); continue; } server->retry2 = n_retries; } send_player_request_packet( server); gettimeofday(&t_lastsend, NULL); n_sent++; } if ( prev_n_sent == n_sent ) { // we didnt send any additional queries debug(2, "%d %d", time_delta( &now, &server->packet_time1 ), (interval*(n_retries+1))); if ( ! server->retry1 ) { // no retries left if ( time_delta( &now, &server->packet_time1 ) > (interval*(n_retries+1) ) ) { cleanup_qserver( server, 1 ); } } else { // decrement as we didnt send any packets server->retry1--; } } } } /* server starts sending data immediately, so we need not do anything */ void send_bfris_request_packet( struct qserver *server) { register_send( server ); } /* First packet for a normal Quake server */ void send_qserver_request_packet( struct qserver *server) { int rc = send_packet( server, server->type->status_packet, server->type->status_len ); if ( rc == SOCKET_ERROR ) { cleanup_qserver( server, 1 ); } } /* First packet for a QuakeWorld server */ void send_qwserver_request_packet( struct qserver *server) { int rc; if ( server->flags & FLAG_BROADCAST) rc= send_broadcast( server, server->type->status_packet, server->type->status_len); else if ( server->server_name == NULL) rc= send( server->fd, server->type->status_packet, server->type->status_len, 0); else if ( server->server_name != NULL && server->type->rule_packet) rc= send( server->fd, server->type->rule_packet, server->type->rule_len, 0); else rc= SOCKET_ERROR; if ( rc == SOCKET_ERROR) { unsigned int ipaddr= ntohl(server->ipaddr); fprintf( stderr, "Error on %d.%d.%d.%d, skipping ...\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff); perror( "send"); cleanup_qserver( server, 1); return; } if ( server->retry1 == n_retries || server->flags & FLAG_BROADCAST) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } else if ( server->server_name == NULL) server->n_retries++; server->retry1--; if ( server->server_name == NULL) server->n_packets++; server->next_player_info = NO_PLAYER_INFO; // we don't have a player packet } // First packet for an Unreal Tournament 2003 server void send_ut2003_request_packet( struct qserver *server) { send_packet( server, server->type->status_packet, server->type->status_len ); server->next_player_info = NO_PLAYER_INFO; } // First packet for an Half-Life 2 server void send_hl2_request_packet( struct qserver *server) { send_packet( server, server->type->status_packet, server->type->status_len ); } /* First packet for an Unreal master */ void send_unrealmaster_request_packet( struct qserver *server) { send_packet( server, server->type->status_packet, server->type->status_len ); } static const char* steam_region[] = { "US East Coast", "US West Coast", "South America", "Europe", "Asia", "Australia", "Middle East", "Africa", NULL }; char * build_hlmaster_packet( struct qserver *server, int *len) { static char packet[1600]; char *pkt, *r, *sep= ""; char *gamedir, *map, *flags; int flen; pkt= &packet[0]; memcpy( pkt, server->type->master_packet, *len ); if ( server->type->flags & TF_MASTER_STEAM ) { // default the region to 0xff const char* regionstring = get_param_value( server, "region", NULL ); int region = 0xFF; if(regionstring) { char* tmp = NULL; region = strtol( regionstring, &tmp, 10); if(tmp == regionstring) { int i = 0; region = 0xFF; for(;steam_region[i]; ++i) { if(!strcmp(regionstring, steam_region[i])) { region = i; break; } } } } *(pkt+1) = region; } pkt+= *len; gamedir = get_param_value( server, "game", NULL); if ( gamedir ) { pkt+= sprintf( pkt, "\\gamedir\\%s", gamedir); } // not valid for steam? map = get_param_value( server, "map", NULL); if ( map ) { pkt+= sprintf( pkt, "\\map\\%s", map); } // not valid for steam? flags= get_param_value( server, "status", NULL); r= flags; while ( flags && sep ) { sep= strchr( r, ':'); if ( sep ) flen= sep-r; else flen= strlen( r); if ( strncmp( r, "notempty", flen) == 0) pkt+= sprintf( pkt, "\\empty\\1"); else if ( strncmp( r, "notfull", flen) == 0) pkt+= sprintf( pkt, "\\full\\1"); else if ( strncmp( r, "dedicated", flen) == 0) { if ( server->type->flags & TF_MASTER_STEAM ) pkt+= sprintf( pkt, "\\type\\d"); else pkt+= sprintf( pkt, "\\dedicated\\1"); } else if ( strncmp( r, "linux", flen) == 0) pkt+= sprintf( pkt, "\\linux\\1"); else if ( strncmp( r, "proxy", flen) == 0) // steam pkt+= sprintf( pkt, "\\proxy\\1"); else if ( strncmp( r, "secure", flen) == 0) // steam pkt+= sprintf( pkt, "\\secure\\1"); r= sep+1; } // always need null terminator *pkt = 0x00; pkt++; *len = pkt - packet; return packet; } /* First packet for a QuakeWorld master server */ void send_qwmaster_request_packet( struct qserver *server) { int rc= 0; server->next_player_info = NO_PLAYER_INFO; if ( server->type->id == Q2_MASTER) { struct sockaddr_in addr; addr.sin_family= AF_INET; if ( no_port_offset || server->flags & TF_NO_PORT_OFFSET) { addr.sin_port= htons(server->port); } else { addr.sin_port= htons((unsigned short)( server->port + server->type->port_offset )); } addr.sin_addr.s_addr= server->ipaddr; memset( &(addr.sin_zero), 0, sizeof(addr.sin_zero)); rc= sendto( server->fd, server->type->master_packet, server->type->master_len, 0, (struct sockaddr *) &addr, sizeof(addr)); } else { char *packet; int packet_len; char query_buf[4096] = {0}; packet= server->type->master_packet; packet_len= server->type->master_len; if ( server->type->id == HL_MASTER) { memcpy( server->type->master_packet+1, server->master_query_tag, 3); if ( server->query_arg) { packet_len = server->type->master_len; packet= build_hlmaster_packet( server, &packet_len); } } else if ( server->type->flags & TF_MASTER_STEAM) { // region int tag_len = strlen( server->master_query_tag ); if ( tag_len < 9 ) { // initial case tag_len = 9; strcpy( server->master_query_tag, "0.0.0.0:0" ); } // 1 byte packet id // 1 byte region // ip:port // 1 byte null packet_len = 2 + tag_len + 1; if ( server->query_arg ) { // build_hlmaster_packet uses server->type->master_packet // as the basis so copy from server->master_query_tag strcpy( server->type->master_packet+2, server->master_query_tag ); packet = build_hlmaster_packet( server, &packet_len ); } else { // default region *(packet + 1) = 0xff; memcpy( packet+2, server->master_query_tag, tag_len ); // filter null *(packet + packet_len ) = 0x00; packet_len++; } } else if ( server->type->flags & TF_QUERY_ARG) { // fill in the master protocol details char *master_protocol= server->query_arg; if ( master_protocol == NULL) { master_protocol= server->type->master_protocol; } packet_len = sprintf( query_buf, server->type->master_packet, master_protocol?master_protocol:"", server->type->master_query?server->type->master_query:""); packet = query_buf; } rc= send( server->fd, packet, packet_len, 0); } if ( rc == SOCKET_ERROR) { perror( "send"); } if ( server->retry1 == n_retries) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } else { server->n_retries++; } server->retry1--; server->n_packets++; } void send_tribes_request_packet( struct qserver *server ) { send_packet( server, server->type->player_packet, server->type->player_len ); } void send_tribes2_request_packet( struct qserver *server ) { int rc; if ( server->flags & FLAG_BROADCAST && server->server_name == NULL) rc= send_broadcast( server, server->type->status_packet, server->type->status_len); else if ( server->server_name == NULL) rc= send( server->fd, server->type->status_packet, server->type->status_len, 0); else rc= send( server->fd, server->type->player_packet, server->type->player_len, 0); if ( rc == SOCKET_ERROR) perror( "send"); register_send( server ); } void send_ghostrecon_request_packet( struct qserver *server) { send_packet( server, server->type->status_packet, server->type->status_len ); } void send_eye_request_packet( struct qserver *server) { send_packet( server, server->type->status_packet, server->type->status_len ); } void send_ravenshield_request_packet( struct qserver *server) { send_packet( server, server->type->status_packet, server->type->status_len ); } void send_savage_request_packet( struct qserver *server) { int len; char* pkt; if ( get_player_info ) { pkt = server->type->player_packet; len = server->type->player_len; } else { pkt = server->type->status_packet; len = server->type->status_len; } send_packet( server, pkt, len ); } void send_farcry_request_packet( struct qserver *server) { int len; char* pkt; if ( get_player_info ) { pkt = server->type->player_packet; len = server->type->player_len; } else { pkt = server->type->status_packet; len = server->type->status_len; } send_packet( server, pkt, len ); } void send_tribes2master_request_packet( struct qserver *server) { int rc; unsigned char packet[1600], *pkt; unsigned int len, min_players, max_players, region_mask=0; unsigned int build_version, max_bots, min_cpu, status; char *game, *mission, *buddies; static char *region_list[]= { "naeast", "nawest", "sa", "aus", "asia", "eur", NULL }; static char *status_list[]= { "dedicated", "nopassword", "linux" }; if ( strcmp( get_param_value( server, "query", ""), "types") == 0) { rc= send( server->fd, tribes2_game_types_request, sizeof(tribes2_game_types_request), 0); goto send_done; } memcpy( packet, server->type->master_packet, server->type->master_len); pkt= packet + 7; game= get_param_value( server, "game", "any"); len= strlen(game); if ( len > 255) len= 255; *pkt++= len; memcpy( pkt, game, len); pkt+= len; mission= get_param_value( server, "mission", "any"); len= strlen(mission); if ( len > 255) len= 255; *pkt++= len; memcpy( pkt, mission, len); pkt+= len; min_players= get_param_ui_value( server, "minplayers", 0); max_players= get_param_ui_value( server, "maxplayers", 255); *pkt++= min_players; *pkt++= max_players; region_mask= get_param_ui_value( server, "regions", 0xffffffff); if ( region_mask == 0) { char *regions= get_param_value( server, "regions", ""); char *r= regions; char **list, *sep; do { sep= strchr( r, ':'); if ( sep) len= sep-r; else len= strlen( r); for ( list= region_list; *list; list++) if ( strncasecmp( r, *list, len) == 0) break; if ( *list) region_mask|= 1<<(list-region_list); r= sep+1; } while ( sep); } if ( little_endian) memcpy( pkt, ®ion_mask, 4); else { pkt[0]= region_mask&0xff; pkt[1]= (region_mask>>8)&0xff; pkt[2]= (region_mask>>16)&0xff; pkt[3]= (region_mask>>24)&0xff; } pkt+= 4; build_version= get_param_ui_value( server, "build", 0); /* if ( build_version && build_version < 22337) { packet[1]= 0; build_version= 0; } */ if ( little_endian) memcpy( pkt, &build_version, 4); else { pkt[0]= build_version&0xff; pkt[1]= (build_version>>8)&0xff; pkt[2]= (build_version>>16)&0xff; pkt[3]= (build_version>>24)&0xff; } pkt+= 4; status= get_param_ui_value( server, "status", -1); if ( status == 0) { char *flags= get_param_value( server, "status", ""); char *r= flags; char **list, *sep; do { sep= strchr( r, ':'); if ( sep) len= sep-r; else len= strlen( r); for ( list= status_list; *list; list++) if ( strncasecmp( r, *list, len) == 0) break; if ( *list) status|= 1<<(list-status_list); r= sep+1; } while ( sep); } else if ( status == -1) status= 0; *pkt++= status; max_bots= get_param_ui_value( server, "maxbots", 255); *pkt++= max_bots; min_cpu= get_param_ui_value( server, "mincpu", 0); if ( little_endian) memcpy( pkt, &min_cpu, 2); else { pkt[0]= min_cpu&0xff; pkt[1]= (min_cpu>>8)&0xff; } pkt+= 2; buddies= get_param_value( server, "buddies", NULL); if ( buddies) { char *b= buddies, *sep; unsigned int buddy, n_buddies= 0; unsigned char *n_loc= pkt++; do { sep= strchr( b, ':'); if ( sscanf( b, "%u", &buddy)) { n_buddies++; if ( little_endian) memcpy( pkt, &buddy, 4); else { pkt[0]= buddy&0xff; pkt[1]= (buddy>>8)&0xff; pkt[2]= (buddy>>16)&0xff; pkt[3]= (buddy>>24)&0xff; } pkt+= 4; } b= sep+1; } while ( sep && n_buddies < 255); *n_loc= n_buddies; } else *pkt++= 0; rc= send( server->fd, (char*)packet, pkt-packet, 0); send_done: if ( rc == SOCKET_ERROR) perror( "send"); if ( server->retry1 == n_retries) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } else server->n_retries++; server->retry1--; server->n_packets++; } static struct _gamespy_query_map { char *qstat_type; char *gamespy_type; } gamespy_query_map[] = { { "qws", "quakeworld" }, { "q2s", "quake2" }, { "q3s", "quake3" }, { "tbs", "tribes" }, { "uns", "ut" }, { "sgs", "shogo" }, { "hls", "halflife" }, { "kps", "kingpin" }, { "hrs", "heretic2" }, { "sfs", "sofretail" }, { NULL, NULL } }; void send_gamespy_master_request( struct qserver *server) { int rc, i; char request[1024]; if ( server->n_packets) return; rc= send( server->fd, server->type->master_packet, server->type->master_len, 0); if ( rc != server->type->master_len) perror( "send"); strcpy( request, server->type->status_packet); for ( i= 0; gamespy_query_map[i].qstat_type; i++) if ( strcasecmp( server->query_arg, gamespy_query_map[i].qstat_type) == 0) break; if ( gamespy_query_map[i].gamespy_type == NULL) strcat( request, server->query_arg); else strcat( request, gamespy_query_map[i].gamespy_type); strcat(request, "\\final\\"); assert(strlen(request) < sizeof(request)); rc= send( server->fd, request, strlen( request), 0); if ( rc != strlen( request)) perror( "send"); if ( server->retry1 == n_retries) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } server->n_packets++; } void send_rule_request_packet( struct qserver *server) { int rc, len; debug(3, "%p", server); /* Server created via broadcast, so bind it */ if ( server->fd == -1) { if ( bind_qserver( server) < 0) goto setup_retry; } if(server->type->rule_query_func && server->type->rule_query_func != send_rule_request_packet) { server->type->rule_query_func(server); return; } if ( server->type->id == Q_SERVER) { strcpy( (char*)q_rule.data, server->next_rule); len= Q_HEADER_LEN + strlen((char*)q_rule.data) + 1; q_rule.length= htons( (short)len); } else len= server->type->rule_len; rc= send( server->fd, (const char *) server->type->rule_packet, len, 0); if ( rc == SOCKET_ERROR) perror( "send"); setup_retry: if ( server->retry1 == n_retries) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } else if ( server->server_name == NULL) server->n_retries++; server->retry1--; if ( server->server_name == NULL) server->n_packets++; } void send_player_request_packet( struct qserver *server) { int rc; if(!server->type->player_packet) return; /* Server created via broadcast, so bind it */ if ( server->fd == -1) { if ( bind_qserver( server) < 0) goto setup_retry; } if(server->type->player_query_func && server->type->player_query_func != send_player_request_packet) { server->type->player_query_func(server); return; } if(!server->type->player_packet) { debug(0, "error: server %p has no player_packet", server); return; } if ( server->type->id == Q_SERVER) q_player.data[0]= server->next_player_info; rc= send( server->fd, (const char *) server->type->player_packet, server->type->player_len, 0); if ( rc == SOCKET_ERROR) perror( "send"); setup_retry: if ( server->retry2 == n_retries) { gettimeofday( &server->packet_time2, NULL); server->n_requests++; } else server->n_retries++; server->retry2--; server->n_packets++; } void qserver_disconnect(struct qserver* server) { #ifdef _WIN32 int i; #endif if ( server->fd != -1) { close( server->fd); #ifndef _WIN32 connmap[server->fd]= NULL; #else for ( i= 0; i < max_connmap; i++) { if ( connmap[i] == server) { connmap[i]= NULL; break; } } #endif server->fd= -1; connected--; } } /* Functions for figuring timeouts and when to give up * Returns 1 if the query is done (server may be freed) and 0 if not. */ int cleanup_qserver( struct qserver *server, int force ) { int close_it = force; if ( server->server_name == NULL) { close_it = 1; if ( server->type->id & MASTER_SERVER && server->master_pkt != NULL) { server->server_name = MASTER; } else { server->server_name = TIMEOUT; num_servers_timed_out++; } } else if ( server->type->flags & TF_SINGLE_QUERY ) { close_it = 1; } else if ( server->next_rule == NO_SERVER_RULES && server->next_player_info >= server->num_players ) { close_it = 1; } debug( 3, "close_it %d", close_it ); if ( close_it ) { if ( server->saved_data.data) { SavedData *sdata= server->saved_data.next; free(server->saved_data.data); server->saved_data.data= NULL; while ( sdata != NULL) { SavedData *next; free(sdata->data); next= sdata->next; free(sdata); sdata= next; } server->saved_data.next= NULL; } qserver_disconnect(server); if ( server->server_name != TIMEOUT) { num_servers_returned++; if ( server->server_name != DOWN) { num_players_total+= server->num_players; max_players_total+= server->max_players; } } if ( server->server_name == TIMEOUT || server->server_name == DOWN) { server->ping_total= 999999; } if ( server->type->master) { waiting_for_masters--; if ( waiting_for_masters == 0) { add_servers_from_masters(); } } if ( ! server_sort) { display_server( server); } return 1; } return 0; } /** must be called only on connected servers * @returns time in ms until server needs timeout handling. timeout handling is needed if <= zero */ static int qserver_get_timeout(struct qserver* server, struct timeval* now) { int diff, diff1, diff2, interval; if ( server->type->id & MASTER_SERVER) interval= master_retry_interval; else interval= retry_interval; diff2= 0xffff; diff1= interval*(n_retries-server->retry1+1) - time_delta( now, &server->packet_time1); if (server->next_player_info < server->num_players) { diff2= interval*(n_retries-server->retry2+1) - time_delta( now, &server->packet_time2); } debug(2, "timeout for %p is diff1 %d diff2 %d", server, diff1, diff2); diff= (diff1fd == -1; server= server->next) ; /* if there are unconnected servers and slots left we retry in 10ms */ if ( server == NULL || (num_servers > connected && connected < max_simultaneous)) { timeout->tv_sec= 0; timeout->tv_usec= 10 * 1000; return; } first_server_bind= server; gettimeofday( &now, NULL); for ( ; server != NULL && bind_count < connected; server= server->next) { if ( server->fd == -1) continue; diff = qserver_get_timeout(server, &now); if ( diff < smallest) smallest= diff; bind_count++; } if ( smallest < 10) smallest= 10; timeout->tv_sec= smallest / 1000; timeout->tv_usec= (smallest % 1000) * 1000; } #ifdef USE_SELECT static fd_set select_read_fds; static int select_maxfd; static int select_cursor; int set_fds( fd_set *fds) { int maxfd= -1, i; for ( i= 0; i < max_connmap; i++) { if ( connmap[i] != NULL) { FD_SET( connmap[i]->fd, fds); if ( connmap[i]->fd > maxfd) { maxfd= connmap[i]->fd; } } } return maxfd; } void set_file_descriptors() { FD_ZERO( &select_read_fds); select_maxfd= set_fds( &select_read_fds); } int wait_for_file_descriptors( struct timeval *timeout) { select_cursor= 0; return select( select_maxfd+1, &select_read_fds, NULL, NULL, timeout); } struct qserver * get_next_ready_server() { while ( select_cursor < max_connmap && ( connmap[select_cursor] == NULL || ! FD_ISSET( connmap[select_cursor]->fd, &select_read_fds)) ) { select_cursor++; } if ( select_cursor >= max_connmap) return NULL; return connmap[select_cursor++]; } int wait_for_timeout( unsigned int ms) { struct timeval timeout; timeout.tv_sec= ms/1000; timeout.tv_usec= (ms%1000) * 1000; return select( 0, 0, NULL, NULL, &timeout); } #endif /* USE_SELECT */ #ifdef USE_POLL static struct pollfd *pollfds; static int n_pollfds; static int max_pollfds= 0; static int poll_cursor; void set_file_descriptors() { struct pollfd *p; int i; if ( max_connmap > max_pollfds) { max_pollfds= max_connmap; pollfds= (struct pollfd *) realloc( pollfds, max_pollfds * sizeof(struct pollfd)); } p= pollfds; for ( i= 0; i < max_connmap; i++) if ( connmap[i] != NULL) { p->fd= connmap[i]->fd; p->events= POLLIN; p->revents= 0; p++; } n_pollfds= p - pollfds; } int wait_for_file_descriptors( struct timeval *timeout) { poll_cursor= 0; return poll( pollfds, n_pollfds, timeout->tv_sec*1000 + timeout->tv_usec/1000); } struct qserver * get_next_ready_server() { for ( ; poll_cursor < n_pollfds; poll_cursor++) { if ( pollfds[ poll_cursor].revents) break; } if ( poll_cursor >= n_pollfds) return NULL; return connmap[pollfds[poll_cursor++].fd]; } int wait_for_timeout( unsigned int ms) { return poll( 0, 0, ms); } #endif /* USE_POLL */ void free_server( struct qserver *server) { struct player *player, *next_player; struct rule *rule, *next_rule; /* remove from servers list */ if ( server == servers) { servers= server->next; if ( servers) servers->prev= NULL; } if ( (void*) &server->next == (void*) last_server) { if ( server->prev) last_server= & server->prev->next; else last_server= & servers; } if ( server == first_server_bind) first_server_bind= server->next; if ( server == last_server_bind) last_server_bind= server->next; if ( server->prev) server->prev->next= server->next; if ( server->next) server->next->prev= server->prev; /* remove from server hash table */ remove_server_from_hash( server); /* free all the data */ for ( player= server->players; player; player= next_player) { next_player= player->next; free_player( player); } for ( rule= server->rules; rule; rule= next_rule) { next_rule= rule->next; free_rule( rule); } if ( server->arg) free( server->arg); if ( server->host_name) free( server->host_name); if ( server->error) free( server->error); if ( server->address) free( server->address); if ( server->map_name) free( server->map_name); if ( !(server->flags&FLAG_DO_NOT_FREE_GAME) && server->game) free(server->game); if ( server->master_pkt) free( server->master_pkt); free(server->query_arg); /* These fields are never malloc'd: outfilename */ if ( server->server_name != NULL && server->server_name != DOWN && server->server_name != HOSTNOTFOUND && server->server_name != SYSERROR && server->server_name != MASTER && server->server_name != SERVERERROR && server->server_name != TIMEOUT && server->server_name != GAMESPY_MASTER_NAME && server->server_name != BFRIS_SERVER_NAME) { free( server->server_name); } /* params ... saved_data ... */ free( server); --num_servers; } void free_player( struct player *player) { if ( player->name) free( player->name); if ( ! (player->flags&PLAYER_FLAG_DO_NOT_FREE_TEAM) && player->team_name) free( player->team_name); if ( player->address) free( player->address); if ( player->tribe_tag) free( player->tribe_tag); if ( player->skin) free( player->skin); if ( player->mesh) free( player->mesh); if ( player->face) free( player->face); free( player); } void free_rule( struct rule *rule) { if ( rule->name) free( rule->name); if ( rule->value) free( rule->value); free( rule); } /* Functions for handling response packets */ /* Packet from normal Quake server */ void deal_with_q_packet( struct qserver *server, char *rawpkt, int pktlen) { struct q_packet *pkt= (struct q_packet *)rawpkt; int rc; if ( ntohs( pkt->length) != pktlen) { fprintf( stderr, "%s Ignoring bogus packet; length %d != %d\n", server->arg, ntohs( pkt->length), pktlen); cleanup_qserver(server,FORCE); return; } rawpkt[pktlen]= '\0'; switch ( pkt->op_code) { case Q_CCREP_ACCEPT: case Q_CCREP_REJECT: return; case Q_CCREP_SERVER_INFO: server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); rc= server_info_packet( server, pkt, pktlen-Q_HEADER_LEN); break; case Q_CCREP_PLAYER_INFO: server->ping_total+= time_delta( &packet_recv_time, &server->packet_time2); rc= player_info_packet( server, pkt, pktlen-Q_HEADER_LEN); break; case Q_CCREP_RULE_INFO: server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); rc= rule_info_packet( server, pkt, pktlen-Q_HEADER_LEN); break; case Q_CCREQ_CONNECT: case Q_CCREQ_SERVER_INFO: case Q_CCREQ_PLAYER_INFO: case Q_CCREQ_RULE_INFO: default: return; } if ( rc == -1) fprintf( stderr, "%s error on packet opcode %x\n", server->arg, (int)pkt->op_code); cleanup_qserver( server, (rc == -1) ? FORCE : 0); } /* Packet from QuakeWorld server */ void deal_with_qw_packet( struct qserver *server, char *rawpkt, int pktlen) { if ( server->server_name == NULL) server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); if ( ((rawpkt[0] != '\377' && rawpkt[0] != '\376') || rawpkt[1] != '\377' || rawpkt[2] != '\377' || rawpkt[3] != '\377') && show_errors) { unsigned int ipaddr= ntohl(server->ipaddr); fprintf( stderr, "Odd packet from server %d.%d.%d.%d:%hu, processing ...\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, ntohs(server->port)); print_packet( server, rawpkt, pktlen); } rawpkt[pktlen]= '\0'; if ( rawpkt[4] == 'n') { if ( server->type->id != QW_SERVER) server->type= find_server_type_id( QW_SERVER); deal_with_q1qw_packet( server, rawpkt, pktlen); return; } else if ( rawpkt[4] == '\377' && rawpkt[5] == 'n') { if ( server->type->id != HW_SERVER) server->type= find_server_type_id( HW_SERVER); deal_with_q1qw_packet( server, rawpkt, pktlen); return; } else if ( strncmp( &rawpkt[4], "print\n\\", 7) == 0) { deal_with_q2_packet( server, rawpkt+10, pktlen-10, 0); return; } else if ( strncmp( &rawpkt[4], "print\n", 6) == 0) { /* work-around for occasional bug in Quake II status packets */ char *c, *p; p= c= &rawpkt[10]; while ( *p != '\\' && (c= strchr( p, '\n'))) p= c+1; if ( *p == '\\' && c != NULL) { deal_with_q2_packet( server, p, pktlen-(p-rawpkt), 0); return; } } else if ( strncmp( &rawpkt[4], "infoResponse", 12) == 0 || (rawpkt[4] == '\001' && strncmp( &rawpkt[5], "infoResponse", 12) == 0) ) { /* quake3 info response */ if ( rawpkt[4] == '\001') { rawpkt++; pktlen--; } rawpkt+= 12; pktlen-= 12; for ( ; pktlen && *rawpkt != '\\'; pktlen--, rawpkt++) ; if ( !pktlen) return; if ( rawpkt[pktlen-1] == '"') { rawpkt[pktlen-1]= '\0'; pktlen--; } if ( get_player_info || get_server_rules) server->next_rule= ""; deal_with_q2_packet( server, rawpkt, pktlen, 0); if ( (get_player_info || get_server_rules) && ( server->flags & FLAG_BROADCAST || server->fd != -1)) { send_rule_request_packet( server); server->retry1= n_retries-1; } return; } else if ( strncmp( &rawpkt[4], "statusResponse\n", 15) == 0 || (rawpkt[4] == '\001' && strncmp( &rawpkt[5], "statusResponse\n", 15) == 0) ) { /* quake3 status response */ server->next_rule= NO_SERVER_RULES; server->retry1 = 0; if ( rawpkt[4] == '\001') { rawpkt++; pktlen--; } deal_with_q2_packet( server, rawpkt + 19, pktlen - 19, CHECK_DUPLICATE_RULES); return; } else if ( strncmp( &rawpkt[4], "infostringresponse", 19) == 0) { deal_with_q2_packet( server, rawpkt+23, pktlen-23, 0); return; } if ( show_errors) { unsigned int ipaddr= ntohl(server->ipaddr); fprintf( stderr, "Odd packet from server %d.%d.%d.%d:%hu, ignoring ...\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, ntohs(server->port)); print_packet( server, rawpkt, pktlen); cleanup_qserver( server, 1); } else cleanup_qserver( server, 0); } void deal_with_q1qw_packet( struct qserver *server, char *rawpkt, int pktlen) { char *key, *value, *end; struct player *player= NULL, **last_player= &server->players; int len, rc, complete= 0; int number, frags, connect_time, ping; char *pkt= &rawpkt[5]; if ( server->type->id == HW_SERVER) pkt= &rawpkt[6]; while ( *pkt && pkt-rawpkt < pktlen) { if ( *pkt == '\\') { pkt++; end= strchr( pkt, '\\'); if ( end == NULL) break; *end= '\0'; key= pkt; pkt+= strlen(pkt)+1; end= strchr( pkt, '\\'); if ( end == NULL) end= strchr( pkt, '\n'); value= (char*) malloc(end-pkt+1); memcpy( value, pkt, end-pkt); value[end-pkt]= '\0'; pkt= end; if ( strcmp( key, "hostname") == 0) server->server_name= value; else if ( strcmp( key, "map") == 0) server->map_name= value; else if ( strcmp( key, "maxclients") == 0) { server->max_players= atoi(value); free( value); } else if ( get_server_rules || strncmp( key, "*game", 5) == 0) { add_rule( server, key, value, NO_VALUE_COPY); if ( strcmp( key, "*gamedir") == 0) { server->game= value; server->flags |= FLAG_DO_NOT_FREE_GAME; } } } else if ( *pkt == '\n') { pkt++; if ( pkt-rawpkt>=pktlen || *pkt == '\0') break; rc= sscanf( pkt, "%d %d %d %d %n", &number, &frags, &connect_time, &ping, &len); if ( rc != 4) { char *nl; /* assume it's an error packet */ server->error= (char*)malloc( pktlen+1); nl= strchr( pkt, '\n'); if ( nl != NULL) { strncpy( server->error, pkt, nl-pkt); server->error[nl-pkt]= '\0'; } else strcpy( server->error, pkt); server->server_name= SERVERERROR; complete= 1; break; } if ( get_player_info) { player= (struct player *) calloc( 1, sizeof( struct player)); player->number= number; player->frags= frags; player->connect_time= connect_time * 60; player->ping= ping; } else player= NULL; pkt+= len; if ( *pkt != '"') break; pkt++; end= strchr( pkt, '"'); if ( end == NULL) break; if ( player != NULL) { player->name= (char*) malloc(end-pkt+1); memcpy( player->name, pkt, end-pkt); player->name[end-pkt]= '\0'; } pkt= end+2; if ( *pkt != '"') break; pkt++; end= strchr( pkt, '"'); if ( end == NULL) break; if ( player != NULL) { player->skin= (char*) malloc(end-pkt+1); memcpy( player->skin, pkt, end-pkt); player->skin[end-pkt]= '\0'; } pkt= end+2; if ( player != NULL) { sscanf( pkt, "%d %d%n", &player->shirt_color, &player->pants_color, &len); *last_player= player; last_player= & player->next; } else sscanf( pkt, "%*d %*d%n", &len); pkt+= len; server->num_players++; } else pkt++; complete= 1; } if ( !complete) { if ( rawpkt[4] != 'n' || rawpkt[5] != '\0') { fprintf( stderr, "Odd packet from QW server %d.%d.%d.%d:%hu ...\n", (server->ipaddr>>24)&0xff, (server->ipaddr>>16)&0xff, (server->ipaddr>>8)&0xff, server->ipaddr&0xff, ntohs(server->port)); print_packet( server, rawpkt, pktlen); } } else if ( server->server_name == NULL) server->server_name= strdup(""); cleanup_qserver( server, 0); } void deal_with_q2_packet( struct qserver *server, char *rawpkt, int pktlen, int check_duplicate_rules) { char *key, *value, *end; struct player *player= NULL; struct player **last_player= & server->players; int len, rc, complete= 0; int frags=0, ping=0, num_players= 0; char *pkt= rawpkt; while ( *pkt && pkt-rawpkt < pktlen) { if ( *pkt == '\\') { pkt++; if ( *pkt == '\n' && server->type->id == SOF_SERVER) goto player_info; end= strchr( pkt, '\\'); if ( end == NULL) break; *end= '\0'; key= pkt; pkt+= strlen(pkt)+1; end= strpbrk( pkt, "\\\n"); if(!end) { end= rawpkt+pktlen; } value= (char*) malloc(end-pkt+1); memcpy( value, pkt, end-pkt); value[end-pkt]= '\0'; pkt= end; debug(3, "%s = %s", key, value); if ( server->server_name == NULL && (strcmp( key, "hostname") == 0 || strcmp( key, "sv_hostname") == 0)) server->server_name= value; else if ( strcmp( key, "mapname") == 0 || (strcmp( key, "map") == 0 && server->map_name == NULL)) { if ( server->map_name != NULL) free( server->map_name); server->map_name= value; } else if ( strcmp( key, "maxclients") == 0 || strcmp( key, "sv_maxclients") == 0 || strcmp( key, "max") == 0) { server->max_players= atoi(value); /* MOHAA Q3 protocol max players is always 0 */ if ( server->max_players == 0) server->max_players= -1; free(value); } else if ( strcmp( key, "clients") == 0 || strcmp( key, "players") == 0) { server->num_players= atoi(value); free(value); } else if ( server->server_name == NULL && strcmp( key, "pure") == 0) { add_rule( server, key, value, NO_VALUE_COPY); } else if ( get_server_rules || strncmp( key, "game", 4) == 0) { if ( add_rule( server, key, value, NO_VALUE_COPY|check_duplicate_rules) == NULL) { free(value); /* duplicate, so free value */ } if ( server->game == NULL && strcmp( key, server->type->game_rule) == 0) { server->game= value; server->flags |= FLAG_DO_NOT_FREE_GAME; } } else free(value); } else if ( *pkt == '\n') { player_info: pkt++; if ( *pkt == '\0') break; if(!strncmp(pkt, "\\challenge\\", 11)) { // qfusion // This doesnt support getstatus looking at warsow source: // server/sv_main.c: SV_ConnectionlessPacket server->next_rule = NO_SERVER_RULES; break; } rc= sscanf( pkt, "%d %n", &frags, &len); if ( rc == 1 && pkt[len] != '"') { pkt+= len; rc= sscanf( pkt, "%d %n", &ping, &len); } else if ( rc == 1) { /* MOHAA Q3 protocol only provides player ping */ ping= frags; frags= 0; } if ( rc != 1) { char *nl; /* assume it's an error packet */ server->error= (char*)malloc( pktlen+1); nl= strchr( pkt, '\n'); if ( nl != NULL) strncpy( server->error, pkt, nl-pkt); else strcpy( server->error, pkt); server->server_name= SERVERERROR; complete= 1; break; } if ( get_player_info) { player= (struct player *) calloc( 1, sizeof( struct player)); player->number= 0; player->connect_time= -1; player->frags= frags; player->ping= ping; } else player= NULL; pkt+= len; if ( isdigit((unsigned char)*pkt)) { /* probably an SOF2 1.01 server, includes team # */ int team; rc= sscanf( pkt, "%d %n", &team, &len); if ( rc == 1) { pkt+= len; if ( player) { player->team= team; server->flags|= FLAG_PLAYER_TEAMS; } } } if ( *pkt != '"') break; pkt++; end= strchr( pkt, '"'); if ( end == NULL) break; if ( player != NULL) { player->name= (char*) malloc(end-pkt+1); memcpy( player->name, pkt, end-pkt); player->name[end-pkt]= '\0'; } pkt= end+1; //WarSoW team number if ( *pkt != '\n') { int team; rc= sscanf( pkt, "%d%n", &team, &len); if ( rc == 1) { pkt+= len; if ( player) { player->team= team; server->flags|= FLAG_PLAYER_TEAMS; } } } if ( player != NULL) { player->skin= NULL; player->shirt_color= -1; player->pants_color= -1; *last_player= player; last_player= & player->next; } num_players++; } else pkt++; complete= 1; } if ( server->num_players == 0 || num_players > server->num_players) server->num_players= num_players; if ( !complete) { cleanup_qserver( server, 1); return; } else if ( server->server_name == NULL) server->server_name= strdup(""); cleanup_qserver( server, 0); } void ack_descent3master_packet( struct qserver *server, char *curtok ) { int rc; char packet[0x1e]; memcpy( packet, descent3_masterquery,0x1a); packet[1]= 0x1d; packet[0x16]= 1; memcpy( packet + 0x1a, curtok, 4); rc= send( server->fd, packet, sizeof(packet), 0); if ( rc == SOCKET_ERROR) perror( "send"); } /* Packet from Descent3 master server (PXO) */ void deal_with_descent3master_packet( struct qserver *server, char *rawpkt, int pktlen) { int i= 0, lastpacket= 0; char *names= rawpkt + 0x1f; char *ips= rawpkt + 0x29f; char *ports= rawpkt + 0x2ef; /* printf ("s=%p p=%p l=%i\n",server,rawpkt,pktlen); */ while ( i<20) { if ( *names) { char *c; server->master_pkt_len += 6; server->master_pkt= (char*)realloc( server->master_pkt, server->master_pkt_len); c= server->master_pkt + server->master_pkt_len - 6; memcpy( c, ips, 4); memcpy( c + 4, ports, 2); }else if (i>0) lastpacket= 1; names+= 0x20; ips+= 4; ports+= 2; i++; } ack_descent3master_packet( server, rawpkt+0x1a); server->n_servers= server->master_pkt_len / 6; server->next_player_info= -1; server->retry1= 0; if (lastpacket) { cleanup_qserver( server, 0); } } /* Packet from QuakeWorld master server */ void deal_with_qwmaster_packet( struct qserver *server, char *rawpkt, int pktlen) { server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); if ( rawpkt[0] == QW_NACK) { server->error= strdup( &rawpkt[2]); server->server_name= SERVERERROR; cleanup_qserver( server, 1); return; } if ( *((unsigned int*)rawpkt) == 0xffffffff) { rawpkt+= 4; /* QW 1.5 */ pktlen-= 4; } if ( rawpkt[0] == QW_SERVERS && rawpkt[1] == QW_NEWLINE) { rawpkt+= 2; pktlen-= 2; } else if ( rawpkt[0] == HL_SERVERS && rawpkt[1] == 0x0d ) { // 2 byte id + 4 byte sequence memcpy( server->master_query_tag, rawpkt+2, 3); rawpkt+= 6; pktlen-= 6; } else if ( rawpkt[0] == HL_SERVERS && rawpkt[1] == 0x0a ) { // no sequence id for steam // instead we use the ip:port of the last recieved server struct in_addr *sin_addr = (struct in_addr*)(rawpkt+pktlen-6); char *ip = inet_ntoa( *sin_addr ); unsigned short port = htons( *((unsigned short*)(rawpkt+pktlen-2)) ); //fprintf( stderr, "NEXT IP=%s:%u\n", ip, port ); sprintf( server->master_query_tag, "%s:%u", ip, port ); // skip over the 2 byte id rawpkt+= 2; pktlen-= 2; } else if ( strncmp( rawpkt, "servers", 7) == 0) { rawpkt+= 8; pktlen-= 8; } else if ( strncmp( rawpkt, "getserversResponse", 18) == 0) { static int q3m_debug= 0; rawpkt+= 18; pktlen-= 18; for ( ; *rawpkt != '\\' && pktlen; pktlen--, rawpkt++) { } if ( !pktlen) { return; } rawpkt++; pktlen--; if ( q3m_debug) printf( "q3m pktlen %d lastchar %x\n", pktlen, (unsigned int)rawpkt[pktlen-1]); server->master_pkt= (char*)realloc( server->master_pkt, server->master_pkt_len + pktlen+1); if ( server->type->id == STEF_MASTER) { decode_stefmaster_packet( server, rawpkt, pktlen); } else { decode_q3master_packet( server, rawpkt, pktlen); } if ( q3m_debug) printf( "q3m %d servers\n", server->n_servers); return; } else if ( show_errors) { unsigned int ipaddr= ntohl(server->ipaddr); fprintf( stderr, "Odd packet from QW master %d.%d.%d.%d, processing ...\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff ); print_packet( server, rawpkt, pktlen); } server->master_pkt= (char*)realloc( server->master_pkt, server->master_pkt_len+pktlen+1); rawpkt[pktlen]= '\0'; memcpy( server->master_pkt+server->master_pkt_len, rawpkt, pktlen+1); server->master_pkt_len+= pktlen; server->n_servers= server->master_pkt_len / 6; if ( server->type->flags & TF_MASTER_MULTI_RESPONSE) { server->next_player_info= -1; server->retry1= 0; } else if ( server->type->id == HL_MASTER ) { if ( server->master_query_tag[0] == 0 && server->master_query_tag[1] == 0 && server->master_query_tag[2] == 0 ) { // all done server->server_name = MASTER; cleanup_qserver( server, 1); bind_sockets(); } else { // more to come server->retry1++; send_qwmaster_request_packet( server); } } else if ( server->type->flags & TF_MASTER_STEAM ) { // should the HL_MASTER be the same as this? int i; for ( i = pktlen - 6; i < pktlen && 0x00 == rawpkt[i] ; i++ ) { } if ( i == pktlen ) { // last 6 bytes where 0x00 so we have reached the last packet server->n_servers--; server->master_pkt_len -= 6; server->server_name = MASTER; cleanup_qserver( server, 1); bind_sockets(); } else { // more to come server->retry1++; send_qwmaster_request_packet( server ); } } else { server->server_name = MASTER; cleanup_qserver( server, 0); bind_sockets(); } } void decode_q3master_packet( struct qserver *server, char *pkt, int pktlen) { char *p; pkt[pktlen]= 0; p= pkt; while ( *p && p < &pkt[pktlen-6]) { memcpy( server->master_pkt + server->master_pkt_len, &p[0], 4); memcpy( server->master_pkt + server->master_pkt_len + 4, &p[4], 2); server->master_pkt_len += 6; p+= 6; while ( *p && *p == '\\') p++; } server->n_servers= server->master_pkt_len / 6; // server->next_player_info= -1; evil, causes busy loop! server->retry1 = 0; // received at least one packet so no need to retry } void decode_stefmaster_packet( struct qserver *server, char *pkt, int pktlen) { unsigned char *p, *m, *end; unsigned int i, b; pkt[pktlen]= 0; p= (unsigned char*) pkt; m= (unsigned char*) server->master_pkt + server->master_pkt_len; end= (unsigned char*) &pkt[pktlen-12]; while ( *p && p < end) { for ( i= 6; i; i--) { sscanf( (char*)p, "%2x", &b); p+= 2; *m++= b; } server->master_pkt_len += 6; while ( *p && *p == '\\') p++; } server->n_servers= server->master_pkt_len / 6; server->next_player_info= -1; server->retry1= 0; } /* Packet from Tribes master server */ void deal_with_tribesmaster_packet( struct qserver *server, char *rawpkt, int pktlen) { unsigned char *upkt= (unsigned char*) rawpkt; int packet_number= upkt[2]; int n_packets= upkt[3]; unsigned char *p; char *mpkt; int len; unsigned int ipaddr; if ( memcmp( rawpkt, tribes_master_response, sizeof(tribes_master_response)) != 0) { fprintf( stderr, "Odd packet from Tribes master server\n"); print_packet( server, rawpkt, pktlen); } /* 0x1006 01 packet number 08 # packets 02 0000 66 0d length of following string "Tribes Master" 3c length of following string "Check out the Starsiege demo now! www.starsiegeplayers.com" 0035 06 d143 4764 812c 06 d1e2 8df3 616d 06 1804 6d50 616d 06 d81c 6dc0 616d */ /* 0x1006 02 08 02 0000 66 00 3f 06 cf88 344c 1227 */ /* printf( "packet_number %d n_packets %d\n", packet_number, n_packets); */ len= upkt[8]; if ( len > 0) { p= (unsigned char*) rawpkt+9; /* printf( "%.*s\n", len, p); */ p+= len; len= upkt[8+len+1]; /* printf( "%.*s\n", len, p+1); */ p+= len+1; p+= 2; } else p= (unsigned char*) rawpkt+10; if ( server->master_pkt == NULL) { server->master_pkt= (char*)malloc( n_packets*64*6); mpkt= server->master_pkt; } else mpkt= server->master_pkt + server->n_servers*6; while ( (char*)p < rawpkt+pktlen) { if ( *p != 0x6) printf( "*p %u\n", (unsigned)*p); memcpy( mpkt, p+1, sizeof(ipaddr)); if ( 0) { mpkt[4]= p[5]; mpkt[5]= p[6]; } else { mpkt[5]= p[5]; mpkt[4]= p[6]; } /* printf( "%08x:%hu %u.%u.%u.%u:%hu\n", ipaddr, port, ipaddr>>24, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, port); */ p+= 7; mpkt+= 6; } /* if ( (char*)p != rawpkt+pktlen) printf( "%x %x\n", p, rawpkt+pktlen); */ server->master_pkt_len= mpkt - server->master_pkt; server->n_servers= server->master_pkt_len / 6; server->server_name= MASTER; server->next_player_info= -1; if ( packet_number >= n_packets) cleanup_qserver( server, 1); else cleanup_qserver( server, 0); } char * display_tribes2_string_list( unsigned char *pkt) { char *delim=""; unsigned int count, len; count= *pkt; pkt++; for ( ; count; count--) { len= *pkt; pkt++; if ( len > 0) { if ( raw_display) { fprintf( OF, "%s%.*s", delim, (int)len, pkt); delim= raw_delimiter; } else fprintf( OF, "%.*s\n", (int)len, pkt); } pkt+= len; } if ( raw_display) fputs( "\n", OF); return (char*)pkt; } void deal_with_tribes2master_packet( struct qserver *server, char *pkt, int pktlen) { unsigned int n_servers, index, total, server_limit; char *p, *mpkt; if ( pkt[0] == TRIBES2_RESPONSE_GAME_TYPES) { pkt+= 6; if ( raw_display) { fprintf( OF, "%s%s%s%s", server->type->type_prefix, raw_delimiter, server->arg, raw_delimiter); } else { fprintf( OF, "Game Types\n"); fprintf( OF, "----------\n"); } pkt= display_tribes2_string_list( (unsigned char *)pkt); if ( raw_display) { fprintf( OF, "%s%s%s%s", server->type->type_prefix, raw_delimiter, server->arg, raw_delimiter); } else { fprintf( OF, "\nMission Types\n"); fprintf( OF, "-------------\n"); } display_tribes2_string_list( (unsigned char *)pkt); server->master_pkt_len= 0; server->n_servers= 0; server->server_name= MASTER; server->next_player_info= -1; cleanup_qserver( server, 1); return; } if ( pkt[0] != TRIBES2_RESPONSE_MASTER) { /* error */ cleanup_qserver( server, 1); return; } server_limit= get_param_ui_value( server, "limit", ~0); n_servers= little_endian ? *(unsigned short*)(pkt+8) : swap_short(pkt+8); index= *(unsigned char*)(pkt+6); total= *(unsigned char*)(pkt+7); if ( server->master_pkt == NULL) { server->master_pkt= (char*)malloc( total * n_servers * 6); mpkt= server->master_pkt; } else mpkt= server->master_pkt + server->n_servers*6; p= pkt+10; for ( ; n_servers && ((char*)mpkt - server->master_pkt)/6 < server_limit; n_servers--, p+= 6, mpkt+= 6) { memcpy( mpkt, p, 4); mpkt[4]= p[5]; mpkt[5]= p[4]; } server->master_pkt_len= (char*)mpkt - server->master_pkt; server->n_servers= server->master_pkt_len / 6; server->server_name= MASTER; server->next_player_info= -1; if ( index >= total-1 || server->n_servers >= server_limit) cleanup_qserver( server, 1); else cleanup_qserver( server, 0); } int server_info_packet( struct qserver *server, struct q_packet *pkt, int datalen) { int off= 0; /* ignore duplicate packets */ if ( server->server_name != NULL) return 0; server->address= strdup((char*)&pkt->data[off]); off+= strlen(server->address) + 1; if ( off >= datalen) return -1; server->server_name= strdup((char*)&pkt->data[off]); off+= strlen(server->server_name) + 1; if ( off >= datalen) return -1; server->map_name= strdup((char*)&pkt->data[off]); off+= strlen(server->map_name) + 1; if ( off > datalen) return -1; server->num_players= pkt->data[off++]; server->max_players= pkt->data[off++]; server->protocol_version= pkt->data[off++]; server->retry1= n_retries; if ( get_server_rules) send_rule_request_packet( server); if ( get_player_info) send_player_request_packet( server); return 0; } int player_info_packet( struct qserver *server, struct q_packet *pkt, int datalen) { char *name, *address; int off, colors, frags, connect_time, player_number; struct player *player, *last; off= 0; player_number= pkt->data[off++]; name= (char*) &pkt->data[off]; off+= strlen(name)+1; if ( off >= datalen) return -1; colors= pkt->data[off+3]; colors= (colors<<8) + pkt->data[off+2]; colors= (colors<<8) + pkt->data[off+1]; colors= (colors<<8) + pkt->data[off]; off+= sizeof(colors); frags= pkt->data[off+3]; frags= (frags<<8) + pkt->data[off+2]; frags= (frags<<8) + pkt->data[off+1]; frags= (frags<<8) + pkt->data[off]; off+= sizeof(frags); connect_time= pkt->data[off+3]; connect_time= (connect_time<<8) + pkt->data[off+2]; connect_time= (connect_time<<8) + pkt->data[off+1]; connect_time= (connect_time<<8) + pkt->data[off]; off+= sizeof(connect_time); address= (char*) &pkt->data[off]; off+= strlen(address)+1; if ( off > datalen) return -1; last= server->players; while ( last != NULL && last->next != NULL) { if ( last->number == player_number) return 0; last= last->next; } if ( last != NULL && last->number == player_number) return 0; player= (struct player *) calloc( 1, sizeof(struct player)); player->number= player_number; player->name= strdup( name); player->address= strdup( address); player->connect_time= connect_time; player->frags= frags; player->shirt_color= colors>>4; player->pants_color= colors&0xf; player->next= NULL; if ( last == NULL) server->players= player; else last->next= player; server->next_player_info++; server->retry2= n_retries; if ( server->next_player_info < server->num_players) send_player_request_packet( server); return 0; } int rule_info_packet( struct qserver *server, struct q_packet *pkt, int datalen) { int off= 0; struct rule *rule, *last; char *name, *value; /* Straggler packet after we've already given up fetching rules */ if ( server->next_rule == NULL) return 0; if ( ntohs(pkt->length) == Q_HEADER_LEN) { server->next_rule= NULL; return 0; } name= (char*)&pkt->data[off]; off+= strlen( name)+1; if ( off >= datalen) return -1; value= (char*)&pkt->data[off]; off+= strlen( value)+1; if ( off > datalen) return -1; last= server->rules; while ( last != NULL && last->next != NULL) { if ( strcmp( last->name, name) == 0) return 0; last= last->next; } if ( last != NULL && strcmp( last->name, name) == 0) return 0; rule= (struct rule *) malloc( sizeof( struct rule)); rule->name= strdup( name); rule->value= strdup( value); rule->next= NULL; if ( last == NULL) server->rules= rule; else last->next= rule; server->n_rules++; server->next_rule= rule->name; server->retry1= n_retries; send_rule_request_packet( server); return 0; } struct info * player_add_info( struct player *player, char *key, char *value, int flags) { struct info *info; if ( flags & CHECK_DUPLICATE_RULES ) { for ( info = player->info; info; info = info->next ) { if ( 0 == strcmp( info->name, key ) ) { return NULL; } } } if ( flags & COMBINE_VALUES ) { for ( info = player->info; info; info = info->next ) { if ( 0 == strcmp( info->name, key ) ) { char *full_value = (char*)calloc( sizeof(char), strlen( info->value ) + strlen( value ) + 2 ); if ( NULL == full_value ) { fprintf( stderr, "Failed to malloc combined value\n" ); exit( 1 ); } sprintf( full_value, "%s%s%s", info->value, multi_delimiter, value ); // We should be able to free this free( info->value ); info->value = full_value; return info; } } } info = (struct info *) malloc( sizeof( struct info)); if ( flags & NO_KEY_COPY) { info->name = key; } else { info->name = strdup(key); } if ( flags & NO_VALUE_COPY) { info->value = value; } else { info->value = strdup(value); } info->next = NULL; if ( NULL == player->info ) { player->info = info; } else { *player->last_info = info; } player->last_info = &info->next; player->n_info++; return info; } struct rule * add_rule( struct qserver *server, char *key, char *value, int flags) { struct rule *rule; if ( flags & CHECK_DUPLICATE_RULES ) { for ( rule = server->rules; rule; rule = rule->next ) { if ( 0 == strcmp( rule->name, key ) ) { return NULL; } } } if ( flags & COMBINE_VALUES ) { for ( rule = server->rules; rule; rule = rule->next ) { if ( 0 == strcmp( rule->name, key ) ) { char *full_value = (char*)calloc( sizeof(char), strlen( rule->value ) + strlen( value ) + 2 ); if ( NULL == full_value ) { fprintf( stderr, "Failed to malloc combined value\n" ); exit( 1 ); } sprintf( full_value, "%s%s%s", rule->value, multi_delimiter, value ); // We should be able to free this free( rule->value ); rule->value = full_value; return rule; } } } rule = (struct rule *) malloc( sizeof( struct rule)); if ( flags & NO_KEY_COPY) { rule->name = key; } else { rule->name = strdup(key); } if ( flags & NO_VALUE_COPY) { rule->value = value; } else { rule->value = strdup(value); } rule->next = NULL; *server->last_rule = rule; server->last_rule = & rule->next; server->n_rules++; return rule; } void add_nrule( struct qserver *server, char *key, char *value, int len) { struct rule *rule; for ( rule= server->rules; rule; rule= rule->next) if ( strcmp( rule->name, key) == 0) return; rule= (struct rule *) malloc( sizeof( struct rule)); rule->name= strdup(key); rule->value= strndup(value,len); rule->next= NULL; *server->last_rule= rule; server->last_rule= & rule->next; server->n_rules++; } struct player * add_player( struct qserver *server, int player_number ) { struct player *player; for ( player = server->players; player; player = player->next ) { if ( player->number == player_number) { return NULL; } } player = (struct player *) calloc( 1, sizeof( struct player)); player->number = player_number; player->next = server->players; player->n_info = 0; player->score = NA_INT; player->deaths = NA_INT; player->frags = NA_INT; player->last_info = NULL; server->players = player; server->n_player_info++; return player; } STATIC struct player * get_player_by_number( struct qserver *server, int player_number) { struct player *player; for ( player= server->players; player; player= player->next) if ( player->number == player_number) return player; return NULL; } // Updates a servers port information. // Sets the rules: // _queryport // hostport void change_server_port( struct qserver *server, unsigned short port, int force ) { if ( port > 0 && port != server->port ) { // valid port and changing char arg[64]; if ( show_game_port || force || server->flags & TF_SHOW_GAME_PORT ) { unsigned int ipaddr = ntohl(server->ipaddr); // Update the servers hostname as required sprintf( arg, "%d.%d.%d.%d:%hu", ipaddr>>24, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, port ); if ( 0 != strcmp( server->arg, server->host_name )) { // hostname isnt the query arg char *colon = strchr( server->host_name, ':' ); if ( colon ) { // dns hostname or hostname:port char *hostname = malloc( strlen(server->host_name) + 6 ); *colon= '\0'; sprintf( hostname, "%s:%hu", server->host_name, port); free( server->host_name); server->host_name= hostname; } } // Update the server arg free( server->arg ); server->arg = strdup( arg ); // Add a rule noting the previous query port sprintf( arg, "%hu", server->port ); add_rule( server, "_queryport", arg, NO_FLAGS); // Update the servers port server->port = port; } // Add a rule noting the servers hostport sprintf( arg, "%hu", port ); add_rule( server, "hostport", arg, NO_FLAGS); } } STATIC void players_set_teamname( struct qserver *server, int teamid, char *teamname ) { struct player *player; for ( player= server->players; player; player= player->next) { if ( player->team == teamid ) { player->team_name = strdup( teamname ); } } } STATIC char * dup_nstring( const char *pkt, const char *end, char **next) { char *pt = (char*)pkt; int len= ((unsigned char*)pkt)[0]; pt++; if ( *pt == '\1') { len++; } if ( pt + len > end) { return NULL; } *next = pt+len; return strndup( pt, len ); } STATIC char * dup_n1string( char *pkt, char *end, char **next) { unsigned len; if(!pkt || pkt >= end) return NULL; len = (unsigned char)pkt[0]-1; pkt++; if ( pkt + len > end) return NULL; *next= pkt+len; return strndup( pkt, len); } STATIC int pariah_basic_packet( struct qserver *server, char *rawpkt, char *end) { char *next; char *string; change_server_port( server, swap_short_from_little( &rawpkt[14]), 0 ); if ( NULL == ( string = ut2003_strdup( &rawpkt[18], end, &next) ) ) { return -1; } if ( server->server_name == NULL) { server->server_name = string; } else { free(string); } if ( NULL == ( string = ut2003_strdup( next, end, &next) ) ) { return -1; } if ( server->map_name == NULL) { server->map_name = string; } else { free(string); } if ( NULL == ( string= ut2003_strdup( next, end, &next) ) ) { return -1; } if ( server->game == NULL) { server->game = string; add_rule( server, "gametype", server->game, NO_FLAGS | CHECK_DUPLICATE_RULES); } else { free(string); } server->num_players = (unsigned char)next[0]; server->max_players = (unsigned char)next[1]; return 0; } STATIC int ut2003_basic_packet( struct qserver *server, char *rawpkt, char *end) { char *next; char *string; change_server_port( server, swap_short_from_little( &rawpkt[6]), 0 ); if ( NULL == ( string = ut2003_strdup( &rawpkt[14], end, &next) ) ) { return -1; } if ( server->server_name == NULL) { server->server_name = string; } else { free(string); } if ( NULL == ( string = ut2003_strdup( next, end, &next) ) ) { return -1; } if ( server->map_name == NULL) { server->map_name= string; } else { free(string); } if ( NULL == ( string= ut2003_strdup( next, end, &next) ) ) { return -1; } if ( server->game == NULL) { server->game= string; add_rule( server, "gametype", server->game, NO_FLAGS | CHECK_DUPLICATE_RULES); } else { free(string); } server->num_players= swap_long_from_little( next); next+= 4; server->max_players= swap_long_from_little( next); return 0; } STATIC int pariah_rule_packet( struct qserver *server, char *rawpkt, char *end ) { char *key, *value; unsigned char no_rules = (unsigned char)rawpkt[1]; unsigned char seen = 0; // type + no_rules rawpkt+=2; // we get size encoded key = value pairs while ( rawpkt < end && no_rules > seen ) { // first byte is the rule count seen = (unsigned char)rawpkt[0]; rawpkt++; if ( NULL == ( key = ut2003_strdup( rawpkt, end, &rawpkt) ) ) { break; } if ( '\0' == rawpkt[0] ) { value = strdup( "" ); rawpkt++; } else if ( NULL == ( value = ut2003_strdup( rawpkt, end, &rawpkt) ) ) { break; } if ( NULL == add_rule( server, key, value, NO_KEY_COPY | NO_VALUE_COPY | COMBINE_VALUES ) ) { /* duplicate, so free key and value */ free(value); free(key); } seen++; } if ( no_rules == seen ) { // all done server->next_rule = NULL; return 1; } return 0; } STATIC int ut2003_rule_packet( struct qserver *server, char *rawpkt, char *end ) { char *key, *value; int result= 0; // Packet Type rawpkt++; // we get size encoded key = value pairs while ( rawpkt < end ) { if ( NULL == ( key = ut2003_strdup( rawpkt, end, &rawpkt) ) ) { break; } if ( NULL == ( value = ut2003_strdup( rawpkt, end, &rawpkt) ) ) { break; } if ( strcmp( key, "minplayers") == 0) { result = atoi(value); } if ( NULL == add_rule( server, key, value, NO_KEY_COPY | NO_VALUE_COPY | COMBINE_VALUES ) ) { /* duplicate, so free key and value */ free(value); free(key); } } return result; } char * ut2003_strdup( const char *string, const char *end, char **next ) { unsigned char len = string[0]; char *result = NULL; if ( len < 128 ) { // type 1 string //fprintf( stderr, "Type 1:" ); result = dup_nstring( string, end, next ); } else { // type 2 string //fprintf( stderr, "Type 2:\n" ); const char *last; char *resp, *pos; // minus indicator len -= 128; // double byte chars so * 2 len = len * 2; last = string + len; if ( last > end ) { *next = (char*)end; fprintf( stderr, "Type 2 string format error ( too short )\n" ); return NULL; } *next = (char*)last+1; if ( NULL == ( result = (char*)calloc( last - string, sizeof(char) ) ) ) { fprintf( stderr, "Failed to malloc string memory\n" ); return NULL; } resp = result; pos = (char*)string + 1; while ( pos <= last ) { // check for a color code if ( pos + 6 <= last && 0 == memcmp( pos, "^\0#\0", 4 ) ) { // we have a color code //fprintf( stderr, "color:%02hhx%02hhx\n", pos[4], pos[5] ); // indicator transformed to ^\1 *resp = *pos; resp++; pos++; *resp = '\1'; resp++; pos+=3; // color byte *resp = *pos; resp++; pos+=2; //pos += 6; } // standard char //fprintf( stderr, "char: %02hhx\n", *pos ); *resp = *pos; resp++; pos += 2; } } //fprintf( stderr, "'%s'\n", result ); return result; } STATIC int pariah_player_packet( struct qserver *server, char *rawpkt, char *end) { unsigned char no_players = rawpkt[1]; unsigned char seen = 0; /* XXX: cannot work this way, it takes only this packet into consideration. What if player info is spread across multiple packets? */ // type + no_players + some unknown preamble rawpkt += 3; while ( rawpkt < end && seen < no_players ) { struct player *player; // Player Number rawpkt += 4; // Create a player if ( NULL == ( player = add_player( server, server->n_player_info ) ) ) { return 0; } // Name ( min 3 bytes ) player->name = ut2003_strdup( rawpkt, end, &rawpkt ); // Ping player->ping = swap_long_from_little( rawpkt ); rawpkt += 4; // Frags player->frags = (unsigned char)rawpkt[0]; rawpkt++; // unknown rawpkt++; seen++; } if ( no_players == seen ) { // all done server->num_players = server->n_player_info; return 1; } // possibly more to come return 0; } STATIC int ut2003_player_packet( struct qserver *server, char *rawpkt, char *end) { // skip type rawpkt++; switch ( server->protocol_version ) { case 0x7e: // XMP packet //fprintf( stderr, "XMP packet\n" ); while ( rawpkt < end ) { struct player *player; char *var, *val; unsigned char no_props; if ( rawpkt + 24 > end ) { malformed_packet( server, "player info too short" ); rawpkt = end; return 1; } // Player Number never set rawpkt += 4; // Player ID never set rawpkt += 4; if ( NULL == ( player = add_player( server, server->n_player_info ) ) ) { return 0; } // Name ( min 3 bytes ) player->name = ut2003_strdup( rawpkt, end, &rawpkt ); // Ping player->ping = swap_long_from_little( rawpkt ); rawpkt += 4; // Frags player->frags = swap_long_from_little( rawpkt ); rawpkt += 4; // Stat ID never set rawpkt += 4; // Player properties no_props = rawpkt[0]; //fprintf( stderr, "noprops %d\n", no_props ); rawpkt++; while( rawpkt < end && no_props > 0 ) { if ( NULL == ( var = ut2003_strdup( rawpkt, end, &rawpkt ) ) ) { break; } if ( NULL == ( val = ut2003_strdup( rawpkt, end, &rawpkt ) ) ) { break; } //fprintf( stderr, "attrib: %s = %s\n", var, val ); // Things we can use if ( 0 == strcmp( var, "team" ) ) { player->team_name = val; } else if ( 0 == strcmp( var, "class" ) ) { player->skin = val; } else { free( val ); } free( var ); no_props--; } } break; default: while ( rawpkt < end ) { struct player *player; if(rawpkt+4 > end) { malformed_packet(server, "player packet too short"); return 1; } if ( NULL == ( player = add_player( server, swap_long_from_little(rawpkt) ) ) ) { return 0; } player->name = ut2003_strdup( rawpkt+4, end, &rawpkt ); if(rawpkt+8 > end) { malformed_packet(server, "player packet too short"); return 1; } player->ping = swap_long_from_little(rawpkt); rawpkt+= 4; player->frags = swap_long_from_little(rawpkt); rawpkt+= 4; { unsigned team = swap_long_from_little(rawpkt); rawpkt+= 4; player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; if(team & 1<<29) player->team_name = "red"; else if(team & 1<<30) player->team_name = "blue"; } } } return 0; } char * get_rule( struct qserver *server, char *name) { struct rule *rule; rule= server->rules; for ( ; rule != NULL; rule= rule->next) { if ( strcmp( name, rule->name) == 0) return rule->value; } return NULL; } void deal_with_ut2003_packet( struct qserver *server, char *rawpkt, int pktlen) { // For protocol spec see: // http://unreal.student.utwente.nl/UT2003-queryspec.html char *end; int error = 0, before; unsigned int packet_header; rawpkt[pktlen]= '\0'; end = &rawpkt[pktlen]; packet_header = swap_long_from_little( &rawpkt[0] ); rawpkt += 4; server->protocol_version = packet_header; if ( packet_header != 0x77 // Pariah Demo? && packet_header != 0x78 // UT2003 Demo && packet_header != 0x79 // UT2003 Retail && packet_header != 0x7e // Unreal2 XMP && packet_header != 0x7f // UT2004 Demo && packet_header != 0x80 // UT2004 Retail ) { malformed_packet(server, "Unknown type 0x%x", packet_header); } switch( rawpkt[0] ) { case 0x00: // Server info if ( server->server_name == NULL ) { server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); } error = ut2003_basic_packet( server, rawpkt, end ); if ( ! error ) { if(get_server_rules || get_player_info) { int requests = server->n_requests; server->next_rule = ""; server->retry1 = n_retries; server->retry2 = 0; // don't wait for player packet send_rule_request_packet( server); server->n_requests = requests; // would produce wrong ping } } break; case 0x01: // Game info ut2003_rule_packet( server, rawpkt, end ); server->next_rule = ""; server->retry1 = 0; /* we received at least one rule packet so no need to retry. We'd get double entries otherwise. */ break; case 0x02: // Player info before = server->n_player_info; error = ut2003_player_packet( server, rawpkt, end); if (before == server->n_player_info ) { error = 1; } break; case 0x10: // Pariah Server info if ( server->server_name == NULL ) { server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); } error = pariah_basic_packet( server, rawpkt, end ); if ( ! error ) { // N.B. pariah always sends a rules and players packet int requests = server->n_requests; server->next_rule = ""; server->retry1 = n_retries; server->retry2 = 0; server->n_requests = requests; // would produce wrong ping } break; case 0x11: // Game info pariah_rule_packet( server, rawpkt, end ); server->retry1 = 0; /* we received at least one rule packet so no need to retry. We'd get double entries otherwise. */ break; case 0x12: // Player info before = server->n_player_info; pariah_player_packet( server, rawpkt, end ); if ( before == server->n_player_info ) { error = 1; } break; default: malformed_packet(server, "Unknown packet type 0x%x", (unsigned)rawpkt[0]); break; } /* don't cleanup if we fetch server rules. We would lose * rule packets as we don't know how many we get * We do clean up if we don't fetch server rules so we don't * need to wait for timeout. */ if (error || (!get_server_rules && !get_player_info) || (!get_server_rules && server->num_players == server->n_player_info) || (server->next_rule == NULL && server->num_players == server->n_player_info)) { cleanup_qserver( server, 1 ); } } int deal_with_unrealmaster_packet( struct qserver *server, char *rawpkt, int pktlen) { if ( pktlen == 0) { cleanup_qserver( server, 1); return 0; } print_packet( server, rawpkt, pktlen); puts( "--"); return 0; } /* Returns 1 if the query is done (server may be freed) and 0 if not. */ int deal_with_halflife_packet( struct qserver *server, char *rawpkt, int pktlen) { char *pkt; char *end= &rawpkt[pktlen]; int pkt_index= 0, pkt_max= 0; char number[16]; short pkt_id; if ( server->server_name == NULL) server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); if ( pktlen < 5) return cleanup_qserver( server, 1); if ( ((rawpkt[0] != '\377' && rawpkt[0] != '\376') || rawpkt[1] != '\377' || rawpkt[2] != '\377' || rawpkt[3] != '\377') && show_errors) { unsigned int ipaddr= ntohl(server->ipaddr); fprintf( stderr, "Odd packet from server %d.%d.%d.%d:%hu, processing ...\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff, ntohs(server->port)); print_packet( server, rawpkt, pktlen); } if ( ((unsigned char*)rawpkt)[0] == 0xfe) { SavedData *sdata; pkt_index= ((unsigned char*)rawpkt)[8] >> 4; pkt_max= ((unsigned char*)rawpkt)[8] & 0xf; memcpy( &pkt_id, &rawpkt[4], 2); if ( server->saved_data.data == NULL) sdata= & server->saved_data; else { sdata= (SavedData*) calloc( 1, sizeof(SavedData)); sdata->next= server->saved_data.next; server->saved_data.next= sdata; } sdata->pkt_index= pkt_index; sdata->pkt_max= pkt_max; sdata->pkt_id= pkt_id; sdata->datalen= pktlen-9; sdata->data= (char*) malloc( pktlen-9); memcpy( sdata->data, &rawpkt[9], pktlen-9); /* combine_packets will call us recursively */ return combine_packets( server); /* fprintf( OF, "pkt_index %d pkt_max %d\n", pkt_index, pkt_max); rawpkt+= 9; pktlen-= 9; */ } /* 'info' response */ if ( rawpkt[4] == 'C' || rawpkt[4] == 'm') { if ( server->server_name != NULL) return 0; pkt= &rawpkt[5]; server->address= strdup( pkt); pkt+= strlen(pkt)+1; server->server_name= strdup( pkt); pkt+= strlen(pkt)+1; server->map_name= strdup( pkt); pkt+= strlen(pkt)+1; if ( *pkt) add_rule( server, "gamedir", pkt, NO_FLAGS); if ( *pkt && strcmp( pkt, "valve") != 0) { server->game= add_rule( server, "game", pkt, NO_FLAGS)->value; server->flags |= FLAG_DO_NOT_FREE_GAME; } pkt+= strlen(pkt)+1; if ( *pkt) add_rule( server, "gamename", pkt, NO_FLAGS); pkt+= strlen(pkt)+1; server->num_players= (unsigned int)pkt[0]; server->max_players= (unsigned int)pkt[1]; pkt+= 2; if ( pkt < end) { int protocol= *((unsigned char *)pkt); sprintf( number, "%d", protocol); add_rule( server, "protocol", number, NO_FLAGS); pkt++; } if ( rawpkt[4] == 'm') { if ( *pkt == 'd') add_rule( server, "sv_type", "dedicated", NO_FLAGS); else if ( *pkt == 'l') add_rule( server, "sv_type", "listen", NO_FLAGS); else add_rule( server, "sv_type", "?", NO_FLAGS); pkt++; if ( *pkt == 'w') add_rule( server, "sv_os", "windows", NO_FLAGS); else if ( *pkt == 'l') add_rule( server, "sv_os", "linux", NO_FLAGS); else { char str[2]= "\0"; str[0]= *pkt; add_rule( server, "sv_os", str, NO_FLAGS); } pkt++; add_rule( server, "sv_password", *pkt ? "1" : "0", NO_FLAGS); pkt++; add_rule( server, "mod", *pkt ? "1" : "0", NO_FLAGS); if ( *pkt) { int n; /* pull out the mod infomation */ pkt++; add_rule( server, "mod_info_url", pkt, NO_FLAGS); pkt+= strlen( pkt)+1; if ( *pkt) add_rule( server, "mod_download_url", pkt, NO_FLAGS); pkt+= strlen( pkt)+1; if ( *pkt) add_rule( server, "mod_detail", pkt, NO_FLAGS); pkt+= strlen( pkt)+1; n= swap_long_from_little( pkt); sprintf( number, "%d", n); add_rule( server, "modversion", number, NO_FLAGS); pkt+= 4; n= swap_long_from_little( pkt); sprintf( number, "%d", n); add_rule( server, "modsize", number, NO_FLAGS); pkt+= 4; add_rule( server, "svonly", *pkt ? "1" : "0", NO_FLAGS); pkt++; add_rule( server, "cldll", *pkt ? "1" : "0", NO_FLAGS); pkt++; if ( pkt < end) add_rule( server, "secure", *pkt ? "1" : "0", NO_FLAGS); } } if ( get_player_info && server->num_players) { int requests = server->n_requests; server->next_player_info= server->num_players-1; send_player_request_packet( server); server->n_requests = requests; // prevent wrong ping } if ( get_server_rules) { int requests = server->n_requests; server->next_rule= ""; server->retry1= n_retries; send_rule_request_packet( server); server->n_requests = requests; // prevent wrong ping } } /* 'players' response */ else if ( rawpkt[4] == 'D' && server->players == NULL) { unsigned int n= 0, temp; struct player *player; struct player **last_player= & server->players; if ( (unsigned int)rawpkt[5] > server->num_players) server->num_players= (unsigned int)rawpkt[5]; pkt= &rawpkt[6]; rawpkt[pktlen]= '\0'; while (1) { if ( *pkt != n+1) break; n++; pkt++; player= (struct player*) calloc( 1, sizeof(struct player)); player->name= strdup( pkt); pkt+= strlen(pkt)+1; memcpy( &player->frags, pkt, 4); pkt+= 4; memcpy( &temp, pkt, 4); pkt+= 4; if ( big_endian) { player->frags= swap_long( &player->frags); } player->connect_time= swap_float_from_little(&temp); *last_player= player; last_player= & player->next; } if ( n > server->num_players) server->num_players= n; server->next_player_info= server->num_players; } /* 'rules' response */ else if ( rawpkt[4] == 'E' && server->next_rule != NULL) { int n= 0; n= ((unsigned char*)rawpkt)[5] + ((unsigned char *)rawpkt)[6]*256; pkt= &rawpkt[7]; while ( n) { char *key= pkt; char *value; pkt+= strlen(pkt)+1; if ( pkt > end) break; value= pkt; pkt+= strlen(pkt)+1; if ( pkt > end) break; if ( key[0] == 's' && strcmp( key, "sv_password") == 0) add_rule( server, key, value, CHECK_DUPLICATE_RULES); else add_rule( server, key, value, NO_FLAGS); n--; } server->next_rule= NULL; } else if ( rawpkt[4] != 'E' && rawpkt[4] != 'D' && rawpkt[4] != 'm' && rawpkt[4] != 'C' && show_errors) { /* if ( pkt_count) { rawpkt-= 9; pktlen+= 9; } */ fprintf( stderr, "Odd packet from HL server %s (packet len %d)\n", server->arg, pktlen); print_packet( server, rawpkt, pktlen); } return cleanup_qserver( server, 0); } static int tribes_debug= 0; void deal_with_tribes_packet( struct qserver *server, char *rawpkt, int pktlen) { unsigned char *pkt, *end; int len, pnum, ping, packet_loss, n_teams, t; struct player *player; struct player **teams= NULL; struct player **last_player= & server->players; char buf[24]; if ( server->server_name == NULL) { server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); } else { gettimeofday( &server->packet_time1, NULL); } if ( pktlen < sizeof( tribes_info_reponse)) { cleanup_qserver( server, 1); return; } if ( strncmp( rawpkt, tribes_players_reponse, sizeof( tribes_players_reponse)) != 0) { cleanup_qserver( server, 1); return; } pkt= (unsigned char*) &rawpkt[sizeof( tribes_info_reponse)]; len= *pkt; /* game name: "Tribes" */ add_nrule( server, "gamename", (char*)pkt+1, len); pkt+= len+1; len= *pkt; /* version */ add_nrule( server, "version", (char*)pkt+1, len); pkt+= len+1; len= *pkt; /* server name */ server->server_name= strndup( (char*)pkt+1, len); pkt+= len+1; add_rule( server, "dedicated", *pkt?"1":"0", NO_FLAGS); pkt++; /* flag: dedicated server */ add_rule( server, "needpass", *pkt?"1":"0", NO_FLAGS); pkt++; /* flag: password on server */ server->num_players= *pkt++; server->max_players= *pkt++; sprintf( buf, "%u", (unsigned int)pkt[0] + (unsigned int)pkt[1]*256); add_rule( server, "cpu", buf, NO_FLAGS); pkt++; /* cpu speed, lsb */ pkt++; /* cpu speed, msb */ len= *pkt; /* Mod (game) */ add_nrule( server, "mods", (char*)pkt+1, len); pkt+= len+1; len= *pkt; /* game (mission): "C&H" */ add_nrule( server, "game", (char*)pkt+1, len); pkt+= len+1; len= *pkt; /* Mission (map) */ server->map_name= strndup( (char*)pkt+1, len); pkt+= len+1; len= *pkt; /* description (contains Admin: and Email: ) */ if ( tribes_debug) printf( "%.*s\n", len, pkt+1); pkt+= len+1; n_teams= *pkt++; /* number of teams */ if ( n_teams == 255) { cleanup_qserver( server, 1); return; } sprintf( buf, "%d", n_teams); add_rule( server, "numteams", buf, NO_FLAGS); len= *pkt; /* first title */ if ( tribes_debug) printf( "%.*s\n", len, pkt+1); pkt+= len+1; len= *pkt; /* second title */ if ( tribes_debug) printf( "%.*s\n", len, pkt+1); pkt+= len+1; if ( n_teams > 1) { teams= (struct player**) calloc( 1, sizeof(struct player*) * n_teams); for ( t= 0; t < n_teams; t++) { teams[t]= (struct player*) calloc(1, sizeof(struct player)); teams[t]->number= TRIBES_TEAM; teams[t]->team= t; len= *pkt; /* team name */ teams[t]->name= strndup( (char*)pkt+1, len); if ( tribes_debug) printf( "team#0 <%.*s>\n", len, pkt+1); pkt+= len+1; len= *pkt; /* team score */ if ( len <= 2 && tribes_debug) printf( "%s score len %d\n", server->arg, len); if ( len > 2) { strncpy( buf, (char*)pkt+1+3, len-3); buf[len-3]= '\0'; } else buf[0]= '\0'; teams[t]->frags= atoi( buf); if ( tribes_debug) printf( "team#0 <%.*s>\n", len-3, pkt+1+3); pkt+= len+1; } } else { len= *pkt; /* DM team? */ if ( tribes_debug) printf( "%.*s\n", len, pkt+1); pkt+= len+1; pkt++; n_teams= 0; } pnum= 0; while ( (char*)pkt < (rawpkt+pktlen)) { ping= (unsigned int)*pkt << 2; pkt++; packet_loss= *pkt; pkt++; if ( tribes_debug) printf( "player#%d, team #%d\n", pnum, (int)*pkt); pkt++; len= *pkt; if ( (char*)pkt+len > (rawpkt+pktlen)) break; player= (struct player*) calloc( 1, sizeof(struct player)); player->team= pkt[-1]; if ( n_teams && player->team < n_teams) player->team_name= teams[player->team]->name; else if ( player->team == 255 && n_teams) player->team_name= "Unknown"; player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; player->ping= ping; player->packet_loss= packet_loss; player->name= strndup( (char*)pkt+1, len); if ( tribes_debug) printf( "player#%d, name %.*s\n", pnum, len, pkt+1); pkt+= len+1; len= *pkt; if ( tribes_debug) printf( "player#%d, info <%.*s>\n", pnum, len, pkt+1); end= (unsigned char*) strchr( (char*)pkt+9, 0x9); if ( end) { strncpy( buf, (char*)pkt+9, end-(pkt+9)); buf[end-(pkt+9)]= '\0'; player->frags= atoi( buf); if ( tribes_debug) printf( "player#%d, score <%.*s>\n", pnum, (unsigned)(end-(pkt+9)), pkt+9); } *last_player= player; last_player= & player->next; pkt+= len+1; pnum++; } for ( t= n_teams; t;) { t--; teams[t]->next= server->players; server->players= teams[t]; } free( teams); cleanup_qserver( server, 0); } void get_tribes2_player_type( struct player *player) { char *name= player->name; for ( ; *name; name++) { switch ( *name) { case 0x8: player->type_flag= PLAYER_TYPE_NORMAL; continue; case 0xc: player->type_flag= PLAYER_TYPE_ALIAS; continue; case 0xe: player->type_flag= PLAYER_TYPE_BOT; continue; case 0xb: break; default: continue; } name++; if ( isprint( *name)) { char *n= name; for ( ; isprint(*n); n++) ; player->tribe_tag= strndup( name, n-name); name= n; } if ( !*name) break; } } void deal_with_tribes2_packet( struct qserver *server, char *pkt, int pktlen) { char str[256], *pktstart= pkt, *term, *start; unsigned int minimum_net_protocol, build_version, i, t, len, s, status; unsigned int net_protocol; unsigned short cpu_speed; int n_teams= 0, n_players; struct player **teams= NULL, *player; struct player **last_player= & server->players; int query_version; pkt[pktlen]= '\0'; if ( server->server_name == NULL) server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); /* else gettimeofday( &server->packet_time1, NULL); */ if ( pkt[0] == TRIBES2_RESPONSE_PING) { if ( pkt[6] < 4 || pkt[6] > 12 || strncmp( pkt+7, "VER", 3) != 0) { cleanup_qserver( server, 1); return; } strncpy( str, pkt+10, pkt[6]-3); str[ pkt[6]-3]= '\0'; query_version= atoi( str); add_nrule(server,"queryversion", pkt+7, pkt[6]); pkt+= 7 + pkt[6]; server->protocol_version= query_version; if ( query_version != 3 && query_version != 5) { server->server_name= strdup( "Unknown query version"); cleanup_qserver( server, 1); return; } if ( query_version == 5) { net_protocol= swap_long_from_little( pkt); sprintf( str, "%u", net_protocol); add_rule(server,"net_protocol",str, NO_FLAGS); pkt+= 4; } minimum_net_protocol= swap_long_from_little( pkt); sprintf( str, "%u", minimum_net_protocol); add_rule(server,"minimum_net_protocol",str, NO_FLAGS); pkt+= 4; build_version= swap_long_from_little( pkt); sprintf( str, "%u", build_version); add_rule(server,"build_version",str, NO_FLAGS); pkt+= 4; server->server_name= strndup( pkt+1, *(unsigned char*)(pkt)); /* Always send the player request because the ping packet * contains very little information */ send_player_request_packet(server); return; } else if ( pkt[0] != TRIBES2_RESPONSE_INFO) { cleanup_qserver( server, 1); return; } pkt+= 6; for ( i= 0; i < *(unsigned char *)pkt; i++) if ( !isprint(pkt[i+1])) { cleanup_qserver( server, 1); return; } add_nrule( server, server->type->game_rule, pkt+1, *(unsigned char *)pkt); server->game= strndup( pkt+1, *(unsigned char *)pkt); pkt+= *pkt + 1; add_nrule( server, "mission", pkt+1, *(unsigned char *)pkt); pkt+= *pkt + 1; server->map_name= strndup( pkt+1, *(unsigned char *)pkt); pkt+= *pkt + 1; status= *(unsigned char *)pkt; sprintf( str, "%u", status); add_rule( server, "status", str, NO_FLAGS); if ( status & TRIBES2_STATUS_DEDICATED) add_rule( server, "dedicated", "1", NO_FLAGS); if ( status & TRIBES2_STATUS_PASSWORD) add_rule( server, "password", "1", NO_FLAGS); if ( status & TRIBES2_STATUS_LINUX) add_rule( server, "linux", "1", NO_FLAGS); if ( status & TRIBES2_STATUS_TEAMDAMAGE) add_rule( server, "teamdamage", "1", NO_FLAGS); if ( server->protocol_version == 3) { if ( status & TRIBES2_STATUS_TOURNAMENT_VER3) add_rule( server, "tournament", "1", NO_FLAGS); if ( status & TRIBES2_STATUS_NOALIAS_VER3) add_rule( server, "no_aliases", "1", NO_FLAGS); } else { if ( status & TRIBES2_STATUS_TOURNAMENT) add_rule( server, "tournament", "1", NO_FLAGS); if ( status & TRIBES2_STATUS_NOALIAS) add_rule( server, "no_aliases", "1", NO_FLAGS); } pkt++; server->num_players= *(unsigned char *)pkt; pkt++; server->max_players= *(unsigned char *)pkt; pkt++; sprintf( str, "%u", *(unsigned char *)pkt); add_rule( server, "bot_count", str, NO_FLAGS); pkt++; cpu_speed= swap_short_from_little( pkt); sprintf( str, "%hu", cpu_speed); add_rule( server, "cpu_speed", str, NO_FLAGS); pkt+= 2; if ( strcmp( server->server_name, "VER3") == 0) { free( server->server_name); server->server_name= strndup( pkt+1, *(unsigned char*)pkt); } else add_nrule( server, "info", pkt+1, *(unsigned char*)pkt); pkt+= *(unsigned char*)pkt + 1; len= swap_short_from_little( pkt); pkt+= 2; start= pkt; if ( len+(pkt-pktstart) > pktlen) len-= (len+(pkt-pktstart)) - pktlen; if ( len == 0 || pkt-pktstart >= pktlen) goto info_done; term= strchr( pkt, 0xa); if ( !term) goto info_done; *term= '\0'; n_teams= atoi( pkt); sprintf( str, "%d", n_teams); add_rule( server, "numteams", str, NO_FLAGS); pkt= term + 1; if ( pkt-pktstart >= pktlen) goto info_done; teams= (struct player**) calloc( 1, sizeof(struct player*) * n_teams); for ( t= 0; t < n_teams; t++) { teams[t]= (struct player*) calloc(1, sizeof(struct player)); teams[t]->number= TRIBES_TEAM; teams[t]->team= t; /* team name */ term= strchr( pkt, 0x9); if ( !term) { n_teams= t; goto info_done; } teams[t]->name= strndup( pkt, term-pkt); pkt= term+1; term= strchr( pkt, 0xa); if ( !term) { n_teams= t; goto info_done; } *term='\0'; teams[t]->frags= atoi(pkt); pkt= term+1; if ( pkt-pktstart >= pktlen) goto info_done; } term= strchr( pkt, 0xa); if ( !term || term-start >= len) goto info_done; *term= '\0'; n_players= atoi( pkt); pkt= term + 1; for ( i= 0; i < n_players && pkt-start < len; i++) { pkt++; /* skip first byte (0x10) */ if ( pkt-start >= len) break; player= (struct player*) calloc( 1, sizeof(struct player)); term= strchr( pkt, 0x11); if ( !term || term-start >= len) { free( player); break; } player->name= strndup( pkt, term-pkt); get_tribes2_player_type( player); pkt= term+1; pkt++; /* skip 0x9 */ if ( pkt-start >= len) break; term= strchr( pkt, 0x9); if ( !term || term-start >= len) { free( player->name); free( player); break; } for ( t= 0; t < n_teams; t++) { if ( term-pkt == strlen(teams[t]->name) && strncmp( pkt, teams[t]->name, term-pkt) == 0) break; } if ( t == n_teams) { player->team= -1; player->team_name= "Unassigned"; } else { player->team= t; player->team_name= teams[t]->name; } player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; pkt= term+1; for ( s= 0; *pkt != 0xa && pkt-start < len; pkt++) str[s++]= *pkt; str[s]= '\0'; player->frags= atoi(str); if ( *pkt == 0xa) pkt++; *last_player= player; last_player= & player->next; } info_done: for ( t= n_teams; t;) { t--; teams[t]->next= server->players; server->players= teams[t]; } if ( teams) free( teams); cleanup_qserver( server, 1); return; } static const char GrPacketHead[]={'\xc0','\xde','\xf1','\x11'}; static const char PacketStart='\x42'; static char Dat2Reply1_2_10[]={'\xf4','\x03','\x14','\x02','\x0a','\x41','\x02','\x0a','\x41','\x00','\x00','\x78','\x30','\x63'}; static char Dat2Reply1_3[] ={'\xf4','\x03','\x14','\x03','\x05','\x41','\x03','\x05','\x41','\x00','\x00','\x78','\x30','\x63'}; static char Dat2Reply1_4[] ={'\xf4','\x03','\x14','\x04','\x00','\x41','\x04','\x00','\x41','\x00','\x00','\x78','\x30','\x63'}; //static char HDat2[]={'\xea','\x03','\x02','\x00','\x14'}; #define SHORT_GR_LEN 75 #define LONG_GR_LEN 500 #define UNKNOWN_VERSION 0 #define VERSION_1_2_10 1 #define VERSION_1_3 2 #define VERSION_1_4 3 void deal_with_ghostrecon_packet( struct qserver *server, char *pkt, int pktlen) { char str[256], *start, *end, StartFlag, *lpszIgnoreServerPlayer; char *lpszMission; unsigned int iIgnoreServerPlayer, iDedicatedServer, iUseStartTimer; unsigned short GrPayloadLen; int i; struct player *player; int iLen, iTemp; short sLen; int iSecsPlayed; long iSpawnType; int ServerVersion=UNKNOWN_VERSION; float flStartTimerSetPoint; start = pkt; end=&pkt[pktlen]; pkt[pktlen]= '\0'; /* This function walks a packet that is recieved from a ghost recon server - default from port 2348. It does quite a few sanity checks along the way as the structure is not documented. The packet is mostly binary in nature with many string fields being variable in length, ie the length is listed foloowed by that many bytes. There are two structure arrays that have an array size followed by structure size * number of elements (player name and player data). This routine walks this packet and increments a pointer "pkt" to extract the info. */ if ( server->server_name == NULL) server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); /* sanity check against packet */ if (memcmp(pkt,GrPacketHead,sizeof(GrPacketHead))!=0) { server->server_name= strdup( "Unknown Packet Header"); cleanup_qserver( server, 1); return; }; pkt += sizeof(GrPacketHead); StartFlag=pkt[0]; pkt += 1; if (StartFlag != 0x42) { server->server_name= strdup( "Unknown Start Flag"); cleanup_qserver( server, 1); return; }; /* compare packet length recieved to included size - header info */ sLen = swap_short_from_little(pkt); pkt += 2; GrPayloadLen = pktlen - sizeof(GrPacketHead) -3; // 3 = size slen + size start flag if (sLen != GrPayloadLen) { server->server_name= strdup( "Packet Size Mismatch"); cleanup_qserver( server, 1); return; }; /* Will likely need to verify and add to this "if" construct with every patch / add-on. */ if (memcmp(pkt, Dat2Reply1_2_10, sizeof(Dat2Reply1_2_10)) == 0) ServerVersion=VERSION_1_2_10; else if (memcmp(pkt, Dat2Reply1_3, sizeof(Dat2Reply1_3)) == 0) ServerVersion=VERSION_1_3; else if (memcmp(pkt, Dat2Reply1_4, sizeof(Dat2Reply1_4)) == 0) ServerVersion=VERSION_1_4; if (ServerVersion == UNKNOWN_VERSION) { server->server_name= strdup( "Unknown GR Version"); cleanup_qserver( server, 1); return; }; switch (ServerVersion) { case VERSION_1_2_10: { strcpy(str,"1.2.10"); pkt+=sizeof(Dat2Reply1_2_10); break; }; case VERSION_1_3: { strcpy(str,"1.3"); pkt+=sizeof(Dat2Reply1_3); break; }; case VERSION_1_4: { strcpy(str,"1.4"); pkt+=sizeof(Dat2Reply1_4); break; }; }; add_rule(server, "patch", str, NO_FLAGS); /* have player packet */ // Ghost recon has one of the player slots filled up with the server program itself. By default we will // drop the first player listed. This causes a bit of a mess here and below but makes for the best display // a user can specify -grs,ignoreserverplayer=no to override this behaviour. lpszIgnoreServerPlayer = get_param_value( server, "ignoreserverplayer", "yes"); for (i=0; i<4; i++) str[i]=tolower(lpszIgnoreServerPlayer[i]); if (strcmp(str,"yes")==0)iIgnoreServerPlayer=1; else iIgnoreServerPlayer=0; pkt+=4; /* unknown */ // this is the first of many variable strings. get the length, // increment pointer over length, check for sanity, // get the string, increment the pointer over string (using length) iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >SHORT_GR_LEN)) { server->server_name= strdup( "Server Name too Long"); cleanup_qserver(server, 1); return; }; server->server_name = strndup( pkt, iLen); pkt += iLen; iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >SHORT_GR_LEN)) { add_rule(server, "error", "Map Name too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; server->map_name = strndup( pkt, iLen); pkt += iLen; iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >SHORT_GR_LEN)) { add_rule(server, "error", "Mission Name too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; /* mission does not make sense unless a coop game type. Since we dont know that now, we will save the mission and set the rule and free memory below when we know game type */ lpszMission = strndup( pkt, iLen); pkt += iLen; iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >SHORT_GR_LEN)) { add_rule(server, "error", "Mission Type too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; add_nrule( server, "missiontype", pkt, iLen); pkt += iLen; if ( pkt[1]) { add_rule( server, "password", "Yes", NO_FLAGS); } else { add_rule( server, "password", "No", NO_FLAGS); }; pkt += 2; server->max_players= swap_long_from_little(pkt); pkt += 4; if (server->max_players > 36) { add_rule(server, "error", "Max players more then 36", NO_FLAGS); cleanup_qserver(server, 1); return; }; server->num_players= swap_long_from_little(pkt); pkt += 4; if (server->num_players > server->max_players) { add_rule(server, "error", "More then MAX Players", NO_FLAGS); cleanup_qserver(server, 1); return; }; if (iIgnoreServerPlayer) // skip past first player { server->num_players--; server->max_players--; iLen = swap_long_from_little(pkt); pkt += 4; pkt += iLen; }; for (i=0;inum_players;i++) // read each player name { iLen = swap_long_from_little(pkt); pkt += 4; player= (struct player*) calloc( 1, sizeof(struct player)); if ((iLen<1) || (iLen >SHORT_GR_LEN)) { add_rule(server, "error", "Player Name too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; player->name= strndup( pkt, iLen); pkt += iLen; /* player name */ player->team= i; // tag so we can find this record when we have player dat. player->team_name= "Unassigned"; player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; player->frags=0; player->next= server->players; server->players= player; }; pkt += 17; iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >SHORT_GR_LEN)) { add_rule(server, "error", "Version too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; strncpy(str,pkt,iLen); add_rule( server, "version", str, NO_FLAGS); pkt += iLen; /* version */ iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >LONG_GR_LEN)) { add_rule(server, "error", "Mods too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; server->game= strndup( pkt, iLen); for (i=0;i<(int)strlen(server->game)-5;i++) // clean the "/mods/" part from every entry { if (memcmp(&server->game[i],"\\mods\\",6)==0) { server->game[i]=' '; strcpy(&server->game[i+1],&server->game[i+6]); }; }; add_rule(server, "game", server->game, NO_FLAGS); pkt += iLen; /* mods */ iDedicatedServer=pkt[0]; if ( iDedicatedServer) add_rule( server, "dedicated", "Yes", NO_FLAGS); else add_rule( server, "dedicated", "No", NO_FLAGS); pkt += 1; /* unknown */ iSecsPlayed = swap_float_from_little(pkt); add_rule(server, "timeplayed", play_time(iSecsPlayed,2), NO_FLAGS); pkt += 4; /* time played */ switch (pkt[0]) { case 3 : strcpy(str,"Joining"); break; case 4 : strcpy(str,"Playing"); break; case 5 : strcpy(str,"Debrief"); break; default : strcpy(str,"Undefined"); }; add_rule( server, "status", str, NO_FLAGS); pkt += 1; pkt += 3; /* unknown */ switch (pkt[0]) { case 2: strcpy(str,"COOP"); break; case 3: strcpy(str,"SOLO"); break; case 4: strcpy(str,"TEAM"); break; default: sprintf(str,"UNKOWN %u",pkt[0]); break; }; add_rule( server, "gamemode", str, NO_FLAGS); if (pkt[0]==2) add_rule( server, "mission", lpszMission, NO_FLAGS); else add_rule( server, "mission", "No Mission", NO_FLAGS); free(lpszMission); pkt += 1; /* Game Mode */ pkt += 3; /* unknown */ iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >LONG_GR_LEN)) { add_rule(server, "error", "MOTD too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; strncpy(str,pkt,sizeof(str)); str[sizeof(str)-1]=0; add_rule(server, "motd", str, NO_FLAGS); pkt += iLen; /* MOTD */ iSpawnType = swap_long_from_little(pkt); switch (iSpawnType) { case 0: strcpy(str,"None"); break; case 1: strcpy(str,"Individual"); break; case 2: strcpy(str,"Team"); break; case 3: strcpy(str,"Infinite"); break; default:strcpy(str,"Unknown"); }; add_rule( server, "spawntype", str, NO_FLAGS); pkt += 4; /* spawn type */ iTemp = swap_float_from_little(pkt); add_rule(server, "gametime", play_time(iTemp,2), NO_FLAGS); iTemp = iTemp-iSecsPlayed; if (iTemp <= 0) iTemp=0; add_rule(server, "remainingtime", play_time(iTemp,2), NO_FLAGS); pkt += 4; /* Game time */ iTemp = swap_long_from_little(pkt); if (iIgnoreServerPlayer) { iTemp--; }; if (iTemp != server->num_players) { add_rule(server, "error", "Number of Players Mismatch", NO_FLAGS); }; pkt += 4; /* player count 2 */ if (iIgnoreServerPlayer) { pkt+=5; // skip first player data }; for (i=0;inum_players;i++) // for each player get binary data { player=server->players; // first we must find the player - lets look for the tag while (player && (player->team != i)) player=player->next; /* get to player - linked list is in reverse order */ if (player) { player->team= pkt[2]; switch (player->team) { case 1: player->team_name= "Red"; break; case 2: player->team_name= "Blue"; break; case 3: player->team_name= "Yellow"; break; case 4: player->team_name= "Green"; break; case 5: player->team_name= "Unassigned"; break; default: player->team_name= "Not Known"; break; }; player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; player->deaths=pkt[1]; }; pkt += 5; /* player data*/ }; for (i=0;i<5;i++) { pkt += 8; /* team data who knows what they have in here */ }; pkt +=1; iUseStartTimer=pkt[0]; // UseStartTimer pkt +=1; iTemp = flStartTimerSetPoint = swap_float_from_little(pkt);// Start Timer Set Point pkt += 4; if (iUseStartTimer) { add_rule( server, "usestarttime", "Yes", NO_FLAGS); add_rule( server, "starttimeset", play_time(iTemp,2), NO_FLAGS); } else { add_rule( server, "usestarttime", "No", NO_FLAGS); add_rule( server, "starttimeset", play_time(0,2), NO_FLAGS); }; if ((ServerVersion == VERSION_1_3) || // stuff added in patch 1.3 (ServerVersion == VERSION_1_4)) { iTemp = swap_float_from_little(pkt);// Debrief Time add_rule( server, "debrieftime", play_time(iTemp,2), NO_FLAGS); pkt += 4; iTemp = swap_float_from_little(pkt);// Respawn Min add_rule( server, "respawnmin", play_time(iTemp,2), NO_FLAGS); pkt += 4; iTemp = swap_float_from_little(pkt);// Respawn Max add_rule( server, "respawnmax", play_time(iTemp,2), NO_FLAGS); pkt += 4; iTemp = swap_float_from_little(pkt);// Respawn Invulnerable add_rule( server, "respawnsafe", play_time(iTemp,2), NO_FLAGS); pkt += 4; } else { add_rule( server, "debrieftime", "Undefined", NO_FLAGS); add_rule( server, "respawnmin", "Undefined", NO_FLAGS); add_rule( server, "respawnmax", "Undefined", NO_FLAGS); add_rule( server, "respawnsafe", "Undefined", NO_FLAGS); }; pkt+=4; // 4 iTemp=pkt[0]; // Spawn Count if ((iSpawnType == 1) || (iSpawnType == 2)) /* Individual or team */ sprintf( str, "%u", iTemp); else /* else not used */ sprintf( str, "%u", 0); add_rule( server, "spawncount", str, NO_FLAGS); pkt += 1; // 5 pkt +=4; // 9 iTemp=pkt[0]; // Allow Observers if (iTemp) strcpy( str, "Yes"); else /* else not used */ strcpy( str, "No"); add_rule( server, "allowobservers", str, NO_FLAGS); pkt +=1; // 10 pkt +=3; // 13 // pkt += 13; if (iUseStartTimer) { iTemp=swap_float_from_little(pkt); // Start Timer Count add_rule( server, "startwait", play_time(iTemp,2), NO_FLAGS); } else { add_rule( server, "startwait", play_time(0,2), NO_FLAGS); }; pkt += 4; //17 iTemp = pkt[0]; // IFF switch (iTemp) { case 0 : strcpy(str,"None"); break; case 1 : strcpy(str,"Reticule"); break; case 2 : strcpy(str,"Names"); break; default : strcpy(str,"Unknown"); break; }; add_rule( server, "iff", str, NO_FLAGS); pkt += 1; // 18 iTemp = pkt [0]; // Threat Indicator if (iTemp) add_rule(server, "ti", "ON ", NO_FLAGS); else add_rule(server, "ti", "OFF", NO_FLAGS); pkt += 1; // 19 pkt += 5; // 24 iLen = swap_long_from_little(pkt); pkt += 4; if ((iLen<1) || (iLen >SHORT_GR_LEN) ) { add_rule(server, "error", "Restrictions too Long", NO_FLAGS); cleanup_qserver(server, 1); return; }; add_rule( server, "restrict", pkt, NO_FLAGS); pkt += iLen; /* restrictions */ pkt += 23; /* if ( ghostrecon_debug) print_packet( pkt, GrPayloadLen); */ cleanup_qserver( server, 1); return; } char* find_ravenshield_game( char *gameno ) { switch( atoi( gameno ) ) { case 8: return strdup( "Team Deathmatch" ); break; case 13: return strdup( "Deathmatch" ); break; case 14: return strdup( "Team Deathmatch" ); break; case 15: return strdup( "Bomb" ); break; case 16: return strdup( "Escort Pilot" ); break; default: // 1.50 and above actually uses a string so // return that return strdup( gameno ); break; } } char* find_savage_game( char *gametype ) { if ( 0 == strcmp( "RTSS", gametype ) ) { return strdup( "RTSS" ); } else { return strdup( "Unknown" ); } } void deal_with_ravenshield_packet( struct qserver *server, char *rawpkt, int pktlen) { char *s, *key, *value; server->n_servers++; if ( NULL == server->server_name ) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL ); } rawpkt[pktlen]= '\0'; s = rawpkt; while ( *s ) { // Find the seperator while ( *s && *s != '\xB6' ) { s++; } if ( !*s ) { // Hit the end no more break; } // key start key = ++s; while ( *s && *s != ' ' ) { s++; } if ( *s != ' ') { // malformed break; } *s++ = '\0'; // key end // value start value = s; while ( *s && *s != '\xB6' ) { s++; } if ( *s == '\xB6' ) { *(s-1) = '\0'; } // Decode current key par if ( 0 == strcmp( "A1", key ) ) { // Max players server->max_players = atoi( value ); } else if ( 0 == strcmp( "A2", key ) ) { // TeamKillerPenalty add_rule( server, "TeamKillerPenalty", value, NO_FLAGS ); } else if ( 0 == strcmp( "B1", key ) ) { // Current players server->num_players = atoi( value ); } else if ( 0 == strcmp( "B2", key ) ) { // AllowRadar add_rule( server, "AllowRadar", value, NO_FLAGS ); } else if ( 0 == strcmp( "D2", key ) ) { // Version info add_rule( server, "Version", value, NO_FLAGS ); } else if ( 0 == strcmp( "E1", key ) ) { // Current map server->map_name = strdup( value ); } else if ( 0 == strcmp( "E2", key ) ) { // Unknown } else if ( 0 == strcmp( "F1", key ) ) { // Game type server->game = find_ravenshield_game( value ); add_rule( server, server->type->game_rule, server->game, NO_FLAGS ); } else if ( 0 == strcmp( "F2", key ) ) { // Unknown } else if ( 0 == strcmp( "G1", key ) ) { // Password add_rule( server, "Password", value, NO_FLAGS ); } else if ( 0 == strcmp( "G2", key ) ) { // Query port } else if ( 0 == strcmp( "H1", key ) ) { // Unknown } else if ( 0 == strcmp( "H2", key ) ) { // Number of Terrorists add_rule( server, "nbTerro", value, NO_FLAGS ); } else if ( 0 == strcmp( "I1", key ) ) { // Server name server->server_name = strdup( value ); } else if ( 0 == strcmp( "I2", key ) ) { // Unknown } else if ( 0 == strcmp( "J1", key ) ) { // Game Type Order // Not pretty ignore for now //add_rule( server, "Game Type Order", value, NO_FLAGS ); } else if ( 0 == strcmp( "J2", key ) ) { // RotateMap add_rule( server, "RotateMap", value, NO_FLAGS); } else if ( 0 == strcmp( "K1", key ) ) { // Map Cycle // Not pretty ignore for now //add_rule( server, "Map Cycle", value, NO_FLAGS ); } else if ( 0 == strcmp( "K2", key ) ) { // Force First Person Weapon add_rule( server, "ForceFPersonWeapon", value, NO_FLAGS); } else if ( 0 == strcmp( "L1", key ) ) { // Players names int player_number = 0; char *n = value; if ( *n == '/' ) { // atleast 1 player n++; while( *n && *n != '\xB6' ) { char *player_name = n; while ( *n && *n != '/' && *n != '\xB6' ) { n++; } if ( *n == '/' ) { *n++ = '\0'; } else if ( *n == '\xB6' ) { *(n-1) = '\0'; } if ( 0 != strlen( player_name ) ) { struct player *player = add_player( server, player_number ); if ( NULL != player ) { player->name = strdup( player_name ); } player_number++; } } } } else if ( 0 == strcmp( "L3", key ) ) { // PunkBuster state add_rule( server, "PunkBuster", value, NO_FLAGS ); } else if ( 0 == strcmp( "M1", key ) ) { // Players times int player_number = 0; char *n = value; if ( *n == '/' ) { // atleast 1 player n++; while( *n && *n != '\xB6' ) { char *time = n; while ( *n && *n != '/' && *n != '\xB6' ) { n++; } if ( *n == '/' ) { *n++ = '\0'; } else if ( *n == '\xB6' ) { *(n-1) = '\0'; } if ( 0 != strlen( time ) ) { int mins, seconds; if ( 2 == sscanf( time, "%d:%d", &mins, &seconds ) ) { struct player *player = get_player_by_number( server, player_number ); if ( NULL != player ) { player->connect_time = mins * 60 + seconds; } } player_number++; } } } } else if ( 0 == strcmp( "N1", key ) ) { // Players ping int player_number = 0; char *n = value; if ( *n == '/' ) { // atleast 1 player n++; while( *n && *n != '\xB6' ) { char *ping = n; while ( *n && *n != '/' && *n != '\xB6' ) { n++; } if ( *n == '/' ) { *n++ = '\0'; } else if ( *n == '\xB6' ) { *(n-1) = '\0'; } if ( 0 != strlen( ping ) ) { struct player *player = get_player_by_number( server, player_number ); if ( NULL != player ) { player->ping = atoi( ping ); } player_number++; } } } } else if ( 0 == strcmp( "O1", key ) ) { // Players fags int player_number = 0; char *n = value; if ( *n == '/' ) { // atleast 1 player n++; while( *n && *n != '\xB6' ) { char *frags = n; while ( *n && *n != '/' && *n != '\xB6' ) { n++; } if ( *n == '/' ) { *n++ = '\0'; } else if ( *n == '\xB6' ) { *(n-1) = '\0'; } if ( 0 != strlen( frags ) ) { struct player *player = get_player_by_number( server, player_number ); if ( NULL != player ) { player->frags = atoi( frags ); } player_number++; } } } } else if ( 0 == strcmp( "P1", key ) ) { // Game port // Not pretty ignore for now /* change_server_port( server, atoi( value ), 0 ); */ } else if ( 0 == strcmp( "Q1", key ) ) { // RoundsPerMatch add_rule( server, "RoundsPerMatch", value, NO_FLAGS ); } else if ( 0 == strcmp( "R1", key ) ) { // RoundTime add_rule( server, "RoundTime", value, NO_FLAGS ); } else if ( 0 == strcmp( "S1", key ) ) { // BetweenRoundTime add_rule( server, "BetweenRoundTime", value, NO_FLAGS ); } else if ( 0 == strcmp( "T1", key ) ) { // BombTime add_rule( server, "BombTime", value, NO_FLAGS ); } else if ( 0 == strcmp( "W1", key ) ) { // ShowNames add_rule( server, "ShowNames", value, NO_FLAGS ); } else if ( 0 == strcmp( "X1", key ) ) { // InternetServer add_rule( server, "InternetServer", value, NO_FLAGS ); } else if ( 0 == strcmp( "Y1", key ) ) { // FriendlyFire add_rule( server, "FriendlyFire", value, NO_FLAGS ); } else if ( 0 == strcmp( "Z1", key ) ) { // Autobalance add_rule( server, "Autobalance", value, NO_FLAGS ); } } cleanup_qserver( server, 1 ); return; } void deal_with_savage_packet( struct qserver *server, char *rawpkt, int pktlen) { char *s, *key, *value, *end; server->n_servers++; if ( NULL == server->server_name ) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL ); } rawpkt[pktlen]= '\0'; end = s = rawpkt; end += pktlen; while ( *s ) { // Find the seperator while ( s <= end && *s != '\xFF' ) { s++; } if ( s >= end ) { // Hit the end no more break; } // key start key = ++s; while ( s < end && *s != '\xFE' ) { s++; } if ( *s != '\xFE') { // malformed break; } *s++ = '\0'; // key end // value start value = s; while ( s < end && *s != '\xFF' ) { s++; } if ( *s == '\xFF' ) { *s = '\0'; } //fprintf( stderr, "'%s' = '%s'\n", key, value ); // Decode current key par if ( 0 == strcmp( "cmax", key ) ) { // Max players server->max_players = atoi( value ); } else if ( 0 == strcmp( "cnum", key ) ) { // Current players server->num_players = atoi( value ); } else if ( 0 == strcmp( "bal", key ) ) { // Balance add_rule( server, "Balance", value, NO_FLAGS ); } else if ( 0 == strcmp( "world", key ) ) { // Current map server->map_name = strdup( value ); } else if ( 0 == strcmp( "gametype", key ) ) { // Game type server->game = find_savage_game( value ); add_rule( server, server->type->game_rule, server->game, NO_FLAGS ); } else if ( 0 == strcmp( "pure", key ) ) { // Pure add_rule( server, "Pure", value, NO_FLAGS ); } else if ( 0 == strcmp( "time", key ) ) { // Current game time add_rule( server, "Time", value, NO_FLAGS ); } else if ( 0 == strcmp( "notes", key ) ) { // Notes add_rule( server, "Notes", value, NO_FLAGS ); } else if ( 0 == strcmp( "needcmdr", key ) ) { // Need Commander add_rule( server, "Need Commander", value, NO_FLAGS ); } else if ( 0 == strcmp( "name", key ) ) { // Server name server->server_name = strdup( value ); } else if ( 0 == strcmp( "fw", key ) ) { // Firewalled add_rule( server, "Firewalled", value, NO_FLAGS ); } else if ( 0 == strcmp( "players", key ) ) { // Players names int player_number = 0; int team_number = 1; char *team_name, *player_name, *n; n = team_name = value; // team name n++; while( *n && *n != '\x0a' ) { n++; } if ( *n != '\x0a' ) { // Broken data break; } *n = '\0'; player_name = ++n; while( *n ) { while( *n && *n != '\x0a' ) { n++; } if ( *n != '\x0a' ) { // Broken data break; } *n = '\0'; n++; if ( 0 == strncmp( "Team ", player_name, 5 ) ) { team_name = player_name; team_number++; } else { if ( 0 != strlen( player_name ) ) { struct player *player = add_player( server, player_number ); if ( NULL != player ) { player->name = strdup( player_name ); player->team = team_number; player->team_name = strdup( team_name ); } player_number++; } } player_name = n; } } *s = '\xFF'; } cleanup_qserver( server, 1 ); return; } void deal_with_farcry_packet( struct qserver *server, char *rawpkt, int pktlen) { char *s, *key, *value, *end; server->n_servers++; if ( NULL == server->server_name ) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL ); } rawpkt[pktlen]= '\0'; end = s = rawpkt; end += pktlen; while ( *s ) { // Find the seperator while ( s <= end && *s != '\xFF' ) { s++; } if ( s >= end ) { // Hit the end no more break; } // key start key = ++s; while ( s < end && *s != '\xFE' ) { s++; } if ( *s != '\xFE') { // malformed break; } *s++ = '\0'; // key end // value start value = s; while ( s < end && *s != '\xFF' ) { s++; } if ( *s == '\xFF' ) { *s = '\0'; } //fprintf( stderr, "'%s' = '%s'\n", key, value ); // Decode current key par if ( 0 == strcmp( "cmax", key ) ) { // Max players server->max_players = atoi( value ); } else if ( 0 == strcmp( "cnum", key ) ) { // Current players server->num_players = atoi( value ); } else if ( 0 == strcmp( "bal", key ) ) { // Balance add_rule( server, "Balance", value, NO_FLAGS ); } else if ( 0 == strcmp( "world", key ) ) { // Current map server->map_name = strdup( value ); } else if ( 0 == strcmp( "gametype", key ) ) { // Game type server->game = find_savage_game( value ); add_rule( server, server->type->game_rule, server->game, NO_FLAGS ); } else if ( 0 == strcmp( "pure", key ) ) { // Pure add_rule( server, "Pure", value, NO_FLAGS ); } else if ( 0 == strcmp( "time", key ) ) { // Current game time add_rule( server, "Time", value, NO_FLAGS ); } else if ( 0 == strcmp( "notes", key ) ) { // Notes add_rule( server, "Notes", value, NO_FLAGS ); } else if ( 0 == strcmp( "needcmdr", key ) ) { // Need Commander add_rule( server, "Need Commander", value, NO_FLAGS ); } else if ( 0 == strcmp( "name", key ) ) { // Server name server->server_name = strdup( value ); } else if ( 0 == strcmp( "fw", key ) ) { // Firewalled add_rule( server, "Firewalled", value, NO_FLAGS ); } else if ( 0 == strcmp( "players", key ) ) { // Players names int player_number = 0; int team_number = 1; char *team_name, *player_name, *n; n = team_name = value; // team name n++; while( *n && *n != '\x0a' ) { n++; } if ( *n != '\x0a' ) { // Broken data break; } *n = '\0'; player_name = ++n; while( *n ) { while( *n && *n != '\x0a' ) { n++; } if ( *n != '\x0a' ) { // Broken data break; } *n = '\0'; n++; if ( 0 == strncmp( "Team ", player_name, 5 ) ) { team_name = player_name; team_number++; } else { if ( 0 != strlen( player_name ) ) { struct player *player = add_player( server, player_number ); if ( NULL != player ) { player->name = strdup( player_name ); player->team = team_number; player->team_name = strdup( team_name ); } player_number++; } } player_name = n; } } *s = '\xFF'; } cleanup_qserver( server, 1 ); return; } /* postions of map name, player name (in player substring), zero-based */ #define BFRIS_MAP_POS 18 #define BFRIS_PNAME_POS 11 void deal_with_bfris_packet( struct qserver *server, char *rawpkt, int pktlen) { int i, player_data_pos, nplayers; SavedData *sdata; unsigned char *saved_data; int saved_data_size; server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); /* add to the data previously saved */ sdata= & server->saved_data; if (! sdata->data) sdata->data = (char*)malloc(pktlen); else sdata->data = (char*)realloc(sdata->data,sdata->datalen + pktlen); memcpy(sdata->data + sdata->datalen, rawpkt, pktlen); sdata->datalen += pktlen; saved_data= (unsigned char*) sdata->data; saved_data_size= sdata->datalen; /* after we get the server portion of the data, server->game != NULL */ if (!server->game) { /* server data goes up to map name */ if (sdata->datalen <= BFRIS_MAP_POS) return; /* see if map name is complete */ player_data_pos=0; for (i=BFRIS_MAP_POS; imap_name = strdup((char*)saved_data + BFRIS_MAP_POS); server->max_players = saved_data[12]; server->protocol_version = saved_data[11]; /* save game type */ switch (saved_data[13] & 15) { case 0: server->game = "FFA"; break; case 5: server->game = "Rover"; break; case 6: server->game = "Occupation"; break; case 7: server->game = "SPAAL"; break; case 8: server->game = "CTF"; break; default: server->game = "unknown"; break; } server->flags |= FLAG_DO_NOT_FREE_GAME; add_rule(server,server->type->game_rule,server->game, NO_FLAGS); if (get_server_rules) { char buf[24]; /* server revision */ sprintf(buf,"%d",(unsigned int)saved_data[11]); add_rule(server,"Revision",buf, NO_FLAGS); /* latency */ sprintf(buf,"%d",(unsigned int)saved_data[10]); add_rule(server,"Latency",buf, NO_FLAGS); /* player allocation */ add_rule(server,"Allocation",saved_data[13] & 16 ? "Automatic" : "Manual", NO_FLAGS); } } /* If we got this far, we know the data saved goes at least to the start of the player information, and that the server data is taken care of. */ /* start of player data */ player_data_pos = BFRIS_MAP_POS + strlen((char*)saved_data+BFRIS_MAP_POS) + 1; /* ensure all player data have arrived */ nplayers = 0; while (saved_data[player_data_pos] != '\0') { player_data_pos += BFRIS_PNAME_POS; /* does player data extend to player name? */ if (saved_data_size <= player_data_pos + 1) return; /* does player data extend to end of player name? */ for (i=0; player_data_pos + i < saved_data_size; i++) { if (saved_data_size == player_data_pos + i + 1) return; if (saved_data[player_data_pos + i] == '\0') { player_data_pos += i + 1; nplayers++; break; } } } /* all player data are complete */ server->num_players = nplayers; if (get_player_info) { /* start of player data */ player_data_pos = BFRIS_MAP_POS + strlen((char*)saved_data+BFRIS_MAP_POS) + 1; for (i=0; iship = saved_data[player_data_pos + 1]; player->ping = saved_data[player_data_pos + 2]; player->frags = saved_data[player_data_pos + 3]; player->team = saved_data[player_data_pos + 4]; switch (player->team) { case 0: player->team_name = "silver"; break; case 1: player->team_name = "red"; break; case 2: player->team_name = "blue"; break; case 3: player->team_name = "green"; break; case 4: player->team_name = "purple"; break; case 5: player->team_name = "yellow"; break; case 6: player->team_name = "cyan"; break; default: player->team_name = "unknown"; break; } player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM; player->room = saved_data[player_data_pos + 5]; /* score is little-endian integer */ player->score = saved_data[player_data_pos+7] + (saved_data[player_data_pos+8] << 8) + (saved_data[player_data_pos+9] << 16) + (saved_data[player_data_pos+10] << 24); /* for archs with > 4-byte int */ if (player->score & 0x80000000) player->score = -(~(player->score)) - 1; player_data_pos += BFRIS_PNAME_POS; player->name = strdup((char*)saved_data + player_data_pos); player_data_pos += strlen(player->name) + 1; } } server->server_name = BFRIS_SERVER_NAME; cleanup_qserver(server, 1); return; } struct rule * add_uchar_rule( struct qserver *server, char *key, unsigned char value) { char buf[24]; sprintf( buf, "%u", (unsigned)value); return add_rule( server, key, buf, NO_FLAGS); } void deal_with_descent3_packet( struct qserver *server, char *rawpkt, int pktlen) { char *pkt; char buf[24]; if ( server->server_name == NULL) server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); if ( pktlen < 4) { fprintf( stderr, "short descent3 packet\n"); print_packet( server, rawpkt, pktlen); cleanup_qserver( server, 1); return; } /* 'info' response */ if ( rawpkt[1] == 0x1f) { if ( server->server_name != NULL) { cleanup_qserver( server, 1); return; } pkt= &rawpkt[0x15]; server->server_name= strdup( pkt); pkt+= strlen(pkt)+2; server->map_name= strdup( pkt); /* mission name (blah.mn3) */ pkt+= strlen(pkt)+2; add_rule( server, "level_name", pkt, NO_FLAGS); pkt+= strlen(pkt)+2; add_rule( server, "gametype", pkt, NO_FLAGS); pkt+= strlen(pkt)+1; sprintf( buf, "%hu", swap_short_from_little(pkt)); add_rule( server, "level_num", buf, NO_FLAGS); pkt+=2; server->num_players= swap_short_from_little(pkt); pkt+=2; server->max_players= swap_short_from_little(pkt); pkt+=2; /* unknown/undecoded fields.. stuff like permissible, banned items/ships, etc */ add_uchar_rule( server, "u0", pkt[0]); add_uchar_rule( server, "u1", pkt[1]); add_uchar_rule( server, "u2", pkt[2]); add_uchar_rule( server, "u3", pkt[3]); add_uchar_rule( server, "u4", pkt[4]); add_uchar_rule( server, "u5", pkt[5]); add_uchar_rule( server, "u6", pkt[6]); add_uchar_rule( server, "u7", pkt[7]); add_uchar_rule( server, "u8", pkt[8]); add_uchar_rule( server, "randpowerup", !(pkt[4]&1)); /* randomize powerup spawn */ add_uchar_rule( server, "acccollisions", (pkt[5]&4) > 0); /* accurate collision detection */ add_uchar_rule( server, "brightships", (pkt[5]&16) > 0); /* bright player ships */ add_uchar_rule( server, "mouselook", (pkt[6]&1) > 0); /* mouselook enabled */ sprintf( buf, "%s%s", (pkt[4]&16)?"PP":"CS", (pkt[6]&1)?"-ML":""); add_rule( server, "servertype", buf, NO_FLAGS); sprintf( buf, "%hhu", pkt[9]); add_rule( server, "difficulty", buf, NO_FLAGS); /* unknown/undecoded fields after known flags removed */ add_uchar_rule( server, "x4", pkt[4] & ~(1+16)); add_uchar_rule( server, "x5", pkt[5] & ~(4+16)); add_uchar_rule( server, "x6", pkt[6] & ~1); if ( get_player_info && server->num_players) { server->next_player_info= 0; send_player_request_packet( server); cleanup_qserver( server, 0); return; } } /* MP_PLAYERLIST_DATA */ else if ( rawpkt[1] == 0x73) { struct player *player; struct player **last_player= & server->players; if ( server->players != NULL) { cleanup_qserver( server, 1); return; } pkt= &rawpkt[0x4]; while (*pkt) { player= (struct player*) calloc( 1, sizeof(struct player)); player->name= strdup( pkt); pkt+= strlen(pkt) + 1; *last_player= player; last_player= & player->next; } server->next_player_info= NO_PLAYER_INFO; } else { fprintf( stderr, "unknown d3 packet\n"); print_packet( server, rawpkt, pktlen); } cleanup_qserver( server, 1); return; } #define EYE_NAME_MASK 1 #define EYE_TEAM_MASK 2 #define EYE_SKIN_MASK 4 #define EYE_SCORE_MASK 8 #define EYE_PING_MASK 16 #define EYE_TIME_MASK 32 void deal_with_eye_packet( struct qserver *server, char *rawpkt, int pktlen) { char *next, *end, *value, *key; struct player **last_player; unsigned char pkt_index, pkt_max; unsigned int pkt_id; if ( pktlen < 4) { cleanup_qserver( server, 1); return; } if ( rawpkt[0] != 'E' || rawpkt[1] != 'Y' || rawpkt[2] != 'E') { cleanup_qserver( server, 1); return; } server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); end= rawpkt + pktlen; pkt_index= rawpkt[3] - '0'; if ( pktlen == 1364 || pkt_index != 1) { /* fragmented packet */ SavedData *sdata; /* EYE doesn't tell us how many packets to expect. Two packets * is enough for 100+ players on a BF1942 server with standard * server rules. */ pkt_max= 2; memcpy( &pkt_id, &rawpkt[pktlen-4], 4); if ( server->saved_data.data == NULL) { sdata= & server->saved_data; } else { sdata= (SavedData*) calloc( 1, sizeof(SavedData)); sdata->next= server->saved_data.next; server->saved_data.next= sdata; } sdata->pkt_index= pkt_index-1; sdata->pkt_max= pkt_max; sdata->pkt_id= pkt_id; if ( pkt_index == 1) { sdata->datalen= pktlen-4; } else { sdata->datalen= pktlen-8; } sdata->data= (char*) malloc( sdata->datalen); if ( NULL == sdata->data ) { fprintf( stderr, "Out of memory\n" ); cleanup_qserver( server, 1 ); return; } if ( pkt_index == 1) { memcpy( sdata->data, &rawpkt[0], sdata->datalen); } else { memcpy( sdata->data, &rawpkt[4], sdata->datalen); } /* combine_packets will call us recursively */ combine_packets( server); return; } value= dup_n1string( &rawpkt[4], end, &next); if ( value == NULL) { goto eye_protocol_error; } add_rule( server, "gamename", value, NO_VALUE_COPY); value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } add_rule( server, "hostport", value, NO_VALUE_COPY); value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } server->server_name= value; value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } server->game= value; add_rule( server, server->type->game_rule, value, NO_FLAGS); value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } server->map_name= value; value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } add_rule( server, "_version", value, NO_VALUE_COPY); value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } add_rule( server, "_password", value, NO_VALUE_COPY); value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } server->num_players= atoi(value); free(value); value= dup_n1string( next, end, &next); if ( value == NULL) { goto eye_protocol_error; } server->max_players= atoi(value); free(value); /* rule1,value1,rule2,value2, ... empty string */ do { key= dup_n1string( next, end, &next); if ( key == NULL) { break; } else if ( key[0] == '\0') { free(key); break; } value= dup_n1string( next, end, &next); if ( value == NULL) { free(key); break; } add_rule( server, key, value, NO_VALUE_COPY | NO_KEY_COPY); } while ( 1); /* [mask1][mask2]... */ last_player= & server->players; while ( next && next < end ) { struct player *player; unsigned mask= *((unsigned char*)next); next++; if ( next >= end) { break; } if ( mask == 0) { break; } player= (struct player*) calloc( 1, sizeof(struct player)); if ( player == NULL) { break; } if ( mask & EYE_NAME_MASK) { player->name= dup_n1string( next, end, &next); //fprintf( stderr, "Player '%s'\n", player->name ); if ( player->name == NULL) { break; } } if ( mask & EYE_TEAM_MASK) { value= dup_n1string( next, end, &next); if ( value == NULL) { break; } if ( isdigit((unsigned char)value[0])) { player->team= atoi(value); free(value); } else { player->team_name= value; } } if ( mask & EYE_SKIN_MASK) { player->skin= dup_n1string( next, end, &next); if ( player->skin == NULL) { break; } } if ( mask & EYE_SCORE_MASK) { value= dup_n1string( next, end, &next); if ( value == NULL) { break; } player->score= atoi(value); player->frags= player->score; free(value); } if ( mask & EYE_PING_MASK) { value= dup_n1string( next, end, &next); if ( value == NULL) { break; } player->ping= atoi(value); free(value); } if ( mask & EYE_TIME_MASK) { value= dup_n1string( next, end, &next); if ( value == NULL) { break; } player->connect_time= atoi(value); free(value); } *last_player= player; last_player= & player->next; //fprintf( stderr, "Player '%s'\n", player->name ); } cleanup_qserver( server, 1); return; eye_protocol_error: cleanup_qserver( server, 1); } static const char hl2_statusresponse[] = "\xFF\xFF\xFF\xFF\x49"; static const char hl2_playersresponse[] = "\xFF\xFF\xFF\xFF\x44"; static const char hl2_rulesresponse[] = "\xFF\xFF\xFF\xFF\x45"; static const int hl2_response_size = sizeof(hl2_statusresponse) - 1; #define HL2_STATUS 1 #define HL2_PLAYERS 2 #define HL2_RULES 3 void deal_with_hl2_packet( struct qserver *server, char *rawpkt, int pktlen) { char *ptr = rawpkt; char *end = rawpkt + pktlen; char temp[512]; int type = 0; unsigned char protocolver = 0; int n_sent = 0; server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); } else { gettimeofday( &server->packet_time1, NULL); } // Check if correct reply if ( pktlen < hl2_response_size ) { malformed_packet(server, "short response type"); cleanup_qserver( server, 1); return; } else { if ( 0 == memcmp( hl2_statusresponse, ptr, hl2_response_size ) ) { if ( pktlen < hl2_response_size + 20 ) { malformed_packet(server, "short packet"); cleanup_qserver( server, 1); return; } type = HL2_STATUS; } else if ( 0 == memcmp( hl2_playersresponse, ptr, hl2_response_size ) ) { type = HL2_PLAYERS; } else if ( 0 == memcmp( hl2_rulesresponse, ptr, hl2_response_size ) ) { type = HL2_RULES; } else { malformed_packet(server, "unknown response"); cleanup_qserver( server, 1); return; } } // header ptr += hl2_response_size; switch( type ) { case HL2_STATUS: // protocol version protocolver = *ptr; ptr++; debug(2, "protocol: 0x%02X", protocolver ); // Commented out till out of beta /* if( '\x02' != protocolver ) { malformed_packet(server, "protocol version != 0x02"); cleanup_qserver( server, 1); return; } */ server->protocol_version = protocolver; sprintf( temp, "%d", protocolver ); add_rule( server, "protocol", temp, NO_FLAGS); // server name server->server_name = strdup( ptr ); ptr += strlen( ptr ) + 1; // map server->map_name = strdup( ptr ); ptr += strlen( ptr ) + 1; // gamedir server->game = strdup( ptr ); add_rule( server, "gamedir", ptr, NO_FLAGS ); ptr += strlen( ptr ) + 1; // description add_rule( server, "description", ptr, NO_FLAGS ); ptr += strlen( ptr ) + 1; // appid ptr += 2; // num players server->num_players = *ptr; ptr++; // max players server->max_players = *ptr; ptr++; // bot players sprintf( temp, "%hhu", (*ptr) ); add_rule( server, "bot_players", temp, NO_FLAGS ); ptr++; // dedicated if ( 'd' == *ptr ) { add_rule( server, "sv_type", "dedicated", NO_FLAGS ); } else if ( 'l' == *ptr ) { add_rule( server, "sv_type", "listen", NO_FLAGS ); } else { char tmp[2] = { *ptr, '\0' }; add_rule( server, "sv_type", tmp, NO_FLAGS ); } ptr++; // OS if ( 'l' == *ptr ) { add_rule( server, "sv_os", "linux", NO_FLAGS ); } else if ( 'w' == *ptr ) { add_rule( server, "sv_os", "windows", NO_FLAGS ); } else { char tmp[2] = { *ptr, '\0' }; add_rule( server, "sv_os", tmp, NO_FLAGS ); } ptr++; // passworded add_rule( server, "sv_password", *ptr ? "1" : "0", NO_FLAGS); ptr++; // secure add_rule( server, "secure", *ptr ? "1" : "0", NO_FLAGS); ptr++; // send the other request packets if wanted if ( get_server_rules ) { int requests = server->n_requests; send_rule_request_packet( server ); server->n_requests = requests; // prevent wrong ping n_sent++; } else if ( get_player_info ) { int requests = server->n_requests; send_player_request_packet( server ) ; server->n_requests = requests; // prevent wrong ping n_sent++; } break; case HL2_RULES: // num_players ptr++; // max_players ptr++; while ( ptr < end ) { char *var = ptr; char *val; ptr += strlen( var ) + 1; val = ptr; ptr += strlen( val ) + 1; add_rule( server, var, val, NO_FLAGS ); } if ( get_player_info ) { send_player_request_packet( server ) ; n_sent++; } break; case HL2_PLAYERS: // num_players ptr++; while ( ptr < end ) { struct player *player = add_player( server, server->n_player_info ); // player no ptr++; // name player->name = strdup( ptr ); ptr += strlen( ptr ) + 1; // frags player->frags = swap_long_from_little( ptr ); ptr += 4; // time player->connect_time = swap_float_from_little( ptr ); ptr += 4; } break; default: malformed_packet( server, "unknown response" ); cleanup_qserver( server, 1); return; } if ( 0 == n_sent ) { cleanup_qserver( server, 1 ); } return; } void deal_with_gamespy_master_response( struct qserver *server, char *rawpkt, int pktlen) { if ( pktlen == 0) { int len= server->saved_data.datalen; char *data= server->saved_data.data; char *ip, *portstr; unsigned int ipaddr; unsigned short port; int master_pkt_max; server->server_name= GAMESPY_MASTER_NAME; master_pkt_max= (len / 20) * 6; server->master_pkt= (char*) malloc( master_pkt_max); server->master_pkt_len= 0; while ( len) { for ( ; len && *data == '\\'; data++, len--) ; if ( len < 3) break; if ( data[0] == 'i' && data[1] == 'p' && data[2] == '\\') { data+= 3; len-= 3; ip= data; portstr= NULL; for ( ; len && *data != '\\'; data++, len--) { if ( *data == ':') { portstr= data+1; *data= '\0'; } } if ( len == 0) break; *data++= '\0'; len--; ipaddr= inet_addr( ip); if ( portstr) port= htons( (unsigned short)atoi( portstr)); else port= htons( 28000); /* ## default port */ if ( server->master_pkt_len >= master_pkt_max) { master_pkt_max+= 20*6; server->master_pkt= (char*) realloc( server->master_pkt, master_pkt_max); } memcpy( server->master_pkt + server->master_pkt_len, &ipaddr, 4); memcpy( server->master_pkt + server->master_pkt_len + 4, &port, 2); server->master_pkt_len+= 6; } else for ( ; len && *data != '\\'; data++, len--) ; } server->n_servers= server->master_pkt_len / 6; server->next_player_info= -1; server->retry1= 0; cleanup_qserver( server, 1); return; } if (! server->saved_data.data) server->saved_data.data= (char*)malloc( pktlen); else server->saved_data.data= (char*)realloc( server->saved_data.data, server->saved_data.datalen + pktlen); memcpy( server->saved_data.data + server->saved_data.datalen, rawpkt, pktlen); server->saved_data.datalen+= pktlen; } /* Misc utility functions */ char * strndup( const char *string, size_t len) { char *result; result= (char*) malloc( len+1); memcpy( result, string, len); result[len]= '\0'; return result; } unsigned int swap_long( void *l) { unsigned char *b= (unsigned char *) l; return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); } unsigned short swap_short( void *l) { unsigned char *b= (unsigned char *) l; return (unsigned short)b[0] | (b[1]<<8); } unsigned int swap_long_from_little( void *l) { unsigned char *b= (unsigned char *) l; unsigned int result; if ( little_endian) memcpy( &result, l, 4); else result= (unsigned int)b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); return result; } float swap_float_from_little( void *f ) { union { int i; float fl; } temp; temp.i = swap_long_from_little(f); return temp.fl; }; unsigned short swap_short_from_little( void *l) { unsigned char *b= (unsigned char *) l; unsigned short result; if ( little_endian) memcpy( &result, l, 2); else result= (unsigned short)b[0] | ((unsigned short)b[1]<<8); return result; } /** write four byte to buf */ void put_long_little(unsigned val, char* buf) { buf[0] = val & 0xFF; buf[1] = (val >> 8) & 0xFF; buf[2] = (val >> 16) & 0xFF; buf[3] = (val >> 24) & 0xFF; } #define MAXSTRLEN 2048 char * xml_escape( char *string) { static char _buf[4][MAXSTRLEN+8]; static int _buf_index= 0; char *result, *b, *end; unsigned char c; if ( string == NULL) return ""; result= &_buf[_buf_index][0]; _buf_index= (_buf_index+1) % 4; end= &result[MAXSTRLEN]; b= result; for ( ; *string && b < end; string++) { c= *string; switch ( c) { case '&': *b++= '&'; *b++= 'a'; *b++= 'm'; *b++= 'p'; *b++= ';'; continue; case '<': *b++= '&'; *b++= 'l'; *b++= 't'; *b++= ';'; continue; case '>': *b++= '&'; *b++= 'g'; *b++= 't'; *b++= ';'; continue; default: break; } if ( ! name_xforms) { *b++= c; } else if ( xml_encoding == ENCODING_LATIN_1) { if ( isprint(c)) *b++= c; else b+= sprintf( b, "&#%u;", c); } else if ( xml_encoding == ENCODING_UTF_8) { if ( (c & 0x80) == 0) *b++= c; else { *b++= 0xC0 | (0x03 & (c >> 6)) ; *b++= 0x80 | (0x3F & c) ; } } } *b= '\0'; return result; } static char *quake3_escape_colors[8] = { "black", "red", "green", "yellow", "blue", "cyan", "magenta", "white" }; static char *sof_colors[32] = { "FFFFFF","FFFFFF","FF0000","00FF00","FFFF00","0000FF","FF00FF","00FFFF", "000000","7F7F7F","702D07","7F0000","007F00","FFFFFF","007F7F","00007F", "564D28","4C5E36","370B65","005572","54647E","1E2A63","66097B","705E61", "980053","960018","702D07","54492A","61A997","CB8F39","CF8316","FF8020" }; char * xform_name( char *string, struct qserver *server) { static char _buf1[2048], _buf2[2048]; static char *_q= &_buf1[0]; unsigned char *s= (unsigned char*) string; char *q; int is_server_name = (string == server->server_name); int font_tag= 0; _q= _q == _buf1 ? _buf2 : _buf1; q= _q; if ( s == NULL) { q[0]= '?'; q[1]= '\0'; return _q; } if ( ! name_xforms) { strcpy( _q, string); return _q; } if ( (hex_player_names && !is_server_name) || (hex_server_names && is_server_name)) { for ( ; *s; s++, q+= 2) { sprintf( q, "%02x", *s); } *q= '\0'; return _q; } if ( server->type->flags & TF_QUAKE3_NAMES) { for ( ; *s; s++) { if ( *s == '^' && *(s+1) != '^') { if ( *(s+1) == '\0') { break; } if ( html_names == 1) { q+= sprintf( q, "%s", font_tag?"":"", quake3_escape_colors[ *(s+1) & 0x7]); s++; font_tag= 1; } else if ( strip_carets) { s++; } else { *q++= *s; } } else { int inc = html_entity( *s, q ); if ( 0 != inc ) { q += inc; } else if ( isprint(*s)) { *q++= *s; } else if ( *s == '\033') { } else if ( *s == 0x80) { *q++= '('; } else if ( *s == 0x81) { *q++= '='; } else if ( *s == 0x82) { *q++= ')'; } else if ( *s == 0x10 || *s == 0x90) { *q++= '['; } else if ( *s == 0x11 || *s == 0x91) { *q++= ']'; } else if ( *s >= 0x92 && *s <= 0x9a) { *q++= *s - 98; } else if ( *s >= 0xa0 && *s <= 0xe0) { *q++= *s - 128; } else if ( *s >= 0xe1 && *s <= 0xfa) { *q++= *s - 160; } else if ( *s >= 0xfb && *s <= 0xfe) { *q++= *s - 128; } } } *q= '\0'; } else if ( !is_server_name && (server->type->flags & TF_TRIBES2_NAMES)) { for ( ; *s; s++) { int inc = html_entity( *s, q ); if ( 0 != inc ) { q += inc; continue; } else if ( isprint(*s)) { *q++= *s; continue; } if ( html_names == 1 && s[1] != '\0') { char *font_color; switch( *s) { case 0x8: font_color= "white"; break; /* normal */ case 0xb: font_color= "yellow"; break; /* tribe tag */ case 0xc: font_color= "blue"; break; /* alias */ case 0xe: font_color= "green"; break; /* bot */ default: font_color= NULL; } if ( font_color) { q+= sprintf( q, "%s", font_tag?"":"", font_color); font_tag= 1; } } } *q= '\0'; } else if ( server->type->flags & TF_U2_NAMES ) { for ( ; *s; s++) { if ( 0 == memcmp( s, "^\1", 2 ) ) { // xmp Color follows s += 2; q += u2xmp_html_color( (unsigned char)*s, q, &font_tag ); } else if ( 0 == memcmp( s, "\x1b", 1 ) ) { // Color follows s += 1; q += ut2k4_html_color( s, q, &font_tag ); s += 2; } else { int inc = html_entity( *s, q ); if ( 0 != inc ) { q += inc; } else if ( isprint(*s)) { *q++= *s; } else if ( 0xa0 == *s ) { *q++= ' '; } } } *q = '\0'; } else if ( server->type->flags & TF_TM_NAMES ) { int open = 0; for ( ; *s; s++) { if ( *s == '$' ) { s++; switch ( *s ) { case 'i': case 'I': // italic if ( 1 == html_names ) { strcat( q, "" ); q += 32; open++; } break; case 's': case 'S': // shadowed break; case 'w': case 'W': // wide break; case 'n': case 'N': // narrow break; case 'm': case 'M': // normal if ( 1 == html_names ) { strcat( q, "" ); q += 32; open++; } break; case 'g': case 'G': // default color strcat( q, "" ); q += 26; open++; break; case 'z': case 'Z': // reset all while ( open ) { strcat( q, "" ); q += 7; open--; } open = 0; break; case 't': case 'T': // capitalise if ( 1 == html_names ) { strcat( q, "" ); q += 40; open++; } break; case '$': // literal $ *q++ = '$'; break; default: // color if ( 1 == html_names ) { sprintf( q, "", *s, *s, *(s+1), *(s+1), *(s+2), *(s+2) ); q += 27; open++; } if ( *(s+1) ) { s++; } if ( *(s+1) ) { s++; } break; } } else { *q++ = *s; } } while ( open ) { strcat( q, "" ); q += 7; open--; } *q = '\0'; } else if ( !is_server_name || server->type->flags & TF_SOF_NAMES ) { // Catch all for NOT is_server_name OR TF_SOF_NAMES // The may not be the intention but is needed for q1 at least for ( ; *s; s++) { int inc = html_entity( *s, q ); if ( 0 != inc ) { q += inc; continue; } if ( *s < ' ' ) { if ( html_names == 1) { q+= sprintf( q, "%s", font_tag?"":"", sof_colors[ *(s) ]); font_tag= 1; } } else if ( isprint(*s)) { *q++= *s; } // ## more fixes below; double check against real sof servers else if ( *s >= 0xa0) { *q++= *s & 0x7f; } else if ( *s >= 0x92 && *s < 0x9c) { *q++= '0' + (*s - 0x92); } else if ( *s >= 0x12 && *s < 0x1c) { *q++= '0' + (*s - 0x12); } else if ( *s == 0x90 || *s == 0x10) { *q++= '['; } else if ( *s == 0x91 || *s == 0x11) { *q++= ']'; } else if ( *s == 0xa || *s == 0xc || *s == 0xd) { *q++= ']'; } } *q= '\0'; } else { strcpy( _q, string); } if ( font_tag ) { q+= sprintf( q, ""); } return _q; } int u2xmp_html_color( short color, char *dest, int *font_tag ) { if ( 1 == html_names ) { int len = sprintf( dest, "%s", *font_tag ? "" : "", unreal_rgb_colors[ color - 1 ] ); *font_tag = 1; return len; } return 0; } int ut2k4_html_color( const unsigned char *color, char *dest, int *font_tag ) { if ( 1 == html_names ) { int len = sprintf( dest, "%s", *font_tag ? "" : "", color[0], color[1], color[2] ); *font_tag = 1; return len; } return 0; } int is_default_rule( struct rule *rule) { if ( strcmp( rule->name, "sv_maxspeed") == 0) return strcmp( rule->value, Q_DEFAULT_SV_MAXSPEED) == 0; if ( strcmp( rule->name, "sv_friction") == 0) return strcmp( rule->value, Q_DEFAULT_SV_FRICTION) == 0; if ( strcmp( rule->name, "sv_gravity") == 0) return strcmp( rule->value, Q_DEFAULT_SV_GRAVITY) == 0; if ( strcmp( rule->name, "noexit") == 0) return strcmp( rule->value, Q_DEFAULT_NOEXIT) == 0; if ( strcmp( rule->name, "teamplay") == 0) return strcmp( rule->value, Q_DEFAULT_TEAMPLAY) == 0; if ( strcmp( rule->name, "timelimit") == 0) return strcmp( rule->value, Q_DEFAULT_TIMELIMIT) == 0; if ( strcmp( rule->name, "fraglimit") == 0) return strcmp( rule->value, Q_DEFAULT_FRAGLIMIT) == 0; return 0; } int html_entity( const char c, char *dest ) { if ( html_mode ) { switch( c ) { case '<': strcpy( dest, "<" ); return 4; case '>': strcpy( dest, ">" ); return 4; case '&': strcpy( dest, "&" ); return 5; default: break; } } return 0; } char * strherror( int h_err) { static char msg[100]; switch (h_err) { case HOST_NOT_FOUND: return "host not found"; case TRY_AGAIN: return "try again"; case NO_RECOVERY: return "no recovery"; case NO_ADDRESS: return "no address"; default: sprintf( msg, "%d", h_err); return msg; } } int time_delta( struct timeval *later, struct timeval *past) { if ( later->tv_usec < past->tv_usec) { later->tv_sec--; later->tv_usec+= 1000000; } return (later->tv_sec - past->tv_sec) * 1000 + (later->tv_usec - past->tv_usec) / 1000; } int connection_refused() { #ifdef _WIN32 return WSAGetLastError() == WSAECONNABORTED; #else return errno == ECONNREFUSED; #endif } void set_non_blocking( int fd) { #ifdef _WIN32 int one= 1; ioctlsocket( fd, FIONBIO, (unsigned long*)&one); #else #ifdef O_NONBLOCK fcntl( fd, F_SETFL, O_NONBLOCK); #else fcntl( fd, F_SETFL, O_NDELAY); #endif // O_NONBLOCK #endif // _WIN32 } char * quake_color( int color) { static char *colors[] = { "White", /* 0 */ "Brown", /* 1 */ "Lavender", /* 2 */ "Khaki", /* 3 */ "Red", /* 4 */ "Lt Brown", /* 5 */ "Peach", /* 6 */ "Lt Peach", /* 7 */ "Purple", /* 8 */ "Dk Purple", /* 9 */ "Tan", /* 10 */ "Green", /* 11 */ "Yellow", /* 12 */ "Blue", /* 13 */ "Blue", /* 14 */ "Blue" /* 15 */ }; static char *rgb_colors[] = { "#ffffff", /* 0 */ "#8b4513", /* 1 */ "#e6e6fa", /* 2 */ "#f0e68c", /* 3 */ "#ff0000", /* 4 */ "#deb887", /* 5 */ "#eecbad", /* 6 */ "#ffdab9", /* 7 */ "#9370db", /* 8 */ "#5d478b", /* 9 */ "#d2b48c", /* 10 */ "#00ff00", /* 11 */ "#ffff00", /* 12 */ "#0000ff", /* 13 */ "#0000ff", /* 14 */ "#0000ff" /* 15 */ }; static char *color_nr[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" }; if ( color_names ) { if ( color_names == 1) { return colors[color&0xf]; } else { return rgb_colors[color&0xf]; } } else { return color_nr[color&0xf]; } } const char * unreal_color( int color ) { if ( color_names ) { if ( color_names == 1) { return unreal_colors[color&0xf]; } else { return unreal_rgb_colors[color&0xf]; } } return (char*)(unsigned long)color; } #define FMT_HOUR_1 "%2dh" #define FMT_HOUR_2 "%dh" #define FMT_MINUTE_1 "%2dm" #define FMT_MINUTE_2 "%dm" #define FMT_SECOND_1 "%2ds" #define FMT_SECOND_2 "%ds" char * play_time( int seconds, int show_seconds) { static char time_string[24]; if ( time_format == CLOCK_TIME) { char *fmt_hour= show_seconds==2 ? FMT_HOUR_2 : FMT_HOUR_1; char *fmt_minute= show_seconds==2 ? FMT_MINUTE_2 : FMT_MINUTE_1; char *fmt_second= show_seconds==2 ? FMT_SECOND_2 : FMT_SECOND_1; time_string[0]= '\0'; if ( seconds/3600) sprintf( time_string, fmt_hour, seconds/3600); else if ( show_seconds < 2) strcat( time_string, " "); if ( (seconds%3600)/60 || seconds/3600) sprintf( time_string+strlen(time_string), fmt_minute, (seconds%3600)/60); else if ( ! show_seconds) sprintf( time_string+strlen(time_string), " 0m"); else if ( show_seconds < 2) strcat( time_string, " "); if ( show_seconds) sprintf( time_string+strlen(time_string), fmt_second, seconds%60); } else if ( time_format == STOPWATCH_TIME) { if ( show_seconds) sprintf( time_string, "%02d:%02d:%02d", seconds/3600, (seconds%3600)/60, seconds % 60); else sprintf( time_string, "%02d:%02d", seconds/3600, (seconds%3600)/60); } else sprintf( time_string, "%d", seconds); return time_string; } char * ping_time( int ms) { static char time_string[24]; if ( ms < 1000) sprintf( time_string, "%dms", ms); else if ( ms < 1000000) sprintf( time_string, "%ds", ms/1000); else sprintf( time_string, "%dm", ms/1000/60); return time_string; } int count_bits( int n) { int b= 0; for ( ; n; n>>=1) if ( n&1) b++; return b; } int strcmp_withnull( char *one, char *two) { if ( one == NULL && two == NULL) return 0; if ( one != NULL && two == NULL) return -1; if ( one == NULL) return 1; return strcasecmp( one, two); } /* * Sorting functions */ void sort_servers( struct qserver **array, int size) { quicksort( (void**)array, 0, size-1, (int (*)(void*,void*)) server_compare); } void sort_players( struct qserver *server) { struct player **array, *player, *last_team= NULL, **next; int np, i; if ( server->num_players == 0 || server->players == NULL) return; player= server->players; for ( ; player != NULL && player->number == TRIBES_TEAM; ) { last_team= player; player= player->next; } if ( player == NULL) return; array= (struct player **) malloc( sizeof(struct player *) * server->num_players); for ( np= 0; player != NULL && np < server->num_players; np++) { array[np]= player; player= player->next; } quicksort( (void**)array, 0, np-1, (int (*)(void*,void*)) player_compare); if ( last_team) next= &last_team->next; else next= &server->players; for ( i= 0; i < np; i++) { *next= array[i]; array[i]->next= NULL; next= &array[i]->next; } free( array); } int server_compare( struct qserver *one, struct qserver *two) { int rc; char *key= sort_keys; for ( ; *key; key++) { switch( *key) { case 'g': rc= strcmp_withnull( one->game, two->game); if ( rc) return rc; break; case 'p': if ( one->n_requests == 0) return two->n_requests; else if ( two->n_requests == 0) return -1; rc= one->ping_total/one->n_requests - two->ping_total/two->n_requests; if ( rc) return rc; break; case 'i': if ( one->ipaddr > two->ipaddr) return 1; else if ( one->ipaddr < two->ipaddr) return -1; else if ( one->port > two->port) return 1; else if ( one->port < two->port) return -1; break; case 'h': rc= strcmp_withnull( one->host_name, two->host_name); if ( rc) return rc; break; case 'n': rc= two->num_players - one->num_players; if ( rc) return rc; break; } } return 0; } int type_option_compare( server_type *one, server_type *two ) { return strcmp_withnull( one->type_option, two->type_option ); } int type_string_compare( server_type *one, server_type *two ) { return strcmp_withnull( one->type_string, two->type_string ); } int player_compare( struct player *one, struct player *two) { int rc; char *key= sort_keys; for ( ; *key; key++) { switch( *key) { case 'P': rc= one->ping - two->ping; if ( rc) return rc; break; case 'F': rc= two->frags - one->frags; if ( rc) return rc; break; case 'S': rc= two->score - one->score; if ( rc) return rc; break; case 'T': rc= one->team - two->team; if ( rc) return rc; rc = strcmp_withnull( one->team_name, two->team_name ); if ( rc ) return rc; break; case 'N': rc= strcmp_withnull( one->name, two->name ); if ( rc ) return rc; return one->number - two->number; break; } } return 0; } void quicksort( void **array, int i, int j, int (*compare)(void*,void*)) { int q= 0; if ( i < j) { q = qpartition(array,i,j, compare); quicksort(array,i,q, compare); quicksort(array,q+1,j, compare); } } int qpartition( void **array, int a, int b, int (*compare)(void*,void*)) { /* this is our comparison point. when we are done splitting this array into 2 parts, we want all the elements on the left side to be less then or equal to this, all the elements on the right side need to be greater then or equal to this */ void *z; /* indicies into the array to sort. Used to calculate a partition point */ int i = a-1; int j = b+1; /* temp pointer used to swap two array elements */ void * tmp = NULL; z = array[a]; while (1) { /* move the right indice over until the value of that array elem is less than or equal to z. Stop if we hit the left side of the array (ie, j == a); */ do { j--; } while( j > a && compare(array[j],z) > 0); /* move the left indice over until the value of that array elem is greater than or equal to z, or until we hit the right side of the array (ie i == j) */ do { i++; } while( i <= j && compare(array[i],z) < 0); /* if i is less then j, we need to switch those two array elements, if not then we are done partitioning this array section */ if(i < j) { tmp = array[i]; array[i] = array[j]; array[j] = tmp; } else return j; } } // vim: sw=8 ts=8 noet qstat-2.11/qstat.h0000644002404400000620000031113310464730441011020 00000000000000/* * qstat.h * by Steve Jankowski * steve@qstat.org * http://www.qstat.org * * Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski */ #ifndef __H_QSTAT #define __H_QSTAT #ifdef HAVE_CONFIG_H #include "gnuconfig.h" #endif #ifdef __EMX__ #include #include #define strcasecmp stricmp #define strncasecmp strnicmp #endif #ifdef _WIN32 # include # include # define PATH_MAX MAX_PATH # include # define _POSIX_ 1 # ifndef FD_SETSIZE # define FD_SETSIZE 256 # endif # define close(a) closesocket(a) static int gettimeofday(struct timeval *now, void *blah) { struct timeb timeb; ftime( &timeb); now->tv_sec= timeb.time; now->tv_usec= (unsigned int)timeb.millitm * 1000; return 0; } # define sockerr() WSAGetLastError() # define strcasecmp stricmp # define strncasecmp strnicmp # define STATIC # ifndef EADDRINUSE # define EADDRINUSE WSAEADDRINUSE # endif # define snprintf _snprintf #else # include # define SOCKET_ERROR -1 #endif /* _WIN32 */ #include typedef struct _server_type server_type; #ifdef __GNUC__ #define GCC_FORMAT_PRINTF(a, b) __attribute__ ((format (printf, a, b))) #else #define GCC_FORMAT_PRINTF(a, b) #endif #include "qserver.h" // Packet modules #include "ut2004.h" #include "doom3.h" #include "a2s.h" #include "gps.h" #include "gs2.h" #include "gs3.h" #include "ts2.h" #include "tm.h" /* * Various magic numbers. */ #define Q_DEFAULT_PORT 26000 #define HEXEN2_DEFAULT_PORT 26900 #define Q2_DEFAULT_PORT 27910 #define Q3_DEFAULT_PORT 27960 #define Q2_MASTER_DEFAULT_PORT 27900 #define Q3_MASTER_DEFAULT_PORT 27950 #define QW_DEFAULT_PORT 27500 #define QW_MASTER_DEFAULT_PORT 27000 #define HW_DEFAULT_PORT 26950 #define UNREAL_DEFAULT_PORT 7777 #define UNREAL_MASTER_DEFAULT_PORT 28900 #define HALFLIFE_DEFAULT_PORT 27015 #define HL_MASTER_DEFAULT_PORT 27010 #define SIN_DEFAULT_PORT 22450 #define SHOGO_DEFAULT_PORT 27888 #define TRIBES_DEFAULT_PORT 28001 #define TRIBES_MASTER_DEFAULT_PORT 28000 #define BFRIS_DEFAULT_PORT 44001 #define KINGPIN_DEFAULT_PORT 31510 #define HERETIC2_DEFAULT_PORT 28910 #define SOF_DEFAULT_PORT 28910 #define GAMESPY_MASTER_DEFAULT_PORT 28900 #define TRIBES2_DEFAULT_PORT 28000 #define TRIBES2_MASTER_DEFAULT_PORT 28002 #define DESCENT3_GAMESPY_DEFAULT_PORT 20142 #define DESCENT3_DEFAULT_PORT 2092 #define DESCENT3_MASTER_DEFAULT_PORT 3445 #define RTCW_DEFAULT_PORT 27960 #define RTCW_MASTER_DEFAULT_PORT 27950 #define STEF_DEFAULT_PORT 27960 #define STEF_MASTER_DEFAULT_PORT 27953 #define JK3_DEFAULT_PORT 29070 #define JK3_MASTER_DEFAULT_PORT 29060 #define GHOSTRECON_PLAYER_DEFAULT_PORT 2346 #define RAVENSHIELD_DEFAULT_PORT 8777 #define SAVAGE_DEFAULT_PORT 11235 #define FARCRY_DEFAULT_PORT 49001 #define STEAM_MASTER_DEFAULT_PORT 27010 #define HL2_DEFAULT_PORT 27015 #define HL2_MASTER_DEFAULT_PORT 27011 #define TS2_DEFAULT_PORT 51234 #define TM_DEFAULT_PORT 5000 #define Q_UNKNOWN_TYPE 0 #define MASTER_SERVER 0x40000000 #define Q_SERVER 1 #define QW_SERVER 2 #define QW_MASTER (3 | MASTER_SERVER) #define H2_SERVER 4 #define Q2_SERVER 5 #define Q2_MASTER (6|MASTER_SERVER) #define HW_SERVER 7 #define UN_SERVER 8 #define UN_MASTER (9|MASTER_SERVER) #define HL_SERVER 10 #define HL_MASTER (11|MASTER_SERVER) #define SIN_SERVER 12 #define SHOGO_SERVER 13 #define TRIBES_SERVER 14 #define TRIBES_MASTER (15|MASTER_SERVER) #define Q3_SERVER 16 #define Q3_MASTER (17|MASTER_SERVER) #define BFRIS_SERVER 18 #define KINGPIN_SERVER 19 #define HERETIC2_SERVER 20 #define SOF_SERVER 21 #define GAMESPY_PROTOCOL_SERVER 22 #define GAMESPY_MASTER (23|MASTER_SERVER) #define TRIBES2_SERVER 24 #define TRIBES2_MASTER (25|MASTER_SERVER) #define DESCENT3_GAMESPY_SERVER 26 #define DESCENT3_PXO_SERVER 27 #define DESCENT3_SERVER 28 #define DESCENT3_MASTER (29|MASTER_SERVER) #define RTCW_SERVER 30 #define RTCW_MASTER (31|MASTER_SERVER) #define STEF_SERVER 32 #define STEF_MASTER (33|MASTER_SERVER) #define UT2003_SERVER 34 #define GHOSTRECON_SERVER 35 #define ALLSEEINGEYE_PROTOCOL_SERVER 36 #define RAVENSHIELD_SERVER 37 #define SAVAGE_SERVER 38 #define FARCRY_SERVER 39 #define GAMESPY2_PROTOCOL_SERVER 40 #define STEAM_MASTER (41|MASTER_SERVER) #define JK3_SERVER 42 #define JK3_MASTER (43|MASTER_SERVER) #define DOOM3_SERVER 44 #define DOOM3_MASTER (45|MASTER_SERVER) #define HL2_SERVER 46 #define HL2_MASTER (47|MASTER_SERVER) #define UT2004_MASTER (48|MASTER_SERVER) #define A2S_SERVER 49 #define PARIAH_SERVER 50 #define GAMESPY3_PROTOCOL_SERVER 51 #define TS2_PROTOCOL_SERVER 52 #define QUAKE4_SERVER 53 #define QUAKE4_MASTER (53|MASTER_SERVER) #define ARMYOPS_SERVER 54 #define GAMESPY4_PROTOCOL_SERVER 55 #define PREY_SERVER 56 #define TM_PROTOCOL_SERVER 57 #define LAST_BUILTIN_SERVER 57 #define TF_SINGLE_QUERY (1<<1) #define TF_OUTFILE (1<<2) #define TF_MASTER_MULTI_RESPONSE (1<<3) #define TF_TCP_CONNECT (1<<4) #define TF_QUERY_ARG (1<<5) #define TF_QUERY_ARG_REQUIRED (1<<6) #define TF_QUAKE3_NAMES (1<<7) #define TF_TRIBES2_NAMES (1<<8) #define TF_SOF_NAMES (1<<9) #define TF_U2_NAMES (1<<10) #define TF_RAW_STYLE_QUAKE (1<<11) #define TF_RAW_STYLE_TRIBES (1<<12) #define TF_RAW_STYLE_GHOSTRECON (1<<13) #define TF_NO_PORT_OFFSET (1<<14) #define TF_SHOW_GAME_PORT (1<<15) #define TF_MASTER_STEAM (1<<16) /* supports steam server filter */ // What response type are we expecting // XXX: this is not what server->flags is for #define TF_STATUS_QUERY (1<<17) #define TF_PLAYER_QUERY (1<<18) #define TF_RULES_QUERY (1<<19) #define TF_TM_NAMES (1<<20) #define TRIBES_TEAM -1 struct q_packet; typedef void (*DisplayFunc)( struct qserver *); typedef void (*QueryFunc)( struct qserver *); typedef void (*PacketFunc)( struct qserver *, char *rawpkt, int pktlen); /* * Output and formatting functions */ void display_server( struct qserver *server); void display_qwmaster( struct qserver *server); void display_server_rules( struct qserver *server); void display_player_info( struct qserver *server); void display_q_player_info( struct qserver *server); void display_qw_player_info( struct qserver *server); void display_q2_player_info( struct qserver *server); void display_unreal_player_info( struct qserver *server); void display_shogo_player_info( struct qserver *server); void display_halflife_player_info( struct qserver *server); void display_tribes_player_info( struct qserver *server); void display_tribes2_player_info( struct qserver *server); void display_bfris_player_info( struct qserver *server); void display_descent3_player_info( struct qserver *server); void display_ravenshield_player_info( struct qserver *server); void display_savage_player_info( struct qserver *server); void display_farcry_player_info( struct qserver *server); void display_ghostrecon_player_info( struct qserver *server); void display_eye_player_info( struct qserver *server); void display_armyops_player_info( struct qserver *server); void display_gs2_player_info( struct qserver *server); void display_doom3_player_info( struct qserver *server); void display_hl2_player_info( struct qserver *server); void display_ts2_player_info( struct qserver *server); void display_tm_player_info( struct qserver *server); void raw_display_server( struct qserver *server); void raw_display_server_rules( struct qserver *server); void raw_display_player_info( struct qserver *server); void raw_display_q_player_info( struct qserver *server); void raw_display_qw_player_info( struct qserver *server); void raw_display_q2_player_info( struct qserver *server); void raw_display_unreal_player_info( struct qserver *server); void raw_display_halflife_player_info( struct qserver *server); void raw_display_tribes_player_info( struct qserver *server); void raw_display_tribes2_player_info( struct qserver *server); void raw_display_bfris_player_info( struct qserver *server); void raw_display_ravenshield_player_info( struct qserver *server); void raw_display_savage_player_info( struct qserver *server); void raw_display_farcry_player_info( struct qserver *server); void raw_display_descent3_player_info( struct qserver *server); void raw_display_ghostrecon_player_info( struct qserver *server); void raw_display_eye_player_info( struct qserver *server); void raw_display_armyops_player_info( struct qserver *server); void raw_display_gs2_player_info( struct qserver *server); void raw_display_doom3_player_info( struct qserver *server); void raw_display_hl2_player_info( struct qserver *server); void raw_display_ts2_player_info( struct qserver *server); void raw_display_tm_player_info( struct qserver *server); void xml_display_server( struct qserver *server); void xml_header(); void xml_footer(); void xml_display_server_rules( struct qserver *server); void xml_display_player_info( struct qserver *server); void xml_display_q_player_info( struct qserver *server); void xml_display_qw_player_info( struct qserver *server); void xml_display_q2_player_info( struct qserver *server); void xml_display_unreal_player_info( struct qserver *server); void xml_display_halflife_player_info( struct qserver *server); void xml_display_tribes_player_info( struct qserver *server); void xml_display_tribes2_player_info( struct qserver *server); void xml_display_ravenshield_player_info( struct qserver *server); void xml_display_savage_player_info( struct qserver *server); void xml_display_farcry_player_info( struct qserver *server); void xml_display_bfris_player_info( struct qserver *server); void xml_display_descent3_player_info( struct qserver *server); void xml_display_ghostrecon_player_info( struct qserver *server); void xml_display_eye_player_info( struct qserver *server); void xml_display_armyops_player_info( struct qserver *server); void xml_display_gs2_player_info( struct qserver *server); void xml_display_doom3_player_info( struct qserver *server); void xml_display_hl2_player_info( struct qserver *server); void xml_display_ts2_player_info( struct qserver *server); void xml_display_tm_player_info( struct qserver *server); char *xml_escape( char*); char *str_replace( char *, char *, char *); void send_server_request_packet( struct qserver *server); void send_qserver_request_packet( struct qserver *server); void send_qwserver_request_packet( struct qserver *server); void send_ut2003_request_packet( struct qserver *server); void send_tribes_request_packet( struct qserver *server); void send_qwmaster_request_packet( struct qserver *server); void send_bfris_request_packet( struct qserver *server); void send_player_request_packet( struct qserver *server); void send_rule_request_packet( struct qserver *server); void send_ravenshield_request_packet( struct qserver *server); void send_savage_request_packet( struct qserver *server); void send_farcry_request_packet( struct qserver *server); void send_gamespy_master_request( struct qserver *server); void send_tribes2_request_packet( struct qserver *server); void send_tribes2master_request_packet( struct qserver *server); void send_ghostrecon_request_packet( struct qserver *server); void send_eye_request_packet( struct qserver *server); void send_gs2_request_packet( struct qserver *server); void send_doom3_request_packet( struct qserver *server); void send_hl2_request_packet( struct qserver *server); void send_ts2_request_packet( struct qserver *server); void send_tm_request_packet( struct qserver *server); void deal_with_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_q_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_qw_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_q1qw_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_q2_packet( struct qserver *server, char *pkt, int pktlen, int check_duplicate_rules); void deal_with_doom3master_packet( struct qserver *server, char *rawpkt, int pktlen); void deal_with_qwmaster_packet( struct qserver *server, char *pkt, int pktlen); int deal_with_halflife_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_ut2003_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_tribes_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_tribesmaster_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_bfris_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_gamespy_master_response( struct qserver *server, char *pkt, int pktlen); void deal_with_ravenshield_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_savage_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_farcry_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_tribes2_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_tribes2master_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_descent3_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_descent3master_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_ghostrecon_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_eye_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_doom3_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_hl2_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_ts2_packet( struct qserver *server, char *pkt, int pktlen); void deal_with_tm_packet( struct qserver *server, char *pkt, int pktlen); struct _server_type { int id; char *type_prefix; char *type_string; char *type_option; char *game_name; int master; unsigned short default_port; unsigned short port_offset; int flags; char *game_rule; char *template_var; char *status_packet; int status_len; char *player_packet; int player_len; char *rule_packet; int rule_len; char *master_packet; int master_len; char *master_protocol; char *master_query; DisplayFunc display_player_func; DisplayFunc display_rule_func; DisplayFunc display_raw_player_func; DisplayFunc display_raw_rule_func; DisplayFunc display_xml_player_func; DisplayFunc display_xml_rule_func; QueryFunc status_query_func; QueryFunc rule_query_func; QueryFunc player_query_func; PacketFunc packet_func; }; extern server_type builtin_types[]; extern server_type *types; extern int n_server_types; extern server_type* default_server_type; server_type* find_server_type_string( char* type_string); #ifdef QUERY_PACKETS #undef QUERY_PACKETS /* QUAKE */ struct q_packet { unsigned char flag1; unsigned char flag2; unsigned short length; unsigned char op_code; unsigned char data[19]; }; #define Q_HEADER_LEN 5 /* struct { unsigned char flag1; unsigned char flag2; unsigned short length; unsigned char op_code; char name[6]; unsigned char version; }; */ #define Q_FLAG1 0x80 #define Q_FLAG2 0x00 #define Q_CCREQ_SERVER_INFO 0x02 #define Q_CCREQ_PLAYER_INFO 0x03 #define Q_CCREQ_RULE_INFO 0x04 /* The \003 below is the protocol version */ #define Q_SERVERINFO_LEN 12 struct q_packet q_serverinfo = { Q_FLAG1, Q_FLAG2, Q_SERVERINFO_LEN, Q_CCREQ_SERVER_INFO, "QUAKE\000\003" }; struct q_packet q_rule = {Q_FLAG1,Q_FLAG2, 0, Q_CCREQ_RULE_INFO, ""}; struct q_packet q_player = {Q_FLAG1,Q_FLAG2, 6, Q_CCREQ_PLAYER_INFO, ""}; /* QUAKE WORLD */ struct { char prefix[4]; char command[7]; } qw_serverstatus = { { '\377', '\377', '\377', '\377' }, { 's', 't', 'a', 't', 'u', 's', '\n' } }; /* QUAKE3 */ struct { char prefix[4]; char command[10]; } q3_serverstatus = { { '\377', '\377', '\377', '\377' }, { 'g', 'e', 't', 's', 't', 'a', 't', 'u', 's', '\n' } }; struct { char prefix[4]; char command[8]; } q3_serverinfo = { { '\377', '\377', '\377', '\377' }, { 'g', 'e', 't', 'i', 'n', 'f', 'o', '\n' } }; /* DOOM 3 */ struct { char prefix[2]; char command[12]; } doom3_serverinfo = { { '\377', '\377' }, { 'g', 'e', 't', 'I', 'n', 'f', 'o', '\0', '\0', '\0', '\0', '\0' } }; /* HALF-LIFE 2 */ char hl2_serverinfo[20] = { '\xFF', '\xFF', '\xFF', '\xFF', 'T', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; char hl2_playerinfo[20] = { '\xFF', '\xFF', '\xFF', '\xFF', 'U', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; char hl2_ruleinfo[20] = { '\xFF', '\xFF', '\xFF', '\xFF', 'V', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; /* HEXEN WORLD */ struct { char prefix[5]; char command[7]; } hw_serverstatus = { { '\377', '\377', '\377', '\377', '\377' }, { 's', 't', 'a', 't', 'u', 's', '\n' } }; /* HEXEN 2 */ /* The \004 below is the protocol version */ #define H2_SERVERINFO_LEN 14 struct q_packet h2_serverinfo = { Q_FLAG1, Q_FLAG2, H2_SERVERINFO_LEN, Q_CCREQ_SERVER_INFO, "HEXENII\000\004" }; /* UNREAL */ char unreal_serverstatus[8] = { '\\', 's','t','a','t','u','s', '\\' }; /* char unreal_serverstatus[] = { '\\', 's','t','a','t','u','s', '\\', '\\', 'p','l','a','y','e','r','s', '\\', '\\' }; */ char unreal_masterlist[23] = "\\list\\\\gamename\\unreal"; /* UT 2003 */ char ut2003_basicstatus[] = { 0x78, 0,0,0, 0 }; //char ut2003_ruleinfo[] = { 0x78, 0,0,0, 1 }; //char ut2003_playerinfo[] = { 0x78, 0,0,0, 2 }; char ut2003_allinfo[] = { 0x78, 0,0,0, 3 }; /* Pariah */ char pariah_basicstatus[] = { 0x77, 0,0,0, 0x13 }; /* HALF LIFE */ char hl_ping[9] = { '\377', '\377', '\377', '\377', 'p', 'i', 'n', 'g', '\0' }; char hl_rules[10] = { '\377', '\377', '\377', '\377', 'r', 'u', 'l', 'e', 's', '\0' }; char hl_info[9] = { '\377', '\377', '\377', '\377', 'i', 'n', 'f', 'o', '\0' }; char hl_players[12] = { '\377', '\377', '\377', '\377', 'p', 'l', 'a', 'y', 'e', 'r', 's', '\0' }; char hl_details[12] = { '\377', '\377', '\377', '\377', 'd', 'e', 't', 'a', 'i', 'l', 's', '\0' }; /* QUAKE WORLD MASTER */ #define QW_GET_SERVERS 'c' char qw_masterquery[] = { QW_GET_SERVERS, '\n', '\0' }; /* QUAKE 2 MASTER */ char q2_masterquery[] = { 'q', 'u', 'e', 'r', 'y', '\n', '\0' }; /* QUAKE 3 MASTER */ char q3_master_query_template[] = "\377\377\377\377getservers %s %s"; char q3_master_default_protocol[] = "68"; char q3_master_default_query[] = "empty full demo\n"; /* RETURN TO CASTLE WOLFENSTEIN */ char rtcw_master_default_protocol[] = "60"; /* STAR TREK: ELITE FORCE */ char stef_master_default_protocol[] = "24"; /* JEDI KNIGHT: JEDI ACADEMY */ char jk3_master_default_protocol[] = "26"; /* HALF-LIFE MASTER */ char hl_masterquery[4] = { 'e', '\0', '\0', '\0' }; char new_hl_masterquery_prefix[5] = { '1', '\0', '\0', '\0', '\0' }; /* TRIBES */ char tribes_info[] = { '`', '*', '*' }; char tribes_players[] = { 'b', '*', '*' }; /* This is what the game sends to get minimal status { '\020', '\03', '\377', 0, (unsigned char)0xc5, 6 }; */ char tribes_info_reponse[] = { 'a', '*', '*', 'b' }; char tribes_players_reponse[] = { 'c', '*', '*', 'b' }; char tribes_masterquery[] = { 0x10, 0x3, '\377', 0, 0x2 }; char tribes_master_response[] = { 0x10, 0x6 }; /* GAMESPY */ char gamespy_master_request_prefix[] = "\\list\\\\gamename\\"; char gamespy_master_validate[] = "\\gamename\\gamespy2\\gamever\\020109017\\location\\5\\validate\\12345678\\final\\"; /* TRIBES 2 */ #define TRIBES2_QUERY_GAME_TYPES 2 #define TRIBES2_QUERY_MASTER 6 #define TRIBES2_QUERY_PING 14 #define TRIBES2_QUERY_INFO 18 #define TRIBES2_RESPONSE_GAME_TYPES 4 #define TRIBES2_RESPONSE_MASTER 8 #define TRIBES2_RESPONSE_PING 16 #define TRIBES2_RESPONSE_INFO 20 #define TRIBES2_NO_COMPRESS 2 #define TRIBES2_DEFAULT_PACKET_INDEX 255 #define TRIBES2_STATUS_DEDICATED (1<<0) #define TRIBES2_STATUS_PASSWORD (1<<1) #define TRIBES2_STATUS_LINUX (1<<2) #define TRIBES2_STATUS_TOURNAMENT (1<<3) #define TRIBES2_STATUS_NOALIAS (1<<4) #define TRIBES2_STATUS_TEAMDAMAGE (1<<5) #define TRIBES2_STATUS_TOURNAMENT_VER3 (1<<6) #define TRIBES2_STATUS_NOALIAS_VER3 (1<<7) char tribes2_game_types_request[] = { TRIBES2_QUERY_GAME_TYPES, 0, 1,2,3,4 }; char tribes2_ping[] = { TRIBES2_QUERY_PING, TRIBES2_NO_COMPRESS, 1,2,3,4 }; char tribes2_info[] = { TRIBES2_QUERY_INFO, TRIBES2_NO_COMPRESS, 1,2,3,4 }; unsigned char tribes2_masterquery[] = { TRIBES2_QUERY_MASTER, 128, /* <= build 22228, this was 0 */ 11,12,13,14, 255, 3, 'a', 'n', 'y', 3, 'a', 'n', 'y', 0, 255, /* min/max players */ 0xff, 0xff, 0xff, 0xff, /* region mask */ 0, 0, 0, 0, /* build version */ 0, /* status */ 255, /* max bots */ 0, 0, /* min cpu */ 0 /* # buddies */ }; #define TRIBES2_ID_OFFSET 2 unsigned char descent3_masterquery[] = { 0x03, /* ID or something */ 0x24, 0x00, 0x00, 0x00, /* packet len */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* unknown */ 0x07, /* type */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* unknown */ 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x00 /* "global" */ }; /* for some reason Descent3 uses a different request for pxo/non-pxo games. blah. */ unsigned char descent3_pxoinfoquery[] = { 0x01, /* "internal descent3 routing" */ 0x29, /* request server info? (pxo listed servers) */ 0x0b, 0x00, /* packet length (- routing byte) */ 0x1b, 0x2f, 0xf4, 0x41, 0x09, 0x00, 0x00, 0x00 /* unknown */ }; unsigned char descent3_tcpipinfoquery[] = { 0x01, /* "internal descent3 routing" */ 0x1e, /* request server info? (tcpip only servers) */ 0x0b, 0x00, /* packet length (- routing byte) */ 0x1b, 0x2f, 0xf4, 0x41, 0x09, 0x00, 0x00, 0x00 /* unknown */ }; /* http://ml.warpcore.org/d3dl/200101/msg00001.html * http://ml.warpcore.org/d3dl/200101/msg00004.html */ unsigned char descent3_playerquery[] = { 0x01, /* "internal descent3 routing" */ 0x72, /* MP_REQUEST_PLAYERLIST */ 0x03, 0x00 /* packet length (- routing byte) */ }; unsigned char ghostrecon_serverquery[] = { 0xc0,0xde,0xf1,0x11, /* const ? header */ 0x42, /* start flag */ 0x03,0x00, /* data len */ 0xe9,0x03,0x00 /* server request ?? */ }; unsigned char ghostrecon_playerquery[] = { 0xc0,0xde,0xf1,0x11, /* const ? header */ 0x42, /* start flag */ 0x06,0x00, /* data len */ 0xf5,0x03,0x00,0x78,0x30,0x63 /* player request ?? may be flag 0xf5; len 0x03,0x00; data 0x78, 0x30, 0x63 */ }; /* All Seeing Eye */ char eye_status_query[1]= "s"; char eye_ping_query[1]= "p"; // Gamespy v2 // Format: // 1 - 3: query head // 4 - 7: queryid // 8: server + rules info (00 to disable) // 9: Player information (00 to disable) // 10: Team information (00 to disable) unsigned char gs2_status_query[] = { 0xfe,0xfd,0x00,0x10,0x20,0x30,0x40,0xff,0xff,0xff }; // Gamespy v3 // Format: // 1 - 3: query head // 4 - 7: queryid // 8: server + rules info (00 to disable) // 9: Player information (00 to disable) // 10: Team information (00 to disable) // 11: Request new format unsigned char gs3_player_query[] = { 0xfe,0xfd,0x00,0x10,0x20,0x30,0x40,0xff,0xff,0xff,0x01 }; // Format: // 1 - 3: query head // 4 - 7: queryid // 8: requested number of rules // 9 - 9 + no_rules: requested ruleid // last 2 : terminator? // Known ruleid's: // 0x01: hostname // 0x03: version // 0x04: hostport // 0x05: map // 0x06: gametype // 0x07: gamevarient // 0x08: num_players // 0x0a: max_players // 0x0b: gamemode unsigned char gs3_status_query[] = { 0xfe,0xfd,0x00, 0x10,0x20,0x30,0x40, 0x06,0x01,0x06,0x05,0x08,0x0a,0x04,0x00,0x00 }; // Gamespy v3 + challenge // Format: // 1 - 3: query head // 4 - 7: queryid unsigned char gs3_challenge[] = { 0xfe,0xfd,0x09,0x10,0x20,0x30,0x40 }; // Steam // Format: // 1. Request type ( 1 byte ) // 2. Region ( 1 byte ) // 3. ip ( string + null ) // 4. Filter ( optional + null ) // // Regions: // 0 = US East Coast // 1 = US West Coast // 2 = South America // 3 = Europe // 4 = Asia // 5 = Australia // 6 = Middle East // 7 = Africa // 255 = N/A // Filter: // \type\d = Returns only dedicated servers // // \secure\1 = Returns servers running anti-cheat technology // // \gamedir\[mod] = Servers running the specified modification. // The parameter is the directory that the mod resides in e.g. // cstrike for Counter-Strike or dod for Day of Defeat. // // \map\[map] = Returns servers running the specified map // (e.g. de_dust2 or cs_italy) // // \linux\1 = Servers running on the Linux platform // // \empty\1 = Servers that are not empty // // \full\1 = Servers that are not full // // \proxy\1 = Servers that are spectator proxies // // End the filter with 0x00 // unsigned char steam_masterquery_template[] = "1%c%s%c%s"; unsigned char savage_serverquery[] = { 0x9e,0x4c,0x23,0x00,0x00,0xc8,0x01,0x21,0x00,0x00 }; unsigned char savage_playerquery[] = { 0x9e,0x4c,0x23,0x00,0x00,0xce,0x76,0x46,0x00,0x00 }; unsigned char farcry_serverquery[] = { 0x08,0x80 }; char ravenshield_serverquery[] = "REPORT"; unsigned char ts2_status_query[] = "si"; server_type builtin_types[] = { { /* QUAKE */ Q_SERVER, /* id */ "QS", /* type_prefix */ "qs", /* type_string */ "-qs", /* type_option */ "Quake", /* game_name */ 0, /* master */ Q_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_RAW_STYLE_QUAKE, /* flags */ "*gamedir", /* game_rule */ "QUAKE", /* template_var */ (char*) &q_serverinfo, /* status_packet */ Q_SERVERINFO_LEN, /* status_len */ (char*) &q_player, /* player_packet */ Q_HEADER_LEN+1, /* player_len */ (char*) &q_rule, /* rule_packet */ sizeof( q_rule), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_q_packet, /* packet_func */ }, { /* HEXEN 2 */ H2_SERVER, /* id */ "H2S", /* type_prefix */ "h2s", /* type_string */ "-h2s", /* type_option */ "Hexen II", /* game_name */ 0, /* master */ HEXEN2_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_RAW_STYLE_QUAKE, /* flags */ "*gamedir", /* game_rule */ "HEXEN2", /* template_var */ (char*) &h2_serverinfo, /* status_packet */ H2_SERVERINFO_LEN, /* status_len */ (char*) &q_player, /* player_packet */ Q_HEADER_LEN+1, /* player_len */ (char*) &q_rule, /* rule_packet */ sizeof( q_rule), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_q_packet, /* packet_func */ }, { /* QUAKE WORLD */ QW_SERVER, /* id */ "QWS", /* type_prefix */ "qws", /* type_string */ "-qws", /* type_option */ "QuakeWorld", /* game_name */ 0, /* master */ QW_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "*gamedir", /* game_rule */ "QUAKEWORLD", /* template_var */ (char*) &qw_serverstatus, /* status_packet */ sizeof( qw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qw_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_qw_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_qw_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* HEXEN WORLD */ HW_SERVER, /* id */ "HWS", /* type_prefix */ "hws", /* type_string */ "-hws", /* type_option */ "HexenWorld", /* game_name */ 0, /* master */ HW_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "*gamedir", /* game_rule */ "HEXENWORLD", /* template_var */ (char*) &hw_serverstatus, /* status_packet */ sizeof( hw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qw_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_qw_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_qw_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* QUAKE 2 */ Q2_SERVER, /* id */ "Q2S", /* type_prefix */ "q2s", /* type_string */ "-q2s", /* type_option */ "Quake II", /* game_name */ 0, /* master */ Q2_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gamedir", /* game_rule */ "QUAKE2", /* template_var */ (char*) &qw_serverstatus, /* status_packet */ sizeof( qw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* QUAKE 3 */ Q3_SERVER, /* id */ "Q3S", /* type_prefix */ "q3s", /* type_string */ "-q3s", /* type_option */ "Quake III: Arena", /* game_name */ 0, /* master */ Q3_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES /* TF_SINGLE_QUERY */, /* flags */ "game", /* game_rule */ "QUAKE3", /* template_var */ (char*) &q3_serverinfo, /* status_packet */ sizeof( q3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ (char*) &q3_serverstatus, /* rule_packet */ sizeof( q3_serverstatus), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* DOOM 3 */ DOOM3_SERVER, /* id */ "DM3S", /* type_prefix */ "dm3s", /* type_string */ "-dm3s", /* type_option */ "Doom 3", /* game_name */ 0, /* master */ DOOM3_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES, /* flags */ "fs_game", /* game_rule */ "DOOM3", /* template_var */ (char*) &doom3_serverinfo, /* status_packet */ sizeof( doom3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_doom3_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_doom3_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_doom3_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_doom3_packet, /* packet_func */ }, { /* HALFLIFE 2 */ HL2_SERVER, /* id */ "HL2S", /* type_prefix */ "hl2s", /* type_string */ "-hl2s", /* type_option */ "Half-Life 2", /* game_name */ 0, /* master */ HL2_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES, /* flags */ "", /* game_rule */ "HL2", /* template_var */ (char*) &hl2_serverinfo, /* status_packet */ sizeof( hl2_serverinfo), /* status_len */ (char*) &hl2_playerinfo, /* player_packet */ sizeof( hl2_playerinfo), /* player_len */ (char*) &hl2_ruleinfo, /* rule_packet */ sizeof( hl2_ruleinfo), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_hl2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_hl2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_hl2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_hl2_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_hl2_packet, /* packet_func */ }, { /* RETURN TO CASTLE WOLFENSTEIN */ RTCW_SERVER, /* id */ "RWS", /* type_prefix */ "rws", /* type_string */ "-rws", /* type_option */ "Return to Castle Wolfenstein", /* game_name */ 0, /* master */ RTCW_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES /* TF_SINGLE_QUERY */, /* flags */ "game", /* game_rule */ "RTCW", /* template_var */ (char*) &q3_serverinfo, /* status_packet */ sizeof( q3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ (char*) &q3_serverstatus, /* rule_packet */ sizeof( q3_serverstatus), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* STAR TREK: ELITE FORCE */ STEF_SERVER, /* id */ "EFS", /* type_prefix */ "efs", /* type_string */ "-efs", /* type_option */ "Star Trek: Elite Force", /* game_name */ 0, /* master */ STEF_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES /* TF_SINGLE_QUERY */, /* flags */ "game", /* game_rule */ "ELITEFORCE", /* template_var */ (char*) &q3_serverinfo, /* status_packet */ sizeof( q3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ (char*) &q3_serverstatus, /* rule_packet */ sizeof( q3_serverstatus), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* JEDI KNIGHT: JEDI ACADEMY */ JK3_SERVER, /* id */ "JK3S", /* type_prefix */ "jk3s", /* type_string */ "-jk3s", /* type_option */ "Jedi Knight: Jedi Academy", /* game_name */ 0, /* master */ JK3_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES /* TF_SINGLE_QUERY */, /* flags */ "game", /* game_rule */ "JEDIKNIGHT3", /* template_var */ (char*) &q3_serverinfo, /* status_packet */ sizeof( q3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ (char*) &q3_serverstatus, /* rule_packet */ sizeof( q3_serverstatus), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* UNREAL TOURNAMENT 2003 */ UT2003_SERVER, /* id */ "UT2S", /* type_prefix */ "ut2s", /* type_string */ "-ut2s", /* type_option */ "Unreal Tournament 2003", /* game_name */ 0, /* master */ UNREAL_DEFAULT_PORT, /* default_port */ 1, /* port_offset */ TF_U2_NAMES, /* flags */ "gametype", /* game_rule */ "UNREALTOURNAMENT2003", /* template_var */ (char*) &ut2003_basicstatus,/* status_packet */ sizeof( ut2003_basicstatus),/* status_len */ NULL, /* player_packet */ 0, /* player_len */ (char*) &ut2003_allinfo, /* rule_packet */ sizeof( ut2003_allinfo), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ 0, /* master_query */ display_unreal_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_unreal_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_unreal_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_ut2003_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_ut2003_packet, /* packet_func */ }, { /* UNREAL */ UN_SERVER, /* id */ "UNS", /* type_prefix */ "uns", /* type_string */ "-uns", /* type_option */ "Unreal", /* game_name */ 0, /* master */ UNREAL_DEFAULT_PORT, /* default_port */ 1, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gametype", /* game_rule */ "UNREAL", /* template_var */ (char*) &unreal_serverstatus, /* status_packet */ sizeof( unreal_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_unreal_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_unreal_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_unreal_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gps_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gps_packet, /* packet_func */ }, { /* HALF LIFE */ HL_SERVER, /* id */ "HLS", /* type_prefix */ "hls", /* type_string */ "-hls", /* type_option */ "Half-Life", /* game_name */ 0, /* master */ HALFLIFE_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ 0, /* flags */ "game", /* game_rule */ "HALFLIFE", /* template_var */ (char*) &hl_details, /* status_packet */ sizeof( hl_details), /* status_len */ (char*) &hl_players, /* player_packet */ sizeof( hl_players), /* player_len */ (char*) &hl_rules, /* rule_packet */ sizeof( hl_rules), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_halflife_player_info,/* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_halflife_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_halflife_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ (void (*)( struct qserver *, char *, int)) deal_with_halflife_packet, /* packet_func */ }, { /* SIN */ SIN_SERVER, /* id */ "SNS", /* type_prefix */ "sns", /* type_string */ "-sns", /* type_option */ "Sin", /* game_name */ 0, /* master */ SIN_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gamedir", /* game_rule */ "SIN", /* template_var */ (char*) &qw_serverstatus, /* status_packet */ sizeof( qw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* SHOGO */ SHOGO_SERVER, /* id */ "SGS", /* type_prefix */ "sgs", /* type_string */ "-sgs", /* type_option */ "Shogo: Mobile Armor Division", /* game_name */ 0, /* master */ SHOGO_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ 0, /* flags */ "", /* game_rule */ "SHOGO", /* template_var */ (char*) &unreal_serverstatus, /* status_packet */ sizeof( unreal_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gps_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gps_packet, /* packet_func */ }, { /* TRIBES */ TRIBES_SERVER, /* id */ "TBS", /* type_prefix */ "tbs", /* type_string */ "-tbs", /* type_option */ "Tribes", /* game_name */ 0, /* master */ TRIBES_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "game", /* game_rule */ "TRIBES", /* template_var */ (char*) &tribes_info, /* status_packet */ sizeof( tribes_info), /* status_len */ (char*) &tribes_players, /* player_packet */ sizeof( tribes_players), /* player_len */ (char*) &tribes_players, /* rule_packet */ sizeof( tribes_players), /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_tribes_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_tribes_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_tribes_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_tribes_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_tribes_packet, /* packet_func */ }, { /* BFRIS */ BFRIS_SERVER, /* id */ "BFS", /* type_prefix */ "bfs", /* type_string */ "-bfs", /* type_option */ "BFRIS", /* game_name */ 0, /* master */ BFRIS_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_TCP_CONNECT, /* flags */ "Rules", /* game_rule */ "BFRIS", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_bfris_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_bfris_player_info,/* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_bfris_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_bfris_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_bfris_packet, /* packet_func */ }, { /* KINGPIN */ KINGPIN_SERVER, /* id */ "KPS", /* type_prefix */ "kps", /* type_string */ "-kps", /* type_option */ "Kingpin", /* game_name */ 0, /* master */ KINGPIN_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gamedir", /* game_rule */ "KINGPIN", /* template_var */ (char*) &qw_serverstatus, /* status_packet */ sizeof( qw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* HERETIC II */ HERETIC2_SERVER, /* id */ "HRS", /* type_prefix */ "hrs", /* type_string */ "-hrs", /* type_option */ "Heretic II", /* game_name */ 0, /* master */ HERETIC2_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gamedir", /* game_rule */ "HERETIC2", /* template_var */ (char*) &qw_serverstatus, /* status_packet */ sizeof( qw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* SOLDIER OF FORTUNE */ SOF_SERVER, /* id */ "SFS", /* type_prefix */ "sfs", /* type_string */ "-sfs", /* type_option */ "Soldier of Fortune", /* game_name */ 0, /* master */ SOF_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY|TF_SOF_NAMES, /* flags */ "gamedir", /* game_rule */ "SOLDIEROFFORTUNE", /* template_var */ (char*) &qw_serverstatus, /* status_packet */ sizeof( qw_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_q2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_q2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_q2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qw_packet, /* packet_func */ }, { /* GAMESPY PROTOCOL */ GAMESPY_PROTOCOL_SERVER, /* id */ "GPS", /* type_prefix */ "gps", /* type_string */ "-gps", /* type_option */ "Gamespy Protocol", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY|TF_U2_NAMES, /* flags */ "gametype", /* game_rule */ "GAMESPYPROTOCOL", /* template_var */ (char*) &unreal_serverstatus, /* status_packet */ sizeof( unreal_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_unreal_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_unreal_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_unreal_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gps_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gps_packet, /* packet_func */ }, { /* TRIBES 2 */ TRIBES2_SERVER, /* id */ "T2S", /* type_prefix */ "t2s", /* type_string */ "-t2s", /* type_option */ "Tribes 2", /* game_name */ 0, /* master */ TRIBES2_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ 0, /* flags */ "game", /* game_rule */ "TRIBES2", /* template_var */ (char*) &tribes2_ping, /* status_packet */ sizeof( tribes2_ping), /* status_len */ (char*) &tribes2_info, /* player_packet */ sizeof( tribes2_info), /* player_len */ (char*) NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_tribes2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_tribes2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_tribes2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_tribes2_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_tribes2_packet, /* packet_func */ }, { /* DESCENT3 GAMESPY PROTOCOL */ DESCENT3_GAMESPY_SERVER, /* id */ "D3G", /* type_prefix */ "d3g", /* type_string */ "-d3g", /* type_option */ "Descent3 Gamespy Protocol", /* game_name */ 0, /* master */ DESCENT3_GAMESPY_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gametype", /* game_rule */ "DESCENT3", /* template_var */ (char*) &unreal_serverstatus, /* status_packet */ sizeof( unreal_serverstatus), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_descent3_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_descent3_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_descent3_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gps_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gps_packet, /* packet_func */ }, { /* DESCENT3 PROTOCOL */ DESCENT3_SERVER, /* id */ "D3S", /* type_prefix */ "d3s", /* type_string */ "-d3s", /* type_option */ "Descent3", /* game_name */ 0, /* master */ DESCENT3_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ 0, /* flags */ "gametype", /* game_rule */ "DESCENT3", /* template_var */ (char*) &descent3_tcpipinfoquery, /* status_packet */ sizeof( descent3_tcpipinfoquery), /* status_len */ (char*) &descent3_playerquery, /* player_packet */ sizeof( descent3_playerquery), /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_descent3_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_descent3_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_descent3_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gps_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_descent3_packet, /* packet_func */ }, { /* DESCENT3 PROTOCOL */ DESCENT3_PXO_SERVER, /* id */ "D3P", /* type_prefix */ "d3p", /* type_string */ "-d3p", /* type_option */ "Descent3 PXO protocol", /* game_name */ 0, /* master */ DESCENT3_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ 0, /* flags */ "gametype", /* game_rule */ "DESCENT3", /* template_var */ (char*) &descent3_pxoinfoquery, /* status_packet */ sizeof( descent3_pxoinfoquery), /* status_len */ (char*) &descent3_playerquery, /* player_packet */ sizeof( descent3_playerquery), /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_descent3_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_descent3_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_descent3_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gps_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_descent3_packet, /* packet_func */ }, { /* GHOSTRECON PROTOCOL */ GHOSTRECON_SERVER, /* id */ "GRS", /* type_prefix */ "grs", /* type_string */ "-grs", /* type_option */ "Ghost Recon", /* game_name */ 0, /* master */ GHOSTRECON_PLAYER_DEFAULT_PORT, /* default_port */ 2, /* port_offset */ TF_QUERY_ARG, /* flags */ "gametype", /* game_rule */ "GHOSTRECON", /* template_var */ (char*) &ghostrecon_playerquery, /* status_packet */ sizeof( ghostrecon_playerquery), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_ghostrecon_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_ghostrecon_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_ghostrecon_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_ghostrecon_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_ghostrecon_packet, /* packet_func */ }, { /* ALL SEEING EYE PROTOCOL */ ALLSEEINGEYE_PROTOCOL_SERVER, /* id */ "EYE", /* type_prefix */ "eye", /* type_string */ "-eye", /* type_option */ "All Seeing Eye Protocol", /* game_name */ 0, /* master */ 0, /* default_port */ 123, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gametype", /* game_rule */ "EYEPROTOCOL", /* template_var */ (char*) &eye_status_query, /* status_packet */ sizeof( eye_status_query), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_eye_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_eye_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_eye_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_eye_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_eye_packet, /* packet_func */ }, { /* GAMESPY V2 PROTOCOL */ GAMESPY2_PROTOCOL_SERVER, /* id */ "GS2", /* type_prefix */ "gs2", /* type_string */ "-gs2", /* type_option */ "Gamespy V2 Protocol", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gametype", /* game_rule */ "GPS2PROTOCOL", /* template_var */ (char*) &gs2_status_query, /* status_packet */ sizeof( gs2_status_query), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_gs2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_gs2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_gs2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gs2_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gs2_packet, /* packet_func */ }, { /* AMERICA'S ARMY EXTENSION (GS2 BASED) */ ARMYOPS_SERVER, /* id */ "AMS", /* type_prefix */ "ams", /* type_string */ "-ams", /* type_option */ "America's Army v2.x", /* game_name */ 0, /* master */ 1716, /* default_port */ 1, /* port_offset */ TF_SINGLE_QUERY|TF_U2_NAMES, /* flags */ "gametype", /* game_rule */ "AMERICASARMY", /* template_var */ (char*) &gs2_status_query, /* status_packet */ sizeof( gs2_status_query), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_armyops_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_armyops_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_armyops_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gs2_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gs2_packet, /* packet_func */ }, { /* RAVENSHIELD PROTOCOL */ RAVENSHIELD_SERVER, /* id */ "RSS", /* type_prefix */ "rss", /* type_string */ "-rss", /* type_option */ "Ravenshield", /* game_name */ 0, /* master */ RAVENSHIELD_DEFAULT_PORT, /* default_port */ 1000, /* port_offset */ TF_QUERY_ARG, /* flags */ "gametype", /* game_rule */ "RAVENSHIELD", /* template_var */ (char*)ravenshield_serverquery, /* status_packet */ sizeof( ravenshield_serverquery ) - 1, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_ravenshield_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_ravenshield_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_ravenshield_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_ravenshield_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_ravenshield_packet, /* packet_func */ }, { /* SAVAGE PROTOCOL */ SAVAGE_SERVER, /* id */ "SAS", /* type_prefix */ "sas", /* type_string */ "-sas", /* type_option */ "Savage", /* game_name */ 0, /* master */ SAVAGE_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUERY_ARG, /* flags */ "gametype", /* game_rule */ "SAVAGE", /* template_var */ (char*)savage_serverquery, /* status_packet */ sizeof( savage_serverquery ) - 1, /* status_len */ (char*)savage_playerquery, /* player_packet */ sizeof( savage_playerquery ) - 1, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_savage_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_savage_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_savage_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_savage_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_savage_packet, /* packet_func */ }, { /* FARCRY PROTOCOL */ FARCRY_SERVER, /* id */ "FCS", /* type_prefix */ "fcs", /* type_string */ "-fcs", /* type_option */ "FarCry", /* game_name */ 0, /* master */ FARCRY_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUERY_ARG, /* flags */ "gametype", /* game_rule */ "FARCRY", /* template_var */ (char*)farcry_serverquery, /* status_packet */ sizeof( savage_serverquery ) - 1, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_farcry_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_farcry_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_farcry_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_farcry_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_farcry_packet, /* packet_func */ }, /* --- MASTER SERVERS --- */ { /* QUAKE WORLD MASTER */ QW_MASTER, /* id */ "QWM", /* type_prefix */ "qwm", /* type_string */ "-qwm", /* type_option */ /* ## also "-qw" */ "QuakeWorld Master", /* game_name */ QW_SERVER, /* master */ QW_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY|TF_OUTFILE, /* flags */ "", /* game_rule */ "QWMASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) &qw_masterquery, /* master_packet */ sizeof( qw_masterquery), /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* QUAKE 2 MASTER */ Q2_MASTER, /* id */ "Q2M", /* type_prefix */ "q2m", /* type_string */ "-q2m", /* type_option */ /* ## also "-qw" */ "Quake II Master", /* game_name */ Q2_SERVER, /* master */ Q2_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY|TF_OUTFILE, /* flags */ "", /* game_rule */ "Q2MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ q2_masterquery, /* master_packet */ sizeof( q2_masterquery), /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* QUAKE 3 MASTER */ Q3_MASTER, /* id */ "Q3M", /* type_prefix */ "q3m", /* type_string */ "-q3m", /* type_option */ "Quake III Master", /* game_name */ Q3_SERVER, /* master */ Q3_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE | TF_QUERY_ARG, /* flags */ "", /* game_rule */ "Q3MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ q3_master_query_template, /* master_packet */ 0, /* master_len */ q3_master_default_protocol, /* master_protocol */ q3_master_default_query, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* DOOM 3 MASTER */ DOOM3_MASTER, /* id */ "DM3M", /* type_prefix */ "dm3m", /* type_string */ "-dm3m", /* type_option */ "Doom 3 Master", /* game_name */ DOOM3_SERVER, /* master */ DOOM3_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE|TF_QUERY_ARG, /* flags */ "", /* game_rule */ "DOOM3MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_doom3master_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_doom3master_packet, /* packet_func */ }, { /* RETURN TO CASTLE WOLFENSTEIN MASTER */ RTCW_MASTER, /* id */ "RWM", /* type_prefix */ "rwm", /* type_string */ "-rwm", /* type_option */ "Return to Castle Wolfenstein Master", /* game_name */ RTCW_SERVER, /* master */ RTCW_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE | TF_QUERY_ARG, /* flags */ "", /* game_rule */ "RTCWMASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ q3_master_query_template, /* master_packet */ 0, /* master_len */ rtcw_master_default_protocol, /* master_protocol */ q3_master_default_query, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* STAR TREK: ELITE FORCE MASTER */ STEF_MASTER, /* id */ "EFM", /* type_prefix */ "efm", /* type_string */ "-efm", /* type_option */ "Star Trek: Elite Force", /* game_name */ STEF_SERVER, /* master */ STEF_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE | TF_QUERY_ARG, /* flags */ "", /* game_rule */ "ELITEFORCEMASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ q3_master_query_template, /* master_packet */ 0, /* master_len */ stef_master_default_protocol, /* master_protocol */ q3_master_default_query, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* JEDI KNIGHT 3 FORCE MASTER */ JK3_MASTER, /* id */ "JK3M", /* type_prefix */ "jk3m", /* type_string */ "-jk3m", /* type_option */ "Jedi Knight: Jedi Academy", /* game_name */ JK3_SERVER, /* master */ JK3_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE | TF_QUERY_ARG, /* flags */ "", /* game_rule */ "JK3MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ q3_master_query_template, /* master_packet */ 0, /* master_len */ jk3_master_default_protocol, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* HALF-LIFE MASTER */ HL_MASTER, /* id */ "HLM", /* type_prefix */ "hlm", /* type_string */ "-hlm", /* type_option */ /* ## also "-qw" */ "Half-Life Master", /* game_name */ HL_SERVER, /* master */ HL_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY|TF_OUTFILE|TF_QUERY_ARG, /* flags */ "", /* game_rule */ "HLMASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) &new_hl_masterquery_prefix, /* master_packet */ sizeof( new_hl_masterquery_prefix), /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* TRIBES MASTER */ TRIBES_MASTER, /* id */ "TBM", /* type_prefix */ "tbm", /* type_string */ "-tbm", /* type_option */ "Tribes Master", /* game_name */ TRIBES_SERVER, /* master */ TRIBES_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE, /* flags */ "", /* game_rule */ "TRIBESMASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) &tribes_masterquery,/* master_packet */ sizeof( tribes_masterquery),/* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_tribesmaster_packet,/* packet_func */ }, { /* GAMESPY MASTER */ GAMESPY_MASTER, /* id */ "GSM", /* type_prefix */ "gsm", /* type_string */ "-gsm", /* type_option */ "Gamespy Master", /* game_name */ GAMESPY_PROTOCOL_SERVER, /* master */ GAMESPY_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE | TF_TCP_CONNECT | TF_QUERY_ARG | TF_QUERY_ARG_REQUIRED, /* flags */ "", /* game_rule */ "GAMESPYMASTER", /* template_var */ (char*) &gamespy_master_request_prefix, /* status_packet */ sizeof( gamespy_master_request_prefix)-1, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) &gamespy_master_validate,/* master_packet */ sizeof( gamespy_master_validate)-1,/* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_gamespy_master_request,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gamespy_master_response,/* packet_func */ }, { /* TRIBES 2 MASTER */ TRIBES2_MASTER, /* id */ "T2M", /* type_prefix */ "t2m", /* type_string */ "-t2m", /* type_option */ "Tribes 2 Master", /* game_name */ TRIBES2_SERVER, /* master */ TRIBES2_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE | TF_QUERY_ARG, /* flags */ "", /* game_rule */ "TRIBES2MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) &tribes2_masterquery,/* master_packet */ sizeof( tribes2_masterquery),/* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_tribes2master_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_tribes2master_packet,/* packet_func */ }, { /* DESCENT3 MASTER */ DESCENT3_MASTER, /* id */ "D3M", /* type_prefix */ "d3m", /* type_string */ "-d3m", /* type_option */ /* ## also "-qw" */ "Descent3 Master (PXO)", /* game_name */ DESCENT3_PXO_SERVER, /* master */ DESCENT3_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_MASTER_MULTI_RESPONSE|TF_OUTFILE, /* flags */ "", /* game_rule */ "D3MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*)descent3_masterquery, /* master_packet */ sizeof( descent3_masterquery), /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_descent3master_packet, /* packet_func */ }, { /* STEAM MASTER */ STEAM_MASTER, /* id */ "STM", /* type_prefix */ "stm", /* type_string */ "-stm", /* type_option */ /* ## also "-qw" */ "Steam Master", /* game_name */ A2S_SERVER, /* master */ STEAM_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY|TF_OUTFILE|TF_QUERY_ARG|TF_MASTER_STEAM, /* flags */ "", /* game_rule */ "STEAMMASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) &steam_masterquery_template, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_qwmaster_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_qwmaster_packet, /* packet_func */ }, { /* UT2004 MASTER */ UT2004_MASTER, /* id */ "UT2004M", /* type_prefix */ "ut2004m", /* type_string */ "-ut2004m", /* type_option */ "UT2004 Master", /* game_name */ UT2003_SERVER, /* master */ 28902, /* default_port */ 0, /* port_offset */ TF_OUTFILE|TF_QUERY_ARG|TF_TCP_CONNECT, /* flags */ "", /* game_rule */ "UT2004MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_ut2004master_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_ut2004master_packet, /* packet_func */ }, { /* HALFLIFE 2 */ A2S_SERVER, /* id */ "A2S", /* type_prefix */ "a2s", /* type_string */ "-a2s", /* type_option */ "Half-Life 2 new", /* game_name */ 0, /* master */ HL2_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES, /* flags */ "gamedir", /* game_rule */ "A2S", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_hl2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_hl2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_hl2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_a2s_request_packet, /* status_query_func */ send_a2s_rule_request_packet, /* rule_query_func */ NULL, /* player_query_func */ deal_with_a2s_packet, /* packet_func */ }, { /* PARIAH */ PARIAH_SERVER, /* id */ "PRS", /* type_prefix */ "prs", /* type_string */ "-prs", /* type_option */ "Pariah", /* game_name */ 0, /* master */ UNREAL_DEFAULT_PORT, /* default_port */ 1, /* port_offset */ TF_U2_NAMES, /* flags */ "gametype", /* game_rule */ "UNREALTOURNAMENT2003", /* template_var */ (char*) &pariah_basicstatus,/* status_packet */ sizeof( pariah_basicstatus),/* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ 0, /* master_query */ display_unreal_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_unreal_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_unreal_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_ut2003_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_ut2003_packet, /* packet_func */ }, { /* GAMESPY V3 PROTOCOL */ GAMESPY3_PROTOCOL_SERVER, /* id */ "GS3", /* type_prefix */ "gs3", /* type_string */ "-gs3", /* type_option */ "Gamespy V3 Protocol", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gametype", /* game_rule */ "GPS3PROTOCOL", /* template_var */ (char*) &gs3_status_query, /* status_packet */ sizeof( gs3_status_query), /* status_len */ (char*) &gs3_player_query, /* player_packet */ sizeof( gs3_player_query), /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_gs2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_gs2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_gs2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gs3_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gs3_packet, /* packet_func */ }, { /* TEAMSPEAK 2 PROTOCOL */ TS2_PROTOCOL_SERVER, /* id */ "TS2", /* type_prefix */ "ts2", /* type_string */ "-ts2", /* type_option */ "Teamspeak 2", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_TCP_CONNECT|TF_QUERY_ARG_REQUIRED|TF_QUERY_ARG, /* flags */ "N/A", /* game_rule */ "TS2PROTOCOL", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_ts2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_ts2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_ts2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_ts2_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_ts2_packet, /* packet_func */ }, { /* QUAKE 4 */ QUAKE4_SERVER, /* id */ "Q4S", /* type_prefix */ "q4s", /* type_string */ "-q4s", /* type_option */ "Quake 4", /* game_name */ 0, /* master */ QUAKE4_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES, /* flags */ "fs_game", /* game_rule */ "QUAKE4", /* template_var */ (char*) &doom3_serverinfo, /* status_packet */ sizeof( doom3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_doom3_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_doom3_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_doom3_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_quake4_packet, /* packet_func */ }, { /* QUAKE 4 MASTER */ QUAKE4_MASTER, /* id */ "Q4M", /* type_prefix */ "q4m", /* type_string */ "-q4m", /* type_option */ "Quake 4 Master", /* game_name */ QUAKE4_SERVER, /* master */ QUAKE4_MASTER_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_OUTFILE|TF_QUERY_ARG, /* flags */ "", /* game_rule */ "QUAKE4MASTER", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_qwmaster, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ send_quake4master_request_packet,/* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_doom3master_packet, /* packet_func */ }, { /* GAMESPY V4 PROTOCOL */ GAMESPY4_PROTOCOL_SERVER, /* id */ "GS4", /* type_prefix */ "gs4", /* type_string */ "-gs4", /* type_option */ "Gamespy V4 Protocol", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_SINGLE_QUERY, /* flags */ "gametype", /* game_rule */ "GPS4PROTOCOL", /* template_var */ (char*) &gs3_challenge, /* status_packet */ sizeof( gs3_challenge), /* status_len */ (char*) &gs3_challenge, /* player_packet */ sizeof( gs3_challenge), /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_gs2_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_gs2_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_gs2_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_gs3_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_gs3_packet, /* packet_func */ }, { /* PREY */ PREY_SERVER, /* id */ "PREYS", /* type_prefix */ "preys", /* type_string */ "-preys", /* type_option */ "PREY", /* game_name */ 0, /* master */ PREY_DEFAULT_PORT, /* default_port */ 0, /* port_offset */ TF_QUAKE3_NAMES, /* flags */ "fs_game", /* game_rule */ "PREY", /* template_var */ (char*) &doom3_serverinfo, /* status_packet */ sizeof( doom3_serverinfo), /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_doom3_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_doom3_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_doom3_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_qwserver_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_prey_packet, /* packet_func */ }, { /* TRACKMANIA PROTOCOL */ TM_PROTOCOL_SERVER, /* id */ "TM", /* type_prefix */ "tm", /* type_string */ "-tm", /* type_option */ "TrackMania", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ TF_TCP_CONNECT|TF_QUERY_ARG|TF_TM_NAMES, /* flags */ "N/A", /* game_rule */ "TMPROTOCOL", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ NULL, /* master_packet */ 0, /* master_len */ NULL, /* master_protocol */ NULL, /* master_query */ display_tm_player_info, /* display_player_func */ display_server_rules, /* display_rule_func */ raw_display_tm_player_info, /* display_raw_player_func */ raw_display_server_rules, /* display_raw_rule_func */ xml_display_tm_player_info, /* display_xml_player_func */ xml_display_server_rules, /* display_xml_rule_func */ send_tm_request_packet, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ deal_with_tm_packet, /* packet_func */ }, { Q_UNKNOWN_TYPE, /* id */ "", /* type_prefix */ "", /* type_string */ "", /* type_option */ "", /* game_name */ 0, /* master */ 0, /* default_port */ 0, /* port_offset */ 0, /* flags */ "", /* game_rule */ "", /* template_var */ NULL, /* status_packet */ 0, /* status_len */ NULL, /* player_packet */ 0, /* player_len */ NULL, /* rule_packet */ 0, /* rule_len */ (char*) NULL, /* master_packet */ 0, /* master_len */ NULL, /* display_player_func */ NULL, /* display_rule_func */ NULL, /* display_raw_player_func */ NULL, /* display_raw_rule_func */ NULL, /* display_xml_player_func */ NULL, /* display_xml_rule_func */ NULL, /* status_query_func */ NULL, /* rule_query_func */ NULL, /* player_query_func */ NULL, /* packet_func */ } }; #endif /* QUERY_PACKETS */ /* Structures for keeping information about Quake servers, server * rules, and players. */ struct player; #define FLAG_BROADCAST (1<<1) #define FLAG_PLAYER_TEAMS (1<<2) #define FLAG_DO_NOT_FREE_GAME (1<<3) #define PLAYER_TYPE_NORMAL 1 #define PLAYER_TYPE_BOT 2 #define PLAYER_TYPE_ALIAS 4 #define PLAYER_FLAG_DO_NOT_FREE_TEAM 1 struct player { int number; char *name; int frags; int team; /* Unreal and Tribes only */ char *team_name; /* Tribes, BFRIS only, do not free() */ int connect_time; int shirt_color; int pants_color; char *address; int ping; short flags; short type_flag; /* Tribes 2 only */ int packet_loss; /* Tribes only */ char *tribe_tag; /* Tribes 2 / Quake 4 clan name */ char *skin; char *mesh; /* Unreal only */ char *face; /* Unreal only */ int score; /* BFRIS only */ int ship; /* BFRIS only */ int room; /* BFRIS only */ int deaths; /* Descent3 only */ char *next_info; int n_info; struct info *info; struct info **last_info; int missing_rules; struct player *next; }; struct rule { char *name; char *value; struct rule *next; }; struct info { char *name; char *value; struct info *next; }; extern char *qstat_version; extern char *DOWN; extern char *SYSERROR; extern char *TIMEOUT; extern char *MASTER; extern char *SERVERERROR; extern char *HOSTNOTFOUND; extern int n_retries; extern struct timeval packet_recv_time; #define DEFAULT_RETRIES 3 #define DEFAULT_RETRY_INTERVAL 500 /* milli-seconds */ #define MAXFD_DEFAULT 20 #define SORT_GAME 1 #define SORT_PING 2 extern int first_sort_key; extern int second_sort_key; #define SECONDS 0 #define CLOCK_TIME 1 #define STOPWATCH_TIME 2 #define DEFAULT_TIME_FMT_RAW SECONDS #define DEFAULT_TIME_FMT_DISPLAY CLOCK_TIME extern int time_format; extern int color_names; extern int show_errors; extern int get_player_info; extern int get_server_rules; extern int no_port_offset; /* Definitions for the original Quake network protocol. */ #define PACKET_LEN 0xffff /* Quake packet formats and magic numbers */ struct qheader { unsigned char flag1; unsigned char flag2; unsigned short length; unsigned char op_code; }; #define Q_NET_PROTOCOL_VERSION 3 #define HEXEN2_NET_PROTOCOL_VERSION 4 #define Q_CCREQ_CONNECT 0x01 #define Q_CCREP_ACCEPT 0x81 #define Q_CCREP_REJECT 0x82 #define Q_CCREP_SERVER_INFO 0x83 #define Q_CCREP_PLAYER_INFO 0x84 #define Q_CCREP_RULE_INFO 0x85 #define Q_DEFAULT_SV_MAXSPEED "320" #define Q_DEFAULT_SV_FRICTION "4" #define Q_DEFAULT_SV_GRAVITY "800" #define Q_DEFAULT_NOEXIT "0" #define Q_DEFAULT_TEAMPLAY "0" #define Q_DEFAULT_TIMELIMIT "0" #define Q_DEFAULT_FRAGLIMIT "0" /* Definitions for the QuakeWorld network protocol */ /* #define QW_GET_SERVERS 'c' */ #define QW_SERVERS 'd' #define HL_SERVERS 'f' /* HL master: send 'a', master responds with a small 'l' packet containing the text "Outdated protocol" HL master: send 'e', master responds with a small 'f' packet HL master: send 'g', master responds with a small 'h' packet containing name of master server HL master: send 'i', master responds with a small 'j' packet */ #define QW_GET_USERINFO 'o' #define QW_USERINFO 'p' #define QW_GET_SEENINFO 'u' #define QW_SEENINFO 'v' #define QW_NACK 'm' #define QW_NEWLINE '\n' #define QW_RULE_SEPARATOR '\\' #define QW_REQUEST_LENGTH 20 int is_default_rule( struct rule *rule); char *xform_name( char*, struct qserver *server); char *quake_color( int color); char *play_time( int seconds, int show_seconds); char *ping_time( int ms); char *get_qw_game( struct qserver *server); /* * Query status and packet handling functions */ int cleanup_qserver( struct qserver *server, int force); void change_server_port( struct qserver *server, unsigned short port, int force ); int server_info_packet( struct qserver *server, struct q_packet *pkt, int datalen ); int player_info_packet( struct qserver *server, struct q_packet *pkt, int datalen ); int rule_info_packet( struct qserver *server, struct q_packet *pkt, int datalen ); int time_delta( struct timeval *later, struct timeval *past); char * strherror( int h_err); int connection_refused(); void add_file( char *filename); int add_qserver( char *arg, server_type* type, char *outfilename, char *query_arg); struct qserver* add_qserver_byaddr( unsigned int ipaddr, unsigned short port, server_type* type, int *new_server); void init_qserver( struct qserver *server, server_type* type); int bind_qserver( struct qserver *server); int bind_sockets(); void send_packets(); struct qserver * find_server_by_address( unsigned int ipaddr, unsigned short port); void add_server_to_hash( struct qserver *server); #define NO_FLAGS 0 #define NO_VALUE_COPY 1 #define CHECK_DUPLICATE_RULES 2 #define NO_KEY_COPY 4 #define COMBINE_VALUES 8 struct player* get_player_by_number( struct qserver *server, int player_number ); struct rule* add_rule( struct qserver *server, char *key, char *value, int flags) ; struct player* add_player( struct qserver *server, int player_number ); struct info* player_add_info( struct player *player, char *key, char *value, int flags ); void players_set_teamname( struct qserver *server, int teamid, char *teamname ); /* * Output template stuff */ int read_qserver_template( char *filename); int read_rule_template( char *filename); int read_header_template( char *filename); int read_trailer_template( char *filename); int read_player_template( char *filename); int have_server_template(); int have_header_template(); int have_trailer_template(); void template_display_server( struct qserver *server); void template_display_header(); void template_display_trailer(); void template_display_players( struct qserver *server); void template_display_player( struct qserver *server, struct player *player); void template_display_rules( struct qserver *server); void template_display_rule( struct qserver *server, struct rule *rule); /* * Host cache stuff */ int hcache_open( char *filename, int update); void hcache_write( char *filename); void hcache_invalidate(); void hcache_validate(); unsigned long hcache_lookup_hostname( char *hostname); char * hcache_lookup_ipaddr( unsigned long ipaddr); void hcache_write_file( char *filename); void hcache_update_file(); unsigned int swap_long_from_little( void *l); unsigned short swap_short_from_little( void *l); float swap_float_from_little( void *f); /** \brief write four bytes in little endian order */ void put_long_little(unsigned val, char* buf); /* * Exported Globals */ extern int show_game_port; #define NA_INT -32767 #define NO_PLAYER_INFO 0xffff #define NO_SERVER_RULES NULL #endif qstat-2.11/ts2.c0000644002404400000620000000555510435066370010400 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Gamespy query protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms * */ #include #ifndef _WIN32 #include #endif #include #include #include #include "debug.h" #include "qstat.h" #include "packet_manip.h" void send_ts2_request_packet( struct qserver *server ) { char buf[256]; int serverport = get_param_i_value( server, "port", 0 ); change_server_port( server, serverport, 1 ); if ( get_player_info ) { server->flags |= TF_PLAYER_QUERY|TF_RULES_QUERY; sprintf( buf, "si %d\npl %d\nquit\n", serverport, serverport ); server->saved_data.pkt_index = 2; } else { server->flags |= TF_STATUS_QUERY; sprintf( buf, "si %d\nquit\n", serverport ); server->saved_data.pkt_index = 1; } send_packet( server, buf, strlen( buf ) ); } void deal_with_ts2_packet( struct qserver *server, char *rawpkt, int pktlen ) { char *s, *end; int ping, connect_time; char name[256]; debug( 2, "processing..." ); server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 ); } else { gettimeofday( &server->packet_time1, NULL); } rawpkt[pktlen]= '\0'; end = &rawpkt[pktlen]; s = rawpkt; s = strtok( rawpkt, "\015\012" ); while ( NULL != s ) { char *key = s; char *value = strchr( key, '=' ); if ( NULL != value ) { // Server Rule *value = '\0'; value++; if ( 0 == strcmp( "server_name", key ) ) { server->server_name = strdup( value ); } else if ( 0 == strcmp( "server_udpport", key ) ) { change_server_port( server, atoi( value ), 0 ); add_rule( server, key, value, NO_FLAGS ); } else if ( 0 == strcmp( "server_maxusers", key ) ) { server->max_players = atoi( value ); } else if ( 0 == strcmp( "server_currentusers", key ) ) { server->num_players = atoi( value); } else { add_rule( server, key, value, NO_FLAGS); } } else if ( 3 == sscanf( s, "%*d %*d %*d %*d %*d %*d %*d %d %d %*d %*d %*d %*d \"0.0.0.0\" \"%255[^\"]", &ping, &connect_time, name ) ) { // Player info struct player *player = add_player( server, server->n_player_info ); if ( NULL != player ) { player->name = strdup( name ); player->ping = ping; player->connect_time = connect_time; } } else if ( 0 == strcmp( "OK", s ) ) { // end of request result server->saved_data.pkt_index--; } else if ( 0 == strcmp( "[TS]", s ) ) { // nothing to do } else if ( 0 == strcmp( "ERROR, invalid id", s ) ) { // bad server server->server_name = DOWN; server->saved_data.pkt_index = 0; } s = strtok( NULL, "\015\012" ); } if ( 0 == server->saved_data.pkt_index ) { server->map_name = strdup( "N/A" ); cleanup_qserver( server, 1 ); } } qstat-2.11/ts2.h0000644002404400000620000000063510314271063010370 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Teamspeak 2 protocol * Copyright 2005 Steven Hartland * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_GPS_H #define QSTAT_GPS_H #include "qserver.h" // Packet processing methods void deal_with_ts2_packet( struct qserver *server, char *pkt, int pktlen ); void send_ts2_request_packet( struct qserver *server ); #endif qstat-2.11/doom3.c0000644002404400000620000002602610455041101010670 00000000000000/* * qstat 2.9 * by Steve Jankowski * * Doom3 / Quake4 protocol * Copyright 2005 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include #ifndef _WIN32 #include #endif #include #include #include "qstat.h" #include "debug.h" #include "assert.h" static const char doom3_master_query[] = "\xFF\xFFgetServers\x00\x00\x00\x00\x00\x00"; // version ^^^^^^^^^^^^^^^^ // null terminated mod string ^^^^ // filterbyte ^^^^ static const char quake4_master_query[] = "\xFF\xFFgetServers\x00\x00\x00\x00\x00\x00\x00\x00"; // version ^^^^^^^^^^^^^^^^ // null terminated mod string ^^^^ // null terminated player string ^^^^ // null terminated clan string ^^^^ // filterbyte ^^^^ static unsigned put_param_string(struct qserver* server, const char* paramname, char* buf, unsigned buflen, unsigned off) { char* val = get_param_value( server, paramname, NULL); if(val && strlen(val) < buflen-off-2) { strcpy(buf+off, val); off += strlen(val) + 1; } else { buf[off++] = '\0'; } return off; } static char* build_doom3_masterfilter(struct qserver* server, char* buf, unsigned* buflen, int q4) { int flen = 0; char *pkt, *r, *sep= ""; unsigned char b = 0; char *proto = server->query_arg; unsigned ver; unsigned off = 13; if(!proto) { if(q4) { *buflen = sizeof(quake4_master_query); return (char*)quake4_master_query; } else { *buflen = sizeof(doom3_master_query); return (char*)doom3_master_query; } } ver = (atoi(proto) & 0xFFFF) << 16; proto = strchr(proto, '.'); if(proto && *++proto) { ver |= (atoi(proto) & 0xFFFF); } if(q4) { ver |= 1 << 31; // third party flag } memcpy(buf, doom3_master_query, sizeof(doom3_master_query)); put_long_little(ver, buf+off); off += 4; off = put_param_string(server, "game", buf, *buflen, off); if(q4) { off = put_param_string(server, "player", buf, *buflen, off); off = put_param_string(server, "clan", buf, *buflen, off); } pkt = get_param_value( server, "status", NULL); r = pkt ; while ( pkt && sep ) { sep= strchr( r, ':'); if ( sep ) flen= sep-r; else flen= strlen(r); if ( strncmp( r, "password", flen) == 0) b |= 0x01; else if ( strncmp( r, "nopassword", flen) == 0) b |= 0x02; else if ( strncmp( r, "notfull", flen) == 0) b |= 0x04; else if ( strncmp( r, "notfullnotempty", flen) == 0) b |= 0x08; r= sep+1; } pkt = get_param_value( server, "gametype", NULL); if(pkt) { if ( strncmp( pkt, "dm", flen) == 0) b |= 0x10; else if ( strncmp( pkt, "tourney", flen) == 0) b |= 0x20; else if ( strncmp( pkt, "tdm", flen) == 0) b |= 0x30; } buf[off++] = (char)b; *buflen = off; return buf; } void send_doom3master_request_packet( struct qserver *server) { int rc = 0; int packet_len = -1; char* packet = NULL; char query_buf[4096] = {0}; server->next_player_info = NO_PLAYER_INFO; packet_len = sizeof(query_buf); packet = build_doom3_masterfilter(server, query_buf, (unsigned*)&packet_len, 0); rc= send( server->fd, packet, packet_len, 0); if ( rc == SOCKET_ERROR) { perror( "send"); } if ( server->retry1 == n_retries) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } else { server->n_retries++; } server->retry1--; server->n_packets++; } void send_quake4master_request_packet( struct qserver *server) { int rc = 0; int packet_len = -1; char* packet = NULL; char query_buf[4096] = {0}; server->next_player_info = NO_PLAYER_INFO; packet_len = sizeof(query_buf); packet = build_doom3_masterfilter(server, query_buf, (unsigned*)&packet_len, 1); rc= send( server->fd, packet, packet_len, 0); if ( rc == SOCKET_ERROR) { perror( "send"); } if ( server->retry1 == n_retries) { gettimeofday( &server->packet_time1, NULL); server->n_requests++; } else { server->n_retries++; } server->retry1--; server->n_packets++; } static const char doom3_masterresponse[] = "\xFF\xFFservers"; void deal_with_doom3master_packet( struct qserver *server, char *rawpkt, int pktlen) { char* pkt, *dest; int len; server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); if ( pktlen < sizeof(doom3_masterresponse) + 6 // at least one server || (pktlen - sizeof(doom3_masterresponse)) % 6 || memcmp( doom3_masterresponse, rawpkt, sizeof(doom3_masterresponse) ) != 0 ) { server->server_name= SERVERERROR; server->master_pkt_len = 0; malformed_packet(server, "too short or invalid response"); cleanup_qserver( server, 1); return; } server->retry1 = 0; // received at least one packet so no need to retry pkt = rawpkt + sizeof(doom3_masterresponse); len = pktlen - sizeof(doom3_masterresponse); server->master_pkt = (char*)realloc( server->master_pkt, server->master_pkt_len + len); dest = server->master_pkt + server->master_pkt_len; server->master_pkt_len += len; while(len > 0) { memcpy(dest, pkt, 4 ); dest[4] = pkt[5]; dest[5] = pkt[4]; dest += 6; pkt += 6; len -= 6; } assert(len == 0); server->n_servers= server->master_pkt_len / 6; debug(2, "%d servers added", server->n_servers); } static const char doom3_inforesponse[] = "\xFF\xFFinfoResponse"; static unsigned MAX_DOOM3_ASYNC_CLIENTS = 32; static void _deal_with_doom3_packet( struct qserver *server, char *rawpkt, int pktlen, unsigned version ) { char *ptr = rawpkt; char *end = rawpkt + pktlen; int type = 0; unsigned num_players = 0; unsigned challenge = 0; unsigned protocolver = 0; char tmp[32]; server->n_servers++; if ( server->server_name == NULL) { server->ping_total += time_delta( &packet_recv_time, &server->packet_time1); } else { gettimeofday( &server->packet_time1, NULL); } // Check if correct reply if ( pktlen < sizeof(doom3_inforesponse) +4 +4 +1 || memcmp( doom3_inforesponse, ptr, sizeof(doom3_inforesponse)) != 0 ) { malformed_packet(server, "too short or invalid response"); cleanup_qserver( server, 1); return; } ptr += sizeof(doom3_inforesponse); challenge = swap_long_from_little(ptr); ptr += 4; protocolver = swap_long_from_little(ptr); ptr += 4; snprintf(tmp, sizeof(tmp), "%u.%u", protocolver >> 16, protocolver & 0xFFFF); debug(2, "challenge: 0x%08X, protocol: %s (0x%X)", challenge, tmp, protocolver); // Commented out until we have a better way to specify the expected version // This is due to prey demo requiring version 4 yet prey retail version 3 /* if( protocolver >> 16 != version ) { malformed_packet(server, "protocol version %u, expected %u", protocolver >> 16, version ); cleanup_qserver( server, 1); return; } */ server->protocol_version = protocolver; add_rule( server, "protocol", tmp, NO_FLAGS ); while ( ptr < end ) { // server info: // name value pairs null seperated // empty name && value signifies the end of section char *key, *val; unsigned keylen, vallen; key = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "no rule key" ); cleanup_qserver( server, 1); return; } keylen = ptr - key; val = ++ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "no rule value" ); cleanup_qserver( server, 1); return; } vallen = ptr - val; ++ptr; debug( 2, "key:%s=%s:", key, val); if(keylen == 0 && vallen == 0) { type = 1; break; // end } // Lets see what we've got if ( 0 == strcasecmp( key, "si_name" ) ) { server->server_name = strdup( val ); } else if( 0 == strcasecmp( key, "fs_game" ) ) { server->game = strdup( val ); } #if 0 else if( 0 == strcasecmp( key, "si_version" ) ) { // format: // DOOM 1.0.1262.win-x86 Jul 8 2004 16:46:37 server->protocol_version = atoi( val+1 ); } #endif else if( 0 == strcasecmp( key, "si_map" ) ) { server->map_name = strdup( val ); } else if( 0 == strcasecmp( key, "si_maxplayers" ) ) { server->max_players = atoi( val ); } add_rule( server, key, val, NO_FLAGS ); } if ( type != 1 ) { // no more info should be player headers here as we // requested it malformed_packet( server, "player info missing" ); cleanup_qserver( server, 1); return; } // now each player details while( ptr < end ) { struct player *player; char *val; unsigned char player_id = *ptr++; short prediction = 0; unsigned rate = 0; if(player_id == MAX_DOOM3_ASYNC_CLIENTS) break; /* id's are not steady if(player_id != num_players) { malformed_packet(server, "unexpected player id"); cleanup_qserver( server, 1); return; } */ if ( ptr + 7 > end ) // 2 pred + 4 rate + empty player name ('\0') { // run off the end and shouldnt have malformed_packet( server, "player info too short" ); cleanup_qserver( server, 1); return; } player = add_player( server, player_id ); player->score = 0; player->frags = 0; prediction = swap_short_from_little(ptr); ptr += 2; player->ping = prediction; // seems to be ping rate = swap_long_from_little(ptr); ptr += 4; { char buf[16]; snprintf(buf, sizeof(buf), "%u", rate); player_add_info(player, "rate", buf, NO_FLAGS); } val = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "player name not null terminated" ); cleanup_qserver( server, 1); return; } ++ptr; player->name = strdup( val ); if( 2 == version ) { val = ptr; ptr = memchr(ptr, '\0', end-ptr); if ( !ptr ) { malformed_packet( server, "player clan not null terminated" ); cleanup_qserver( server, 1); return; } ++ptr; player->tribe_tag = strdup( val ); } debug( 2, "Player[%d] = %s, prediction %hu, rate %u, id %hhu, clan %s", num_players, player->name, prediction, rate, player_id, player->tribe_tag); ++num_players; } if(end - ptr >= 4) { snprintf(tmp, sizeof(tmp), "0x%X", swap_long_from_little(ptr)); add_rule( server, "osmask", tmp, NO_FLAGS ); debug( 2, "osmask %s", tmp); ptr += 4; } else { malformed_packet(server, "osmask missing"); } #if 0 if(end - ptr) { malformed_packet(server, "%ld byes left", end-ptr); } #endif server->num_players = num_players; cleanup_qserver( server, 1 ); return; } void deal_with_doom3_packet( struct qserver *server, char *rawpkt, int pktlen) { _deal_with_doom3_packet( server, rawpkt, pktlen, 1 ); } void deal_with_quake4_packet( struct qserver *server, char *rawpkt, int pktlen) { _deal_with_doom3_packet( server, rawpkt, pktlen, 2 ); } void deal_with_prey_demo_packet( struct qserver *server, char *rawpkt, int pktlen ) { _deal_with_doom3_packet( server, rawpkt, pktlen, 4 ); } void deal_with_prey_packet( struct qserver *server, char *rawpkt, int pktlen ) { _deal_with_doom3_packet( server, rawpkt, pktlen, 3 ); } qstat-2.11/doom3.h0000644002404400000620000000151510446475557010723 00000000000000/* * qstat 2.9 * by Steve Jankowski * * Doom3 / Quake4 protocol * Copyright 2005 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_DOOM3_H #define QSTAT_DOOM3_H #include "qstat.h" #define DOOM3_DEFAULT_PORT 27666 #define DOOM3_MASTER_DEFAULT_PORT 27650 #define QUAKE4_DEFAULT_PORT 28004 #define QUAKE4_MASTER_DEFAULT_PORT 27650 #define PREY_DEFAULT_PORT 27719 #define PREY_MASTER_DEFAULT_PORT 27655 void send_doom3master_request_packet( struct qserver *server); void deal_with_doom3_packet( struct qserver *server, char *rawpkt, int pktlen); void send_quake4master_request_packet( struct qserver *server); void deal_with_quake4_packet( struct qserver *server, char *rawpkt, int pktlen); void deal_with_prey_packet( struct qserver *server, char *rawpkt, int pktlen); #endif qstat-2.11/ut2004.c0000644002404400000620000003731010436307026010615 00000000000000/* * qstat 2.6 * by Steve Jankowski * * UT2004 master query functions * Copyright 2004 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms * * This code is inspired by ideas from 'Nurulwai' * */ #include #ifndef _WIN32 #include #endif #include #include #include "debug.h" #include "qstat.h" #include "md5.h" /** \brief convert bytes into hex string * * \param in data to convert * \param len length of data * \param out location to store string to. Must be 2*len */ static void bin2hex(const char* in, size_t len, char* out); #define CD_KEY_LENGTH 23 // arbitrary #define MAX_LISTING_RECORD_LEN 0x04FF #define RESPONSE_OFFSET_CDKEY 5 #define RESPONSE_OFFSET_CHALLENGE 39 static const char challenge_response[] = { 0x68, 0x00, 0x00, 0x00, '!', 0xCD, 0xCD, 0xCD, /* length | ! MD5SUM, CD is placeholder */ 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0x00, '!', 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0x00, 0x0c, 'U', 'T', '2', 'K', '4', 'C', 'L', /*^^ 12 byte string */ 'I', 'E', 'N', 'T', 0x00, 0xfb, 0x0c, 0x00, /* | unknown */ 0x00, 0x06, 0x04, 'i', 'n', 't', 0x00, 0x00, /* | ^^ 4 byte string | ? */ 0x00, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x11, /* unknown */ 0x00, 0x00, 0x00, 0x01 }; static const char approved[] = { 0x0e, 0x00, 0x00, 0x00, 0x09, 'A', 'P', 'P', 'R', 'O', 'V', 'E', 'D', 0x00, 0x03, 0x00, 0x00, 0x00 }; static const char approved_response[] = { 0x22, 0x00, 0x00, 0x00, '!', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 0x00 }; static const char verified[] = { 0x0a, 0x00, 0x00, 0x00, 0x09, 'V', 'E', 'R', 'I', 'F', 'I', 'E', 'D', 0x00 }; #if 0 struct server_listing_record_head { unsigned len; unsigned ip; short port; short queryport; char name[]; // char map[] }; struct server_listing_record_foot { unsigned char marker1[3]; unsigned char unknown1; unsigned char maxplayers; unsigned char unknown2[4]; unsigned char marker2[3]; }; #endif static char cdkey[CD_KEY_LENGTH+1] = ""; enum ut2004_state { STATE_CHALLENGE = 0x00, STATE_APPROVED = 0x01, STATE_VERIFIED = 0x02, STATE_LISTING = 0x03, }; void send_ut2004master_request_packet(struct qserver *server) { if(server->n_packets) { cleanup_qserver(server, 1); return; } if(!*cdkey) { char* param = get_param_value( server, "cdkey", NULL); if(!param) { debug(0, "Error: missing cdkey parameter"); server->server_name = SYSERROR; cleanup_qserver(server, 1); return; } if(*param == '/') { FILE* fp = fopen(param, "r"); if(!fp || fread(cdkey, 1, CD_KEY_LENGTH, fp) != CD_KEY_LENGTH) { debug(0, "Error: can't key from %s", param); server->server_name = SYSERROR; cleanup_qserver(server, 1); if(fp) fclose(fp); return; } fclose(fp); } else if(strchr(param, '-') && strlen(param) == CD_KEY_LENGTH) { memcpy(cdkey, param, CD_KEY_LENGTH); } else if( *param == '$' && (param = getenv(param+1)) // replaces param! && strlen(param) == CD_KEY_LENGTH) { memcpy(cdkey, param, CD_KEY_LENGTH); } else { debug(0, "Error: invalid cdkey parameter"); server->server_name = SYSERROR; cleanup_qserver(server, 1); return; } } qserver_send(server, NULL, 0); #if 0 // XXX since we do not send but rather expect a reply directly after // connect it's pointless to retry doing nothing debug(0, "retry1: %d", server->retry1); server->retry1 = 0; #endif server->master_query_tag[0] = STATE_CHALLENGE; } static void ut2004_server_done(struct qserver* server) { if(server->saved_data.next) { debug(0, "%d bytes of unprocessed data left. Premature EOF!?", server->saved_data.next->datalen); free(server->saved_data.next->data); free(server->saved_data.next); server->saved_data.next = NULL; } } // we use n_servers to store number of used bytes in master_pkt so // it needs to be divided by 6 when finished static void ut2004_parse_record(struct qserver* server, char* pkt) { char* dest; #if 0 unsigned ip; unsigned short port; memcpy(&ip, pkt+4, 4); port = swap_short_from_little(pkt+4+4); debug(2, "got %d.%d.%d.%d:%hu", ip&0xff, (ip>>8)&0xff, (ip>>16)&0xff, (ip>>24)&0xff, port); #endif if(server->n_servers+6 > server->master_pkt_len) { if(!server->master_pkt_len) server->master_pkt_len = 180; else server->master_pkt_len *= 2; server->master_pkt = (char*)realloc(server->master_pkt, server->master_pkt_len); } dest = server->master_pkt + server->n_servers; memcpy(dest, pkt+4, 4 ); dest[4] = pkt[9]; dest[5] = pkt[8]; server->n_servers += 6; } static char* put_bytes(char* buf, const char* bytes, size_t len, size_t* left) { if(!buf || len > *left) return NULL; memcpy(buf, bytes, len); *left -= len; return buf+len; } static char* put_string(char* buf, const char* string, size_t* left) { size_t len = strlen(string)+1; char l; if(!buf || len > 0xFF || *left < len+1) return NULL; l = len; buf = put_bytes(buf, &l, 1, left); return put_bytes(buf, string, len, left); } /** \brief assemble the server filter and send the master query the query consists of four bytes length (excluding the four length bytes), a null byte and then the number of item pairs that follow. Each pair consists of two ut2 strings (length+null terminated string) followed by a byte which is either zero or 0x04 which means negate the query (e.g. not zero curplayers means not empty). */ static int ut2004_send_query(struct qserver* server) { char buf[4096] = {0}; size_t left = sizeof(buf); char *b = buf; char *param, *r, *sep= ""; unsigned flen = 0; unsigned char items = 0; // header is done later b += 6; left -= 6; param = get_param_value( server, "gametype", NULL); if(param) { ++items; b = put_string(b, "gametype", &left); b = put_string(b, param, &left); b = put_bytes(b, "", 1, &left); } param = get_param_value( server, "status", NULL); r = param; while ( param && sep ) { sep= strchr( r, ':'); if ( sep ) flen= sep-r; else flen= strlen(r); if ( strncmp( r, "standard", flen) == 0 || strncmp( r, "nostandard", flen) == 0) { ++items; b = put_string(b, "standard", &left); if(*r == 'n') b = put_string(b, "false", &left); else b = put_string(b, "true", &left); b = put_bytes(b, "", 1, &left); } else if ( strncmp( r, "password", flen) == 0 || strncmp( r, "nopassword", flen) == 0) { ++items; b = put_string(b, "password", &left); if(*r == 'n') b = put_string(b, "false", &left); else b = put_string(b, "true", &left); b = put_bytes(b, "", 1, &left); } else if ( strncmp( r, "notempty", flen) == 0) { ++items; b = put_string(b, "currentplayers", &left); b = put_string(b, "0", &left); b = put_bytes(b, "\x04", 1, &left); } else if ( strncmp( r, "notfull", flen) == 0) { ++items; b = put_string(b, "freespace", &left); b = put_string(b, "0", &left); b = put_bytes(b, "\x04", 1, &left); } else if ( strncmp( r, "nobots", flen) == 0) { ++items; b = put_string(b, "nobots", &left); b = put_string(b, "true", &left); b = put_bytes(b, "", 1, &left); } else if ( strncmp( r, "stats", flen) == 0 || strncmp( r, "nostats", flen) == 0) { ++items; b = put_string(b, "stats", &left); if(*r == 'n') b = put_string(b, "false", &left); else b = put_string(b, "true", &left); b = put_bytes(b, "", 1, &left); } else if ( strncmp( r, "weaponstay", flen) == 0 || strncmp( r, "noweaponstay", flen) == 0) { ++items; b = put_string(b, "weaponstay", &left); if(*r == 'n') b = put_string(b, "false", &left); else b = put_string(b, "true", &left); b = put_bytes(b, "", 1, &left); } else if ( strncmp( r, "transloc", flen) == 0 || strncmp( r, "notransloc", flen) == 0) { ++items; b = put_string(b, "transloc", &left); if(*r == 'n') b = put_string(b, "false", &left); else b = put_string(b, "true", &left); b = put_bytes(b, "", 1, &left); } r= sep+1; } param = get_param_value( server, "mutator", NULL); r = param; sep = ""; while ( param && sep ) { char neg = '\0'; unsigned char l; sep= strchr( r, ':'); if ( sep ) flen= sep-r; else flen= strlen(r); if(*r == '-') { neg = '\x04'; ++r; --flen; } if(!flen) continue; b = put_string(b, "mutator", &left); l = flen+1; b = put_bytes(b, (char*)&l, 1, &left); b = put_bytes(b, r, flen, &left); b = put_bytes(b, "", 1, &left); b = put_bytes(b, &neg, 1, &left); ++items; r= sep+1; } if(!b) { debug(0, "Error: query buffer too small. Please file a bug report!"); return 0; } put_long_little(b-buf-4, buf); buf[5] = items; return (qserver_send(server, buf, sizeof(buf)-left) > 0); } void deal_with_ut2004master_packet(struct qserver *server, char *rawpkt, int pktlen) { unsigned char* state = (unsigned char*)&server->master_query_tag[0]; md5_state_t md5; if(!pktlen) { ut2004_server_done(server); goto cleanup_out; } server->ping_total+= time_delta( &packet_recv_time, &server->packet_time1); switch(*state) { case STATE_CHALLENGE: // ensure at least one byte challenge, fit into buffer, // match challenge, null terminated if( pktlen < 4 +1 +1 +1 || pktlen > 4 +1 +8 +1 || rawpkt[pktlen-1] != '\0') { malformed_packet(server, "invalid challenge" ); goto cleanup_out; } else { char response[sizeof(challenge_response)]; char* challenge = rawpkt+5; char sum[16]; memcpy(response, challenge_response, sizeof(challenge_response)); debug(2, "challenge: %s", challenge); md5_init(&md5); md5_append(&md5, (unsigned char*)cdkey, CD_KEY_LENGTH); md5_finish(&md5, (unsigned char*)sum); bin2hex(sum, 16, response+RESPONSE_OFFSET_CDKEY); md5_init(&md5); md5_append(&md5, (unsigned char*)cdkey, CD_KEY_LENGTH); md5_append(&md5, (unsigned char*)challenge, strlen(challenge)); md5_finish(&md5, (unsigned char*)sum); bin2hex(sum, 16, response+RESPONSE_OFFSET_CHALLENGE); qserver_send(server, response, sizeof(response)); server->server_name = MASTER; *state = STATE_APPROVED; } break; case STATE_APPROVED: if(pktlen != sizeof(approved) || 0 != memcmp(rawpkt, approved, pktlen)) { malformed_packet(server, "CD key not approved" ); goto cleanup_out; } debug(2, "got approval, sending verify"); qserver_send(server, approved_response, sizeof(approved_response)); *state = STATE_VERIFIED; break; case STATE_VERIFIED: if(pktlen != sizeof(verified) || 0 != memcmp(rawpkt, verified, pktlen)) { malformed_packet(server, "CD key not verified" ); goto cleanup_out; } if(!ut2004_send_query(server)) goto cleanup_out; *state = STATE_LISTING; break; case STATE_LISTING: // first packet. contains number of servers to expect if(!server->saved_data.pkt_id) { /* server->saved_data.data = malloc(pktlen); memcpy(server->saved_data.data, rawpkt, pktlen); server->saved_data.datalen = pktlen; */ server->saved_data.pkt_id = 1; if(pktlen == 9) { unsigned num = swap_long_from_little(rawpkt+4); debug(2, "expect %u servers", num); #if 1 if(num < 10000) { server->master_pkt_len = num*6; server->master_pkt = (char*)realloc(server->master_pkt, server->master_pkt_len); } #endif } } else if(pktlen < 4) { malformed_packet(server, "packet too short"); goto cleanup_out; } else { char* p = rawpkt; unsigned recordlen = 0; if(server->saved_data.next) { unsigned need = 0; SavedData* data = server->saved_data.next; // nasty, four bytes of record length are split up. since // we alloc'ed at least four bytes we just copy the 4-x // bytes to data->data if(data->datalen < 4) { need = 4 - data->datalen; debug(2, "need %d bytes more for recordlen", need); if( need > pktlen) { // XXX ok, im lazy now. Stupid server can't even // send four bytes in a row malformed_packet(server, "chunk too small"); goto cleanup_out; } memcpy(data->data+data->datalen, p, need); p += need; data->datalen = 4; } recordlen = swap_long_from_little(data->data); if(!recordlen || recordlen > MAX_LISTING_RECORD_LEN) { malformed_packet(server, "record lengthx %x out of range, position %d", recordlen, (int)(p-rawpkt)); goto cleanup_out; } need = 4+recordlen - data->datalen; debug(2, "recordlen: %d, saved: %d, pkglen: %d, needed: %d", recordlen, data->datalen, pktlen, need); if( need <= pktlen) { data->data = realloc(data->data, 4+recordlen); memcpy(data->data + data->datalen, p, need); ut2004_parse_record(server, data->data); p += need; free(data->data); free(data); server->saved_data.next = NULL; } } while(!server->saved_data.next && p-rawpkt+4 < pktlen) { recordlen = swap_long_from_little(p); // record too large if(!recordlen || recordlen > MAX_LISTING_RECORD_LEN) { malformed_packet(server, "record length %x out of range, position %d", recordlen, (int)(p-rawpkt)); goto cleanup_out; } // recordlen itself is four bytes recordlen += 4; // record fully inside packet if(p-rawpkt+recordlen <= pktlen) { ut2004_parse_record(server, p); p += recordlen; } else break; } // record continues in next packet. save it. if(p-rawpkt < pktlen) { SavedData* data = server->saved_data.next; unsigned tosave = pktlen - (p-rawpkt); if(!data) { data = malloc(sizeof(SavedData)); data->data = malloc(tosave<4?4:tosave); // alloc at least four bytes data->datalen = tosave; memcpy(data->data, p, data->datalen); data->next = NULL; server->saved_data.next = data; debug(1, "saved %d bytes", data->datalen ); } else { data->data = realloc(data->data, data->datalen + tosave ); memcpy(data->data+data->datalen, p, tosave); data->datalen += tosave; debug(1, "saved %d bytes (+)", data->datalen ); } } } break; } #if 0 // would cause extremely short timeout server->next_player_info= -1; // would clean up otherwise <- not true? #endif debug(2, "%d servers total", server->n_servers/6); #if 0 // harms now with new ping scheduling server->retry1= 0; cleanup_qserver( server, 0); bind_sockets(); #endif return; cleanup_out: server->master_pkt_len = server->n_servers; server->n_servers /= 6; cleanup_qserver(server, 1); return; } static const char hexchar[] = "0123456789abcdef"; static void bin2hex(const char* in, size_t len, char* out) { char* o = out+len*2; in += len; do { *--o = hexchar[*--in&0x0F]; *--o = hexchar[(*in>>4)&0x0F]; } while(o != out); } // vim: sw=4 ts=8 noet qstat-2.11/ut2004.h0000644002404400000620000000062410134554421010616 00000000000000/* * qstat 2.6 * by Steve Jankowski * * debug helper functions * Copyright 2004 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_UT2004_H #define QSTAT_UT2004_H #include "qstat.h" void send_ut2004master_request_packet(struct qserver *server); void deal_with_ut2004master_packet(struct qserver *server, char *rawpkt, int pktlen); #endif qstat-2.11/qstatdoc.html0000644002404400000620000022124610337007674012234 00000000000000 QStat 2.10 documentation

NAME

qstat - Get statistics from on-line game servers

SYNOPSIS

qstat [options ...] [-f file] [-of|-af output-file] [-server-option host[:port]]
[-raw delimiter] [-default server-type] host[:port[-port_max]] ...

Version 2.10

DESCRIPTION

QStat is a command-line program that displays information about Internet game servers. The servers are either down, non-responsive, or running a game. For servers running a game, the server name, map name, current number of players, and response time are displayed. Server rules and player information may also be displayed.

Games supported include Quake, QuakeWorld, Hexen II, Quake II, HexenWorld, Unreal, Half-Life, Sin, Shogo, Tribes, Tribes 2, Quake III: Arena, BFRIS, Kingpin, and Heretic II, Unreal Tournament, Soldier of Fortune, Rogue Spear, Redline, Turok II, Blood 2, Descent 3, Drakan, KISS, Nerf Arena Blast, Rally Master, Terminous, Wheel of Time, and Daikatana and many more. Note for Tribes 2: QStat only supports Tribes 2 builds numbered 22075 or higher. Note for Ghost Recon QStat only supports GhostRecon patch 1.2, 1.3, 1.4, Desert Siege, and Island Thunder.

Some games use query protocols compatible with an existing game. These servers can be queried using the flags for the compatible game. For instance, Turok2 should work using the -uns flag. Unreal Tournament is also supported by the -uns but is not really a different game. You can distinguish Unreal Tournament games with the "minnetver" server rule (standard Unreal servers have a "mingamever" server rule).

The Quake servers can be divided into two categories: POQS (Plain Old Quake Server) and QuakeWorld. Quake shareware, Quake commercial (from CD), winquake, winded, unixded, and Hexen II are all POQS. The various versions of QuakeWorld and Quake II use a QuakeWorld type server. The distinction is based on network protocol used to query the servers, and affects the kind of information available for display.

The different server types can be queried simultaneously. If QStat detects that this is being done, the output is keyed by the type of server being displayed. See DISPLAY OPTIONS.

The game server may be specified as an IP address or a hostname. Servers can be listed on the command-line or, with the use of the -f option, a text file.

DISPLAY MODES

One line will be displayed for each server queried. The first component of the line will be the server's address as given on the command-line or the file. This can be used as a key to match input addresses to server status. Server rules and player information are displayed under the server info, indented by one tab stop.

QStat supports three additional display modes: raw, templates, and XML. In raw mode, the server information is displayed using simple delimiters and no formatting. This mode is good for programs that parse and reformat QStat's output. The template mode uses text files to layout the server information within existing text. This is ideal for generating web pages. The XML mode outputs server information wrapped in simple XML tags. The raw mode is enabled using the -raw option, template output is enabled using -Ts, and XML output is enabled with -xml.

GAME OPTIONS

These options select which servers to query and what game type they are running. Servers are specified by IP address (for example: 199.2.18.4) or hostname. Servers can be listed on the command-line or in a file (see option -f.) The game type of a server can be specified with its address, or a default game type can be set for all addresses that don't have a game type.

The following table shows the command-line option and type strings for the supported game types. The type string is used with the -default option and in files with the -f option.

OptionType StringDefault PortGame Server
-qsqs26000Quake
-h2sh2s26900Hexen II
-qwsqws27500QuakeWorld
-hwshws26950HexenWorld
-q2sq2s27910Quake II
-unsuns7777Unreal
-ut2sut2s7777Unreal Tournament 2003
-ut2004mut2004m28902Unreal Tournament 2004 Master requires CD Key
-hlshls27015Half-Life
-snssns22450Sin
-sgssgs27888Shogo: Mobile Armor Division
-tbstbs28001Starsiege: Tribes
-t2st2s28000Tribes 2
-qwmqwm27000QuakeWorld master
-q2mq2m27900Quake II master
-hlmhlm27010Half-Life master
-stmstm27010Half-Life master (Steam)
-tbmtbm28000Tribes master
-t2mt2m28002Tribes 2 master
-q3sq3s27960Quake III
-q3mq3m27950Quake III master
-dm3sdm3s27666Doom 3
-dm3mdm3m27650Doom 3 master
-bfsbfs44001BFRIS
-kpskps31510Kingpin
-hrshrs28910Heretic II
-sfssfs28910Soldier of Fortune
-gsmgsm28900Gamespy master
-gpsgps-Game using "Gamespy style" protocol
-gpsgs2-Game using "Gamespy2 style" protocol
-d3md3m3445Descent 3 PXO master
-d3pd3p2092Descent 3, PXO server
-d3sd3s2092Descent 3, LAN server
-d3gd3g20142Descent 3, Gamespy protocol
-rwsrws27960Return to Castle Wolfestein
-rwmrwm27950Return to Castle Wolfestein master
-efsefs27960Star Trek: Elite Force
-efmefm27953Star Trek: Elite Force master
-efsefs29070Jedi Knight: Jedi Academy
-efmefm29060Jedi Knight: Jedi Academy master
-grsgrs2346Ghost Recon

The command-line options can be specified multiple times, one for each server to be queried.

Configuration Files

The games supported by QStat can be customized with configuration files. The query parameters of built-in game types can be modified and new games can be defined.

For built-in game types, certain parameters can be modified. The parameters are limited to the master server protocol and master server query string.

New game types can be defined as a variation on an existing game type. Most new games use a Quake 3 or Gamespy/Unreal based network engine. These games can already be queried using -q3s or -gps, but they don't have game specific details such as the correct default port, the game name, and the correct "game" or "mod" server rule. And, mostly importantly, they don't get their own game type string (e.g. q3s, rws, t2s). All of these details can be specified in the QStat config file.

QStat comes with a default configuration file called 'qstat.cfg'. If this file is found in the directory where qstat is run, the file will be loaded. Configuration files can also be specified with the QSTAT_CONFIG environment variable and the -cfg command-line option. See Appendix B for a description of the configuration file format.

Descent 3

Support for Descent 3 is a bit fragmented. There are three different protocols for getting status information from a Descent 3 server: PXO, LAN, and Gamespy. If the server was acquired from the PXO master server, then the PXO protocol is used. If the server is running on the local LAN (not reporting to a master server), then the LAN protocol should be used. Finally, if the server's Gamespy query port is known (default is 20142) then the Gamespy protcol can be used. The gamespy protocol can be used on servers listed in the PXO master.

Each protocol reports different information. The Gamespy protocol provides player names, frags, deaths, and ping. The PXO and LAN protocols only provide player names.

The ideal solution would be a PXO server list paired with each server's gamespy query port. Most servers will use the default gamespy query port, unless there are multiple servers on the same machine. A possible approach is to get the server list from the PXO master like this:

qstat -d3m,outfile gt.pxo.net,d3pxo.txt
Then convert the file from "d3p" to "d3g" and remove the port numbers:
sed -e 's/d3p/d3g/' -e 's/:.*$//' d3pxo.txt > d3gs.txt
Then run the servers in d3gs.txt with -f:
qstat -f d3gs.txt
This technique will retrieve the full player info for servers using the default gamespy query port.

Broadcast Queries

QStat has limited support for broadcast queries. Broadcast queries use one network packet to find all the game servers on a local network. A broadcast returns servers of one type on one port. You may only broadcast to networks to which you computer is directly attached (ie. local networks).

A broadcast query is specified by prefixing an address with a '+' (plus sign). The address should be 255.255.255.255 or a valid broadcast address for your local network. On Unixes, 'ifconfig -a' will display the broadcast address for all attached networks.

Port Ranges

Broadcast Queries can scan a range of ports to find game servers that don't run on the default port. Specify the minimum and maximum port of a range separated by a dash.

Query Arguments

Some game types support customized server queries. For example, many master servers can return a select list of servers based on the mod, number of players, or region. Each query can be customized differently.

Server queries are customized by attaching query arguments to the server type option. Each argument is separated by a comma (','). The argument has a name followed by an optional value separated with an equal-sign ('='). The general format looks like this:

-server-option,query-arg[=arg-value][, ...]
See the Master Server sections below for more examples.
General Query Arguments
The follow query arguments can be applied to any server type.
Query ArgumentDescription
showgameportAlways display the game port in QStat output. If the query port was different from the game port, then the query port will be saved in the "_queryport" server rule. This is the same as the -showgameport command-line option, but only applies to one server query.
gpShort-hand for showgameport.
noportoffsetDo not apply the "status port offset" when sending the server query. Some games use different ports for game play and status queries (for example, Unreal, Medal of Honor, etc). QStat will normally add an offset to the game port to find the query port. But not all servers use the standard offset. This option allows QStat to query servers where the query port is known. The server address should be an IP address and a query port (not the game port). This is the same as the -noportoffset command-line option, but only applies to one server query.
qpShort-hand for noportoffset.

Some examples of the general query arguments.

qstat -uns,noportoffset 1.2.3.4:7787
ADDRESS           PLAYERS      MAP   RESPONSE TIME    NAME
1.2.3.4:7787        0/16      Kansas    119 / 0       Example server
The default Unreal game port is 7777 and the query port is usually at offset 1 (port 7778). But this server has a different query port. Note that qstat displays the query port. To display the game port instead:
qstat -uns,noportoffset,showgameport 1.2.3.4:7787
ADDRESS           PLAYERS      MAP   RESPONSE TIME    NAME
1.2.3.4:7777        0/16      Kansas    119 / 0       Example server
Another common usage for "showgameport" is with broadcast queries:
qstat -uns,showgameport +255.255.255.255

Master Servers

Master server addresses don't change very often, but some times they go off-line. The following is a table of some of the master servers I know about.

GameMaster Servers
QuakeWorldsatan.idsoftware.com (ports 27000, 27002, 27003, 27004, 27006), 204.182.161.2, 194.217.251.40, 203.34.140.1, 200.245.221.200, 194.87.251.3
Quake IIsatan.idsoftware.com, q2master.planetquake.com
Half-Life (hlm)half-life.west.won.net, half-life.east.won.net
Half-Life (stm)steam1.steampowered.com:27010, steam2.steampowered.com:27010
Tribestribes.dynamix.com
Quake IIImaster3.idsoftware.com
Doom 3idnet.ua-corp.com
Gamespymaster0.gamespy.com
Tribes 2211.233.32.77:28002, 217.6.160.205:28002
Descent 3gt.pxo.net
Return to Castle Wolfensteinwolfmaster.idsoftware.com
Star Trek: Elite Forcemaster.stef1.ravensoft.com
UT2004ut2004master1.epicgames.com, ut2004master2.epicgames.com, ut2004master3.epicgames.com

Gamespy Master

Access to the gamespy masters has been disabled by Gamespy Inc.

Server lists can be fetched from Gamespy masters by using the gsm game type. A query argument is required to use the Gamespy master. This extra argument indicates which server list to get from the master. The query argument can be one of the QStat supported game types or any other string that will fetch a server list. The following game types can be used as query arguments: qws, q2s, q3s, tbs, uns, sgs, hls, kps, hrs, sfs. For each of the game types, QStat will fetch the appropriate server list and get status from each server.

The query argument can also be any string that the Gamespy master responds to. Most of these games support a "standard" server status protocol that I'll call the "Gamespy status protocol". Not surprisingly, it is almost identical to the Unreal server status protocol. This means that QStat can support any game that supports this protocol. In QStat these games are queried using the gps game type. Through experimentation I've found the following query arguments.

Query ArgumentGame
roguespearRainbow Six: Rogue Spear
redlineRedline Racer
turok2Turok 2: Seeds of Evil
blood2Blood 2: The Chosen
drakanDrakan: Order of the Flame
kissKISS Psycho Circus: The Nightmare Child
nerfarenaNerf Arena Blast
rallyRally Masters: Michelin Race Of Champions
terminousTerminous (?)
wotThe Wheel of Time
daikatanaDaikatana

Tribes 2 Master

The Tribes 2 master server supports a number of filtering options. You can set these filters with QStat by appending query arguments to the server type. The general syntax is:
t2m,query-arg=value, ...
Query ArgumentValuesDescription
gamemod pathMod path the server is using. The mod path of unaltered servers is "base". Use query=types to get the list of known game types.
missionBounty, Capture the Flag, CnH, Deathmatch, Hunters, Rabbit, Siege, TeamHuntersMission type the server is currently running. Use query=types to get the list of known mission types.
minplayers0 - 255Servers with fewer players than this will not be returned.
maxplayers1 - 255Servers with more players than this will not be returned.
regionslist of regions or 0xhex-value Limit servers to those in the given geographical regions. See Region List table. The regionlist is sent as a bit mask to the Tribes 2 master. If you know the bit mask for a region QStat doesn't support, you can specify the bitmask directly by supplying a hex value: regions=0x11.
buildbuild version # Only return servers matching this build version number. [4/20/2001] This filter only seems to work if the build version # is 22337. If the filter is 22228, then the master returns 0 servers. This appears to be a bug in the T2 master.
statuslist of dedicated, linux, nopassword
or 0xhex-value
Limit servers to those with these status flags set. The list is one or more status flags separated by colons (':'). To filter on dedicated Linux servers, specify status=dedicated:linux
If you know a status flag that QStat doesn't support, you can specify the status flags directly by supplying a hex value: status=0x3
maxbots0 - 255Servers with more bots than this will not be returned.
mincpu0 - 65535Servers with lower CPU speed than this will not be returned.
querytypesGet the list of game and mission types. This is not a filter but a different master request. Using this query argument overrides any other query arguments. The list of game and mission types known to the master server will be displayed. In raw mode, the first line is the list of game types and the second line is the list of mission types. There is no output template support for game and mission lists.
Region List
The region list is one or more region arguments separated by colons (':'). For example, to filter on North American servers specify regions=naeast:nawest

Region ArgumentGeography
naeastNorth America East
nawestNorth America West
saSouth America
ausAustralia
asiaAsia
eurEurope

The Tribes 2 master query arguments can be used on the command-line or in a server list file (via the -f option). If the values contain spaces, be sure to quote the arguments for your shell. The second example below demonstrates this usage for most common shells. To query for Capture the Flag servers that have more than 6 players:
qstat -t2m,mission=Capture the Flag,minplayers=6 master-server-ip
qstat -t2m,mission="Capture the Flag",minplayers=6 master-server-ip
If you want to do this in a server list file, that would look like this:
t2m,mission=Capture the Flag,minplayers=6 master-server-ip
Master server filters can be combined with the "outfile" option. Just put outfile some where in the query argument list and put the name of the output file after the master IP address:
t2m,outfile,mission=Siege,minplayers=4 master-server-ip,siegeservers.txt
Warning: There is a bug in the 22075 build of Tribes 2 that doesn't return the game name. For those builds, QStat will use the game info in place of the game name. The bug is fixed in the 22228 build. In fixed servers, the game info can be found in the "info" server rule.

Half-Life Master

The Half-Like master server supports a number of filtering options. You can set these filters with QStat by appending query arguments to the server type. The general syntax is:
hlm,query-arg=value, ...
Query ArgumentValuesDescription
gamemod pathServers running this "mod".
mapmap nameServers running this map.
statuslist of dedicated, linux, notempty, notfull Limit servers to those matching this status. The list is one or more status flags separated by colons (':'). To filter on dedicated servers that are not empty, specify status=dedicated:notempty
See the Tribes 2 master server above for example usage.

Half-Life Master (Steam)

The Half-Life steam master server supports a number of filtering options different from the old WON master.
stm,query-arg=value, ...
Query ArgumentValuesDescription
gamemod pathServers running this "mod".
mapmap nameServers running this map.
regionname or number of regionGeographical Area of the server. You can specify the name or number of the region:
  • 0: US East coast
  • 1: US West coast
  • 2: South America
  • 3: Europe
  • 4: Asia
  • 5: Australia
  • 6: Middle East
  • 7: Africa
statuslist of dedicated, linux, notempty, notfull, secure, proxy Limit servers to those matching this status. The list is one or more status flags separated by colons (':'). To filter on dedicated servers that are not empty, specify status=dedicated:notempty
See the Tribes 2 master server above for example usage.

Doom 3 Master

The Doom 3 master server supports a number of filtering options. You can set these filters with QStat by appending query arguments to the server type. The general syntax is:
hlm,query-arg=value, ...
Query ArgumentValuesDescription
statuscolon separated list of password, nopassword, notfull, notfullnotempty Limit servers to those matching this status. The list is one or more status flags separated by colons (':'). To filter on servers without password that are not full, specify status=nopassword:notfull
gametypeone of dm, tdm or tourney limit servers to those mathing the specified gametype
See the Tribes 2 master server above for example usage.
A special option is a number major.minor which specifies the protocol version.

UT2004 Master

The UT2004 master server supports a number of filtering options. You can set these filters with QStat by appending query arguments to the server type. The general syntax is:
hlm,query-arg=value, ...
Query Argument Values Description
cdkey path to the UT2004 cdkey file You MUST specify a valid CD key to be able to query the master server
status colon separated list of password, nopassword, notfull, notempty, standard, nostandard, nobots, stats, nostats, weaponstay, noweaponstay, transloc, notransloc Limit servers to those matching this status. The list is one or more status flags separated by colons (':'). To filter on standard servers without password that are not full, specify status=standard:nopassword:notfull
gametype any UT2004 gametype, e.g. xMutantGame limit servers to those mathing the specified gametype
mutator colon separated list of Mutators. limit servers to those running the specified mutators. Prepend a dash to include servers that do NOT run the specified mutator
See the Tribes 2 master server above for example usage.

Option Usage

-cfg configuration-file
Load the QStat configuration file. New game types defined in the config file can be used in subsequent command-line options.
-server-option host[:port]
Query game server host for status. The GAME OPTIONS table lists the available server-options and their default port.
-nocfg Ignore qstat configuration loaded from any default location (see Appendix B for a list of default locations). Must be the first option on the command-line. Use this option to have complete control over the configured game types.
-master-server-option host[:port]
Query a game master for its server list and then query all the servers. The GAME OPTIONS table lists the available master-server-options and their default port.
-master-server-option,outfile host[:port],file
Query a game master for its server list and store it in file. If the master cannot be contacted, then file is not changed. If file is - (a single dash), then stdout is used. The GAME OPTIONS table lists the available master-server-options and their default port.
-gsm,query-argument host[:port]
Query a Gamespy master for a server list and then query all the servers. The Gamespy Master section details the supported values for query-argument.
-gsm,query-argument,outfile host[:port],file
Query a Gamespy master for a server list and store it in file. If the master cannot be contacted, then file is not changed. If file is - (a single dash), then stdout is used. The Gamespy Master section details the supported values for query-argument.
-q3m,query-argument host[:port]
Query a Quake 3 Arena master for a protocol-specific server list and then query all the servers. The query-argument should be a Quake 3 protocol version. Protocol version 48 is Quake 3 version 1.27, protocol 46 is Quake 3 version 1.25, protocol 45 is Quake 3 1.17, protocol 43 is Quake 3 version 1.11. The default is protocol version 48.
-q3m,query-argument,outfile host[:port],file
Query a Quake 3 Arena master for a protocol-specific server list and store it in file. The query-argument should be a Quake 3 protocol version. Protocol version 46 is Quake 3 version 1.25, protocol 45 is Quake 3 1.17, protocol 43 is Quake 3 version 1.11. The default is protocol version 45.
-f file
Read host addresses from the given file. If file is -, then read from stdin. Multiple -f options may be used. The file should contain host names or IP addresses separated by white-space (tabs, new-lines, spaces, etc). If an address is preceded by a server type string, then QStat queries the address according to the server type. Otherwise QS is assumed, unless -default is used. The GAME OPTIONS table lists the available server type strings and their default port.
-default type-string
Set the default server type for addresses where the type is not obvious. This affects the addresses at the end of the qstat command-line and those in a file not prefixed by a server type (see -f). The GAME OPTIONS table lists the available server type strings and their default port.
-noportoffset
Do not apply the "status port offset" when sending server queries. Some games use different ports for game play and status queries (for example, Unreal, Medal of Honor, etc). QStat will normally add an offset to the game port to find the query port. But not all servers use the standard offset. This option allows QStat to query servers where the query port is known. The server addresses should be an IP address and a query port (not the game port). This is the same as the noportoffset server query argument, but applies to all servers being queried.

INFO OPTIONS

-R
Fetch and display server rules.
-P
Fetch and display player information.

DISPLAY OPTIONS

The QStat output should be self explanatory. However, the type of information returned is different between game types. If QStat queries multiple server types, then each server status line is prefixed with its type string. The GAME OPTIONS table lists the available type strings.

-of file
Write output to file instead of stdout or the console. file is over written if it already exists.
-af file
Like -of, but append to the file. If file does not exist, it is created.
-u
Only display hosts that are up and running a game server. Does not affect template output.
-nf
Do not display full servers. Does not affect template output.
-ne
Do not display empty servers. Does not affect template output.
-nh
Do not display header line (does not apply to raw or template output.)
-cn
Display color names instead of numbers. This is the default. Only applies to Quake, QuakeWorld, Hexen II, and HexenWorld.
-ncn
Display color numbers instead of color names. This is the default for -raw mode. Only applies to Quake, QuakeWorld, Hexen II, and HexenWorld.
-hc
Display colors in #rrggbb format. This is nice for HTML output. Only applies to Quake, QuakeWorld, Hexen II, and HexenWorld.
-nx
Perform name transforms. Transform game specific player and server name escape sequences into more readable text. This setting is ON by default.
-nnx
No name transforms. Do not transform player and server names. Option -utf8 implies -nnx.
-tc
Display time in clock format (DhDDmDDs). This is the default.
-tsw
Display time in stop-watch format (DD:DD:DD).
-ts
Display time in seconds. This is the default for -raw mode.
-pa
Display player addresses. This is the default for -raw mode. Only available for Quake and Hexen II.
-sort sort-keys
Sort servers and/or players. Servers and players are sorted according to sort-keys. Lower case sort keys are for servers and upper case keys are for players. The following sort keys are supported:
  • p - Sort by ping
  • g - Sort by game (mod)
  • i - Sort by IP address
  • h - Sort by hostname
  • n - Sort by number of players
  • l - Sort by list order
  • P - Sort by player ping
  • F - Sort by frags
  • T - Sort by team

The 'l' (ell) sort key displays servers in the order they were provided to qstat. For example, the order in which they are listed on the command-line or in a file. The 'l' sort key cannot be combined with other server sort keys, but it can be be combined with player sort keys. If the 'l' sort key is used with other sort keys, then the 'l' sort key is ignored.

-hpn
Display player names in hex.
-old
Use pre-qstat 1.5 display style.
-raw delimiter
Display data in "raw" mode. The argument to -raw is used to separate columns of information. All information returned by the game server is displayed.
POQS output -- General server information is displayed in this order: command-line arg (IP address or host name), server name, server address (as returned by Quake server), protocol version, map name, maximum players, current players, average response time, number of retries. Server rules are displayed on one line as rule-name=value. If significant packet loss occurs, rules may be missing. Missing rules are indicated by a "?" as the last rule. Player information is displayed one per line: player number, player name, player address, frags, connect time, shirt color, pants color. A blank line separates each set of server information.
QuakeWorld and HexenWorld server output -- General server information is displayed in this order: command-line arg (IP address or host name), server name, map name, maximum players, current players, average response time, number of retries, game (mod). Server rules are displayed on one line as rule-name=value. Player information is displayed one per line: player number, player name, frags, connect time, shirt color, pants color, ping time (milliseconds), skin name. A blank line separates each set of server information.
All master server output -- Master server information is displayed in this order: command-line arg (IP address or host name), number of servers. No other information is displayed about master servers.
Quake II, Quake III, Half-Life, Sin, BFRIS, Kingpin, Heretic II, Unreal, Tribes 2, and Shogo server output -- General server information and server rules are the same as a QuakeWorld server. The player information varies for each game:
  • Quake II/III, Sin, Kingpin, Heretic II, Shogo: player name, frags, ping time
  • Half-Life: player name, frags, connect time
  • Tribes: player name, frags, ping time, team number, packet loss
  • Tribes 2: player name, frags, team number, team name, player type, tribe tag
  • Unreal: player name, frags, ping time, team number, skin, mesh, face
  • BFRIS: player number, ship, team name, ping time, score, frags, player name
  • Descent 3: player name, frags, deaths, ping time, team
Ping time is in milli-seconds. Connect time is in seconds. A blank line separates each set of server information.
Ghost Recon server output -- General server information and server rules are the detailed in the GhostRecon.txt file. Servers queried using the "Gamespy style" protocol use the same raw output format as Unreal servers.

-raw,game delimiter
Same as -raw but adds the game or mod name as the last item of server info.
-raw-arg
When used with -raw, always display the server address as it appeared in a file or on the command-line. Note that when -H is used with -raw, the first field of the raw output could be a hostname if the server IP address was resolved. This can make matching up input servers addresses with raw output lines fairly difficult. When -raw-arg is also used, an additional field, the unresolved server address, is added at the beginning of all raw output lines.
-progress,count
Print a progress meter. Displays total servers processed, including timeouts and down servers. The meter is just a line of text that writes over itself with <cr>. Handy for interactive use when you are redirecting output to a file (the meter is printed on stderr).
By default, the progress meter is updated for every server. The updates can be limited by appending ,count to the option where count is a number. The meter will be updated every count servers. For example, -progress,10 will update every ten servers.
-Tserver file
-Tplayer file
-Trule file
-Theader file
-Ttrailer file
Output templates. Each template should be a text file containing QStat variables that are substituted for results from the server query. The -Tserver flag must present to enable template output. The other -T flags are optional. The server template is output once for each server queried. The player template, if present, is output once for each player (if -P is also used). The rule template is output once for each server rule (the -R option may be required for some game types). The header template is output once before any servers are output. The trailer template is output once after all servers are output. See Appendix A for the output template formatting and variables.
NOTE: All of of the -T flags may be abbreviated with two characters: -Ts, -Tp, -Tr, -Th, and -Tt.
-htmlnames
Colorize Quake 3 and Tribes 2 player names using html font tags. Enabled by default if $HTML is used in an output template.
-nohtmlnames
Do not colorize Quake 3 and Tribes 2 player names even if $HTML is used in an output template. The $HTMLPLAYERNAME variable will always colorize player names.
-htmlmode
Convert <, >, and & to the equivalent HTML entities. This is the same as $HTML in an output template, but works for raw display mode. Using -htmlmode with -xml will result in double-escaping.
-carets
Display carets in Quake 3 player names. Carets are used for colorized player names and are remove by default. This option has no effect if -htmlnames is enabled.
-xml
Output server information wrapped in XML tags.
-utf8
Use the UTF-8 character encoding for XML output.
-showgameport
Always display the game port in QStat output. If the query port was different from the game port, then the query port will be saved in the "_queryport" server rule. This is the same as the showgameport server query argument, but applies to all server queries.
-errors
Display errors.
-d
Enable debug options. By default, enables printing of all received packets to stderr.

SEARCH OPTIONS

-H
Resolve IP addresses to host names. Use with caution as many game servers do not have registered host names. QStat may take up to a minute to timeout on each unregistered IP address. The duration of the timeout is controlled by your operating system. Names are resolved before attempting to query any servers.
-Hcache cache-file
Cache host name and IP address resolutions in cache-file. If the file does not exist, it is created. If -Hcache is used without -H, then the cache is only used for host to IP address resolution. WARNING A host cache file should not be shared by QStat programs running at the same time. If you run several QStats at the same time, each should have its own cache file.
-interval seconds
Interval in seconds between server retries. Specify as a floating point number. Default interval is 0.5 seconds. This option does not apply to master servers (see -mi.)
-mi seconds
Interval in seconds between master server retries. Specify as a floating point number. Default interval is 2 seconds.
-retry number
Number of retries. QStat will send this many packets to a host before considering it non-responsive. Default is 3 retries.
-maxsimultaneous number
Number of simultaneous servers to query. Unix systems have an operating system imposed limit on the number of open sockets per process. This limit varies between 32 and 100 depending on the platform. On Windows 95 and Windows NT, the "select" winsock function limits the number of simultaneous queries to 64. These limits can be increased by minor changes to the code, but the change is different for each platform. Default is 20 simultaneous queries. This option may be abbreviated -maxsim.
-timeout seconds
Total run time in seconds before giving up. Default is no timeout.

NETWORK OPTIONS

-srcport port-number | port-range
Specify the source ports for sending packets. The ports can be a single number or a range. A range is two numbers separated by a dash ('-'). The numbers should be positive and less than 65535. Use this option to get through a firewall that has source port restrictions. Set -srcport to the range of ports allowed by the firewall.

Example: If your firewall will allow outgoing UDP packets on ports 26000-30000, the qstat option would be -srcport 26000-30000

Note: The number of source ports given should be greater than or equal to the -maxsim (defaults to 20). The number of source ports will limit the number of simultaneous server queries.

-srcip IP-address
Specify a local IP address from which to send packets. This is useful on machines that have multiple IP addresses where the source IP of a packet is checked by the receiver. Normally this option is never needed.

NOTES

The response time is a measure of the expected playability of the server. The first number is the server's average time in milli-seconds to respond to a request packet from QStat. The second number is the total number of retries required to fetch the displayed information. More retries will cause the average response time to be higher. The response time will be more accurate if more requests are made to the server. For POQS, a request is made for each server rule and line of player information. So setting the -P and -R options will result in a more accurate response time. Quake and Hexen II are POQS. For most other game servers, QStat makes just one request to retrieve all the server status information, including server rules and player status. The -P and -R options do not increase the number of requests to the server. Half-Life supports three different requests for information; general status, players, and server rules. Each requires a separate request packet, so a total of three are used to retrieve player and rules.

Quake supports a number of control codes for special effects in player names. QStat normalizes the codes into the ASCII character set before display. The graphic codes are not translated except the orange brackets (hex 90, 10, 91, and 11) which are converted to '[' and ']'. Use the hex-player-names option -hpn to see the complete player name.

POQS do not return version information. But some small amount of info can be gathered from the server rules. The noexit rule did not appear until version 1.01. The Quake II server rules include a "version" key that contains the id build number. Recent releases of QuakeWorld have a "*version" key in the server rules. Unreal servers include a "gamever" key in the server rules that contains the server version without the decimal point. Most other game servers include some kind of version info in the server rules.

EXAMPLES

The following is an example address file that queries a QuakeWorld master, several Hexen II servers, some POQS, and a few Quake II servers.

QWM 192.246.40.12:27004
H2S 207.120.210.4
H2S 204.145.225.124
H2S 207.224.190.21
H2S 165.166.140.154
H2S 203.25.60.3
QS 207.25.198.110
QS 206.154.207.104
QS 205.246.42.31
QS 128.164.136.171
Q2S sm.iquest.net
Q2S 209.39.134.5
Q2S 209.39.134.3

If the above text were in a file called QSERVER.TXT, then the servers could be queried by running:
qstat -f QSERVER.TXT

IMPLEMENTATION NOTES

QStat sends packets to each host and waits for return packets. After some interval, another packet is sent to each host which has not yet responded. This is done several times before the host is considered non-responsive. QStat can wait for responses from up to 20 hosts at a time. For host lists longer than that, QStat checks more hosts as results are determined.

The following applies only applies to POQS. If QStat exceeds the maximum number of retries when fetching server information, it will give up and try to move on to the next information. This means that some rules or player info may occasionally not appear. Player info may also be missing if a player drops out between getting the general server info and requesting the player info. If QStat times out on one rule request, no further rules can be fetched. This is a side-effect of the Quake protocol design.

The number of available file descriptors limits the number of simultaneous servers that can be checked. QStat reuses file descriptors so it can never run out. The macro MAXFD in qstat.c determines how many file descriptors will be simultaneously opened. Raise or lower this value as needed. The default is 20 file descriptors.

Operating systems which translate ICMP Bad Port (ICMP_PORT_UNREACHABLE) into a ECONNREFUSED will display some hosts as DOWN. These hosts are up and connected to the network, but there is no program on the port. Solaris 2.5 and Irix 5.3 correctly support ICMP_PORT_UNREACHABLE, but Solaris 2.4 does not. See page 442 of "Unix Network Programming" by Richard Stevens for a description of this ICMP behavior.

Operating systems without correct ICMP behavior will just report hosts without Quake servers as non-responsive. Windows NT and Windows 95 don't seem to support this ICMP.

For hosts with multiple IP addresses, QStat will only send packets to the first address returned from the name service.

QStat supports Unreal version 2.15 or greater.

BUGS

PORTABILITY

UNIX - QStat has been compiled and tested on Solaris 2.x, Irix 5.3/6.2/6.3/6.4, FreeBSD 2.2/3.0, BSDi, HP-UX 10.20/11.0, and various flavors of Linux.

WINDOWS - The Windows version of QStat (win32/qstat.exe) runs on Windows 95 and Windows NT as a console application. On Windows 95 and NT 4.0, short-cuts can be used to set the arguments to qstat. On Windows NT 3.51, use a batch file.

OS/2 - An OS/2 binary is no longer included. Try contacting Per Hammer for an OS/2 Warp binary. per@mindbend.demon.co.uk.

VMS - The source includes a VMS patch from John Ross Hunt. This patch was tested on QStat 2.0b, but has not been tested on the current version. See COMPILE.txt for instructions.

VERSION

This is QStat version 2.10 The QStat webpage is updated for each new version and contains links to Quake server listings and pages about the Quake and Unreal network protocols. The page can be found at
http://www.qstat.org

Quake, Quake II, QuakeWorld, and Quake III created by id Software. Hexen II, HexenWorld, and Heretic II created by Raven Software. Unreal created by Epic Games. Half-Life created by Valve Software. Sin created by Ritual Entertainment. Shogo: Mobile Armor Division was created by Monolith Productions Inc. Tribes and Tribes 2 created by Dynamix, Inc. BFRIS created by Aegis Simulation Technologies. Kingpin created by Xatrix Entertainment Inc.

AUTHOR

Steve Jankowski
steve@qstat.org

COPYRIGHT

Copyright © 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski

LICENSE

QStat is covered by the terms of the Artistic License. The license terms can be found in LICENSE.txt of the QStat package.


APPENDIX A - Output Templates

QStat output templates provide greater control of the appearance of server status information. The results of a server query can be organized, formatted, and wrapped within any other text. The most obvious use is to generate HTML for web pages. However, it could also generate custom output for redisplay within another tool.

There are four output templates:
TemplateOption 
server-TsOutput once for each server queried. (required)
player-TpOutput once for each player. Must be used with -P. Invoked by the $PLAYERTEMPLATE variable.
rule-TrOutput once for each server rule. Invoked by the $RULETEMPLATE variable.
header-ThOutput once before any servers are queried.
trailer-TtOutput once after all servers are output.

The server template must be specified to enable template output. The other templates are optional.

Each output template is a file containing text and QStat variables. The text is output unchanged by QStat, but the variables are processed and replaced by QStat. Most variables are replaced by values from a queried server. Some variables have hardcoded values, and some generate no output, but affect how the template is processed.

Variables are grouped according to the templates where they can be used. General variables may be used in any of the templates. Server variables may be used in the server or player templates. Player variables may be used in the player template. Expression variables may only be used with the $IF and $IFNOT variables. If a variable is used where it doesn't make sense, it is ignored and generates no output.

Variables are specified using one of several syntaxes:

    $VAR
    $VAR:OPTION
    $(VAR)
    $(VAR:OPTION)
    $(VAR:OPTION(ARGUMENT))
The syntax used does not affect the output. However using the $() syntax is somewhat more readable when the text gets cluttered. If you want the variable to be followed immediately by text, then the $() syntax must be used.

Download considerations

If you are generating output to be downloaded, then you'll want to make your output as small as possible. In the case of HTML, you can reduce the size of your pages by excluding stuff.
  • Remove unneeded spaces (indenting and newlines)
  • Remove unneeded end tags. The HTML spec says the following tags can always be left out: </TD> </TR> </TH>
  • When creating a table, "width" modifiers are only needed on one cell of a column. Put them on the cells of the first row of the table.

    Display options

    The display options -u, -ne, and -nf have no affect on template output. Use the $IF:UP, $IF:ISEMPTY, and $IF:ISFULL conditions to accomplish the same thing.

    General Variables

    $QSTATURLOutput the web address of the QStat home page.
    $QSTATVERSIONOutput the version of QStat being run.
    $QSTATAUTHOROutput the name of the QStat programmer.
    $QSTATAUTHOREMAILOutput the email address of the QStat programmer.
    $HTMLEnable HTML friendly string output. Server results may include characters that have special meaning in HTML. These are replaced by equivalent SGML entities. QStat converts '<', '>', and '&' to '&lt;', '&gt;', and '&amp;'. Use this variable once in the header template.
    $CLEARNEWLINESConvert line feeds and carriage returns into spaces. Applies to all variables that output strings. Use this variable once in the header template.
    $RULENAMESPACESAllow spaces in rule names. Use this variable once in the header template.
    $IFConditional output. If the variable option is "true," the template is output up to a matching $ENDIF variable. If the variable option is "false," the template is ignored until after a matching $ENDIF. See Conditional Options for a list of supported conditional options.
    $IFNOTConditional output. Same as $IF, but the opposite sense.
    $ENDIFEnd conditional output. There must be one $ENDIF for each $IF and $IFNOT within a template.
    $NOWOutput the current local time.
    $TOTALSERVERSThe total number of servers to be queried.
    $TOTALUPThe number of servers up and running.
    $TOTALNOTUPThe number of servers either DOWN or TIMEOUT.
    $TOTALPLAYERSThe number of players found on all servers.
    $TOTALMAXPLAYERSThe sum of the maximum player values for all servers.
    $TOTALUTILIZATIONThe ratio of $TOTALPLAYERS to $TOTALMAXPLAYERS expressed as a percentage (a number between 0 and 100). Reports how full the servers are.
    $\Ignore the next newline. Not really a variable, but a way to curtail the output of extra newlines. Saves space in the output while the template remains readable. Must be the last thing on the line.
    $DEFAULTTYPEThe full name of the default server type specified with -default.

    Server Variables

    $HOSTNAMEOutput the host name of the server if known, otherwise the server address as given to QStat.
    $SERVERNAMEOutput the name of the server.
    $PINGThe time in milli-seconds to get a response from the server. If the server is DOWN or TIMEOUT, nothing is output.
    $PLAYERSThe number of players on the server.
    $MAXPLAYERSThe maximum number of players allowed on the server.
    $MAPThe name of the map being played.
    $GAMEThe name of the game being played. This is usually the name of the "mod" run by the server.
    $GAMETYPEThe type of game being played. Only applies to Quake 3. Typical values are Free For All, Capture the Flag, and Arena.
    $RETRIESThe number of retries needed to get the server status. This is a measure of packet loss.
    $IPADDRThe IP address of the server. Does not include the port number.
    $PORTThe port the server is running on.
    $ARGThe server address as given to QStat.
    $TYPEOutput one of the following depending on the server type:
        Quake
        Quake II
        Quake II Master
        QuakeWorld
        QuakeWorld Master
        Hexen II
        HexenWorld
        Unreal
        Unreal Tournament 2003
        Half-Life
        Half-Life Master
        Sin
        Tribes
        Tribes Master
        Tribes 2
        Tribes 2 Master
        Shogo: Mobile Armor Division
        Quake III: Arena
        Quake III Master
        BFRIS
        Kingpin
        Heretic II
        Soldier of Fortune
        Gamespy Master
        Gamespy Protocol
    
    If the server type is not known, nothing is output.
    $TYPESTRINGThe server's type string (see GAME OPTIONS table.)
    $TYPEPREFIXThe server's type prefix (same as $TYPESTRING but in all-caps.)
    $RULE:nameThe value of a server rule. If the rule is not returned by the server, nothing is output. Must be used with the -R flag. Server rule names can include any alpha-numeric character plus '*', '_', '.', or ' ' (space). The use of space in a rule name will require use of the parenthesized format: $(RULE:name)
    $ALLRULESOutput all the server rules in the format name=value separated by commas. Must be used with the -R flag.
    $PLAYERTEMPLATEInvoke the player template. The player template is output once for each player on the server. Must be used with the -P flag.
    $RULETEMPLATEInvoke the rule template. The rule template is output once for each server rule.

    Player Variables

    The player template is only invoked if $PLAYERTEMPLATE is used in the server template.

    $PLAYERNAMEThe name of the player. If -htmlnames or $HTML is used, then HTML color font tags will be added for Quake 3 and Tribes 2 player names. If $HTML is used but -nohtmlnames is set, then player names will not be colorized.
    $HTMLPLAYERNAMEThe name of the player with HTML color font tags. Only Quake 3 and Tribes 2 are supported.
    $FRAGSThe number of frags scored.
    $DEATHSDescent 3 - The number of times player has died. Ghost Recon - Indicates if the player is dead. Only available for Descent 3 or Ghost Recon.
    $PLAYERPINGThe player's ping time to the server. This value is not available from Half-Life or Ghost Recon servers.
    $CONNECTTIMEHow long the player has been playing. This value is only available from Quake, QuakeWorld, Hexen II, and Half-Life servers.
    $SKINThe name of the player's skin texture. This value is not available from ?? and Ghost Recon servers.
    $MESHThe name of the player's mesh (model). This value is only available from Unreal servers.
    $FACEThe name of the player's face texture. This value is only available from Unreal version 405+ servers.
    $SHIRTCOLORColor of the player's shirt. This value is only available from Quake, QuakeWorld, and Hexen II servers.
    $PANTSCOLORColor of the player's pants. This value is not available from Quake, QuakeWorld, and Hexen II servers.
    $PLAYERIPThe IP address of the player's computer. This value is only available from Quake and Hexen II servers.
    $TEAMNUMThe player's team number. This value is only available from Unreal, Tribes, Tribes 2 and Ghost Recon servers.
    $TEAMNAMEThe player's team name. This value is only available from Tribes and Tribes 2 servers.
    $TRIBETAGThe player's tribe tag. This value is only available from Tribes 2 servers.
    $PLAYERSTATIDThe player's global statistics id. This value is only available from Unreal Tournament 2003 servers.
    $PACKETLOSSThe player's packet loss. This value is only available from Tribes servers.
    $COLORNUMBERSDisplay $SHIRTCOLOR and $PANTSCOLOR as numbers. Equivalent to -ncn command-line option. No output.
    $COLORNAMESDisplay $SHIRTCOLOR and $PANTSCOLOR using color names. Equivalent to -cn command-line option. No output.
    $COLORRGBDisplay $SHIRTCOLOR and $PANTSCOLOR using #rrggbb format. Equivalent to -hc command-line option. No output.
    $TIMESECONDSDisplay $CONNECTTIME as number of seconds. Equivalent to -ts command-line option. No output.
    $TIMECLOCKDisplay $CONNECTTIME in clock format (DhDDmDDs). Equivalent to -tc command-line option. No output.
    $TIMESTOPWATCHDisplay $CONNECTTIME in stop-watch format (DD:DD:DD). Equivalent to -tsw command-line option. No output.

    Rule Variables

    The rule template is only invoked if $RULETEMPLATE is used in the server template. The rule template supports equality tests on rule names and values. See RULENAME and RULEVALUE under Conditional Options.

    $RULENAMEThe server rule name.
    $RULEVALUEThe server rule value.

    Conditional Options

    These options maybe used with the $IF and $IFNOT variables. For example, to display player information, the following could be used in the server template:

        $(IF:PLAYERS)$(IF:FLAG(-P))
        The server has $(PLAYERS) players:
        $(PLAYERTEMPLATE)
        $(ENDIF)$(ENDIF)
    
    The template between the $IF and $ENDIF variables will only be displayed if the server has one or more players and the -P flag was given to QStat.

    GAMETrue if the server is running a "mod."
    PLAYERSTrue if the server has one or more players.
    QUAKETrue if the server is running Quake (the original).
    QUAKE2True if the server is running Quake II.
    Q2MASTERTrue if the server is a Quake II master.
    QUAKEWORLDTrue if the server is running QuakeWorld.
    QWMASTERTrue if the server is a QuakeWorld master.
    HEXEN2True if the server is running Hexen II.
    HEXENWORLDTrue if the server is running HexenWorld.
    UNREALTrue if the server is running Unreal.
    UNREALTOURNAMENT2003True if the server is running Unreal Tournament 2003.
    HALFLIFETrue if the server is running Half-Life.
    HLMASTERTrue if the server is a Half-Life master.
    SINTrue if the server is running Sin.
    TRIBESTrue if the server is running Tribes.
    TRIBESMASTERTrue if the server is a Tribes master.
    TRIBES2True if the server is running Tribes 2.
    TRIBES2MASTERTrue if the server is a Tribes 2 master.
    SHOGOTrue if the server is running Shogo.
    QUAKE3True if the server is running Quake III.
    Q3MASTERTrue if the server is a Quake III master.
    BFRISTrue if the server is running BFRIS.
    KINGPINTrue if the server is running Kingpin.
    HERETIC2True if the server is running Heretic II.
    SOLDIEROFFORTUNETrue if the server is running Soldier of Fortune.
    DESCENT3True if the server is running Descent 3.
    GAMESPYMASTERTrue if the server is a Gamespy Master.
    GAMESPYPROTOCOLTrue if the server is running a "Gamespy style" status protocol.
    RULE(name)True if the rule name is set on the server. Server rule names can include any alpha-numeric character plus '*', '_', or '.'. If $RULENAMESPACES is enabled, then rule names may contain a ' ' (space).
    FLAG(name)True if the flag name was used on the QStat command-line. The only flag names supported are: -H, -P, and -R. Any other flag name returns false.
    UPTrue if the server is up and running.
    DOWNTrue if the server is known to be not running. This is true if the server computer returns an ICMP indicating that nothing is running on the port. Only supported by some operating systems.
    TIMEOUTTrue if the server never responded to a status query.
    HOSTNOTFOUNDTrue if the host name lookup failed.
    ISEMPTYTrue if the server has no players.
    ISMASTERTrue if this is a master server.
    ISFULLTrue if the server has the maximum players.
    ISTEAMTrue if the player is a team. Only available with Tribes and Tribes 2 servers. Only applies to the player template.
    ISBOTTrue if the player is a bot. Only available with Tribes 2 servers. Only applies to the player template.
    ISALIASTrue if the player is using an alias. Only available with Tribes 2 servers. Only applies to the player template.
    TRIBETAGTrue if the player has a tribe tag. Only available with Tribes 2 servers. Only applies to the player template.
    RULENAMETrue if the rule name matches the variable argument. For example $(IF:RULENAME(version)) will be true when the rule template is outputing a "version" server rule. Only applies to the rule template.
    RULEVALUETrue if the rule value matches the variable argument. For example $(IF:RULEVALUE(1)) will be true when the rule template is outputing a server rule whose value is "1". Only applies to the rule template.
    DEATHSTrue if the player has recorded DEATHS in Descent 3 or if the player is dead in Ghost Recon. NOTE if the Ghost Recon player has spawns available they can go from dead to alive.

    APPENDIX B - QStat Configuration File

    QStat configuration files modify built-in game types or create new game types. New command-line options and template variables are created for new game types.

    Please refer to the default configuration file for examples. The default configuration file qstat.cfg can be found in the QStat package.

    Config File Load Order

    QStat will load one default configuration file and zero or more command-line configuration files. The default configuration file will be the first readable file found by the following search.
    1. File named in $QSTAT_CONFIG environment variable.
    2. Unix: $HOME/.qstatrc
      Windows: $HOME/qstat.cfg
    3. Unix: sysconfdir/qstat.cfg
      Windows: location-of-qstat.exe/qstat.cfg
    The default configuration file will be loaded before reading any command-line parameters. Configuration files specified on the command line will be merged with the contents of the default config file. In the case of duplicate game types, the command-line config files will be used. The QStat package includes a qstat.cfg that defines several new game types. If you want to use these game types, you need to place the file where it can be found by the default config file search. Or use the -cfg option.
    Unix Note: The sysconfdir is determined when qstat is compiled. For Unix compiles, the QStat makefiles default to /etc. To compile with a different sysconfdir, set SYSCONFDIR when compiling with gmake. For example, to set sysconfdir to /usr/local/etc
    % gmake SYSCONFDIR=/usr/local/etc
    Windows Note: The location-of-qstat.exe is the directory where the QStat executable (qstat.exe) is located. Just put the default qstat.cfg in the same directory as qstat.exe.

    General Syntax

    QStat configuration files describe game types using "stanzas". A stanza begins with a "gametype" line and is followed by several parameter lines ending with an "end" line. The general syntax looks like this:
    gametype type-string (modify | new extend type-string)
        parameter-name = parameter-value
        ...
    end
    
    The text in bold are keywords that must be used as shown.

    Parameter names are one or more words separated by spaces. The supported parameters and their meaning are listed in Gametype Parameters. Extra white space before, after and within a parameter name is ignored. An equal sign ('=') must separate the parameter name and the parameter value. There can be one parameter setting per line.

    Parameter values are one more characters or escape sequences. Leading and trailing spaces are ignored. All characters are used as-is except for backslash ('\') which begins an escape sequence.

    \\A single backslash ('\')
    \nA newline (ASCII char 10)
    \rA carriage return (ASCII char 13)
    \(space) A space (ASCII char 32). This escape should be entered as two characters: backslash followed by one space.
    \xHHA single character represented by the two-digit hexadecimal code. The hex digits H must be 0-9, A-F, or a-f.
    \DDDA single character represented by the three-digit octal code. The octal digits D must be 0-7.

    Defining New Game Types

    New game types are defined with the new keyword.
    gametype new-type-string new extend existing-type-string
        parameter-name = parameter-value
        ...
    end
    
    The new-type-string must not be a built-in type string. If a new gametype is defined multiple times in configuration files, only the last definition is used. The existing-type-string can be any built-in or configuration defined game type. However, QStat has the best support for extending Q3S, Q2S, GPS, UNS, and Q3M game types.

    The new game type has command-line option, type string and type prefix derived from new-type-string. The case of new-type-string is ignored. The command-line option and type string are always lower-case and the type prefix is always upper case.

    The new game type starts with the same parameters as the existing-type-string except for the type string itself. Game type parameters are set by the following parameter setting lines. Some parameters may only be used with master server and some only with game servers.

    We suggest that new-type-strings be as short as possible and end with an 's' for game servers and an 'm' for master servers. New game types should, but are not required to, set the name, default port, and template var parameters. The template var should be all upper-case and should not contain any spaces.

    Modifying Game Types

    Existing game types can be modified to update their query parameters.
    gametype existing-type-string modify
        parameter-name = parameter-value
        ...
    end
    
    The existing-type-string can be a built-in game type or a configuration defined game type.

    Only certain parameters can be modified: master protocol, master query, and master packet.

    Request Packets

    The request packets used for game server queries can be set with status packet, status2 packet, player packet, and rule packet. Request packets for master servers can be set with the master packet parameter.

    A request packet can only be set if the extended game type uses the same type of request packet. If a game type only uses the status packet, then an extending game type can only set the status packet.

    Request packet typically contain binary characters (those beyond the printable ASCII character set). These can be specified using the hex and octal character escapes.

    If the master packet parameter is set, the master protocol and master query parameters will be ignored.

    Game Type Parameters

    nameSets the name of the game type. Should be the full game name as used by the publisher.
    flagsset the query flags. Bitwise OR of the following constants:
    • TF_SINGLE_QUERY
    • TF_OUTFILE
    • TF_MASTER_MULTI_RESPONSE
    • TF_TCP_CONNECT
    • TF_QUERY_ARG
    • TF_QUERY_ARG_REQUIRED
    • TF_QUAKE3_NAMES
    • TF_TRIBES2_NAMES
    • TF_SOF_NAMES
    • TF_U2_NAMES
    • TF_RAW_STYLE_QUAKE
    • TF_RAW_STYLE_TRIBES
    • TF_RAW_STYLE_GHOSTRECON
    • TF_NO_PORT_OFFSET
    • TF_SHOW_GAME_PORT
    default portDefault network port used by the status protocol.
    status port offsetOffset of the status/query port from the game port.
    game ruleThe server rule containing the name of the game style or game mod.
    template varThe template variable used to test whether a server is of this game type.
    status packetThe status request packet. This is the first packet sent to a server of this game type.
    status2 packetThe second status request packet. If the server responded to the first status packet, then this packet is sent, but only if player or rule info is needed (command-line options -P or -R).
    player packetThe player request packet. Requests player information.
    rule packetThe rule request packet. Requests server rule information.
    master for gametypeSets the type of game returned by this master. The value must be a built-in or configuration defined game type.
    master protocolThe protocol number to use in the master request. The master server will respond with servers that match the protocol number. The numbers change with each version of the game that uses an incompatible network protocol. The master protocol is used mainly with Quake 3 based games.

    The master request packet will combine the master protocol and master query values.

    master queryThe query string to use in the master request. The master query string provides additional filtering for the master server.

    The default master request packet will combine the master protocol and master query values.

    master packetThe master request packet. Requests a server list from the master server. If master packet is set, master protocol and master query are ignored.
    qstat-2.11/configure0000755002404400000620000045166010520647404011433 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for qstat 2.11. # # Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='qstat' PACKAGE_TARNAME='qstat' PACKAGE_VERSION='2.11' PACKAGE_STRING='qstat 2.11' PACKAGE_BUGREPORT='qstat-users@yahoogroups.com' ac_unique_file="qstat.c" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP EGREP LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qstat 2.11 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qstat 2.11:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --disable-debug turn off debugging code --enable-dump enable packet dumps Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF qstat configure 2.11 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qstat $as_me 2.11, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers gnuconfig.h" ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` am__api_version="1.9" # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 test "$program_prefix" != NONE && program_transform_name="s,^,$program_prefix,;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s,\$,$program_suffix,;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$AWK" && break done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='qstat' VERSION='2.11' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi STRIP=$ac_ct_STRIP else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6 rm -f confinc confmf # Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval="$enable_dependency_tracking" fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "${ac_cv_header_sys_mman_h+set}" = set; then echo "$as_me:$LINENO: checking for sys/mman.h" >&5 echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_mman_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking sys/mman.h usability" >&5 echo $ECHO_N "checking sys/mman.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking sys/mman.h presence" >&5 echo $ECHO_N "checking sys/mman.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: sys/mman.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: sys/mman.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: sys/mman.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: sys/mman.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: sys/mman.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: sys/mman.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: sys/mman.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: sys/mman.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: sys/mman.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: sys/mman.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: sys/mman.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------------ ## ## Report this to qstat-users@yahoogroups.com ## ## ------------------------------------------ ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for sys/mman.h" >&5 echo $ECHO_N "checking for sys/mman.h... $ECHO_C" >&6 if test "${ac_cv_header_sys_mman_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_sys_mman_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_sys_mman_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_mman_h" >&6 fi if test $ac_cv_header_sys_mman_h = yes; then have_mman_h=yes fi case $host in *mingw32*) { echo "$as_me:$LINENO: compiling for $host, adding -lwsock32" >&5 echo "$as_me: compiling for $host, adding -lwsock32" >&6;} LIBS="$LIBS -lwsock32" ;; esac echo "$as_me:$LINENO: checking whether to enable debug output" >&5 echo $ECHO_N "checking whether to enable debug output... $ECHO_C" >&6 # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" fi; if test x$enable_debug != xno; then CPPFLAGS="$CPPFLAGS -DDEBUG" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi echo "$as_me:$LINENO: checking whether to enable packet dumps" >&5 echo $ECHO_N "checking whether to enable packet dumps... $ECHO_C" >&6 # Check whether --enable-dump or --disable-dump was given. if test "${enable_dump+set}" = set; then enableval="$enable_dump" fi; if test x$enable_dump != xno; then if test x$have_mman_h = xyes; then CPPFLAGS="$CPPFLAGS -DENABLE_DUMP" echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no, sys/mman.h missing" >&5 echo "${ECHO_T}no, sys/mman.h missing" >&6 fi else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-Wall[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wall" ;; esac fi ac_config_files="$ac_config_files Makefile template/Makefile info/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by qstat $as_me 2.11, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ qstat config.status 2.11 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS section. # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "template/Makefile" ) CONFIG_FILES="$CONFIG_FILES template/Makefile" ;; "info/Makefile" ) CONFIG_FILES="$CONFIG_FILES info/Makefile" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "gnuconfig.h" ) CONFIG_HEADERS="$CONFIG_HEADERS gnuconfig.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@CYGPATH_W@,$CYGPATH_W,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@ACLOCAL@,$ACLOCAL,;t t s,@AUTOCONF@,$AUTOCONF,;t t s,@AUTOMAKE@,$AUTOMAKE,;t t s,@AUTOHEADER@,$AUTOHEADER,;t t s,@MAKEINFO@,$MAKEINFO,;t t s,@install_sh@,$install_sh,;t t s,@STRIP@,$STRIP,;t t s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@mkdir_p@,$mkdir_p,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@am__leading_dot@,$am__leading_dot,;t t s,@AMTAR@,$AMTAR,;t t s,@am__tar@,$am__tar,;t t s,@am__untar@,$am__untar,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@DEPDIR@,$DEPDIR,;t t s,@am__include@,$am__include,;t t s,@am__quote@,$am__quote,;t t s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi # Compute $ac_file's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $ac_file | $ac_file:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X$ac_file : 'X\(//\)[^/]' \| \ X$ac_file : 'X\(//\)$' \| \ X$ac_file : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'`/stamp-h$_am_stamp_count done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_COMMANDS section. # for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_dest=`echo "$ac_file" | sed 's,:.*,,'` ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_dest" : 'X\(//\)[^/]' \| \ X"$ac_dest" : 'X\(//\)$' \| \ X"$ac_dest" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 echo "$as_me: executing $ac_dest commands" >&6;} case $ac_dest in depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`(dirname "$file") 2>/dev/null || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p $dirpart/$fdir else as_dir=$dirpart/$fdir as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi qstat-2.11/template/0000777002404400000620000000000010523107301011375 500000000000000qstat-2.11/template/ghostreconTh.html0000644002404400000620000000045007564605624014673 00000000000000$HTML Ghost Recon Servers

    Ghost Recon Servers

    Last update: $NOW

    Example of Ghost Recon support in QStat.

    qstat-2.11/template/ghostreconTp.html0000644002404400000620000000026107564605624014703 00000000000000 $PLAYERNAME $TEAMNAME $(IF:DEATHS)Dead$(ENDIF)$(IFNOT:DEATHS)Alive$(ENDIF)   qstat-2.11/template/ghostreconTs.html0000644002404400000620000000640407564605624014713 00000000000000
    Server Name Players Map Mission  
    $SERVERNAME $PLAYERS/$MAXPLAYERS $MAP $(RULE:mission)  
    Game Mode Mission Type Dedicated Server Ip Addr  
    $(RULE:gamemode) $(RULE:missiontype) $(RULE:dedicated) $IPADDR:$PORT  
    Status Time Limit Time Played Remaining Time  
    $(RULE:status) $(RULE:gametime) $(RULE:timeplayed) $(RULE:remainingtime)  
    Version Spawn Type Spawn Count Restrictions  
    $(RULE:version) $(RULE:spawntype) $(RULE:spawncount) $(RULE:restrict)  
    Password Threat Indicator Patch Level Observing  
    $(RULE:password) $(RULE:ti) $(RULE:patch) $(RULE:allowobservers)  
    Start Timer Start Time Value Time untill Start Debrief Time  
    $(RULE:usestarttime) $(RULE:starttimeset) $(RULE:startwait) $(RULE:debrieftime)  
    Respawn Minimum Respawn Maximum Respawn Safe IFF Mode  
    $(RULE:respawnmin) $(RULE:respawnmax) $(RULE:respawnsafe) $(RULE:iff)  
    MOTD  
    $(RULE:motd)  
    Mods  
    $GAME  
    $(IF:PLAYERS)$(IF:FLAG(-P)) $PLAYERTEMPLATE
    Player Name Team Health  
    $ENDIF$ENDIF

    qstat-2.11/template/ghostreconTt.html0000644002404400000620000000021707564605624014710 00000000000000

    $TOTALPLAYERS players on $TOTALUP servers.

    Created with QStat $QSTATVERSION

    qstat-2.11/template/brocTh.html0000644002404400000620000000140407564605624013445 00000000000000$HTML broccoli Quake 2 servers

    broccoli Quake 2 servers

    Last update: $NOW

    The Solaris version of Quake II v 3.15 (soon 3.17) is not yet available. As soon as I can get my hands on the bits, I'll be running upgrading the server.

    I run $TOTALSERVERS servers on a Sun Ultra 2 running Solaris 2.5.1. The machine has two CPUs, so performance is good even when I'm using it for work. Enjoy!

    qstat-2.11/template/tribes2th.html0000644002404400000620000000075307564605624014140 00000000000000$HTML Tribes 2 Servers

    Tribes 2 Servers

    Last update: $NOW

    Example of Tribes 2 support in QStat.

    Server Name Players Map Game Address
    qstat-2.11/template/brocTp.html0000644002404400000620000000015307564605624013455 00000000000000 qstat-2.11/template/Makefile.am0000644002404400000620000000004610140661715013356 00000000000000EXTRA_DIST = $(wildcard *.html *.txt) qstat-2.11/template/Makefile.in0000644002404400000620000001723010523107225013366 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = template DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnuconfig.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = $(wildcard *.html *.txt) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign template/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign template/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: qstat-2.11/template/tribes2tp.html0000644002404400000620000000073507564605624014150 00000000000000$HTMLPLAYERNAME $(IF:ISBOT)Bot$(ENDIF)$(IF:ISALIAS)Alias$(ENDIF)$(IF:ISTEAM) $ENDIF $(IF:TRIBETAG)$TRIBETAG$(ENDIF)$(IF:ISTEAM) $ENDIF   qstat-2.11/template/brocTs.html0000644002404400000620000000102307564605624013455 00000000000000 qstat-2.11/template/brocTt.html0000644002404400000620000000021707564605624013462 00000000000000
    Server Name Players Mission Map Address
      $PLAYERNAME $FRAGS $PLAYERPING
      $FRAGS $TEAMNAME$(IF:ISTEAM)TEAM$ENDIF
    $SERVERNAME $(IFNOT:QWMASTER)$PLAYERS/$MAXPLAYERS$(ENDIF) $MAP $GAME $HOSTNAME $(IF:PLAYERS)$(IF:FLAG(-P))
    $PLAYERTEMPLATE
      Player Name Frags Ping  
    $ENDIF$ENDIF
     


    $TOTALPLAYERS players on $TOTALUP servers.

    Created with QStat $QSTATVERSION

    qstat-2.11/template/tribes2ts.html0000644002404400000620000000134007564605624014144 00000000000000$(IFNOT:ISMASTER) $SERVERNAME $PLAYERS/$MAXPLAYERS $RULE:mission $MAP $HOSTNAME $(IF:RULE(info))
    $(RULE:info)
    $(ENDIF) $(IF:PLAYERS)$(IF:FLAG(-P)) $PLAYERTEMPLATE
      Player Name Type Tribe Score   Team  
    $ENDIF$ENDIF   $ENDIF qstat-2.11/template/tribes2tt.html0000644002404400000620000000021707564605624014147 00000000000000


    $TOTALPLAYERS players on $TOTALUP servers.

    Created with QStat $QSTATVERSION

    qstat-2.11/template/README.txt0000644002404400000620000000170007564605624013033 00000000000000This directory contains the output templates used for the old broccoli server status page. ** The broccoli servers are no longer running. You should substitute ** your own server addresses into 'broc.lst'. brocTh.html header template brocTp.html player template brocTs.html server template brocTt.html trailer template broc.lst server list To generate an HTML page for the broccoli servers: qstat -P -f broc.lst -Ts brocTs.html -Th brocTh.html -Tt brocTt.html -Tp brocTp.html -sort g -of qservers.html The HTML output will be put in "qservers.html". I've also included some templates for Unreal/UT. They can be used like this: qstat -P -R -f unreal.lst -Th unrealTh.html -Tp unrealTp.html -Ts unrealTs.html -Tt unrealTt.html -sort g -of unreal.html The HTML output will be put in "unreal.html". qstat -P -R -f tribes2.lst -Th tribes2th.html -Tp tribes2tp.html -Ts tribes2ts.html -Tt tribes2tt.html -sort g -of tribes2.html qstat-2.11/template/unrealTh.html0000644002404400000620000000066607564605624014017 00000000000000$HTML Unreal Servers

    Unreal Servers

    Last update: $NOW

    Example of Unreal support in QStat.

    qstat-2.11/template/unrealTp.html0000644002404400000620000000017707564605624014024 00000000000000 qstat-2.11/template/unrealTs.html0000644002404400000620000000123207564605624014020 00000000000000 qstat-2.11/template/unrealTt.html0000644002404400000620000000021707564605624014023 00000000000000
    Server Name Players Map Address
      $PLAYERNAME $FRAGS $SKIN $TEAMNUM
    $SERVERNAME $(IFNOT:QWMASTER)$PLAYERS/$MAXPLAYERS$(ENDIF) $MAP $HOSTNAME $(IF:RULE(AdminEMail)) $(RULE:AdminEMail)$(ENDIF) $(IF:PLAYERS)$(IF:FLAG(-P))
    $PLAYERTEMPLATE
      Player Name Frags Skin Team  
    $ENDIF$ENDIF
     


    $TOTALPLAYERS players on $TOTALUP servers.

    Created with QStat $QSTATVERSION

    qstat-2.11/configure.ac0000644002404400000620000000242010520647337012001 00000000000000AC_INIT([qstat],[2.11],[qstat-users@yahoogroups.com]) AC_CONFIG_SRCDIR([qstat.c]) AM_CONFIG_HEADER([gnuconfig.h]) AC_PREREQ(2.53) AC_CANONICAL_HOST AM_INIT_AUTOMAKE([1.6 foreign]) dnl Checks for programs. AC_PROG_CC dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADER(sys/mman.h, [have_mman_h=yes]) case $host in *mingw32*) AC_MSG_NOTICE([compiling for $host, adding -lwsock32]) LIBS="$LIBS -lwsock32" ;; esac dnl check if user wants debug AC_MSG_CHECKING([whether to enable debug output]) AC_ARG_ENABLE(debug,[ --disable-debug turn off debugging code]) if test x$enable_debug != xno; then CPPFLAGS="$CPPFLAGS -DDEBUG" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether to enable packet dumps]) AC_ARG_ENABLE(dump,[ --enable-dump enable packet dumps]) if test x$enable_dump != xno; then if test x$have_mman_h = xyes; then CPPFLAGS="$CPPFLAGS -DENABLE_DUMP" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no, sys/mman.h missing]) fi else AC_MSG_RESULT([no]) fi dnl Use -Wall if we have gcc. changequote(,)dnl if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-Wall[\ \ ]*) ;; *) CFLAGS="$CFLAGS -Wall" ;; esac fi changequote([,])dnl AC_CONFIG_FILES([ Makefile template/Makefile info/Makefile ]) AC_OUTPUT qstat-2.11/Makefile.noauto0000644002404400000620000000244110520647352012457 00000000000000## Uncomment if you have gcc #CC = gcc #CFLAGS = -Wall -g -O2 #LDFLAGS = #LDLIBS = #CFLAGS += -Dsysconfdir=\"/etc\" CFLAGS = -DDEBUG=1 ## NOTE: if you get errors when linking qstat (missing symbols or ## libraries), then modify LDFLAGS or LDLIBS SRC = config.c debug.c hcache.c md5.c qserver.c qstat.c template.c ut2004.c a2s.c packet_manip.c gs3.c gs2.c gps.c ts2.c doom3.c tm.c OBJ = $(SRC:.c=.obj) O = $(SRC:.c=.o) SOLARIS_LIBS = -lsocket -lnsl WINDOWS_LIBS = /ML wsock32.lib OS2_LIBS = so32dll.lib tcp32dll.lib EMX_LIBS = -lsocket all: qstat qstat: $(O) $(CC) $(CFLAGS) -o qstat $(O) $(LDFLAGS) $(LDLIBS) solaris: $(SRC) $(CC) $(CFLAGS) -o qstat $(SRC) $(LDFLAGS) $(LDLIBS) $(SOLARIS_LIBS) aix sgi freebsd macosx osx openbsd irix linux: qstat hp hpux: $(SRC) $(CC) $(CFLAGS) -Ae -o qstat $(SRC) $(LDFLAGS) $(LDLIBS) win32: windows windows: $(OBJ) $(CC) /Feqstat.exe $(OBJ) $(LDFLAGS) $(LDLIBS) $(WINDOWS_LIBS) windows_debug: $(SRC) rm -f *.pdb $(CC) $(CFLAGS) /Zi /ML $(SRC) /Feqstat.exe wsock32.lib /link /fixed:no /incremental:no os2: $(SRC) $(CC) /Q /W0 /C+ $(SRC) ilink /PM:VIO $(OBJ) /out:qstat.exe $(LDFLAGS) $(LDLIBS) $(OS2_LIBS) os2emx: $(SRC) $(CC) $(CFLAGS) -o qstat.exe $(SRC) $(LDFLAGS) $(LDLIBS) $(EMX_LIBS) clean: rm -f qstat core qstat.exe $(O) $(OBJ) qstat-2.11/config.guess0000755002404400000620000012512310422550571012033 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. timestamp='2005-07-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}" in i?86) test -z "$VENDOR" && VENDOR=pc ;; *) test -z "$VENDOR" && VENDOR=unknown ;; esac test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerppc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; x86:Interix*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' exit ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; cris:Linux:*:*) echo cris-axis-linux exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux exit ;; frv:Linux:*:*) echo frv-${VENDOR}-linux exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux"; exit; } ;; ppc:Linux:*:*) echo powerpc-${VENDOR}-linux exit ;; ppc64:Linux:*:*) echo powerpc64-${VENDOR}-linux exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-${VENDOR}-linux${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-${VENDOR}-linux ;; PA8*) echo hppa2.0-${VENDOR}-linux ;; *) echo hppa-${VENDOR}-linux ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-${VENDOR}-linux exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR}-linux exit ;; x86_64:Linux:*:*) echo x86_64-${VENDOR}-linux exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-${VENDOR}-linuxaout" exit ;; coff-i386) echo "${UNAME_MACHINE}-${VENDOR}-linuxcoff" exit ;; "") # Either a pre-BFD a.out linker (linuxoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-${VENDOR}-linuxoldld" exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}" | sed 's/linux-gnu/linux/' exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in *86) UNAME_PROCESSOR=i686 ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: qstat-2.11/install-sh0000755002404400000620000002202110422550571011510 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2005-05-14.22 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" chmodcmd="$chmodprog 0755" chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= dstarg= no_target_directory= usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: -c (ignored) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test -n "$1"; do case $1 in -c) shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit $?;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t) dstarg=$2 shift shift continue;; -T) no_target_directory=true shift continue;; --version) echo "$0 $scriptversion"; exit $?;; *) # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. test -n "$dir_arg$dstarg" && break # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done break;; esac done if test -z "$1"; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then mkdircmd=: chmodcmd= else mkdircmd=$mkdirprog fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -d "$dstdir"; then defaultIFS=' ' IFS="${IFS-$defaultIFS}" oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` shift IFS=$oIFS pathcomp= while test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test -d "$pathcomp" || exit fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $mkdircmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. $doit $cpprog "$src" "$dsttmp" && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ || { # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit 1 } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit 1; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit 0 } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: qstat-2.11/config.sub0000755002404400000620000007567610422550571011517 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. timestamp='2005-07-08' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | ms1 \ | msp430 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m32c) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | ms1-* \ | msp430-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa-* \ | ymp-* \ | z8k-*) ;; m32c-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: qstat-2.11/missing0000755002404400000620000002540610422550571011115 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2005-06-08.21 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). case "$1" in lex|yacc) # Not GNU programs, they don't have --version. ;; tar) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: qstat-2.11/contrib.cfg0000644002404400000620000000220107564605621011635 00000000000000# QStat config file # # The following game types were contributed by QStat users. # To use, copy them into your qstat.cfg or add "-f contrib.cfg" to you # qstat command line. gametype aps new extend gps name = Alien vs Predator 2 default port = 27888 template var = AVP2 game rule = gamename end gametype uts new extend uns name = Unreal Tournament default port = 7777 template var = UNREALTOURNAMENT game rule = gametype end gametype sms new extend gps name = Serious Sam default port = 25601 template var = SERIOUSSAM game rule = gametype end gametype gos new extend gps name = Global Operations default port = 28672 template var = GLOBALOPS game rule = gamedir end gametype j2s new extend q3s name = Jedi Knight 2 default port = 28070 template var = JEDIKNIGHT2 game rule = gamename end gametype dks new extend gps name = Daikatana default port = 27992 template var = DAIKATANA game rule = gamedir end gametype vcs new extend gps name = V8 Supercar Challange default port = 16700 template var = V8SUPERCAR game rule = gamedir end qstat-2.11/config.c0000644002404400000620000006041510435066370011131 00000000000000/* * qstat 2.6 * by Steve Jankowski * steve@qstat.org * http://www.qstat.org * * Copyright 1996,1997,1998,1999 by Steve Jankowski * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include #include #include #include #include "config.h" #ifdef __hpux #define STATIC static #else #define STATIC #endif #ifdef _WIN32 #define strcasecmp stricmp #endif #ifdef _WIN32 #define HOME_CONFIG_FILE "qstat.cfg" #else #define HOME_CONFIG_FILE ".qstatrc" #endif static server_type ** config_types; static int n_config_types; static int max_config_types; static int next_gametype_id= LAST_BUILTIN_SERVER+1; static int load_config_file( char *filename); static int try_load_config_file( char *filename, int show_error); static int pf_top_level( char *text, void *context); static int pf_gametype_new( char *text, void *context); static int pf_gametype_modify( char *text, void *context); static int set_game_type_value( server_type *gametype, int key, char *value); static int modify_game_type_value( server_type *gametype, int key, char *value); static int set_packet_value( server_type *gametype, char *value, char *packet_name, char **packet, int *len); static char *first_token( char *text); static char *next_token(); static char *next_token_dup(); static char *next_value(); static char * parse_value( char *source, int len); static unsigned int parse_hex( char *hex, int len, int *error); static unsigned int parse_oct( char *oct, int len, int *error); static char *force_lower_case( char *string); static char *force_upper_case( char *string); static char *get_token(); static void * memdup( void *mem, unsigned int len); int parse_config_file( FILE *file); static int (*parse_func)( char *, void *); static void *parse_context; static int line; static char *current_file_name; static char *parse_text; static char *parse_end; static char *lex; static char *token_end; static char token_buf[1024]; static int value_len; static int debug= 0; #define REPORT_ERROR(a) print_location(); fprintf a; fprintf(stderr, "\n") enum { CK_NONE = 0, CK_MASTER_PROTOCOL, CK_MASTER_QUERY, CK_MASTER_PACKET, CK_FLAGS, CK_NAME, CK_DEFAULT_PORT, CK_GAME_RULE, CK_TEMPLATE_VAR, CK_MASTER_TYPE, CK_STATUS_PACKET, CK_STATUS2_PACKET, CK_PLAYER_PACKET, CK_RULE_PACKET, CK_PORT_OFFSET }; typedef struct _config_key { int key; char *key_name; } ConfigKey; static ConfigKey new_keys[] = { { CK_MASTER_PROTOCOL, "master protocol" }, { CK_MASTER_QUERY, "master query" }, { CK_MASTER_PACKET, "master packet" }, { CK_FLAGS, "flags" }, { CK_NAME, "name" }, { CK_DEFAULT_PORT, "default port" }, { CK_GAME_RULE, "game rule" }, { CK_TEMPLATE_VAR, "template var" }, { CK_MASTER_TYPE, "master for gametype" }, { CK_STATUS_PACKET, "status packet" }, { CK_STATUS2_PACKET, "status2 packet" }, { CK_PLAYER_PACKET, "player packet" }, { CK_RULE_PACKET, "rule packet" }, { CK_PORT_OFFSET, "status port offset" }, { 0, NULL }, }; static ConfigKey modify_keys[] = { { CK_MASTER_PROTOCOL, "master protocol" }, { CK_MASTER_QUERY, "master query" }, { CK_MASTER_PACKET, "master packet" }, { CK_FLAGS, "flags" }, { CK_MASTER_TYPE, "master for gametype" }, { 0, NULL }, }; typedef struct { const char *name; int value; } ServerFlag; #define SERVER_FLAG(x) { #x, x } ServerFlag server_flags[] = { SERVER_FLAG(TF_SINGLE_QUERY), SERVER_FLAG(TF_OUTFILE), SERVER_FLAG(TF_MASTER_MULTI_RESPONSE), SERVER_FLAG(TF_TCP_CONNECT), SERVER_FLAG(TF_QUERY_ARG), SERVER_FLAG(TF_QUERY_ARG_REQUIRED), SERVER_FLAG(TF_QUAKE3_NAMES), SERVER_FLAG(TF_TRIBES2_NAMES), SERVER_FLAG(TF_SOF_NAMES), SERVER_FLAG(TF_U2_NAMES), SERVER_FLAG(TF_RAW_STYLE_QUAKE), SERVER_FLAG(TF_RAW_STYLE_TRIBES), SERVER_FLAG(TF_RAW_STYLE_GHOSTRECON), SERVER_FLAG(TF_NO_PORT_OFFSET), SERVER_FLAG(TF_SHOW_GAME_PORT), { NULL, 0 } }; #undef SERVER_FLAG static int get_config_key( char *first_token, ConfigKey *keys); static void add_config_type( server_type *gametype); static server_type * get_config_type( char *game_type); static void copy_server_type( server_type *dest, server_type *source); static server_type * get_server_type( char *game_type); static server_type * get_builtin_type( char *game_type); typedef struct _gametype_context { char *type; char *extend_type; server_type *gametype; } GameTypeContext; static void print_location() { fprintf( stderr, "%s line %d: ", current_file_name, line); } int qsc_load_default_config_files() { int rc= 0; char *filename= NULL, *var; char path[1024]; var= getenv( "QSTAT_CONFIG"); if ( var != NULL && var[0] != '\0') { rc= try_load_config_file( var, 1); if ( rc == 0 || rc == -1) return rc; } var= getenv( "HOME"); if ( var != NULL && var[0] != '\0') { int len= strlen(var); if ( len > 900) len= 900; strncpy( path, var, len); path[len]= '\0'; strcat( path, "/"); strcat( path, HOME_CONFIG_FILE); /* sprintf( path, "%s/%s", var, HOME_CONFIG_FILE); */ rc= try_load_config_file( path, 0); if ( rc == 0 || rc == -1) return rc; } #ifdef sysconfdir strcpy( path, sysconfdir "/qstat.cfg"); filename= path; #elif defined(_WIN32) if ( filename == NULL && _pgmptr && strchr( _pgmptr, '\\')) { char *slash= strrchr( _pgmptr, '\\'); strncpy( path, _pgmptr, slash - _pgmptr); path[slash - _pgmptr]= '\0'; strcat( path, "\\qstat.cfg"); filename= path; } #endif if ( filename != NULL) { rc= try_load_config_file( filename, 0); if ( rc == 0 || rc == -1) return rc; } return rc; /* if ( rc == -2 && show_error) { perror( filename); fprintf( stderr, "Error: Could not open config file \"%s\"\n", filename); } else if ( rc == -1 && show_error) fprintf( stderr, "Error: Error loading $QSTAT_CONFIG file\n"); return rc; */ #ifdef foo filename= getenv( "HOME"); if ( filename != NULL && filename[0] != '\0') { char path[1024]; sprintf( path, "%s/%s", filename, HOME_CONFIG_FILE); } /* 1. $QSTAT_CONFIG 2. UNIX: $HOME/.qstatrc WIN: $HOME/qstat.cfg 3. UNIX: sysconfdir/qstat.cfg WIN: qstat.exe-dir/qstat.cfg */ rc= load_config_file( "qstat.cfg"); if ( rc == -1) fprintf( stderr, "Warning: Error loading default qstat.cfg\n"); return 0; #endif } int qsc_load_config_file( char *filename) { int rc= load_config_file( filename); if ( rc == -2) { perror( filename); fprintf( stderr, "Could not open config file \"%s\"\n", filename); return -1; } return rc; } server_type ** qsc_get_config_server_types( int *n_config_types_ref) { if ( n_config_types_ref) *n_config_types_ref= n_config_types; return config_types; } STATIC int try_load_config_file( char *filename, int show_error) { int rc= load_config_file( filename); if ( rc == -2 && show_error) { perror( filename); fprintf( stderr, "Error: Could not open config file \"%s\"\n", filename); } else if ( rc == -1) fprintf( stderr, "Error: Could not load config file \"%s\"\n", filename); return rc; } STATIC int load_config_file( char *filename) { FILE *file; int rc; file= fopen( filename, "r"); if ( file == NULL) return -2; current_file_name= filename; rc= parse_config_file( file); fclose(file); return rc; } int parse_config_file( FILE *file) { char buf[4096]; int rc; line= 0; parse_func= pf_top_level; while ( fgets( buf, sizeof(buf), file) != NULL) { int len= strlen(buf); while ( len && (buf[len-1] == '\n' || buf[len-1] == '\r')) len--; buf[len]= '\0'; line++; rc= parse_func( buf, parse_context); if ( rc != 0) return rc; } return 0; } /* Top level * Keywords: gametype */ STATIC int pf_top_level( char *text, void *_context) { GameTypeContext *context; server_type *extend; char *token, *game_type, *extend_type; token= first_token( text); if ( token == NULL) return 0; if ( strcmp( token, "gametype") != 0) { REPORT_ERROR(( stderr, "Unknown config command \"%s\"", token)); return -1; } game_type= next_token_dup(); if ( game_type == NULL) { REPORT_ERROR(( stderr, "Missing game type")); return -1; } force_lower_case( game_type); token= next_token(); if ( token == NULL) { REPORT_ERROR(( stderr, "Expecting \"new\" or \"modify\"")); return -1; } if ( strcmp( token, "new") == 0) { parse_func= pf_gametype_new; } else if ( strcmp( token, "modify") == 0) { parse_func= pf_gametype_modify; } else { REPORT_ERROR(( stderr, "Expecting \"new\" or \"modify\"")); return -1; } context= (GameTypeContext*) malloc( sizeof(GameTypeContext)); context->type= game_type; context->extend_type= NULL; context->gametype= NULL; token= next_token(); if ( parse_func == pf_gametype_modify) { if ( token != NULL) { REPORT_ERROR(( stderr, "Extra text after gametype modify")); return -1; } context->gametype= get_server_type( game_type); if ( context->gametype == NULL) { REPORT_ERROR(( stderr, "Unknown game type \"%s\"", game_type)); free(context); return -1; } parse_context= context; return 0; } if ( token == NULL || strcmp( token, "extend") != 0) { REPORT_ERROR(( stderr, "Expecting \"extend\"")); return -1; } extend_type= next_token(); if ( extend_type == NULL) { REPORT_ERROR(( stderr, "Missing extend game type")); return -1; } force_lower_case( extend_type); if ( strcasecmp( extend_type, game_type) == 0) { REPORT_ERROR(( stderr, "Identical game type and extend type")); return -1; } context->extend_type= extend_type; extend= get_server_type( extend_type); if ( extend == NULL) { REPORT_ERROR(( stderr, "Unknown extend game type \"%s\"", extend_type)); return -1; } /* Over-write a previous gametype new */ context->gametype= get_config_type( game_type); if ( context->gametype == NULL) context->gametype= (server_type*) malloc( sizeof(server_type)); copy_server_type( context->gametype, extend); /* Set flag for new type-id if not re-defining previous config type */ if ( get_config_type( game_type) == NULL) context->gametype->id= 0; context->gametype->type_string= game_type; context->gametype->type_prefix= strdup(game_type); force_upper_case( context->gametype->type_prefix); context->gametype->type_option= (char*)malloc( strlen(game_type)+2); context->gametype->type_option[0]= '-'; strcpy( &context->gametype->type_option[1], game_type); parse_context= context; return 0; } STATIC int pf_gametype_modify( char *text, void *_context) { GameTypeContext *context= (GameTypeContext*) _context; char *token; int key; token= first_token( text); if ( token == NULL) return 0; if ( strcmp( token, "end") == 0) { parse_func= pf_top_level; parse_context= NULL; return 0; } key= get_config_key( token, modify_keys); token= next_token(); if ( strcmp( token, "=") != 0) { REPORT_ERROR(( stderr, "Expecting \"=\", found \"%s\"", token)); return -1; } token= next_value(); if ( token == NULL) { REPORT_ERROR(( stderr, "Missing value after \"=\"")); return -1; } if ( debug) printf( "%d %s = <%s>\n", key, modify_keys[key-1].key_name, token?token:""); return modify_game_type_value( context->gametype, key, token); } STATIC int pf_gametype_new( char *text, void *_context) { GameTypeContext *context= (GameTypeContext*) _context; char *token; int key; token= first_token( text); if ( token == NULL) return 0; if ( strcmp( token, "end") == 0) { add_config_type( context->gametype); parse_func= pf_top_level; parse_context= NULL; return 0; } key= get_config_key( token, new_keys); if ( key <= 0) return key; token= next_token(); if ( strcmp( token, "=") != 0) { REPORT_ERROR(( stderr, "Expecting \"=\", found \"%s\"", token)); return -1; } token= next_value(); if ( token == NULL && (key != CK_MASTER_PROTOCOL && key != CK_MASTER_QUERY)) { REPORT_ERROR(( stderr, "Missing value after \"=\"")); return -1; } if ( debug) printf("%d %s = <%s>\n", key, new_keys[key-1].key_name, token?token:""); return set_game_type_value( context->gametype, key, token); } STATIC int get_config_key( char *first_token, ConfigKey *keys) { char key_name[1024], *token; int key= 0; strcpy( key_name, first_token); do { int k; for ( k= 0; keys[k].key_name; k++) { if ( strcmp( keys[k].key_name, key_name) == 0) { key= keys[k].key; break; } } if ( key) break; token= next_token(); if ( token == NULL || strcmp( token, "=") == 0) break; if ( strlen(key_name) + strlen(token) > sizeof(key_name)-2) { REPORT_ERROR(( stderr, "Key name too long")); return -1; } strcat( key_name, " "); strcat( key_name, token); } while ( 1); if ( key == 0) { REPORT_ERROR(( stderr, "Unknown config key \"%s\"", key_name)); return -1; } return key; } STATIC int get_server_flag_value(const char* value, unsigned len) { int i= 0; for ( i= 0; server_flags[i].name; ++i) { if ( len == strlen(server_flags[i].name) && strncmp( server_flags[i].name, value, len) == 0) { return server_flags[i].value; } } return -1; } STATIC int parse_server_flags(const char* value) { int val = 0, v, first = 1; const char* s = value; const char* e; while(*s) { while(isspace((unsigned char)*s)) ++s; if(!first) { if(*s != '|') { REPORT_ERROR(( stderr, "Syntax error: expecting |")); val = -1; break; } ++s; while(isspace((unsigned char)*s)) ++s; } else first = 0; e = s; while(isalnum((unsigned char)*e) || *e == '_') ++e; if(e == s) { REPORT_ERROR(( stderr, "Syntax error: expecting flag")); val = -1; break; } v = get_server_flag_value(s, e-s); if(v == -1) { REPORT_ERROR(( stderr, "Syntax error: invalid flag")); val = -1; break; } s = e; val |= v; } return val; } STATIC int set_game_type_value( server_type *gametype, int key, char *value) { switch ( key) { case CK_NAME: gametype->game_name= strdup(value); break; case CK_FLAGS: { int flags = parse_server_flags(value); if(flags == -1) return -1; gametype->flags = flags; } break; case CK_DEFAULT_PORT: { unsigned short port; if ( sscanf( value, "%hu", &port) != 1) { REPORT_ERROR(( stderr, "Syntax error on port. Should be a number between 1 and 65535.")); return -1; } gametype->default_port= port; break; } case CK_GAME_RULE: gametype->game_rule= strdup(value); break; case CK_TEMPLATE_VAR: gametype->template_var= strdup(value); force_upper_case( gametype->template_var); break; case CK_MASTER_PROTOCOL: if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master protocol on non-master game type\n")); return -1; } if ( value) gametype->master_protocol= strdup(value); else gametype->master_protocol= NULL; break; case CK_MASTER_QUERY: if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master query on non-master game type\n")); return -1; } if ( value) gametype->master_query= strdup(value); else gametype->master_query= NULL; break; case CK_MASTER_TYPE: { server_type *type; if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master type on non-master game type\n")); return -1; } force_lower_case( value); type= get_server_type( value); if ( type == NULL) { REPORT_ERROR((stderr, "Unknown server type \"%s\"\n", value)); return -1; } gametype->master= type->id; } break; case CK_MASTER_PACKET: if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master packet on non-master game type")); return -1; } if ( value == NULL || value[0] == '\0') { REPORT_ERROR((stderr, "Empty master packet")); return -1; } gametype->master_packet= memdup( value, value_len); gametype->master_len= value_len; break; case CK_STATUS_PACKET: return set_packet_value( gametype, value, "status", &gametype->status_packet, &gametype->status_len); case CK_STATUS2_PACKET: return set_packet_value( gametype, value, "status2", &gametype->rule_packet, &gametype->rule_len); case CK_PLAYER_PACKET: return set_packet_value( gametype, value, "player", &gametype->player_packet, &gametype->player_len); case CK_RULE_PACKET: return set_packet_value( gametype, value, "rule", &gametype->rule_packet, &gametype->rule_len); case CK_PORT_OFFSET: { short port; if ( sscanf( value, "%hd", &port) != 1) { REPORT_ERROR(( stderr, "Syntax error on port. Should be a number between 32767 and -32768.")); return -1; } gametype->port_offset= port; break; } } return 0; } STATIC int set_packet_value( server_type *gametype, char *value, char *packet_name, char **packet, int *len) { if ( gametype->master) { REPORT_ERROR((stderr, "Cannot set info packet on master game type")); return -1; } if ( value == NULL || value[0] == '\0') { REPORT_ERROR((stderr, "Empty %s packet", packet_name)); return -1; } if ( *packet == NULL) { REPORT_ERROR((stderr, "Cannot set %s packet; extend game type does not define a %s packet", packet_name, packet_name)); return -1; } *packet= memdup( value, value_len); *len= value_len; return 0; } STATIC int modify_game_type_value( server_type *gametype, int key, char *value) { switch ( key) { case CK_FLAGS: { int flags = parse_server_flags(value); if(flags == -1) return -1; gametype->flags = flags; } break; case CK_MASTER_PROTOCOL: if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master protocol on non-master game type")); return -1; } if ( value) gametype->master_protocol= strdup(value); else gametype->master_protocol= NULL; break; case CK_MASTER_QUERY: if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master query on non-master game type")); return -1; } if ( value) gametype->master_query= strdup(value); else gametype->master_query= NULL; break; case CK_MASTER_PACKET: if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master packet on non-master game type")); return -1; } if ( value == NULL || value[0] == '\0') { REPORT_ERROR((stderr, "Empty master packet")); return -1; } gametype->master_packet= memdup( value, value_len); gametype->master_len= value_len; break; case CK_MASTER_TYPE: { server_type *type; if ( ! gametype->master) { REPORT_ERROR((stderr, "Cannot set master type on non-master game type\n")); return -1; } force_lower_case( value); type= get_server_type( value); if ( type == NULL) { REPORT_ERROR((stderr, "Unknown server type \"%s\"\n", value)); return -1; } gametype->master= type->id; } break; } return 0; } STATIC server_type * get_server_type( char *game_type) { server_type *result; result= get_builtin_type( game_type); if ( result != NULL) return result; return get_config_type( game_type); } STATIC server_type* get_builtin_type( char* type_string) { server_type *type= &builtin_types[0]; for ( ; type->id != Q_UNKNOWN_TYPE; type++) if ( strcmp( type->type_string, type_string) == 0) return type; return NULL; } STATIC void add_config_type( server_type *gametype) { if ( gametype->id == 0) { if ( next_gametype_id >= MASTER_SERVER) { REPORT_ERROR(( stderr, "Exceeded game type limit, ignoring \"%s\"", gametype->type_string)); return; } gametype->id= next_gametype_id; if ( gametype->master) gametype->id |= MASTER_SERVER; next_gametype_id++; } if ( max_config_types == 0) { max_config_types= 4; config_types= (server_type**) malloc(sizeof(server_type*) * (max_config_types + 1)); } else if ( n_config_types >= max_config_types) { max_config_types*= 2; config_types= (server_type**) realloc( config_types, sizeof(server_type*) * (max_config_types + 1)); } config_types[ n_config_types]= gametype; n_config_types++; } STATIC server_type * get_config_type( char *game_type) { int i; for ( i= 0; i < n_config_types; i++) if ( strcmp( config_types[i]->type_string, game_type) == 0) return config_types[i]; return NULL; } STATIC void copy_server_type( server_type *dest, server_type *source) { *dest= *source; } STATIC void * memdup( void *mem, unsigned int len) { void *result= malloc( len); memcpy( result, mem, len); return result; } /* Parsing primitives */ STATIC char * first_token( char *text) { parse_text= text; parse_end= parse_text + strlen( parse_text); lex= text; token_end= text; if ( *lex == '#') return NULL; return get_token(); } STATIC char * next_token() { lex= token_end; return get_token(); } STATIC char * next_token_dup() { return strdup( next_token()); } STATIC char * get_token() { char *token= &token_buf[0]; while ( isspace((unsigned char)*token_end)) token_end++; if ( token_end == parse_end) return NULL; while ( (isalnum((unsigned char)*token_end) || *token_end == '.' || *token_end == '_' || *token_end == '-') && token < &token_buf[0] + sizeof(token_buf)) *token++= *token_end++; if ( token == &token_buf[0]) *token++= *token_end++; *token= '\0'; return &token_buf[0]; } STATIC char * next_value() { char *token= &token_buf[0]; while ( isspace((unsigned char)*token_end)) token_end++; if ( token_end == parse_end) return NULL; while ( token_end < parse_end && token < &token_buf[0] + sizeof(token_buf)) *token++= *token_end++; *token--= '\0'; if ( strchr( token_buf, '\\')) return parse_value(token_buf, (token - token_buf)+1); while ( isspace((unsigned char)*token)) *token--= '\0'; value_len= token - token_buf + 1; return &token_buf[0]; } STATIC char * parse_value( char *source, int len) { char *value, *v, *end; int error= 0; value= (char*)malloc( len + 1); end = v = value; /* printf( "parse_value <%.*s>\n", len, source); */ for ( ; len; len--, source++) { if ( *source != '\\') { *v++= *source; if ( *source != ' ') end= v; continue; } source++; len--; if ( len == 0) break; if ( *source == '\\') *v++= *source; else if ( *source == 'n') *v++= '\n'; else if ( *source == 'r') *v++= '\r'; else if ( *source == ' ') *v++= ' '; else if ( *source == 'x') { source++; len--; if ( len < 2) break; *v++= parse_hex(source, 2, &error); if ( error) break; source++; len--; } else if ( isdigit( (unsigned char)*source)) { if ( len < 3) break; *v++= parse_oct(source, 3, &error); if ( error) break; source++; len--; source++; len--; } else { error= 1; REPORT_ERROR(( stderr, "Invalid character escape \"%.*s\"", 2, source-1)); break; } end= v; } if ( error) { free(value); return NULL; } value_len= end - value; memcpy( token_buf, value, value_len); token_buf[value_len]= '\0'; free(value); return &token_buf[0]; } STATIC unsigned int parse_hex( char *hex, int len, int *error) { char *save_hex= hex; int save_len= len; unsigned int result= 0; *error= 0; for ( ; len; len--, hex++) { result <<= 4; if ( ! isxdigit( (unsigned char)*hex)) { *error= 1; REPORT_ERROR(( stderr, "Invalid hex \"%.*s\"", save_len+2, save_hex-2)); return 0; } if ( *hex >= '0' && *hex <= '9') result|= *hex - '0'; else if ( *hex >= 'A' && *hex <= 'F') result|= ((*hex - 'A') + 10); else if ( *hex >= 'a' && *hex <= 'f') result|= ((*hex - 'a') + 10); } return result; } STATIC unsigned int parse_oct( char *oct, int len, int *error) { char *save_oct= oct; int save_len= len; unsigned int result= 0; *error= 0; for ( ; len; len--, oct++) { result <<= 3; if ( *oct >= '0' && *oct <= '7') result|= *oct - '0'; else { *error= 1; REPORT_ERROR(( stderr, "Invalid octal \"%.*s\"", save_len+1, save_oct-1)); return 0; } } return result; } STATIC char * force_lower_case( char *string) { char *s= string; for ( ; *s; s++) *s= tolower(*s); return string; } STATIC char * force_upper_case( char *string) { char *s= string; for ( ; *s; s++) *s= toupper(*s); return string; } qstat-2.11/config.h0000644002404400000620000000046507564605621011144 00000000000000/* * config.h * by Steve Jankowski * steve@qstat.org * http://www.qstat.org * * Copyright 1996,1997,1998,1999 by Steve Jankowski */ #include "qstat.h" int qsc_load_default_config_files(); int qsc_load_config_file( char *filename); server_type ** qsc_get_config_server_types( int *n_config_types); qstat-2.11/Makefile.am0000644002404400000620000000125410464730441011547 00000000000000SUBDIRS = template info CPPFLAGS = -Dsysconfdir=\"$(sysconfdir)\" @CPPFLAGS@ bin_PROGRAMS = qstat qstat_SOURCES = \ config.c config.h \ debug.c debug.h \ hcache.c \ md5.c md5.h \ qserver.c qserver.h \ qstat.c qstat.h \ template.c \ a2s.c a2s.h \ packet_manip.c packet_manip.h \ ut2004.c ut2004.h \ doom3.c doom3.h \ gps.c gps.h \ gs2.c gs2.h \ gs3.c gs3.h \ ts2.c ts2.h \ tm.c tm.h dist_configfiles_DATA = qstat.cfg configfilesdir = $(sysconfdir) EXTRA_DIST = CHANGES.txt COMPILE.txt LICENSE.txt \ Makefile.noauto \ ChangeLog \ qstatdoc.html \ contrib.cfg cl: cvs2cl.pl --utc --no-wrap --separate-header --no-times -f ChangeLog.cvs rm -f ChangeLog.cvs.bak qstat-2.11/Makefile.in0000644002404400000620000005751010523107225011560 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = qstat$(EXEEXT) DIST_COMMON = $(am__configure_deps) $(dist_configfiles_DATA) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/gnuconfig.h.in $(top_srcdir)/configure ChangeLog \ config.guess config.sub depcomp install-sh missing subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = gnuconfig.h CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(configfilesdir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_qstat_OBJECTS = config.$(OBJEXT) debug.$(OBJEXT) hcache.$(OBJEXT) \ md5.$(OBJEXT) qserver.$(OBJEXT) qstat.$(OBJEXT) \ template.$(OBJEXT) a2s.$(OBJEXT) packet_manip.$(OBJEXT) \ ut2004.$(OBJEXT) doom3.$(OBJEXT) gps.$(OBJEXT) gs2.$(OBJEXT) \ gs3.$(OBJEXT) ts2.$(OBJEXT) tm.$(OBJEXT) qstat_OBJECTS = $(am_qstat_OBJECTS) qstat_LDADD = $(LDADD) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(qstat_SOURCES) DIST_SOURCES = $(qstat_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; dist_configfilesDATA_INSTALL = $(INSTALL_DATA) DATA = $(dist_configfiles_DATA) ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = -Dsysconfdir=\"$(sysconfdir)\" @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ac_ct_CC = @ac_ct_CC@ ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ datadir = @datadir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ prefix = @prefix@ program_transform_name = @program_transform_name@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = template info qstat_SOURCES = \ config.c config.h \ debug.c debug.h \ hcache.c \ md5.c md5.h \ qserver.c qserver.h \ qstat.c qstat.h \ template.c \ a2s.c a2s.h \ packet_manip.c packet_manip.h \ ut2004.c ut2004.h \ doom3.c doom3.h \ gps.c gps.h \ gs2.c gs2.h \ gs3.c gs3.h \ ts2.c ts2.h \ tm.c tm.h dist_configfiles_DATA = qstat.cfg configfilesdir = $(sysconfdir) EXTRA_DIST = CHANGES.txt COMPILE.txt LICENSE.txt \ Makefile.noauto \ ChangeLog \ qstatdoc.html \ contrib.cfg all: gnuconfig.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .o .obj am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ cd $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) gnuconfig.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/gnuconfig.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status gnuconfig.h $(srcdir)/gnuconfig.h.in: $(am__configure_deps) cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f gnuconfig.h stamp-h1 install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) qstat$(EXEEXT): $(qstat_OBJECTS) $(qstat_DEPENDENCIES) @rm -f qstat$(EXEEXT) $(LINK) $(qstat_LDFLAGS) $(qstat_OBJECTS) $(qstat_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2s.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doom3.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gs2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gs3.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hcache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet_manip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qserver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qstat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/template.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ts2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ut2004.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` uninstall-info-am: install-dist_configfilesDATA: $(dist_configfiles_DATA) @$(NORMAL_INSTALL) test -z "$(configfilesdir)" || $(mkdir_p) "$(DESTDIR)$(configfilesdir)" @list='$(dist_configfiles_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(dist_configfilesDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(configfilesdir)/$$f'"; \ $(dist_configfilesDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(configfilesdir)/$$f"; \ done uninstall-dist_configfilesDATA: @$(NORMAL_UNINSTALL) @list='$(dist_configfiles_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(configfilesdir)/$$f'"; \ rm -f "$(DESTDIR)$(configfilesdir)/$$f"; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) gnuconfig.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) gnuconfig.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) gnuconfig.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) gnuconfig.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) $(DATA) gnuconfig.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(configfilesdir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-dist_configfilesDATA install-exec-am: install-binPROGRAMS install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_configfilesDATA \ uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ check-am clean clean-binPROGRAMS clean-generic clean-recursive \ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ dist-shar dist-tarZ dist-zip distcheck distclean \ distclean-compile distclean-generic distclean-hdr \ distclean-recursive distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dist_configfilesDATA install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-recursive pdf pdf-am ps ps-am \ tags tags-recursive uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-dist_configfilesDATA \ uninstall-info-am cl: cvs2cl.pl --utc --no-wrap --separate-header --no-times -f ChangeLog.cvs rm -f ChangeLog.cvs.bak # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: qstat-2.11/hcache.c0000644002404400000620000002374710377065324011111 00000000000000/* * qstat 2.4 * by Steve Jankowski * steve@activesw.com * http://www.activesw.com/people/steve/qstat.html * * Thanks to Per Hammer for the OS/2 patches (per@mindbend.demon.co.uk) * Thanks to John Ross Hunt for the OpenVMS Alpha patches (bigboote@ais.net) * Thanks to Scott MacFiggen for the quicksort code (smf@activesw.com) * * Inspired by QuakePing by Len Norton * * Copyright 1996,1997,1998,1999 by Steve Jankowski * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include #include #include #include #include #include "qstat.h" #ifndef _WIN32 #include #include #include #include #include #endif #ifdef _WIN32 #include #endif #ifdef __hpux #define STATIC static #else #define STATIC #endif #ifndef INADDR_NONE #define INADDR_NONE ~0 #endif typedef struct _cache_entry { unsigned long ipaddr; char *hostname[5]; } cache_entry; static cache_entry *hcache; static int n_entry; static int max_entry; static char *last_filename; static int n_changes; static int debug; static void write_file(FILE *file); static cache_entry * init_entry( unsigned long ipaddr, char *hostname, cache_entry *known); static cache_entry * find_entry( unsigned long ipaddr); static void free_entry( cache_entry *entry); static cache_entry * validate_entry( cache_entry *entry); static cache_entry * find_host_entry( char *hostname); static void add_hostname( cache_entry *entry, const char *hostname); int hcache_open( char *filename, int update) { FILE *file; char line[500], ipstr[500], hostname[500]; char *l; int line_no, end; unsigned long ip1, ip2, ip3, ip4, ipaddr; cache_entry *entry; file= fopen( filename, update?"r+":"r"); if ( file == NULL) { if ( errno == ENOENT) { fprintf( stderr, "Creating new host cache \"%s\"\n", filename); last_filename= filename; return 0; } perror( filename); return -1; } last_filename= filename; for ( line_no= 1; fgets( line, sizeof(line), file) != NULL; line_no++) { if ( strlen(line) < 2) continue; if ( line[strlen(line)-1] != '\n') { printf( "%d: line too long\n", line_no); continue; } l= line; while ( isspace( (unsigned char)*l)) l++; if ( *l == '#' || *l == '\0') continue; if ( sscanf( l, "%s%n", ipstr, &end) != 1) { printf( "%d: parse error\n", line_no); continue; } if ( sscanf( ipstr, "%lu.%lu.%lu.%lu", &ip1, &ip2, &ip3, &ip4) != 4) { init_entry( 0, ipstr, NULL); continue; } if ( (ip1&0xffffff00) || (ip2&0xffffff00) || (ip3&0xffffff00) || (ip4&0xffffff00)) { printf( "%d: invalid IP address \"%s\"\n", line_no, ipstr); continue; } ipaddr= (ip1<<24) | (ip2<<16) | (ip3<<8) | ip4; entry= init_entry( ipaddr, NULL, NULL); while ( 1) { l+= end; while ( isspace( (unsigned char)*l)) l++; if ( *l == '#' || *l == '\0') break; hostname[0]= '\0'; if ( sscanf( l, "%s%n", hostname, &end) != 1) { printf( "%d: parse error\n", line_no); continue; } init_entry( ipaddr, hostname, entry); } } fclose(file); return 0; } STATIC cache_entry * init_entry( unsigned long ipaddr, char *hostname, cache_entry *known) { cache_entry *entry; int e= 0, h; if ( n_entry == max_entry) { if ( max_entry == 0) { max_entry= 50; hcache= (cache_entry*) malloc(sizeof(cache_entry) * max_entry * 2); } else { hcache= (cache_entry*) realloc( hcache, sizeof(cache_entry) * max_entry * 2); } memset( hcache+n_entry, 0, sizeof(cache_entry) * max_entry * (n_entry==0?2:1)); max_entry*= 2; } if ( ipaddr == 0) { entry= find_host_entry( hostname); if ( entry == NULL) { hcache[n_entry].hostname[0]= strdup( hostname); return &hcache[n_entry++]; } return entry; } if ( known != NULL) entry= known; else { for ( e= 0; e < n_entry; e++) if ( hcache[e].ipaddr == ipaddr) break; entry= &hcache[e]; entry->ipaddr= ipaddr; } if ( hostname && hostname[0] != '\0') { for ( h= 0; h < 5; h++) if ( entry->hostname[h] == NULL) { entry->hostname[h]= strdup( hostname); break; } } if ( e == n_entry) n_entry++; return entry; } STATIC cache_entry * find_host_entry( char *hostname) { cache_entry *entry= &hcache[0]; char **ehost; int e, h; char first= *hostname; for ( e= 0; e < n_entry; e++, entry++) { ehost= &entry->hostname[0]; for ( h= 0; h < 5; h++, ehost++) if ( *ehost && first == **ehost && strcmp( hostname, *ehost) == 0) return entry; } return NULL; } void hcache_write_file( char *filename) { FILE *file; if ( filename != NULL) file= fopen( filename, "w"); else file= stdout; if ( file == NULL) { perror( filename); return; } write_file( file); } void hcache_update_file() { FILE *file; if ( last_filename == NULL || n_changes == 0) return; file= fopen( last_filename, "w"); if ( file == NULL) { perror( last_filename); return; } write_file( file); } STATIC void write_file( FILE *file) { int e, h; for ( e= 0; e < n_entry; e++) { unsigned long ipaddr= hcache[e].ipaddr; if ( ipaddr == 0) continue; fprintf( file, "%lu.%lu.%lu.%lu", (ipaddr&0xff000000)>>24, (ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff); if ( hcache[e].hostname[0]) { for ( h= 0; h < 5; h++) if ( hcache[e].hostname[h] != NULL) fprintf( file, "%c%s", h?' ':'\t', hcache[e].hostname[h]); } fprintf( file, "\n"); } fclose( file); } void hcache_invalidate() { int e; for ( e= 0; e < n_entry; e++) if ( hcache[e].ipaddr != 0) memset( & hcache[e].hostname[0], 0, sizeof( hcache[e].hostname)); } void hcache_validate() { int e; char **alias; struct hostent *ent; unsigned long ipaddr; cache_entry *entry; for ( e= 0; e < n_entry; e++) { fprintf( stderr, "\r%d / %d validating ", e, n_entry); if ( hcache[e].ipaddr != 0) { ipaddr= hcache[e].ipaddr; fprintf( stderr, "%lu.%lu.%lu.%lu", (ipaddr&0xff000000)>>24, (ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff); ipaddr= htonl( ipaddr); ent= gethostbyaddr( (char*)&ipaddr, sizeof(unsigned long), AF_INET); } else if ( hcache[e].hostname[0] != NULL) { fprintf( stderr, "%s", hcache[e].hostname[0]); ent= gethostbyname( hcache[e].hostname[0]); if ( ent != NULL) { memcpy( &ipaddr, ent->h_addr_list[0], sizeof(ipaddr)); ipaddr= ntohl( ipaddr); if ( (entry= find_entry( ipaddr)) != NULL) { add_hostname( entry, hcache[e].hostname[0]); free_entry( &hcache[e]); } else hcache[e].ipaddr= ipaddr; } } else continue; if ( ent == NULL) continue; if ( ent->h_name && ent->h_name[0] != '\0') add_hostname( &hcache[e], ent->h_name); printf( "h_name %s\n", ent->h_name?ent->h_name:"NULL"); alias= ent->h_aliases; while ( *alias) { add_hostname( &hcache[e], *alias); printf( "h_aliases %s\n", *alias); alias++; } } } STATIC cache_entry * validate_entry( cache_entry *entry) { struct hostent *ent; char **alias; cache_entry *tmp; unsigned long ipaddr; if ( entry->ipaddr != 0) { ipaddr= htonl( entry->ipaddr); /* fprintf( stderr, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24, (ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff); */ ent= gethostbyaddr( (char*)&ipaddr, sizeof(unsigned long), AF_INET); } else if ( entry->hostname[0] != NULL) { /* fprintf( stderr, "%s", entry->hostname[0]); */ ent= gethostbyname( entry->hostname[0]); if ( ent != NULL) { memcpy( &ipaddr, ent->h_addr_list[0], sizeof(ipaddr)); ipaddr= ntohl( ipaddr); if ( (tmp= find_entry( ipaddr)) != NULL) { add_hostname( tmp, entry->hostname[0]); free_entry( entry); entry= tmp; } else entry->ipaddr= ipaddr; } } else return NULL; if ( ent == NULL) return NULL; if ( ent->h_name && ent->h_name[0] != '\0') add_hostname( entry, ent->h_name); alias= ent->h_aliases; while ( *alias) { add_hostname( entry, *alias); alias++; } return entry; } unsigned long hcache_lookup_hostname( char *hostname) { cache_entry *entry; int e, h; if ( debug) printf( "looking up %s\n", hostname); for ( e= 0; e < n_entry; e++) { for ( h= 0; h < 5; h++) { if ( hcache[e].hostname[h] && strcmp( hostname, hcache[e].hostname[h]) == 0) return hcache[e].ipaddr; } } entry= init_entry( 0, hostname, NULL); if ( entry->ipaddr == 0) { if ( debug) printf( "validating %s\n", hostname); entry= validate_entry( entry); n_changes++; } if ( debug) printf( "returning %lx\n", entry->ipaddr); if ( entry != NULL && entry->ipaddr) return entry->ipaddr; return INADDR_NONE; } char * hcache_lookup_ipaddr( unsigned long ipaddr) { cache_entry *entry; int e; for ( e= 0; e < n_entry; e++) if ( hcache[e].ipaddr == ipaddr) return hcache[e].hostname[0]; entry= init_entry( ipaddr, 0, NULL); if ( debug) printf( "validating %lx\n", ipaddr); validate_entry( entry); n_changes++; return entry ? entry->hostname[0] : NULL; } STATIC cache_entry * find_entry( unsigned long ipaddr) { int e; for ( e= 0; e < n_entry; e++) if ( hcache[e].ipaddr == ipaddr) return &hcache[e]; return NULL; } STATIC void free_entry( cache_entry *entry) { int h; for ( h= 0; h < 5; h++) if ( entry->hostname[h] != NULL) free( entry->hostname[h]); memset( entry, 0, sizeof(*entry)); } STATIC void add_hostname( cache_entry *entry, const char *hostname) { int h; for ( h= 0; h < 5; h++) { if ( entry->hostname[h] == NULL) break; if ( strcmp( entry->hostname[h], hostname) == 0) return; } if ( h < 5) entry->hostname[h]= strdup( hostname); } /* main(int argc, char *argv[]) { hcache_open( argv[1], 0); hcache_write(NULL); hcache_invalidate(); printf( "invalidate\n"); hcache_write(NULL); hcache_validate(); printf( "validate\n"); hcache_write( "/tmp/qhcache.out"); } */ qstat-2.11/LICENSE.txt0000644002404400000620000001225607564605622011353 00000000000000The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End qstat-2.11/qstat.cfg0000644002404400000620000001271110502340265011322 00000000000000# QStat configuration file # # See qstat documentation (qstatdoc.html) for instructions # http://www.qstat.org gametype SOF2S new extend Q3S name = Soldier of Fortune 2 default port = 20100 template var = SOLDIEROFFORTUNE2 game rule = gametype end # SOF2 public master: master.sof2.ravensoft.com # The 2003 protocol is for SOF2 1.01 # The 2004 protocol is for SOF2 1.02 gametype SOF2M new extend Q3M name = SOF2 Master default port = 20110 template var = SOF2MASTER master protocol = 2004 master query = SOF2FULL master for gametype = sof2s end # The 2002 protocol is for SOF2 1.0 gametype SOF2M1.0 new extend SOF2M name = SOF2 Master (1.0) master protocol = 2002 end gametype CRS new extend GPS name = Command and Conquer: Renegade default port = 25300 template var = CNCRENEGADE game rule = gametype end # MOHAA supports two status protocols, Gamespy and Quake 3. # Seems like servers support one or the other, but not both at the same time. # The Gamespy protocol returns player name, frags, ping, and deaths. gametype MAS new extend GPS name = Medal of Honor: Allied Assault default port = 12300 template var = MOHALLIEDASSAULT game rule = gametype end # MOHAA support for the Q3 protocol is broken and more limited. The # response to "getinfo" does not include the current and max players # (they're always zero). The response to "getstatus" has the correct # current and max players, but only reports player name and ping. # If -R or -P options are specified, then both "getinfo" and "getstatus" # are sent. Otherwise only "getinfo" is sent. gametype MAQS new extend Q3S name = Medal of Honor: Allied Assault (Q) default port = 12300 template var = MOHALLIEDASSAULT game rule = gametype status packet = \xff\xff\xff\xff\x02getinfo\n status2 packet = \xff\xff\xff\xff\x02getstatus\n end # Half-Life supports a Quake 2 style status protocol, but only for # basic status, there's no player or extended rule information. The # server rule names are different from HLS. gametype HLQS new extend Q2S name = Half-Life template var = HALFLIFE default port = 27015 game rule = gamedir status packet = \xff\xff\xff\xffinfostring\x00 end # Config for Serious Sam SMS gametype SMS new extend GPS name = Serious Sam default port = 25600 status port offset = 1 template var = SERIOUSSAM game rule = gametype end # Config for Medal of Honor: Allied Assault MHS gametype MHS new extend Q3S name = Medal of Honor: Allied Assault default port = 12204 template var = MOHALLIEDASSAULT game rule = gametype status packet = \377\377\377\377\002getinfo xxx status2 packet = \377\377\377\377\002getstatus xxx end gametype CODS new extend Q3S name = Call of Duty default port = 28960 template var = CALLOFDUTY game rule = gamename end gametype CODM new extend Q3M name = Call of Duty Master default port = 20510 template var = CODMASTER master protocol = 5 master for gametype = CODS master query = full empty end # enemy territory gametype WOETS new extend Q3S name = Enemy Territory template var = ENEMYTERRITORY game rule = gamename end gametype WOETM new extend Q3M name = Enemy Territory Master template var = WOETSMASTER master protocol = 84 master for gametype = WOETS master query = end # NetPanzer > 0.1.6 gametype NETP new extend GPS name = NetPanzer template var = NETPANZER end gametype NETPM new extend GSM name = NetPanzer Master template var = NETPANZERMASTER master for gametype = NETP end gametype STMHL2 new extend STM name = Steam Master for HL2 template var = STEAMMASTERHL2 master for gametype = HL2S default port = 27011 end gametype STMA2S new extend STM name = Steam Master for A2S template var = STEAMMASTERA2S master for gametype = A2S default port = 27011 end gametype UT2004S new extend UT2S name = UT2004 template var = UT2004 end gametype UT2004M modify master for gametype = UT2004S end gametype NEXUIZS new extend Q3S name = Nexuiz template var = NEXUIZ game rule = gamename end gametype NEXUIZM new extend Q3M name = Nexuiz Master template var = NEXUIZMASTER default port = 27950 master packet = \377\377\377\377getservers Nexuiz %s %s master protocol = 3 master query = empty full master for gametype = NEXUIZS end gametype WARSOWS new extend Q2S name = Warsow default port = 44400 template var = WARSOW game rule = gamename status packet = \377\377\377\377getinfo end gametype WARSOWM new extend Q3M name = Warsow Master template var = WARSOWMASTER default port = 27950 master packet = \377\377\377\377getservers Warsow %s %s master protocol = 8 master query = empty full master for gametype = WARSOWS end gametype TREMULOUS new extend Q3S name = Tremulous template var = TREMULOUS game rule = gamename end gametype TREMULOUSM new extend Q3M name = Tremulous Master template var = TREMULOUSMASTER default port = 30710 master protocol = 69 master for gametype = TREMULOUS end gametype HLA2S new extend A2S name = Half-Life template var = HLA2S end gametype HLA2SM new extend STM master for gametype = HLA2S default port = 27010 end gametype PREYM new extend DM3M name = Prey Master template var = PREYMASTER default port = 27655 master query = empty full master for gametype = PREYS end qstat-2.11/qserver.c0000644002404400000620000000570510435070055011347 00000000000000/* * qstat 2.6 * by Steve Jankowski * * qserver functions * Copyright 2004 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include "qstat.h" #include "qserver.h" #include "debug.h" #ifndef _WIN32 #include #include #endif #include #include #include int qserver_send_initial(struct qserver* server, const char* data, size_t len) { int ret = 0; if(data) { if ( server->flags & FLAG_BROADCAST) ret = send_broadcast(server, data, len); else ret = send( server->fd, data, len, 0); if ( ret == SOCKET_ERROR) { perror( "send"); } } if ( server->retry1 == n_retries || server->flags & FLAG_BROADCAST) { gettimeofday( &server->packet_time1, NULL); } else { server->n_retries++; } server->retry1--; server->n_packets++; return ret; } int qserver_send(struct qserver* server, const char* data, size_t len) { int ret = 0; if(data) { if ( server->flags & FLAG_BROADCAST) ret = send_broadcast(server, data, len); else ret = send( server->fd, data, len, 0); if ( ret == SOCKET_ERROR) { perror( "send"); } } server->retry1 = n_retries; gettimeofday( &server->packet_time1, NULL); server->n_requests++; server->n_packets++; return ret; } int send_broadcast( struct qserver *server, const char *pkt, size_t pktlen) { struct sockaddr_in addr; addr.sin_family= AF_INET; if ( no_port_offset || server->flags & TF_NO_PORT_OFFSET) addr.sin_port= htons(server->port); else addr.sin_port= htons((unsigned short)( server->port + server->type->port_offset )); addr.sin_addr.s_addr= server->ipaddr; memset( &(addr.sin_zero), 0, sizeof(addr.sin_zero)); return sendto( server->fd, (const char*) pkt, pktlen, 0, (struct sockaddr *) &addr, sizeof(addr)); } void register_send( struct qserver *server ) { if ( server->retry1 == n_retries || server->flags & FLAG_BROADCAST ) { server->n_requests++; } else { server->n_retries++; } // New request so reset the sent time. This ensures // that we record an accurate ping time even on retry gettimeofday( &server->packet_time1, NULL); server->retry1--; server->n_packets++; } int send_packet( struct qserver* server, const char* data, size_t len ) { int ret = 0; debug( 2, "[%s] send", server->type->type_prefix ); if( 4 <= get_debug_level() ) { print_packet( server, data, len ); } if( data ) { if ( server->flags & FLAG_BROADCAST ) { ret = send_broadcast( server, data, len ); } else { ret = send( server->fd, data, len, 0 ); } if ( ret == SOCKET_ERROR ) { unsigned int ipaddr = ntohl(server->ipaddr) ; fprintf( stderr, "Error on %d.%d.%d.%d\n", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff ); perror( "send" ); } } register_send( server ); return ret; } qstat-2.11/qserver.h0000644002404400000620000001257310435066370011362 00000000000000/* * qstat 2.6 * by Steve Jankowski * * qserver functions and definitions * Copyright 2004 Ludwig Nussel * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_QSERVER_H #define QSTAT_QSERVER_H struct query_param { char *key; char *value; int i_value; unsigned int ui_value; struct query_param *next; }; typedef struct SavedData { char *data; int datalen; int pkt_index; int pkt_max; unsigned int pkt_id; struct SavedData *next; } SavedData; struct qserver { char *arg; char *host_name; unsigned int ipaddr; int flags; server_type * type; int fd; char *outfilename; char *query_arg; struct query_param *params; unsigned long challenge; unsigned short port; unsigned short query_port; /** \brief number of retries _left_ for status query or rule query. * * That means * if s->retry1 == (global)n_retries then no retries were necessary so far. * if s->retry1 == 0 then the server has to be cleaned up after timeout */ int retry1; /** \brief number retries _left_ for player query. @see retry1 */ int retry2; /** \brief how much retry packets were sent */ int n_retries; /** \brief time when the last packet to the server was sent */ struct timeval packet_time1; struct timeval packet_time2; /** \brief sum of packet deltas * * average server ping is ping_total / n_requests */ int ping_total; /** \brief number of requests send to a server. * * used for ping calculation * @see ping_total */ int n_requests; /** \brief number of packets already sent to this server * * doesn't seemt to have any use */ int n_packets; /** \brief number of servers in master_pkt * * normally master_pkt_len/6 */ int n_servers; /** \brief length of master_pkt */ int master_pkt_len; /** \brief IPs received from master. * * array of four bytes ip, two bytes port in network byte order */ char *master_pkt; /** \brief state info * * used for progressive master 4 bytes for WON 22 for Steam */ char master_query_tag[22]; char *error; /** \brief in-game name of the server. * * A server that has a NULL name did not receive any packets yet and is * considered down after a timeout. */ char *server_name; char *address; char *map_name; char *game; int max_players; int num_players; int protocol_version; SavedData saved_data; /** \brief number of the next player to retrieve info for. * * Only meaningful for servers that have type->player_packet. * This is used by q1 as it sends packets for each player individually. * cleanup_qserver() cleans up a server if next_rule == NULL and * next_player_info >= num_players */ int next_player_info; /** \brief number of player info packets received */ int n_player_info; struct player *players; /** \brief name of next rule to retreive * * Used by Q1 as it needs to send a packet for each rule. Other games would * set this to an empty string to indicate that rules need to be retrieved. * After rule packet is received set this to NULL. */ char *next_rule; int n_rules; struct rule *rules; struct rule **last_rule; int missing_rules; struct qserver *next; struct qserver *prev; }; void qserver_disconnect(struct qserver* server); /* server specific query parameters */ void add_query_param( struct qserver *server, char *arg); /** \brief get a parameter for the server as string * * @param server the server to get the value from * @param key which key to get * @param default_value value to return if key was not found * @return value for key or default_value */ char * get_param_value( struct qserver *server, const char *key, char *default_value); /** @see get_param_value */ int get_param_i_value( struct qserver *server, char *key, int default_value); /** @see get_param_value */ unsigned int get_param_ui_value( struct qserver *server, char *key, unsigned int default_value); /** \brief send an initial query packet to a server * * Sends a unicast packet to the server's file descriptor. The descriptor must * be connected. Updates n_requests or n_retries, retry1, n_packets, packet_time1 * * \param server the server * \param data data to send * \param len length of data * \returns number of bytes sent or SOCKET_ERROR */ int qserver_send_initial(struct qserver* server, const char* data, size_t len); /** \brief send an initial query packet to a server * * Sends a unicast packet to the server's file descriptor. The descriptor must * be connected. Updates n_requests, n_packets, packet_time1. Sets retry1 to * (global) n_retries * * @see qserver_send_initial */ int qserver_send(struct qserver* server, const char* data, size_t len); int send_broadcast( struct qserver *server, const char *pkt, size_t pktlen); /** * Registers the send of a request packet. * * This updates n_requests, n_packets, packet_time1 and decrements n_retries */ void register_send( struct qserver *server ); /** * Sends a packet to the server either direct or via broadcast. * * Once sent calls register_send to register the send of the packet */ int send_packet( struct qserver* server, const char* data, size_t len ); #endif qstat-2.11/CHANGES.txt0000644002404400000620000014344710523106777011344 00000000000000QStat version 2.11 ** UPDATED for 2.11 ** November 04, 2006 Summary of New Features ----------------------- new protocols: Warsow [-warsows, -warsowm] Prey [-preys, -preym] TrackMania [-tm] Tremulous [-tremulous, -tremulousm] add -nx and -nnx options that enable resp. disable name transformation calculate player score for AMS servers Fixes ----- fix segfault when a "tribes2 master" returns garbage -- Steve Jankowski Steven Hartland Ludwig Nussel QStat version 2.10 ** UPDATED for 2.10 ** October 22, 2005 Fixes ----- fix Quake4 master only returning 231 servers fix busy loop when waiting for Quake3 and Quake4/Doom3 master packets fix win32 build -- Steve Jankowski Steven Hartland Ludwig Nussel QStat version 2.9 ** UPDATED for 2.9 ** October 20, 2005 Summary of New Features ----------------------- new protocols: Pariah [-prs] Steam Master for A2S [-stma2s] Nexuiz [-nexuizm, -nexuizs] Gamespy V3 [-gs3] Quake 4 [-q4m, -q4s] add option -allowserverdups to be able to query ts2 servers support for LAN broadcasts with A2S add option -sendinterval for tuning send throttling add support for port ranges support HL1 protocol variant in A2S add 'S' player sort option to sort by score Fixes ----- fix eye protocol not showing the last player always use an offset of 123 with eye protocol fix infinite loop and memory expansion when port is 65535 -- Steve Jankowski Steven Hartland Ludwig Nussel ** UPDATED for 2.8 ** April 03, 2005 Summary of New Features ----------------------- add support for new steam protocol (-a2s) add derived type STMHL2 for steam master returning a2s instead of hls change timing for sending packets to improve ping times of low-ping servers Fixes ----- fix ut2004 master server support -- Steve Jankowski Steven Hartland Ludwig Nussel QStat version 2.7 ** UPDATED for 2.7 ** Dec 22, 2004 Summary of New Features ----------------------- new protocols: UT2004 master [-ut2004m] update steam master protocol to new version add additional output to the player xml of -gps add option -progress,n to print out progress every n packets add doom3 protocol and osmask as server rule use autoconf+automake, a simple Makefile is provided as fallback add "flags" to qstat.cfg Fixes ----- fix hanging qstat when receiving UDP packets with incorrect checksum fix colored names in America's Army (use -ams instead of -gps) -- Steve Jankowski Steven Hartland Ludwig Nussel QStat version 2.6 ** UPDATED for 2.6 ** Aug 15, 2004 Summary of New Features ----------------------- new protocols: All Seeing Eye [-eye] Ravenshield [-rvs] Savage [-sas] FarCry [-fcs] Jedi Knight: Jedi Academy [-jk3m, -jk3s] Gamespy2 [-gs2] Steam master [-stm] Doom3 [-dm3s, -dm3s] Half-Life 2 [-hl2s] (experimental) add option -hsn to display server names in hex [no docs] add "servers/sec" to -progress output add -mdelim parameter to specify the multi value delimiter ( default '|' ) add \final\\ to end of gamespy master request add UT2K4 colored name parsing add UT2 XMP colored name parsing add SOF coloring of server names Fixes ----- fix custom q3 master query for masters created via qstat.cfg fix gamespy protocol to better handle Halo and BF1942 fix for multi value fields in UT2003 e.g. Mutators. fix XML escaping bugs New template variables ---------------------- $SCORE player score Thanks ------ Timothee Besset from id Software for providing Doom3 protocol information Alexander Schfer for fixing version and password field for Ravenshield and of course everyone else who provided feedback and bug reports -- Steve Jankowski Steven Hartland Ludwig Nussel ** UPDATED for 2.5c ** Nov 11, 2002 Summary of New Features ----------------------- Unreal Tournament 2003 support [-ut2s] Including support for the current UT2003 patch Ghost Recon support [-grs] Bob Marriott provided the patch for this. I integrated with very few changes. See info/GhostRecon.txt for more detail. Thanks Bob! Supports versions 1.2, 1.3, 1.4 and expansions -noportoffset to disable adding the port offset to query packets There's a "noportoffset" query argument to set this per-server. -showgameport to output the game port instead of the query port With -showgameport, qstat will report the game port instead of the query port in $ARG, $PORT, and $HOSTNAME. If the query port is different from game port, the query port will be set in the "_queryport" server rule. There's a "showgameport" query argument to set this per-server. New template variables ---------------------- $TOTALMAXPLAYERS Sum of max players from all servers $PLAYERSTATID UT2003 global player stat id (not yet supported by Epic). $UNREALTOURNAMENT2003 $GHOSTRECON $PLAYERLEVEL Character level for NWN $IF:DEATHS True if $DEATHS > 0 $TOTALUTILIZATION How full the servers are (0 to 100 percent) Fixes ----- Fixed packet parsing for Battlefield 1942. Use -gps to query BF1942 servers. The query port is usually 23000. Fix broadcast queries for Tribes 2, Quake 3, UT2003 (hopefully) Fix all output modes to support team-numbers, team-names, and no-team styles Fix xml output; accidentally disabled and Fix player info for NWN and other GPS games Fix sv_password rule on Half-Life servers Removed some debug output Thanks ------ A big round of applause for Bob Marriott, author of the Ghost Recon support. He reverse engineered the GR status protocol and maintained the patch through several protocol revisions. And he wrote documentation! Thanks to Ludwig Nussel and Alex Burger of XQF for testing, suggestions, and some timely stubborness :-) Thanks for testing and suggestions: Kingsley Foreman, Pierre Smolarek, Simon Garner and Paul Witt. Steve, steve@qstat.org ** UPDATED for 2.5b ** August 8, 2002 Whoops, I broke XQF. When using QStat raw mode, XQF and other programs rely on the number of fields returned staying fixed. I added a game/mod field to most raw output which breaks these programs. Summary of New Features ----------------------- Extended -raw with a -raw,game variation that adds the game/mod name to the end of the raw server output. Otherwise, the game/mod info is not output in raw mode. Thanks to Ludwig Nussel for not biting my head off (too much). Steve, steve@qstat.org ** UPDATED for 2.5a ** August 6, 2002 Final version of QStat 2.5a. Please send feedback and bug reports to qstat-users@yahoogroups.com or to steve@qstat.org This version of QStat is being distributed under the Artistic License. The terms of the license can be found in LICENSE.txt in the QStat package. Summary of New Features ----------------------- Config file support to define new game types This is a major new feature. This will allow users to define new game types and master servers, including setting custom request packets. I expect that support for most new game types will be accomplished via config files. The default config file is "qstat.cfg". More game types from QStat users can be found in "contrib.cfg". Added support for "status port offset" to config file; UNS (unreal) has this set to 1. If you extend UNS, the new server type will have the same status port offset. Added a GNUmakefile to support gmake Updated COMPILE.txt with new instructions Improve Half-Life server status; extracts mod information and secure status Add support for server rules template (-Tr file) See qstatdoc.html for instructions. Support broadcast queries for Tribes and Tribes 2 Star Trek: Elite Force server and master (-efs and -efm) Return to Castle Wolfenstein server and master (-rws and -rwm) Debug flag (-d) (uses an improved packet output format) Support color player names in Soldier of Fortune Default Config File (qstat.cfg) ------------------------------- Command and Conquer: Renegade server (-crs) Soldier of Fortune 2 (-sof2s) Soldier of Fortune 2 Master (-sof2m) Medal of Honor: Allied Assault server (-mas) Medal of Honor: Allied Assault server, Quake 3 protocol (-maqs) Half-Life "infostring" protocol (-hlqs) This is a Quake 2 style protocol Fixes ----- Fixed raw output to include the game or mod name as the last item Fix template to allow numbers, '.' and ' ' in rule names Refers to $(RULE:someserverrule) Allowing space ' ' may break existing templates if they use syntax like $RULE:maxbullets Max Bullets This can be fixed by change it to $(RULE:maxbullets) This change was made because SOF2 allows spaces in server rule names. Fix Unreal and Gamespy based servers to support backslashes '\' in player names (only partially worked before) Support Half-Life split packets; this happens to the rules info from some Half-Life servers (usually AdminMod and DOD). XML output; added element, UTF-8 output option (-utf8) XML; added Fix crash on broadcast queries Avoid duplicates in the rule list Fixed -srcip to put address in the right byte-order Work-around for crash on Windows when bind() returns temporary error Finish output when -timeout expires Changed Q3 based servers to use a two-packet status query; I think this gets more accurate mod information. More accurate player count on Quake based servers Compiles on OSX/Darwin Fix one byte overrun on QuakeWorld packet New template variables ---------------------- $TYPEPREFIX The server's game type prefix $RULENAMESPACES Allow spaces in rule names $RULETEMPLATE Invoke the server rule template $RULENAME The rule name $RULEVALUE The rule value $(IF:RULENAME(name)) True if rule name equals "name" $(IF:RULEVALUE(value)) True if rule value equals "value" (see qstat.cfg for gametype variables) Thanks ------ Many thanks to all the beta testers for bug reports and feature suggestions. There are many to list, but the following provided significant help: Kingsley Foreman, Mike Davis, Ludwig Nussel, Pierre Smolarek, aphax, and Simon Garner. and I'm sure I forgot someone Steve, steve@qstat.org ** UPDATED for 2.4e ** Oct 1, 2001 This release is basically to fix Tribes 2 support. That was all my fault, Dynamix/Sierra did nothing wrong. Since I was going through the trouble of a full release, I decided to toss in Descent 3 support. Don't be impressed, a patch for D3 was sitting in my inbox. :-) Summary of New Features ----------------------- Descent 3 support -htmlmode (same as $HTML, but for -raw mode) Fixes ----- Fixed Tribes 2 queries Fixed $SHIRTCOLOR when no color names are used Thanks ------ Many thanks to Matthew Mueller for a patch to support Descent 3. Matthew thanks Brian Hayes, Kevin Bentley, and tcpdump. Thanks to Thomas Hager for putting me on the right track for the Tribe 2 bug. Sorry, the real -noconsole support did not make it into this release. Steve, steve@qstat.org ** UPDATED for 2.4d ** August 8, 2001 Summary of New Features ----------------------- Half-Life master filters Names for Quake 3 game types XML output mode Broadcast support for Gamespy style protocols Append output file option [-af] Option to print carets in Q3 player names [-carets] OS/2 Warp EMX compiler port OpenBSD support Options to specify source ports [-srcport] and source IP address [-srcip] for packets sent by qstat. Handy for getting through firewalls. See docs for details. Fixes ----- Tribes 2 teamdamage flag Fixed writing beyond array bounds when reading templates on Windows. (maybe this will fix the garbage characters some people see) Fixed player sorting for games with teams (tribes 1 and 2). Removed win32/qstat.exe from the tar.gz Trying the MS C 6.0 compiler again (win32/qstat.exe) Fixed running QStat from PHP; would crash or give no data New template variables ---------------------- $CLEARNEWLINES Convert newlines to spaces in all variable output. Handy for Tribes 2 servers with long descriptions. $GAMETYPE Quake 3 only - the name of the game type Thanks ------ Most of this release was contributed by QStat users: XML output Simon Garner Half-Life master filters Ludwig Nussel OS/2 Warp EMX Mikulas Patocka OpenBSD subset A three rail gun salut to ya! And thanks to Tahi 'Linus' Walcher for helping find the PHP bug. strace is a thing of the gods. I was hoping to fix one other problem for Windows users. QStat is a command-line style program, so Windows always gives it a console window. This is annoying if you're running QStat from a web-page or a GUI server browser. I can fix this, but it's not that easy. In the mean time, I've added a -noconsole option that will delete the console as soon as qstat starts. The effect is that a console window will flash on the screen briefly. QStat still runs, you just won't see any output on screen. Anyway, I'll craft a real implementation of -noconsole in the next release. Steve, steve@qstat.org ** UPDATED for 2.4c ** Apr 19, 2001 Summary of New Features ----------------------- Tribes 2 player type and tribe tag information Changed Quake 3 default version to "48" (1.27g) New Tribes 2 master filters. (see documentation) Bug Fixes --------- Fixed win32/qstat.exe binary; re-compiled using old compiler Convert newlines into spaces when printing Tribes 2 server info in raw mode. Fixed problems with the 22337 build of Tribes 2. Tribes 2 raw output is now the same format as most other servers. Note that this reverses the order of current and max players from what they were in 2.4b. And adds ping and # retries values. New template variables ---------------------- $IF:ISBOT $IF:ISALIAS $IF:TRIBETAG $TRIBETAG Notes ----- [ Blarg, I hate it when I blow a release. Many people had problems with the win32/qstat.exe in 2.4b release. I had compiled this with a new compiler version on a new Win2k install. It worked fine for me, but apparently the new compiler has compatibility problems. So, I've gone back to the old compiler and old NT 4.0 install. Several people also reported problems using 2.4b with the new 22337 build of Tribes 2. Sorry about the problems. This release should fix things up. ] The new Tribes 2 player info is available in raw mode (see docs) and templates. But it is not displayed in the interactive output. I've updated the sample Tribes 2 templates to display the new player info. Finally, there seem to be a number of bugs with the Tribes 2 master servers. One of the bugs is noted in the documentation. Dynamix is aware of the problems and working to fix them. Steve, steve@qstat.org ** UPDATED for 2.4b ** Apr 13, 2001 Summary of New Features ----------------------- Support for Tribes 2 [-t2s] (builds numbered 22075 or higher) Support for Tribes 2 master [-t2m] Support for Quake 3 and Tribes 2 colorized player names [-htmlnames] Sample HTML templates for Tribes 2 [template/tribes2*] New QStat web site! http://www.qstat.org New mailing lists for QStat users and announcements! (see web site) New template variables ---------------------- $ISMASTER $TRIBES2 $TRIBES2MASTER $HTMLPLAYERNAME Bug Fixes --------- Fix 'game' value for some Quake 2 based servers Fixed some cases where QStat will hang Fixed some picky compiler warnings Notes ----- The Tribes 2 master server has a number of fancy filtering options. Check the "Tribes 2 Master" section in the documentation for details. Many thanks to Brad Heinz and Dynamix for their help with Tribes 2. Thanks to the QStat beta testers: Dr. Chmod, Marauder, Leif Sawyer, Luca Spada, Simon Garner, and Jose Ivey Steve, steve@qstat.org ** UPDATED for 2.4a ** Oct 5, 2000 Summary of New Features ----------------------- Support for Gamespy master [-gsm] Support for "Gamespy style" protocol queries (adds 12+ games) [-gsm and -gps] More server sort options [-sort] Player sort options [-sort] Option to set the output file [-of] Quake 3 master query argument; can query by protocol version Other Improvements ------------------ Way way way faster Fixed Q3 master server queries Fixed queries of SoF 1.05 servers Servers now queried in the order provided to QStat (was reverse order) Fixed ^ display in Q3 player names Partial fix for '\' in player names Players now displayed in the order the server reports them (was reverse order) Rules now displayed in the order the server reports them (was reverse order) Server variables can be referenced inside player templates Fixed raw display of SoF servers Improved HalfLife queries; fetches sv_type and sv_os server rules Much much much faster New template variables ---------------------- $IF:GAMESPYMASTER $IF:GAMESPYPROTOCOL Notes ----- I'm probably treading on some toes with the Gamespy master support. Someone figured out that the Gamespy server lists are not protected, and sent me the protocol. Once I had that, supporting the master was trivial. See the documentation for details on using a gamespy master. Many games are using the Unreal style server status protocol. Maybe because there are lots of Unreal engine games. Or maybe because developers want Gamespy support, so they use a protocol that Gamespy already supports. There are too many of these games to add individual game types and command-line options. So I've lumped them together as "Gamespy Protocol" servers using the game type "GPS". They all seem to have a server rule called "gamename" set to the name of the game (eg. "roguespear", "turok2"). I made a pile of performance improvements to QStat. Start-up time for large server lists is very fast. Queries on large servers lists is also much faster. And queries require much less CPU time. If you have -maxsim set high to reduce query times, you might see more server timeouts now. QStat can spew out packets so fast, you'll see more packet loss and hence more timeouts. Thanks ------ Many thanks to the beta testers and contributors. They provided bug fixes, bug reports, suggestions, ideas, protocol traces, and kind words. I'll spare them the spam by just mentioning real names: Alex Burger, Conan Ford, Vitaliy Fuks, Mike Dowell, Nico de Vries, and Jose Ivey Steve ** UPDATED for 2.3g ** Feb 3, 2000 BETA is done! The 2.3 release is stable enough now to drop the beta qualifier. Summary of New Features ----------------------- Added options to support Soldier of Fortune [-sfs] New template variables ---------------------- $IF:SOLDIEROFFORTUNE There are command-line options to control the following, but it's handy to have control within the templates as well. $COLORNUMBERS Set the format of $SHIRTCOLOR and $PANTSCOLOR $COLORNAMES $COLORRGB $TIMESECONDS Set the format of $CONNECTTIME $TIMECLOCK $TIMESTOPWATCH Summary of Fixes ---------------- Fix crashes in Unreal -raw player output (duh). Fix hangs doing Unreal server queries. Fix $GAME for Quake 3 servers Fix Kingpin servers reported as Q2 servers Notes ----- The SOF server does not return map information, so you'll just get a '?' or blank for an SOF map. The map info is returned by the master server. But QStat does not yet support the SOF master server. I traced the SOF master protocol, but it's totally different from any other master server. Before I invest the time into writing a parser for the SOF master packets, I'm going to wait to see if it changes before the final retail release. Notes on Future Releases ------------------------ Now that the 2.3 release train is winding down, what's up for QStat 2.4? I don't know, but there's a few frequently requested features: - More sort options; server and player - More games; Delta Force, Descent III - Fetch server lists from web pages - Better templates; variables and full expression evaluation - Better performance on large server lists - Examples and samples I don't know which features will be available when, so don't ask. There may be one or two more 2.3 releases to fix critical bugs or add a new game. Getrnk und ist frhlich, Steve ** UPDATED for 2.3f BETA ** Jan 11, 2000 Summary of Fixes ---------------- Added player ping and face to Unreal -raw output Fix queries for version 405 Unreal servers New template variable --------------------- For the player template: $FACE The texture used on a player's face. This was added to Unreal a while back, but I didn't notice. Notes ----- The fine blokes at Unreal decided to fiddle with the Unreal query protocol. When asked why PingTool and QStat did not work with the new servers, they responded that we must not be following the new GameSpy spec. Ha! As if they publish this information or care to keep other server browser authors informed. Sheesh. Steve ** UPDATED for 2.3e BETA ** Jan 7, 2000 Summary of Fixes ---------------- Quake III Arena master queries Half-Life master queries $(IF:GAME) was true when $GAME was blank (Tribes) Improved Q3A player name translation Fixed raw mode output for Unreal (minor incompatible change) Updated docs for raw mode output Add one to Unreal/UT port to get query port (incompatible change) $GAME and "-sort g" now work for Unreal/UT Summary of New Features ----------------------- Options added for Kingpin and Heretic II game servers. These two games were previously supported with the -q2s option. New options: -kps and -hrs New template conditions: $(IF:KINGPIN) and $(IF:HERETIC2) Notes ----- Numerous people sent me the fix for the Q3A master query problem. I think the first was Ted Milker, but thanks to all for your suggestions and patience. The Half-Life master support wasn't using the latest protocol, so needed an upgrade. Now you can get the full 2100+ server list from the master. BTW, there are more HL servers than Q3A servers. Unreal support was changed to automatically add one to the port number to find the query port. This is probably why people thought QStat didn't support UT. For those that figure it out already, you'll have to remove your own +1 hacks to use this release. I apologize for the long delay between releases. Work, holidays, and health problems cut my free time to less than zero. Best wishes for the new millennium, Steve ** UPDATED for 2.3d BETA ** May 12, 1999 More bug reports and suggestions prompted this release. Quake 3 master -------------- The id Q3 master server isn't working very well. The protocol is lame and its network is way over subscribed. I've enhanced QStat to deal with the changes, but I actually think they (id) have made matters worse rather than better. QStat can now, sometimes, get all the servers from the master, but it often can't get 30-60% of the servers. This is not QStat problem, but id's. I've sent them a detailed analysis of the problems and made some suggestions. Summary of Fixes ---------------- Improve reliability of Q3 master server queries Support Tribes servers with 3+ teams Strip escape sequences from Q3 player names; use -hpn if you want the complete content of player names. Accurately calculate number of servers on a master (ignore duplicates). Fixed $(ISFULL) to be false if the server is empty [duh] New Features ------------ New option to control master server retry interval ("-mi") independent of server retry interval. Increase maximum -maxsim to 256 for Win32. Added $(TYPESTRING) template var; shows server's type string (eg. q2s, hls) Added $(NOWINT) template var; shows the current time in seconds since 00:00:00 UTC, January 1, 1970. Notes ----- Many many thanks to Nico de Vries (Nico.de.Vries@ucc.nl) of CLQ for the many bugs reports, suggestions, etc. Thanks to stincey@nireland.com for figuring out the Tribes 3+ teams bug. Steve, steve@activesw.com ** UPDATED for 2.3c BETA ** May 3, 1999 A slew of bug reports arrived over the weekend. I guess QStat users are weekend warriors. Thanks to the four people that sent patches for the Q3 master breakage. I won't say who's patch I used, but I selected the most elegant. id has said that the Q3 master protocol will be changing alot over the next weeks. I'll try to track their progress, but no promises. They also asked for suggestions on reducing packet size, so I sent them my ideas (all quite clever ). Summary of Fixes ---------------- Q3 master server Q3 server name Tribes -raw mode [forgot to write it] Removed leftover debug print Switched snprintf() to sprintf() [much more portable] Half-Life game rules [useful for TFC] Fixed -progress output Added player ping to Unreal player output Fixed minor mistakes in docs Notes ----- Many thanks to: "Dark Grue" of QStatList Nico de Vries of CLQ "Joe S." of ... I forget what Joe does Sven Grundmann for their bug reports, patches, and suggestions. Steve, steve@activesw.com ** UPDATED for 2.3b BETA ** April 29, 1999 New: Quake III and BFRIS support Not many complaints about problems with 2.3a, looks like the new code is working fine. Summary of New Features ----------------------- Quake III: Arena (Q3Test) Quake III master BFRIS (www.aegistech.com) Minor Changes ------------- A couple people pointed out that the docs and the code did not exactly agree on the server type strings. So, I've fixed the code to match the docs. The following type strings were changed: 2.3a 2.3b ---- ---- QW --> QWS Q2 --> Q2S Notes ----- Voluminous thanks to Dave "Zoid" Kirsch of id Software for supplying diffs to support Quake III. Zoid says has used QStat "from time to time" over the years. Makes me smile. And a sweeping bow to Pete Ratzlaff of Harvard for the diff to support Linux game BFRIS. See www.aegistech.com for info. I gave the diffs the wary eye for fuggly programming, but both were written nicely and applied without a hitch. I performed minimal testing of the new code, please let me know if there are problems. Steve, steve@activesw.com ** UPDATED for 2.3a BETA ** April 19, 1999 Lots of changes and additions in this release, far more than I have patience to test. Please try this release with your web page, stats program, server browser, and what not. If you encounter any problems _please_ send me email! Flames on my sloppy coding are acceptable. Summary of New Features ----------------------- Complete Half-Life support (players and server rules) Half-Life master server (option -hlm) Tribes servers (option -tbs) Tribes master server (option -tbm) Shogo (option -sgs) Hex player colors (option -hc) Several new template variables Created server types table to simplify code Bug Fixes --------- Servers without "hostname" rule appeared to TIMEOUT One or two other boo-boos Incompatible ------------ The option "-qw" has been removed. Please use "-qwm" instead. New variables for output templates ---------------------------------- Generic variables $(DEFAULTTYPE) Full name of the default server type (-default) Server variables $(ISEMPTY) True if the server has no players $(ISFULL) True if the server is full of players Player variables $(PACKETLOSS) Players packets loss (Tribes only) $(ISTEAM) True if this player represents a team (Tribes only) $(TEAMNAME) Name of this player's team (Tribes only) Notes ----- Many thanks to the following for their assistance: zarjazz@barrysworld.com Tribes seb@club-internet.fr, carl@d-n-a.net Shogo sean@msiconsulting.com Half-Life Thanks to the many people who have sent suggestions for improvements. I've incorporated some of them in this release, more will follow in later releases. This release was focused on supporting popular new games and making it easier to add new games to the code. The backlog of new games support is now empty. If there's a game you would like to see supported, please send email. The Linux game BFRIS (http://www.aegistech.com) is the only planned new game support. Steve, steve@activesw.com ** UPDATED for 2.2b ** Jan 15, 1999 D'oh! I need to do more testing. The -raw mode did not work at all for Half-Life. Thanks to Dark Grue for bring that to my attention. Bug Fixes --------- Fix Half-Life support with -raw mode Shush compiler warning on Linux Steve, steve@activesw.com ** UPDATED for 2.2a ** Jan 14, 1999 Not too much in this release, but I've been getting an email a day asking about Half-Life support. The Half-Life status packets are totally different from Quake II, so I've only completed the general info so far. Players and rules from Half-Life will be available in the next release. I also threw in flags to support Sin. Sin was supported in previous releases by pretending it was a Q2 server, but now it has its own flags. Future releases of QStat will support even more games (Shogo, Blood 2, Heretic 2, etc). Summary of New Features ----------------------- Sin support (option -sns) Half-Life (partial) support (option -hls) Bug Fixes --------- Divide-by-zero bug with sorting Memory allocation bug using -H (hostname lookup) New variables for output templates ---------------------------------- Server template variables $SIN True if the server is running Sin $HALFLIFE True if the server is running Half-Life Steve, steve@activesw.com ** UPDATED for 2.1a ** Oct 4, 1998 This release supercedes previous 2.1 releases (2.1z BETA and 2.1y BETA) Summary of New Features ----------------------- Unreal 2.15+ support (option -uns) Broadcast queries (prefix address with '+') Save lists from master servers (option -qw,outfile and -q2m,outfile) Bug Fixes --------- Fixed host cache on Intel platforms Report Host Not Found as a server error (so it appears in templates and raw output) New variables for output templates ---------------------------------- Server template variables $HOSTNOTFOUND True if the host name lookup failed Player template variables $MESH Player mesh (model) name (Unreal only) Notes ----- QStat will support the public Unreal master server once it's done. The current Unreal master server is private to GameSpy (snarl). The broadcast queries is an experimental feature. I've only tested it with Quake II. Other games will be tested and supported in later releases. For example, querying the local net for Q2 servers on the default port: qstat -q2s +255.255.255.255 The '+' makes QStat broadcast to the given address. The default broadcast address for all nets is 255.255.255.255. You can also use a network specific broadcast (eg. 199.2.18.255). On Unixes, 'ifconfig -a' will display the broadcast address for all attached networks. The ",outfile" option for master servers is handy for dealing with unreliable master server (such as the id Q2 master). Run qstat once to save the servers lists to files, and a second time to query the servers: qstat -q2m,outfile satan.idsoftware.com,idq2.lst qstat -f idq2.lst The first command saves the server list from the id Q2 master into "idq2.lst". If the master isn't working, then the file retains its previous contents. The second command queries the servers in that file. I've also included the templates for an example Unreal server list web page. Thanks to my wonderful users for reporting bugs and making suggestions. And a special thanks to the Unreal development team for actually documenting their query protocol (unlike some other well known first person shooter developers). Steve, steve@activesw.com ** UPDATED for 2.1y BETA ** Aug 22, 1998 Summary of New Features ----------------------- HexenWorld support Revived support for id's Q2 master New variables for output templates Faster host cache initialization More efficient server query (Unix only) Support for AIX 4.2 and HPUX 11.0 Bug Fixes --------- Fixed bogus query failure on second server on same IP address. Fixed to ignore QW and Q2 server packets that contain lots of error messages. Also disabled printing of the "Odd packet" messages. They can be enabled with the -errors option. Fixed output templates on Windows Non-feature ----------- Unreal support. Unreal needs to get fixed before QStat can support it. HexenWorld support ------------------ Use the -hws command line option, or the HWS server type key. Revived support for id's Q2 master ---------------------------------- id's Quake II master server was broken for a long time. QStat supported id's Q2 master, but the master only rarely returned anything (and you had to wait up to 30 seconds for a response). When QuakeSpy announced that id had fixed their Q2 master, I was surprised that QStat did not work on the fixed master. Turns out the "fix" also changed the query protocol slightly. New variables for output templates ---------------------------------- General variables $\ Inhibit output of the next newline. Server template variables $HEXENWORLD True if the server is HexenWorld (use with $IF) $UNREAL True if the server is Unreal (use with $IF) Player template variables $DEATHS Number of deaths (Unreal only) $TEAMNUM Team number (Unreal only) un-Unreal support ----------------- I implemented support for the original Unreal server status protocol. However, the Unreal server worked so poorly as to be unusable. Unreal is getting improved Internet support, but it's not ready yet. When Unreal gets fixed, QStat will support the new protocol. I've also included the templates I use for the status page of my own Quake II servers. Steve, steve@activesw.com ** UPDATED for 2.1z BETA ** Feb 28, 1998 Summary of New Features ----------------------- Output templates (HTML generation) Server sorting Host name and IP address cache Support for Quake II master New Flags --------- See the documentation (qstatdoc.html) for complete details. -default server-type Set the default server type which should be one of: QS, QW, QWM, H2S, Q2, or Q2M. -Hcache file Host name cache file -sort sort-key Sort the servers by the sort-key p sort by ping g sort by game -Tserver file Server output template. Displayed once per server. -Tplayer file Player output template. Displayed once per player (if -P is used) -Theader file Header output template. Displayed once before any servers are output -Ttrailer file Trailer output template. Displayed once after all servers and players are output. -q2m Get servers from Quake II master server Summary of Enhancements ----------------------- Remove duplicate server addresses before query Reduce memory usage when -R and/or -P are not specified Work-around a memory leak in Solaris 2.5 Wait for results from all master servers before starting to query servers VMS support Release Notes ------------- This is a major new release of QStat. There is over 1400 lines of new code with all the benefits and drawbacks therein. I hope you like the features, but I really hope it's not riddled with bugs. There might be some portability issues since I only have access to Solaris, HP-UX, Irix, and Windows NT. If you have a problem compiling, please send me a note. No major new features are planned for 2.1 beyond what you see here. However, I plan to make enhancements to the sorting and template code before final release. Please tell me what is missing. Obvious deficiencies include: - No per-server output files (can't have a server list with a link to a page with details about each server). - Missing $ELSE ($IFNOT is a cheap replacement) - Flexible $IF expressions would be nice - The output template variable syntax is kinda lame: you use $(IF:RULE(email)) to test for a rule and $(RULE:email) to output the value - Can only sort on ping and game. Would like to add map, players, etc - Can't sort the player lists - Host cache administration might be nice (re-verify command) - Host cache sharing. Use file locking to allow multiple qstats to share the same host cache. Presence on the list above does not guarantee implementation! Please tell me what you want, even if it's listed above. A host name cache can take a _long_ time to build the first time (30 minutes, minimum). I will try to keep starter cache files on the QStat web site. The current cache file for servers in the QW masters contains over 1000 entries. I've included sample output templates for HTML. They are not the best HTML, but they demonstrate some of the neat tricks you can do. If you use the templates with '-R', then server rules like email and web will be output as links next to the server. If you get player status (-P), then a subtable is output with player info formatted with the correct columns for the server type. A sample command line to use the templates: qstat -f myservers.txt -Ts template/server1.html -Th template/header1.html -Tp template/player1.html -Tt template/trailer1.html > myservers.html (The template files in qstat21z.zip have a ".htm" extension) Finally, the id Quake II master has a bug (gasp!) that makes it _very_ slow to respond some times. QStat tries to work-around the bug by increasing the retry interval by 20 times while waiting for a response from a Quake II master. The retry interval is restored once all the masters have been queried. Thank you for your support. ** UPDATED for 2.0b ** Dec 29, 1997 - Fix map name for Quake II 3.07-09 The rule key changed from "map" to "mapname". If both are present, then "mapname" takes precedence. - Q2: Noticed some servers are running custom games. The rule keys for games are confusing: "gamename" Always seems to be set to "baseq2", unless a custom game is being run, in which case "gamename" is not set at all. "gamedir" Probably the same as "*gamedir" in QW. "game" Always the same as "gamedir" in the servers I stat'd. Maybe this can be used to indicate the name as well as the version of the game being run. For now, QStat displays the value of the "game" key in the non-raw output of Q2 servers. - Print file name and line number information with errors when reading files. - new option: -progress display progress meter Thanks maynard@ultra.net Leave for the Holidays and the id boys change the protocol. A minor change, but a few QStat users noticed right away. The change does not affect people using -raw. ** UPDATED for 2.0a ** Dec 9, 1997 - Support for Quake II servers, see documentation for usage. - Minor fix to connect time formatting. I don't have Quake II, but the status protocol is very similar to QuakeWorld, so I was able to figure it out by poking existing Quake II servers on the net. Id has stated that the network protocol will get an upgrade soon after the in-store release. As always, QStat will track these changes as they become available. ** UPDATED for 1.6 ** Nov 30, 1997 Changes since beta5. Minor enhancements and a few fixes. - Removed all the annoying copyright restrictions. - Added option -ne : no empty servers Thanks secabeen@fnord.rh.uchicago.edu - Added option -raw-arg : special for QStatList (see qstat docs) Thanks darkgrue@iname.com - Added option -timeout : total time in seconds before giving up Can prevent overlapping runs when cron runs qstat every five minutes. - Added gamedir to QW server output (not -raw) - Fixed bug getting long server lists from QuakeWorld masters. Can now get lists in excess of 16,000 servers. How long til that limit is exceeded? - Fixed bug using -H with -qw - Fixed use of select() so systems with large file descriptor limits can query more than 64 servers at a time. - Overhauled the web page, but it is still gif-less. QStat 1.6 has been in alpha / beta just short of a year (1.6 alpha was released Dec 20, 1996). It has been a good year. Many thanks to those who sent suggestions, kind words, and bug reports. And appologies to those who have not seen their request implemented, or who did not even receive a reply. "Mmmgufm gumerfm rerfgmmf." "That's right, Kenny, Steve is a busy guy and doesn't care about your stupid problems." "Merfgl! gumerfm rerfgmmf!" "Dammit, Kenny, turn down the computer, I can't hear you over the splattering bodies." "Gumerfm rerfgmmf." "Oh. Kenny says, Steve does care about your problems, but not the stupid ones." [ A large core dump falls on Kenny, killing him. ] "Steve killed Kenny! You bastard!" Quake II gives me an excuse to crank up the major version dial. QStat 2.0 will feature support for Quake II servers. ** UPDATED for 1.6 beta5 ** Oct 5, 1997 Kitchen sink release to add some of the most requested features. - Extended file format. The file used with the -f option can include server type information to distinguish between Hexen II, Quake, and QuakeWorld servers. You can put all your servers into one file and query them all with one qstat invocation. - Fix bug that caused a QuakeWorld master server query to never timeout. - New option -h2s for specifying a single Hexen II server to query. - New option -maxsimultaneous limits the number of simultaneous server queries. Previously configurable by modifying the MAXFD #define in qstat.h. - Updated docs [FINALLY!] - Compiles on HP-UX 10.20 - Changed packaging: files are in a directory named for the version of qstat, and use gzip instead of compress on unix - Removed pre-QuakeWorld 1.5 support. The -qw1.5 option is obsolete and no longer needed. As are the -qwuserinfo and -qwseeninfo options. - Smarter about when to include server type prefix in formatted output Unless I hear cries for more features, this will be the last beta before the final release of qstat 1.6. Now that the docs are up to date, I've run out of excuses for doing the release. ** UPDATED for 1.6 beta4 ** Sept 2, 1997 Qstat has gone through some minor revs of beta3 and the arrival of Hexen II sparked the need for another release. Summary of fixes and changes: - Support for Hexen II servers. Use the -hexen2 mode to query Hexen II servers: qstat -hexen2 -R -P 165.166.143.15 208.131.24.189 You cannot mix queries of Quake and Hexen II servers. This limitation will be fixed in the final 1.6 release. However you can mix QW and Hexen II queries in one qstat command. [Thanks to Michael Long, mlong@infoave.net, for getting me the protocol magic for Hexen II.] - In the formatted display output (as opposed to -raw), a Hexen II server is indicated with a H2S prefix. This will only be seen if qstat is using different quake protocols at the same time (eg. query a Hexen II and QW server in the same command). - Various fixes to deal with bogus packets from QW servers. The lastest one is caused when the QW server info packet is truncated. It appears that there is a fixed buffer of 1600 bytes in the QW server for building server info responses. The QW server programmers may want to consider increasing this value. On Ethernet, two packets must be used to send 1600 bytes (Ethernet frame size 1518, subtract ~50 for header, leaving ~1468 for data). Might as well set the buffer size to ~3000 bytes so two full packets can be used. - There's some wierd problem on Linux which causes bind() to occasionally fail with EADDRINUSE. Fixed the code to consider this a transient error and retry the address at a later time. If you saw messages like: bind: Address already in use send: Invalid argument from qstat, then this fixes that. No time table for the final 1.6 release. Other than updating the docs, I don't plan any significant new features. ** The docs have not yet been updated. This is all you get for now. ** ** UPDATED for 1.6 beta3 ** April 3, 1997 D'oh! Should never do releases just after midnight. Beta2 had an old win32 executable. Also forgot to check for NULL map name in the -raw display code. Sorry! ** UPDATED for 1.6 beta2 ** April 2, 1997 Features in 1.6 beta2 beyond beta1 Fix crash on negative player colors New option -qw1.5 Use the QuakeWorld 1.5 protocol. Affects the interaction with a QW master (-qw). Fortunately, the rest of the protocol hasn't changed. I imagine the user and seen info won't be available from a QW 1.5 master. The user and seen flags will remain until I have a better understanding of where QW is going. Had to fix a bunch of crashes related to QW 1.5 servers. Some of them don't have common keys like "map". ** UPDATED for 1.6 beta1 ** Feb 7, 1997 Features in 1.6 beta1 over the 1.6 alpha releases: Changes to -qw option Support for user names and user ids Defaults values ("qstat") for user id and password. Most of the QW masters have a qstat user with "qstat" as the password. New option -qws Fetch and display stats for a single QW server. New option -qwuserinfo Fetch and display user information from a QW master. New option -qwseeninfo Fetch and display user information from a QW master. bug fix Better handling of error packets from QW servers and masters. No more "huh?" Thanks to Kris Nosack (kn@byu.edu) for comments and bug reports. ** The following has been updated to reflect the changes and ** additions in 1.6 beta1. The main feature of this release is support for QuakeWorld. A couple minor bug fixes have also been made. QuakeWorld support has been integrated into qstat. You can query normal Quake servers and QuakeWorld servers at the same time. A new prefix is used to distinguish between the different server types. New options ----------- All of these options can be used together in a single run of qstat. To query QuakeWorld servers, use the -qw or -qws options. The first will get the list of QW servers from a QW master and query all of them for status information. The latter, -qws, will just query the given QW server for status information. These options are the only way to get QuakeWorld server stats. Hosts added with -f or on the command-line are treated like normal Quake servers. -qw host:port:uid:password host host name or IP address of QW Master Server port port number (defaults to 27000 if blank) uid valid QW user id or name on host password password for user To get the server list from a master server, qstat needs a valid login on the master. A default login and password can be used if the uid and password are not given. The default is "qstat" for both values. All the known masters should have a "qstat" user with the same password. -qws host:port host host name or IP address of QW server port post number (defaults to 27500 if blank) If you don't use -qw or -qws, qstat will behave identically to qstat 1.5. I use the following command to query QW servers: qstat -qw 204.50.178.66 To get QuakeWorld user information, use the -qwuserinfo and -qwseeninfo options. A QW login is not required to get user information. -qwuserinfo host:port user-list host host name or IP address of QW Master Server port port number (defaults to 27000 if blank) user-list list of QW users (ids or names) The display for a user will include everything in their record. The color name option (-ncn) is applied to 'topcolor' and 'bottomcolor'. The user-list must be _one_ command line argument; use double-quotes to enclose multiple users if they're separated with spaces. You can also use back-slashes to separate users. -qwseeninfo host:port user-list host host name or IP address of QW Master Server port port number (defaults to 27000 if blank) user-list list of QW users (ids or names) The last seen information comes directly from the master, qstat does not perform any additional formatting. The user-list should be _one_ command line argument; use double-quotes to enclose multiple users if they're separated with spaces. You can also use back-slashes to separate users. To get user information for me and qstat and find out who was last slagging me: qstat -qwuserinfo 204.50.178.66 "Act-Steve qstat" -qwseeninfo 204.50.178.66 Act-Steve Display format -------------- The QW servers return different information than the normal servers, so I had to extend the output style. The first field of a server status line is the server type: QS normal Quake server QW QW server QWM QW master server QWU QW user information QWE QW last seen information The for-human-comsumption output is pretty self-evident, but the raw output needs some explanation. The output for normal Quake servers has not changed. QWM server status fields server address, number of QW servers [the uid and password are removed before display, no rules or player info is output] QW server status server address, server name, map name, max players, current players, avg response time, number of retries [If -R is specified, a line of server rules is output. The format is the same as for normal servers: key1=value1,key2=value2] [If -P is specified, one line is output for each player.] player uid, player name, frags, connect time, shirt color, pants color, ping, skin QWU key1, value1, key2, value2, ... [The first seven keys will always be the same; name, userid, skill, efficiency, rank, frags, deaths. But I would not count on that as I'm a fickle programmer and may change my mind.] QWE seen-info [qstat just displays the string returned by the master. The user name is embedded in there, but you'll have to parse it out.] All the existing display options apply to QW servers. Run qstat by hand to better understand the new output before trying to incorporate it into your web page. Errors ------ QStat has a variety of ways of reporting errors such as time outs and server errors. If you see something between angle brackets, , that's an error message directly from a server or master. Some day I'll document how errors are displayed in the raw format. But for now I trust you web masters can figure it out Final words ----------- This version is very beta. If you would like qstat to work differently let me know. And of course, if you have problems or questions, please let me know. Known bugs ---------- qstat often fails to get all the QW server lists if multiple QW masters are specified. You'll see a TIMEOUT or "no response" from the QWM when this happens. I have a fix in mind, but I'm tired and there's beer waiting for me at home. An error is not displayed if qstat times out getting user or last seen information. Steve Jankowski steve@activesw.com --- Version 1.5 adds player info, server rules, response times, and performance improvements. A large number of flags were added to support different output formatting options. Web masters should check out the -raw option which displays all server info with your choice of delimiter. Updated copyright to be more specific about allowable use. Updated the web page with links to Quake protocol pages. Version 1.4 includes a number of new features and bug fixes. There is now support for Linux, flags to set retry timeout and interval, flags to limit output to running or not full servers. A bug was fixed which caused qstat to have a long delay the first time it was run on Windows 95/NT. Version 1.3 fixes a bug introduced in 1.2 and adds a Windows 95/NT executable. The bug caused DOWN servers to be reported multiple times. Version 1.2 fixes the bug with running out of file descriptors. qstat-2.11/ChangeLog0000644002404400000620000000117007626214663011273 00000000000000Sun Feb 23 10:52:18 PST 2003 Added $SCORE for player score Fixed XML escaping bugs Fixed repeated rule values from UT2003 servers Fixed excessive retries to UT2003 servers that set minplayers Fixed reported # players for UT2003 server that set minplayers Changed sof2m default protocol to 2004 (SOF 1.02) Tue Jan 7 16:24:57 PST 2003 Fixed manual compile instructions in COMPILE.txt Updated RTCW master protocol from 58 to 60 Added support for All-Seeing Eye protocol (-eye) [still need to write documentation] Fixed rare divide by zero displaying ping time Added information about UT2003 master server lists to info/UT2003.txt qstat-2.11/packet_manip.c0000644002404400000620000001261710470043631012312 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Packet module * Copyright 2005 Steven Hartland based on code by Steve Jankowski * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include "qstat.h" #include "debug.h" #include #include #define MAX_PACKETS 8 #define MAX_FAGMENTS 16 int pkt_seq = 0; int pkt_id_index = -1; int n_ids; int counts[MAX_PACKETS]; SavedData *segments[MAX_PACKETS][MAX_FAGMENTS]; int combine_packets( struct qserver *server ) { unsigned int ids[MAX_PACKETS]; int maxes[MAX_PACKETS]; int lengths[MAX_PACKETS]; SavedData *sdata = &server->saved_data; int i, p, done = 0; n_ids = 0; memset( &segments[0][0], 0, sizeof(segments) ); memset( &counts[0], 0, sizeof(counts) ); memset( &lengths[0], 0, sizeof(lengths) ); // foreach packet for ( ; sdata != NULL; sdata= sdata->next) { debug( 4, "max:%d, id:%d\n", sdata->pkt_max, sdata->pkt_id ); if ( sdata->pkt_max == 0) { // not expecting multi packets or already processed? continue; } for ( i = 0; i < n_ids; i++ ) { if ( sdata->pkt_id == ids[i]) { // found this packetid break; } } if ( i >= n_ids ) { // packetid we havent seen yet if ( n_ids >= MAX_PACKETS ) { // we only deal up to MAX_PACKETS packetids fprintf( stderr, "Too many distinct packetids %d max %d\n", n_ids, MAX_PACKETS ); continue; } ids[n_ids]= sdata->pkt_id; maxes[n_ids]= sdata->pkt_max; i = n_ids++; } else if ( maxes[i] != sdata->pkt_max ) { // max's dont match debug( 4, "max mismatch %d != %d", maxes[i], sdata->pkt_max ); continue; } if ( segments[i][sdata->pkt_index] == NULL) { // add the packet to the list of segments if ( sdata->pkt_index >= MAX_FAGMENTS ) { // we only deal up to MAX_FAGMENTS packet fragment fprintf( stderr, "Too many fragments for packetid %d max %d\n", sdata->pkt_id, MAX_FAGMENTS ); continue; } segments[i][sdata->pkt_index]= sdata; counts[i]++; lengths[i] += sdata->datalen; } else { debug( 2, "duplicate packet detected for id %d, index %d", sdata->pkt_id, sdata->pkt_index ); } } // foreach distinct packetid for ( pkt_id_index = 0; pkt_id_index < n_ids; pkt_id_index++ ) { char *combined; int datalen= 0; if ( counts[pkt_id_index] != maxes[pkt_id_index] ) { // we dont have all the expected packets yet debug( 4, "more expected: %d != %d\n", counts[pkt_id_index], maxes[pkt_id_index] ); continue; } // combine all the segments combined = (char*)malloc( lengths[pkt_id_index] ); for ( p = 0; p < counts[pkt_id_index]; p++ ) { if ( segments[pkt_id_index][p] == NULL ) { debug( 4, "missing segment[%d][%d]", pkt_id_index, p ); // reset to be unusable pkt_id_index = -1; free( combined ); return 0; } memcpy( combined + datalen, segments[pkt_id_index][p]->data, segments[pkt_id_index][p]->datalen ); datalen += segments[pkt_id_index][p]->datalen; } // prevent reprocessing? for ( p = 0; p < counts[pkt_id_index]; p++) { segments[pkt_id_index][p]->pkt_max = 0; } debug( 4, "callback" ); if( 4 <= get_debug_level() ) { print_packet( server, combined, datalen ); } // Call the server's packet processing method done = ( (int (*)()) server->type->packet_func)( server, combined, datalen ); free( combined ); // Note: this is currently invalid as packet processing methods // are void not int if ( done || server->saved_data.data == NULL) { break; } } // reset to be unusable pkt_id_index = -1; return done; } int add_packet( struct qserver *server, unsigned int pkt_id, int pkt_index, int pkt_max, int datalen, char *data, int calc_max ) { SavedData *sdata; if ( server->saved_data.data == NULL ) { debug( 4, "first packet" ); sdata = &server->saved_data; } else { debug( 4, "another packet" ); if ( calc_max ) { // check we have the correct max SavedData *cdata = &server->saved_data; for ( ; cdata != NULL; cdata = cdata->next ) { if ( cdata->pkt_max > pkt_max ) { pkt_max = cdata->pkt_max; } } // ensure all the packets know about this new max for ( cdata = &server->saved_data; cdata != NULL; cdata = cdata->next ) { cdata->pkt_max = pkt_max; } } debug( 4, "calced max = %d", pkt_max ); // allocate a new packet data and prepend to the list sdata = (SavedData*) calloc( 1, sizeof(SavedData) ); sdata->next = server->saved_data.next; server->saved_data.next = sdata; } sdata->pkt_id = pkt_id; sdata->pkt_index = pkt_index; sdata->pkt_max = pkt_max; sdata->datalen = datalen; sdata->data = (char*)malloc( sdata->datalen ); if ( NULL == sdata->data ) { fprintf( stderr, "Out of memory\n" ); cleanup_qserver( server, 1 ); return 0; } memcpy( sdata->data, data, sdata->datalen ); return 1; } int next_sequence() { return ++pkt_seq; } SavedData* get_packet_fragment( int index ) { if ( -1 == pkt_id_index ) { fprintf( stderr, "Invalid call to get_packet_fragment" ); return NULL; } if ( index > counts[pkt_id_index] ) { debug( 4, "Invalid index requested %d > %d", index, pkt_id_index ); return NULL; } return segments[pkt_id_index][index]; } unsigned combined_length( struct qserver *server, int pkt_id ) { SavedData *sdata = &server->saved_data; unsigned len = 0; for ( ; sdata != NULL; sdata = sdata->next ) { if ( pkt_id == sdata->pkt_id ) { len += sdata->datalen; } } return len; } qstat-2.11/packet_manip.h0000644002404400000620000000111710470043631012310 00000000000000/* * qstat 2.8 * by Steve Jankowski * * Packet module * Copyright 2005 Steven Hartland based on code by Steve Jankowski * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #ifndef QSTAT_PACKETS_H #define QSTAT_PACKETS_H #include "qstat.h" int combine_packets( struct qserver *server ); int add_packet( struct qserver *server, unsigned int pkt_id, int pkt_index, int pkt_max, int datalen, char *data, int calc_max ); int next_sequence(); SavedData* get_packet_fragment( int index ); unsigned combined_length( struct qserver *server, int pkt_id ); #endif qstat-2.11/gnuconfig.h.in0000644002404400000620000000253410520647412012250 00000000000000/* gnuconfig.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION qstat-2.11/template.c0000644002404400000620000006157010377065324011505 00000000000000/* * qstat 2.6 * by Steve Jankowski * steve@qstat.org * http://www.qstat.org * * Thanks to Per Hammer for the OS/2 patches (per@mindbend.demon.co.uk) * Thanks to John Ross Hunt for the OpenVMS Alpha patches (bigboote@ais.net) * Thanks to Scott MacFiggen for the quicksort code (smf@webmethods.com) * * Inspired by QuakePing by Len Norton * * Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski * * Licensed under the Artistic License, see LICENSE.txt for license terms */ #include #include #include #include #include #if defined(__hpux) || defined(_AIX) || defined(__FreeBSD__) #include #endif #ifndef _WIN32 #include #endif #include "qstat.h" #ifdef _WIN32 #define strcasecmp stricmp #define strncasecmp strnicmp #endif #ifdef __hpux #define STATIC static #else #define STATIC #endif /* #ifdef __cplusplus extern "C" { #endif #ifndef _AIX extern unsigned int ntohl(unsigned int n); #endif #ifdef __cplusplus } #endif */ extern int hostname_lookup; extern int num_servers_total; extern int num_servers_timed_out; extern int num_servers_down; extern int num_players_total; extern int max_players_total; extern int html_names; extern int hex_player_names; extern FILE *OF; /* output file */ static char *server_template; static char *rule_template; static char *header_template; static char *trailer_template; static char *player_template; static void display_server_var( struct qserver *server, int var); static void display_player_var( struct player *player, int var, struct qserver *server); static void display_rule_var( struct rule *rule, int var, struct qserver *server); static void display_generic_var( int var); static int parse_var( char *varname, int *varlen); static int read_template( char *filename, char **template_text); static void display_string( char *str); static int is_true( struct qserver *server, struct player *player, struct rule *rule, char *expr); #define VARIABLE_CHAR '$' static char *variable_option; static int if_skip; static int if_level; static int if_skip_save; static int if_level_save; int html_mode= 0; int clear_newlines_mode= 0; int rule_name_spaces= 0; struct vardef { char *var; int varcode; int options; }; #define NO_OPTIONS 0 #define OPTIONS_OK 1 #define EXPR 2 struct vardef variable_defs[] = { #define V_HOSTNAME 1 {"HOSTNAME", V_HOSTNAME, NO_OPTIONS }, #define V_SERVERNAME 2 {"SERVERNAME", V_SERVERNAME, NO_OPTIONS }, #define V_PING 3 {"PING", V_PING, NO_OPTIONS }, #define V_PLAYERS 4 {"PLAYERS", V_PLAYERS, NO_OPTIONS | EXPR }, #define V_MAXPLAYERS 5 {"MAXPLAYERS", V_MAXPLAYERS, NO_OPTIONS }, #define V_MAP 6 {"MAP", V_MAP, NO_OPTIONS }, #define V_GAME 7 {"GAME", V_GAME, NO_OPTIONS | EXPR }, #define V_RETRIES 8 {"RETRIES", V_RETRIES, NO_OPTIONS }, #define V_IPADDR 9 {"IPADDR", V_IPADDR, NO_OPTIONS }, #define V_PORT 10 {"PORT", V_PORT, NO_OPTIONS }, #define V_ARG 11 {"ARG", V_ARG, NO_OPTIONS }, #define V_QSTATURL 12 {"QSTATURL", V_QSTATURL, NO_OPTIONS }, #define V_QSTATVERSION 13 {"QSTATVERSION", V_QSTATVERSION, NO_OPTIONS }, #define V_QSTATAUTHOR 14 {"QSTATAUTHOR", V_QSTATAUTHOR, NO_OPTIONS }, #define V_QSTATAUTHOREMAIL 15 {"QSTATAUTHOREMAIL", V_QSTATAUTHOREMAIL, NO_OPTIONS }, #define V_TYPE 16 {"TYPE", V_TYPE, NO_OPTIONS }, #define V_RULE 17 {"RULE", V_RULE, OPTIONS_OK | EXPR }, #define V_ALLRULES 18 {"ALLRULES", V_ALLRULES, NO_OPTIONS }, #define V_PLAYERTEMPLATE 19 {"PLAYERTEMPLATE", V_PLAYERTEMPLATE, NO_OPTIONS }, #define V_PLAYERNAME 20 {"PLAYERNAME", V_PLAYERNAME, NO_OPTIONS }, #define V_FRAGS 21 {"FRAGS", V_FRAGS, NO_OPTIONS }, #define V_PLAYERPING 22 {"PLAYERPING", V_PLAYERPING, NO_OPTIONS }, #define V_CONNECTTIME 23 {"CONNECTTIME", V_CONNECTTIME, NO_OPTIONS }, #define V_SKIN 24 {"SKIN", V_SKIN, NO_OPTIONS }, #define V_SHIRTCOLOR 25 {"SHIRTCOLOR", V_SHIRTCOLOR, NO_OPTIONS }, #define V_PANTSCOLOR 26 {"PANTSCOLOR", V_PANTSCOLOR, NO_OPTIONS }, #define V_PLAYERIP 27 {"PLAYERIP", V_PLAYERIP, NO_OPTIONS }, #define V_IF 28 {"IF", V_IF, OPTIONS_OK }, #define V_ENDIF 29 {"ENDIF", V_ENDIF, NO_OPTIONS }, #define V_HTML 35 {"HTML", V_HTML, NO_OPTIONS }, #define V_FLAG 36 {"FLAG", V_FLAG, OPTIONS_OK | EXPR }, #define V_UP 37 {"UP", V_UP, NO_OPTIONS | EXPR }, #define V_DOWN 38 {"DOWN", V_DOWN, NO_OPTIONS | EXPR }, #define V_IFNOT 39 {"IFNOT", V_IFNOT, OPTIONS_OK }, #define V_TIMEOUT 40 {"TIMEOUT", V_TIMEOUT, NO_OPTIONS | EXPR }, #define V_NOW 41 {"NOW", V_NOW, NO_OPTIONS }, #define V_TOTALSERVERS 42 {"TOTALSERVERS", V_TOTALSERVERS, NO_OPTIONS }, #define V_TOTALUP 43 {"TOTALUP", V_TOTALUP, NO_OPTIONS }, #define V_TOTALNOTUP 44 {"TOTALNOTUP", V_TOTALNOTUP, NO_OPTIONS }, #define V_TOTALPLAYERS 45 {"TOTALPLAYERS", V_TOTALPLAYERS, NO_OPTIONS }, #define V_TOTALMAXPLAYERS 46 {"TOTALMAXPLAYERS", V_TOTALMAXPLAYERS, NO_OPTIONS }, #define V_TEAMNUM 49 {"TEAMNUM", V_TEAMNUM, NO_OPTIONS }, #define V_BACKSLASH 50 {"\\", V_BACKSLASH, NO_OPTIONS }, #define V_HOSTNOTFOUND 51 {"HOSTNOTFOUND", V_HOSTNOTFOUND, NO_OPTIONS | EXPR }, #define V_MESH 52 {"MESH", V_MESH, NO_OPTIONS }, #define V_ISEMPTY 56 {"ISEMPTY", V_ISEMPTY, NO_OPTIONS | EXPR }, #define V_ISFULL 57 {"ISFULL", V_ISFULL, NO_OPTIONS | EXPR }, #define V_PACKETLOSS 58 {"PACKETLOSS", V_PACKETLOSS, NO_OPTIONS }, #define V_ISTEAM 59 {"ISTEAM", V_ISTEAM, NO_OPTIONS | EXPR }, #define V_TEAMNAME 60 {"TEAMNAME", V_TEAMNAME, NO_OPTIONS }, #define V_DEFAULTTYPE 61 {"DEFAULTTYPE", V_DEFAULTTYPE, NO_OPTIONS }, #define V_TYPESTRING 62 {"TYPESTRING", V_TYPESTRING, NO_OPTIONS }, #define V_FACE 63 {"FACE", V_FACE, NO_OPTIONS }, #define V_SOLDIEROFFORTUNE 64 {"SOLDIEROFFORTUNE", V_SOLDIEROFFORTUNE, NO_OPTIONS }, #define V_COLORNUMBERS 65 {"COLORNUMBERS", V_COLORNUMBERS, NO_OPTIONS }, #define V_COLORNAMES 66 {"COLORNAMES", V_COLORNAMES, NO_OPTIONS }, #define V_COLORRGB 67 {"COLORRGB", V_COLORRGB, NO_OPTIONS }, #define V_TIMESECONDS 68 {"TIMESECONDS", V_TIMESECONDS, NO_OPTIONS }, #define V_TIMECLOCK 69 {"TIMECLOCK", V_TIMECLOCK, NO_OPTIONS }, #define V_TIMESTOPWATCH 70 {"TIMESTOPWATCH", V_TIMESTOPWATCH, NO_OPTIONS }, #define V_NOWINT 71 {"NOWINT", V_NOWINT, NO_OPTIONS }, #define V_ISMASTER 72 {"ISMASTER", V_ISMASTER, NO_OPTIONS | EXPR }, #define V_HTMLPLAYERNAME 73 {"HTMLPLAYERNAME", V_HTMLPLAYERNAME, NO_OPTIONS }, #define V_ISBOT 74 {"ISBOT", V_ISBOT, NO_OPTIONS | EXPR }, #define V_ISALIAS 75 {"ISALIAS", V_ISALIAS, NO_OPTIONS | EXPR }, #define V_TRIBETAG 76 {"TRIBETAG", V_TRIBETAG, NO_OPTIONS | EXPR }, #define V_CLEARNEWLINES 77 {"CLEARNEWLINES", V_CLEARNEWLINES, NO_OPTIONS }, #define V_GAMETYPE 78 {"GAMETYPE", V_GAMETYPE, NO_OPTIONS }, #define V_DEATHS 79 {"DEATHS", V_DEATHS, NO_OPTIONS | EXPR }, #define V_TYPEPREFIX 80 {"TYPEPREFIX", V_TYPEPREFIX, NO_OPTIONS }, #define V_RULENAMESPACES 81 {"RULENAMESPACES", V_RULENAMESPACES, NO_OPTIONS }, #define V_RULETEMPLATE 82 {"RULETEMPLATE", V_RULETEMPLATE, NO_OPTIONS }, #define V_RULENAME 83 {"RULENAME", V_RULENAME, OPTIONS_OK | EXPR }, #define V_RULEVALUE 84 {"RULEVALUE", V_RULEVALUE, OPTIONS_OK | EXPR }, #define V_PLAYERSTATID 85 {"PLAYERSTATID", V_PLAYERSTATID, NO_OPTIONS }, #define V_PLAYERLEVEL 86 {"PLAYERLEVEL", V_PLAYERLEVEL, NO_OPTIONS }, #define V_TOTALUTILIZATION 87 {"TOTALUTILIZATION", V_TOTALUTILIZATION, NO_OPTIONS }, #define V_SCORE 88 {"SCORE", V_SCORE, NO_OPTIONS }, }; int read_qserver_template( char *filename) { return read_template( filename, &server_template); } int read_rule_template( char *filename) { return read_template( filename, &rule_template); } int read_header_template( char *filename) { return read_template( filename, &header_template); } int read_trailer_template( char *filename) { return read_template( filename, &trailer_template); } int read_player_template( char *filename) { return read_template( filename, &player_template); } STATIC int read_template( char *filename, char **template_text) { FILE *file; int length, rc; file= fopen( filename, "r"); if ( file == NULL) { perror( filename); return -1; } fseek( file, 0, SEEK_END); length= ftell( file); fseek( file, 0, SEEK_SET); *template_text= (char*)malloc( length+1); rc= fread( *template_text, 1, length, file); if ( rc == 0 && length > 0) { perror( filename); fclose( file); free( *template_text); *template_text= NULL; return -1; } (*template_text)[rc]= '\0'; return 0; } int have_server_template() { return server_template != NULL; } int have_header_template() { return header_template != NULL; } int have_trailer_template() { return trailer_template != NULL; } void template_display_server( struct qserver *server) { char *t= server_template; int var, varlen; if_level= 0; if_skip= 0; for ( ; *t; t++) { if ( *t != VARIABLE_CHAR) { if ( ! if_skip) putc( *t, OF); continue; } var= parse_var( t, &varlen); if ( var == -1) { if ( ! if_skip) putc( VARIABLE_CHAR, OF); continue; } if ( var == V_BACKSLASH) { t+= 2; if ( *t == '\r') { if ( *++t == '\n') t++; } else if ( *t == '\n') t++; t--; continue; } if ( (var == V_IF || var == V_IFNOT) && variable_option != NULL) { int truth= (var==V_IF)?1:0; if ( !if_skip && is_true( server, NULL, NULL, variable_option) == truth) if_level++; else if_skip++; } else if ( var == V_ENDIF) { if ( if_skip) if_skip--; else if ( if_level) if_level--; } if ( ! if_skip) display_server_var( server, var); t+= varlen; } } void template_display_players( struct qserver *server) { struct player *player; for ( player= server->players; player != NULL; player= player->next) template_display_player( server, player); } void template_display_player( struct qserver *server, struct player *player) { char *t= player_template; int var, varlen; if ( player_template == NULL) return; if_level= 0; if_skip= 0; for ( ; *t; t++) { if ( *t != VARIABLE_CHAR) { if ( ! if_skip) putc( *t, OF); continue; } var= parse_var( t, &varlen); if ( var == -1) { if ( ! if_skip) putc( VARIABLE_CHAR, OF); continue; } if ( var == V_BACKSLASH) { t+= 2; if ( *t == '\r') { if ( *++t == '\n') t++; } else if ( *t == '\n') t++; t--; continue; } if ( (var == V_IF || var == V_IFNOT) && variable_option != NULL) { int truth= (var==V_IF)?1:0; if ( !if_skip && is_true( server, player, NULL, variable_option) == truth) if_level++; else if_skip++; } else if ( var == V_ENDIF) { if ( if_skip) if_skip--; else if ( if_level) if_level--; } if ( ! if_skip) display_player_var( player, var, server); t+= varlen; } } void template_display_rules( struct qserver *server) { struct rule *rule; for ( rule= server->rules; rule != NULL; rule= rule->next) template_display_rule( server, rule); } void template_display_rule( struct qserver *server, struct rule *rule) { char *t= rule_template; int var, varlen; if ( rule_template == NULL) return; if_level= 0; if_skip= 0; for ( ; *t; t++) { if ( *t != VARIABLE_CHAR) { if ( ! if_skip) putc( *t, OF); continue; } var= parse_var( t, &varlen); if ( var == -1) { if ( ! if_skip) putc( VARIABLE_CHAR, OF); continue; } if ( var == V_BACKSLASH) { t+= 2; if ( *t == '\r') { if ( *++t == '\n') t++; } else if ( *t == '\n') t++; t--; continue; } if ( (var == V_IF || var == V_IFNOT) && variable_option != NULL) { int truth= (var==V_IF)?1:0; if ( !if_skip && is_true( server, NULL, rule, variable_option) == truth) if_level++; else if_skip++; } else if ( var == V_ENDIF) { if ( if_skip) if_skip--; else if ( if_level) if_level--; } if ( ! if_skip) display_rule_var( rule, var, server); t+= varlen; } } void template_display_header() { char *t= header_template; int var, varlen; if_level= 0; if_skip= 0; for ( ; *t; t++) { if ( *t != VARIABLE_CHAR) { putc( *t, OF); continue; } var= parse_var( t, &varlen); if ( var == -1) { putc( VARIABLE_CHAR, OF); continue; } if ( var == V_BACKSLASH) { t+= 2; if ( *t == '\r') { if ( *++t == '\n') t++; } else if ( *t == '\n') t++; t--; continue; } display_generic_var( var); t+= varlen; } } void template_display_trailer() { char *t= trailer_template; int var, varlen; if_level= 0; if_skip= 0; for ( ; *t; t++) { if ( *t != VARIABLE_CHAR) { putc( *t, OF); continue; } var= parse_var( t, &varlen); if ( var == -1) { putc( VARIABLE_CHAR, OF); continue; } if ( var == V_BACKSLASH) { t+= 2; if ( *t == '\r') { if ( *++t == '\n') t++; } else if ( *t == '\n') t++; t--; continue; } display_generic_var( var); t+= varlen; } } STATIC void display_server_var( struct qserver *server, int var) { char *game; int full_data= 1; if ( server->server_name == DOWN || server->server_name == TIMEOUT || server->server_name == SYSERROR || server->error != NULL || server->type->master) full_data= 0; switch( var) { case V_HOSTNAME: fputs( (hostname_lookup) ? server->host_name : server->arg, OF); break; case V_SERVERNAME: fputs( xform_name( server->server_name, server), OF); break; case V_PING: if ( server->server_name != TIMEOUT && server->server_name != DOWN && server->server_name != HOSTNOTFOUND && server->server_name != SYSERROR) fprintf( OF, "%d", server->n_requests ? server->ping_total/server->n_requests : 999); break; case V_PLAYERS: if ( full_data) fprintf( OF, "%d", server->num_players); break; case V_MAXPLAYERS: if ( full_data) fprintf( OF, "%d", server->max_players); break; case V_MAP: if ( full_data) fputs( (server->map_name) ? server->map_name : "?", OF); break; case V_GAME: if ( full_data) { game= get_qw_game( server); fputs( (game) ? game : "", OF); } break; case V_GAMETYPE: { struct rule *rule; for ( rule= server->rules; rule != NULL; rule= rule->next) if ( strcasecmp( rule->name, "g_gametype") == 0) break; if ( rule != NULL) { switch ( atoi(rule->value)) { case 0: fputs( "Free For All", OF); break; case 1: fputs( "Tournament", OF); break; case 3: fputs( "Team Deathmatch", OF); break; case 4: fputs( "Capture the Flag", OF); break; case 5: fputs( "Fortress or OSP", OF); break; case 6: fputs( "Capture and Hold", OF); break; case 8: fputs( "Arena", OF); break; default: fputs( "?", OF); break; } } } break; case V_RETRIES: if ( server->server_name != TIMEOUT && server->server_name != DOWN && server->server_name != HOSTNOTFOUND) fprintf( OF, "%d", server->n_retries); break; case V_IPADDR: { unsigned int ipaddr= ntohl(server->ipaddr); fprintf( OF, "%u.%u.%u.%u", (ipaddr>>24)&0xff, (ipaddr>>16)&0xff, (ipaddr>>8)&0xff, ipaddr&0xff); } break; case V_PORT: fprintf( OF, "%hu", server->port); break; case V_ARG: fputs( server->arg, OF); break; case V_TYPE: fputs( server->type->game_name, OF); break; case V_TYPESTRING: fputs( server->type->type_string, OF); break; case V_TYPEPREFIX: fputs( server->type->type_prefix, OF); break; case V_RULE: { struct rule *rule; if ( variable_option == NULL) break; for ( rule= server->rules; rule != NULL; rule= rule->next) if ( strcasecmp( rule->name, variable_option) == 0) display_string( rule->value); } break; case V_ALLRULES: { struct rule *rule; for ( rule= server->rules; rule != NULL; rule= rule->next) { if ( rule != server->rules) fputs( ", ", OF); display_string( rule->name); putc( '=', OF); display_string( rule->value); } } break; case V_PLAYERTEMPLATE: if_level_save= if_level; if_skip_save= if_skip; template_display_players( server); if_level= if_level_save; if_skip= if_skip_save; break; case V_RULETEMPLATE: if_level_save= if_level; if_skip_save= if_skip; template_display_rules( server); if_level= if_level_save; if_skip= if_skip_save; break; default: display_generic_var( var); } } STATIC void display_player_var( struct player *player, int var, struct qserver *server) { switch( var) { case V_PLAYERNAME: fputs( xform_name( player->name, server), OF); break; case V_HTMLPLAYERNAME: { int save_html_names= html_names; int save_hex_player_names= hex_player_names; html_names= 1; hex_player_names= 0; fputs( xform_name( player->name, server), OF); html_names= save_html_names; hex_player_names= save_hex_player_names; } break; case V_TRIBETAG: fputs( xform_name( player->tribe_tag, server), OF); break; case V_FRAGS: fprintf( OF, "%d", player->frags); break; case V_SCORE: fprintf( OF, "%d", player->score); break; case V_DEATHS: fprintf( OF, "%d", player->deaths); break; case V_PLAYERPING: fprintf( OF, "%d", player->ping); break; case V_CONNECTTIME: fputs( play_time(player->connect_time,0), OF); break; case V_SKIN: display_string( player->skin); break; case V_MESH: display_string( player->mesh); break; case V_FACE: display_string( player->face); break; case V_SHIRTCOLOR: if ( color_names) fputs( quake_color(player->shirt_color), OF); else fprintf( OF, "%d", player->shirt_color); break; case V_PANTSCOLOR: if ( color_names) fputs( quake_color(player->pants_color), OF); else fprintf( OF, "%d", player->pants_color); break; case V_PLAYERIP: if ( player->address) fputs( player->address, OF); break; case V_TEAMNUM: fprintf( OF, "%d", player->team); break; case V_PACKETLOSS: fprintf( OF, "%d", player->packet_loss); break; case V_TEAMNAME: if ( player->team_name) fprintf( OF, "%s", player->team_name); break; case V_COLORNUMBERS: color_names= 0; break; case V_COLORNAMES: color_names= 1; break; case V_COLORRGB: color_names= 2; break; case V_TIMESECONDS: time_format= SECONDS; break; case V_TIMECLOCK: time_format= CLOCK_TIME; break; case V_TIMESTOPWATCH: time_format= STOPWATCH_TIME; break; case V_PLAYERSTATID: case V_PLAYERLEVEL: fprintf( OF, "%u", player->ship); break; default: display_server_var( server, var); } } STATIC void display_rule_var( struct rule *rule, int var, struct qserver *server) { switch( var) { case V_RULENAME: fputs( rule->name, OF); break; case V_RULEVALUE: fputs( xform_name( rule->value, server), OF); break; default: display_server_var( server, var); } } STATIC void display_generic_var( int var) { switch( var) { case V_QSTATURL: fputs( "http://www.qstat.org", OF); break; case V_QSTATVERSION: fputs( qstat_version, OF); break; case V_QSTATAUTHOR: fputs( "Steve Jankowski", OF); break; case V_QSTATAUTHOREMAIL: fputs( "steve@qstat.org", OF); break; case V_HTML: html_mode^= 1; if ( html_mode && html_names == -1) html_names= 1; break; case V_CLEARNEWLINES: clear_newlines_mode^= 1; break; case V_NOW: { time_t now= time(0); char *now_string= ctime(&now); now_string[strlen(now_string)-1]= '\0'; fputs( now_string, OF); break; } case V_NOWINT: fprintf( OF, "%u", (unsigned int)time(0)); break; case V_TOTALSERVERS: fprintf( OF, "%d", num_servers_total); break; case V_TOTALUP: fprintf( OF, "%d", num_servers_total - num_servers_timed_out - num_servers_down); break; case V_TOTALNOTUP: fprintf( OF, "%d", num_servers_timed_out + num_servers_down); break; case V_TOTALPLAYERS: fprintf( OF, "%d", num_players_total); break; case V_TOTALMAXPLAYERS: fprintf( OF, "%d", max_players_total); break; case V_TOTALUTILIZATION: fprintf( OF, "%.1f", (100.0 / max_players_total) * num_players_total); break; case V_DEFAULTTYPE: fprintf( OF, "%s", default_server_type->game_name); break; case V_RULENAMESPACES: rule_name_spaces^= 1; break; default: break; } } STATIC int parse_var( char *varname, int *varlen) { char *v= ++varname, *colon= NULL; int i, quote= 0; if ( variable_option != NULL) { free( variable_option); variable_option= NULL; } if ( *v == '(') { v++; varname++; quote++; } else if ( *v == '\\') { *varlen= 1; return V_BACKSLASH; } for ( ; *v; v++) if ( (!quote && !isalpha( (unsigned char)*v)) || (quote && (*v == ')' || *v == ':'))) break; if ( v-varname == 0) return -1; *varlen= v-varname; if ( *v == ':') colon= v; else if ( quote && *v == ')') v++; for ( i= 0; i < sizeof(variable_defs)/sizeof(struct vardef); i++) if ( strncasecmp( varname, variable_defs[i].var, *varlen) == 0 && *varlen == strlen(variable_defs[i].var)) { if ( colon != NULL && ((variable_defs[i].options & OPTIONS_OK) || quote)) { for ( v++; *v; v++) { if ( (!quote && !isalnum( (unsigned char)*v) && *v != '*' && *v != '_' && *v != '.' && (*v == ' ' && !rule_name_spaces)) || (quote==1 && *v == ')')) break; if ( *v == '(') quote++; else if ( *v == ')') quote--; } variable_option= (char*)malloc( v-colon+1); strncpy( variable_option, colon+1, v-colon-1); variable_option[v-colon-1]= '\0'; if ( quote && *v == ')') v++; } *varlen= v-varname+quote; return variable_defs[i].varcode; } return -1; } STATIC int is_true( struct qserver *server, struct player *player, struct rule *rule, char *expr) { int i, len = 0, arglen = 0; char *arg= NULL, *lparen, *rparen; server_type *t; if ( (lparen= strchr( expr, '(')) != NULL) { if ( (rparen= strchr( lparen, ')')) != NULL) { len= lparen - expr; arg= lparen + 1; arglen= rparen - lparen - 1; } } else len= strlen( expr); for ( i= 0; i < sizeof(variable_defs)/sizeof(struct vardef); i++) if ( strncasecmp( expr, variable_defs[i].var, len) == 0 && len == strlen( variable_defs[i].var)) { if ( !(variable_defs[i].options & EXPR)) { fprintf( stderr, "unsupported IF expression \"%s\"\n", expr); return 1; } switch ( variable_defs[i].varcode) { case V_GAME: { char *g= get_qw_game( server); if ( g == NULL || *g == '\0') return 0; else return 1; } case V_PLAYERS: return server->num_players > 0; case V_ISEMPTY: return server->num_players == 0; case V_ISFULL: return server->max_players ? server->num_players >= server->max_players : 0; case V_ISTEAM: return player ? player->number == TRIBES_TEAM : 0; case V_ISBOT: return player ? player->type_flag == PLAYER_TYPE_BOT : 0; case V_ISALIAS: return player ? player->type_flag == PLAYER_TYPE_ALIAS : 0; case V_TRIBETAG: return player ? player->tribe_tag != NULL : 0; case V_RULE: { struct rule *rule; if ( arg == NULL) return 0; for ( rule= server->rules; rule != NULL; rule= rule->next) if ( strncasecmp( rule->name, arg, arglen) == 0 && strlen( rule->name) == arglen) return 1; return 0; } case V_RULENAME: { if ( rule && arg && strncmp( rule->name, arg, arglen) == 0 && strlen( rule->name) == arglen) return 1; else return 0; } case V_RULEVALUE: { if ( rule && arg && strncmp( rule->value, arg, arglen) == 0 && strlen( rule->value) == arglen) return 1; else return 0; } case V_FLAG: { if ( strncmp( "-H", arg, arglen) == 0) return hostname_lookup; if ( strncmp( "-P", arg, arglen) == 0) return get_player_info; if ( strncmp( "-R", arg, arglen) == 0) return get_server_rules; return 0; } case V_UP: return server->server_name != DOWN && server->server_name != TIMEOUT && server->server_name != HOSTNOTFOUND; case V_DOWN: return server->server_name == DOWN; case V_TIMEOUT: return server->server_name == TIMEOUT; case V_HOSTNOTFOUND: return server->server_name == HOSTNOTFOUND; case V_ISMASTER: return (server->type->id & MASTER_SERVER) ? 1 : 0; case V_DEATHS: return player->deaths; default: return 0; } } t= &types[0]; for ( ; t->id; t++) if ( strncasecmp( expr, t->template_var, len) == 0) return server->type->id == t->id; fprintf( stderr, "bad IF expression \"%s\"\n", expr); return 0; } STATIC void display_string( char *str) { if ( str == NULL) return; if ( ! html_mode && ! clear_newlines_mode) { fputs( str, OF); return; } if ( html_mode && ! clear_newlines_mode) { for ( ; *str; str++) switch ( *str) { case '<': fputs( "<", OF); break; case '>': fputs( ">", OF); break; case '&': fputs( "&", OF); break; case '\n': fputs( "NEWLINE", OF); default: putc( *str, OF); } return; } if ( ! html_mode && clear_newlines_mode) { for ( ; *str; str++) switch ( *str) { case '\n': case '\r': putc( ' ', OF); break; default: putc( *str, OF); } return; } for ( ; *str; str++) switch ( *str) { case '<': fputs( "<", OF); break; case '>': fputs( ">", OF); break; case '&': fputs( "&", OF); break; case '\n': case '\r': putc( ' ', OF); break; default: putc( *str, OF); } } qstat-2.11/COMPILE.txt0000644002404400000620000000077510151147310011341 00000000000000Compilation instructions for QStat ---------------------------------- Linux and other GNU systems --------------------------- ./configure && make to install qstat run "make install" to see which configuration parameters can be tweaked, run "./configure --help" If you want to compile from CVS you need to first install autoconf and automake, then run ./autogen.sh. WINDOWS ------- nmake /f Makefile.noauto windows SOLARIS ------- make -f Makefile.noauto solaris HPUX ---- make -f Makefile.noauto hpux