/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure
*
* This program is free software; you can redistribute it and/or modify
* ---
*
* expect.c: Read from the socket, expecting to see a particular code.
- *
+ *
* Known contributors to this file:
* Steve McClure, 1998
+ * Markus Armbruster, 2007
*/
#include <config.h>
#include <ctype.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
-#endif
#include "misc.h"
+#include "proto.h"
int
recvline(int s, char *buf)
{
- int size;
- char *p;
- int n;
- int newline;
- char *ptr;
- int cc;
+ int sz = 1024;
+ char *bp;
+ char ch;
+ ssize_t n;
- size = 1024;
-#ifndef _WIN32
- (void)alarm(30);
-#endif
- ptr = buf;
- n = recv(s, ptr, size, MSG_PEEK);
- if (n <= 0) {
-#ifdef _WIN32
- errno = WSAGetLastError();
-#endif
- perror("recv");
- return 0;
- }
- size -= n;
- buf[n] = '\0';
- if ((p = strchr(ptr, '\n')) == NULL) {
- do {
-#ifndef _WIN32
- cc = read(s, ptr, n);
-#else
- cc = recv(s, ptr, n, 0);
-#endif
- if (cc < 0) {
-#ifdef _WIN32
- errno = WSAGetLastError();
-#endif
- perror("expect: read");
- return 0;
- }
- if (cc != n) {
- fprintf(stderr, "expect: short read (%d not %d)\n", cc, n);
- return 0;
+ bp = buf;
+ for (;;) {
+ n = read(s, &ch, 1);
+ if (n < 0) {
+ if (errno != EINTR) {
+ perror("read");
+ exit(1);
}
- ptr += n;
- if ((n = recv(s, ptr, size, MSG_PEEK)) <= 0) {
-#ifdef _WIN32
- errno = WSAGetLastError();
-#endif
- perror("recv");
- return 0;
- }
- size -= n;
- ptr[n] = '\0';
- } while ((p = strchr(ptr, '\n')) == 0);
- newline = 1 + p - buf;
- *p = 0;
- } else
- newline = 1 + p - ptr;
-#ifndef _WIN32
- cc = read(s, buf, newline);
-#else
- cc = recv(s, buf, newline, 0);
-#endif
- if (cc < 0) {
-#ifdef _WIN32
- errno = WSAGetLastError();
-#endif
- perror("expect: read #2");
- return 0;
- }
- if (cc != newline) {
- fprintf(stderr, "expect: short read #2 (%d not %d)\n",
- cc, newline);
- return 0;
+ continue;
+ }
+ if (n == 0)
+ return -1;
+ if (ch == '\n')
+ break;
+ if (bp < buf + sz - 2)
+ *bp++ = ch;
+ /* else silently truncate */
}
- buf[newline] = '\0';
-#ifndef _WIN32
- (void)alarm(0);
-#endif
- if (!isxdigit(buf[0]) || buf[1] != ' ') {
- fprintf(stderr, "Malformed line %s\n", buf);
- return 0;
+
+ *bp++ = ch;
+ *bp = 0;
+ return parseid(buf);
+}
+
+int
+parseid(char *line)
+{
+ char *end;
+ long id;
+
+ id = strtol(line, &end, 36);
+ if (end == line || *end != ' ') {
+ fprintf(stderr, "Malformed id in line %s", line);
+ id = -1;
}
- return strtol(buf, NULL, 16);
+ if (id > C_LAST)
+ id = -1;
+ return id;
}
int
expect(int s, int match, char *buf)
{
- int code = recvline(s, buf);
- return code == match;
+ return recvline(s, buf) == match;
}
void
sendcmd(int s, char *cmd, char *arg)
{
char buf[128];
- int cc;
+ char *p;
+ ssize_t n;
int len;
- (void)sprintf(buf, "%s %s\n", cmd, arg != NULL ? arg : "");
- len = strlen(buf);
-#ifndef _WIN32
- cc = write(s, buf, len);
-#else
- cc = send(s, buf, len, 0);
-#endif
- if (cc < 0) {
-#ifdef _WIN32
- errno = WSAGetLastError();
-#endif
- perror("sendcmd: write");
+ len = snprintf(buf, sizeof(buf), "%s %s\n",
+ cmd, arg != NULL ? arg : "");
+ if (len >= (int)sizeof(buf)) {
+ fprintf(stderr, "%s too long\n", cmd);
+ exit(1);
}
- if (cc != len) {
- fprintf(stderr, "sendcmd: short write (%d not %d)\n", cc, len);
+ p = buf;
+ while (len > 0) {
+ n = write(s, buf, len);
+ if (n < 0) {
+ if (errno != EINTR) {
+ perror("sendcmd: write");
+ exit(1);
+ }
+ n = 0;
+ }
+ p += n;
+ len -= n;
}
}