diff --git a/xqf/ChangeLog b/xqf/ChangeLog index 7d0eeed..d43e696 100644 --- a/xqf/ChangeLog +++ b/xqf/ChangeLog @@ -1,3 +1,9 @@ +Nov 17, 2004: Ludwig Nussel +- Use non-blocking socket for rcon +- Add small timeout to catch replies with multiple packets in xqf-rcon +- Make xqf-recon optionally read the rcon passwort from the environment + variable XQF_RCON_PASSWORD + Nov 13, 2004: Ludwig Nussel - update German translation - add wolfmp as main mod of rtcw (reportet by Ruediger Meier) diff --git a/xqf/src/Makefile.am b/xqf/src/Makefile.am index 65b1bda..df606aa 100644 --- a/xqf/src/Makefile.am +++ b/xqf/src/Makefile.am @@ -24,7 +24,10 @@ EXTRA_PROGRAMS = xqf-rcon gamesxml2c xqf_LDADD = @INTLLIBS@ $(top_builddir)/src/zip/libunzip.a $(top_builddir)/src/tga/libtga.a $(GTK_LIBS) $(GDK_PIXBUF_LIBS) -lz $(GEOIP_LIB) @PACKAGE_LIBS@ xqf_rcon_LDADD = @INTLLIBS@ $(GLIB_LIBS) $(XQFRCON_LIBS) @PACKAGE_LIBS@ -xqf_rcon_SOURCES = rcon.c debug.c +xqf_rcon_SOURCES = \ + rcon.c rcon.h \ + debug.c debug.h \ + utils.c utils.h xqf_rcon_CFLAGS = -DRCON_STANDALONE $(GLIB_CFLAGS) $(OLD_GTK_SUPPORT) xqf_SOURCES = \ diff --git a/xqf/src/dns.c b/xqf/src/dns.c index 40b9d79..202ebc2 100644 --- a/xqf/src/dns.c +++ b/xqf/src/dns.c @@ -25,7 +25,6 @@ #include /* memset, strdup, strlen, strcmp */ #include /* waitpid */ #include /* errno */ -#include /* fcntl */ #include /* select */ #include /* struct in_addr, inet_aton, inet_ntoa */ #include /* struct in_addr, inet_aton, inet_ntoa */ @@ -122,15 +121,6 @@ static int failed (char *name, char *arg) { } -static void set_nonblock (int fd) { - int flags; - - flags = fcntl (fd, F_GETFL, 0); - if (flags < 0 || fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0) - failed ("fcntl", NULL); -} - - static void master_sigchld_handler (int signum) { int pid; int status; @@ -429,7 +419,8 @@ static int fork_worker (int n, char *str) { dns_workers[n].input = malloc (sizeof (struct dns_stream)); dns_workers[n].input->fd = fdset[0]; - set_nonblock (dns_workers[n].input->fd); + if(set_nonblock (dns_workers[n].input->fd) == -1) + failed ("fcntl", NULL); dns_workers[n].input->pos = 0; dns_workers[n].input->parse = worker_parse_callback; @@ -580,7 +571,8 @@ static void dns_master_init (void) { dns_master_input = malloc (sizeof (struct dns_stream)); dns_master_input->fd = 0; /* stdin */ - set_nonblock (dns_master_input->fd); + if(set_nonblock (dns_master_input->fd) == -1) + failed ("fcntl", NULL); dns_master_input->pos = 0; dns_master_input->parse = master_parse_callback; @@ -724,7 +716,8 @@ int dns_spawn_helper (void) { dns_helper.input = malloc (sizeof (struct dns_stream)); dns_helper.input->fd = fdset1[0]; - set_nonblock (dns_helper.input->fd); + if(set_nonblock (dns_helper.input->fd) == -1) + failed("fcntl", NULL); dns_helper.pid = pid; diff --git a/xqf/src/rcon.c b/xqf/src/rcon.c index f4b2a11..932bd33 100644 --- a/xqf/src/rcon.c +++ b/xqf/src/rcon.c @@ -42,13 +42,13 @@ #include "i18n.h" #include "xqf.h" +#include "utils.h" #ifndef RCON_STANDALONE #include "xqf-ui.h" #include "srv-prop.h" #include "srv-list.h" #include "game.h" #include "dialogs.h" -#include "utils.h" #include "history.h" #include "config.h" #endif @@ -100,6 +100,20 @@ static void rcon_print (char *fmt, ...) { } +static int wait_read_timeout(int fd, long sec, long usec) +{ + fd_set rfds; + struct timeval tv; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = sec; + tv.tv_usec = usec; + + return select(rcon_fd+1, &rfds, NULL, NULL, &tv); +} + static int open_connection (struct in_addr *ip, unsigned short port) { struct sockaddr_in addr; int fd; @@ -159,25 +173,11 @@ static int rcon_send(const char* cmd) bufsize = strlen(buf)+1; send (rcon_fd, buf, bufsize, 0); + if (wait_read_timeout(rcon_fd, 5, 0) <= 0) { - fd_set rfds; - struct timeval tv; - int retval; - - FD_ZERO(&rfds); - FD_SET(rcon_fd, &rfds); - /* Wait up to five seconds. */ - tv.tv_sec = 5; - tv.tv_usec = 0; - - retval = select(rcon_fd+1, &rfds, NULL, NULL, &tv); - - if (!retval) - { - rcon_print ("*** timeout waiting for challenge\n"); - errno = ETIMEDOUT; - return -1; - } + rcon_print ("*** timeout waiting for challenge\n"); + errno = ETIMEDOUT; + return -1; } size = recv (rcon_fd, cbuf, cbufsize, 0); @@ -315,16 +315,18 @@ static char* msg_terminate (char *msg, int size) static char* rcon_receive() { char *msg = "\n"; - int size; + ssize_t size; if (!packet) packet = g_malloc (PACKET_MAXSIZE); size = recv (rcon_fd, packet, PACKET_MAXSIZE, 0); - if (size < 0) { - failed("recv"); + if (size < 0) + { + if(errno != EWOULDBLOCK) failed("recv"); } - else { + else + { switch (rcon_servertype) { case QW_SERVER: @@ -460,6 +462,9 @@ void rcon_dialog (const struct server *s, const char *passwd) { if (rcon_fd < 0) return; + if(set_nonblock(rcon_fd) == -1) + failed("fcntl"); + assemble_server_address (srv, 256, s); g_snprintf (buf, 256, "Remote Console [%s]", srv); @@ -713,12 +718,23 @@ int main(int argc, char* argv[]) { return 1; } - while(!buf || !*buf) + + if(set_nonblock(rcon_fd) == -1) + failed("fcntl"); + + if(getenv("XQF_RCON_PASSWORD")) { - // translator: readline prompt - buf = readline(_("Password: ")); + rcon_password = g_strdup(getenv("XQF_RCON_PASSWORD")); + } + else + { + while(!buf || !*buf) + { + // translator: readline prompt + buf = readline(_("Password: ")); + } + rcon_password = g_strdup(buf); } - rcon_password = g_strdup(buf); buf = readline(prompt); while(buf) @@ -729,26 +745,17 @@ int main(int argc, char* argv[]) } else { + if (wait_read_timeout(rcon_fd, 5, 0) <= 0) { - fd_set rfds; - struct timeval tv; - int retval; - - FD_ZERO(&rfds); - FD_SET(rcon_fd, &rfds); - /* Wait up to five seconds. */ - tv.tv_sec = 5; - tv.tv_usec = 0; - - retval = select(rcon_fd+1, &rfds, NULL, NULL, &tv); - - if (!retval) + printf ("*** timeout waiting for reply\n"); + } + else + { + char* msg; + /* see if more packets arrive within a short interval */ + while(wait_read_timeout(rcon_fd, 0, 50000) > 0) { - printf ("*** timeout waiting for reply\n"); - } - else - { - char* msg = rcon_receive(); + msg = rcon_receive(); printf("%s", msg); g_free(msg); } diff --git a/xqf/src/stat.c b/xqf/src/stat.c index 28a0130..91e6f23 100644 --- a/xqf/src/stat.c +++ b/xqf/src/stat.c @@ -24,8 +24,8 @@ #include /* strtol */ #include /* read, close, fork, pipe, exec, fcntl, _exit */ /* getpid, unlink, write */ -#include /* errno */ #include /* fcntl */ +#include /* errno */ #include /* kill, signal... */ #include /* time */ #include /* inet_ntoa */ @@ -955,18 +955,6 @@ static void stat_servers_input_callback (struct stat_conn *conn, int fd, } } - -static void set_nonblock (int fd) { - int flags; - - flags = fcntl (fd, F_GETFL, 0); - if (flags < 0 || fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0) { - failed ("fcntl", NULL); - return; - } -} - - /** return connection to local file */ @@ -1052,7 +1040,8 @@ static struct stat_conn *start_qstat (struct stat_job *job, char *argv[], if (pid) { /* parent */ close (pipefds[1]); - set_nonblock (pipefds[0]); + if(set_nonblock (pipefds[0]) == -1) + failed("fcntl", NULL); conn = g_malloc (sizeof (struct stat_conn)); conn->buf = g_malloc (BUFFER_MINSIZE); diff --git a/xqf/src/utils.c b/xqf/src/utils.c index e160598..ace8bb9 100644 --- a/xqf/src/utils.c +++ b/xqf/src/utils.c @@ -29,6 +29,7 @@ #include /* tolower */ #include /* stat */ #include /* access */ +#include /* fcntl */ #include @@ -902,3 +903,15 @@ char* timet2string(const time_t* t) return strdup(str); } + +int set_nonblock (int fd) +{ + int flags; + + flags = fcntl (fd, F_GETFL, 0); + if (flags < 0 || fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0) + { + return -1; + } + return 0; +} diff --git a/xqf/src/utils.h b/xqf/src/utils.h index 07da50b..ca06e7c 100644 --- a/xqf/src/utils.h +++ b/xqf/src/utils.h @@ -116,4 +116,10 @@ GSList* slist_sort_remove_dups(GSList* list, GCompareFunc compare_func, void (*u */ char* timet2string(const time_t* t); +/** set fd non blocking + @param fd the file descriptor + @return zero on success, -1 on failure + */ +int set_nonblock (int fd); + #endif /* __UTILS_H__ */ diff --git a/xqf/src/xqf.c b/xqf/src/xqf.c index 4285515..8056b67 100644 --- a/xqf/src/xqf.c +++ b/xqf/src/xqf.c @@ -34,7 +34,6 @@ #include #include #include -#include #include /* kill, ... */ #include @@ -476,15 +475,12 @@ int check_qstat_version() char* cmd[] = {QSTAT_EXEC,NULL}; - int flags; - conn.fd = start_prog_and_return_fd(cmd,&conn.pid); if (conn.fd<0||conn.pid<=0) return FALSE; - flags = fcntl (conn.fd, F_GETFL, 0); - if (flags < 0 || fcntl (conn.fd, F_SETFL, flags | O_NONBLOCK) < 0) + if (set_nonblock(conn.fd) == -1) { xqf_error("fcntl failed: %s", strerror(errno)); return -1;