]> git.pond.sub.org Git - empserver/blob - src/client/main.c
Import of Empire 4.2.12
[empserver] / src / client / main.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  main.c: client main function
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1986
32  *     Steve McClure, 1998
33  */
34
35 #ifdef _NTSDK
36 #undef _NTSDK
37 #endif
38
39 #include "misc.h"
40 #include "proto.h"
41 #include "queue.h"
42 #include "ioqueue.h"
43 #include "bit.h"
44
45 #include <stdio.h>
46 #ifndef _WIN32
47 #include <pwd.h>
48 #endif
49 #include <signal.h>
50 #include <errno.h>
51 #include <time.h>
52 #ifndef _WIN32
53 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <unistd.h>
56 #else
57 #include <windows.h>
58 #include <winsock.h>
59 #include <conio.h>
60 #endif
61
62 #ifdef _WIN32
63 HANDLE hStdIn;
64 #endif
65
66 extern int errno;
67
68 #define RETRY   3
69
70 int     interrupt;
71 int     sock;
72
73 void saveargv();
74 void getsose();
75 int hostport();
76 int hostaddr();
77 int hostconnect();
78 int login();
79 void ioq_init();
80 void io_init();
81 void bit_copy();
82 int handleintr();
83 int termio();
84 int serverio();
85 void servercmd();
86 void ioq_drain();
87
88
89 #ifdef _WIN32
90 s_char *
91 index(str, c)
92 s_char *str;
93 char c;
94 {
95         static s_char *p;
96
97         p = str;
98         while (p && *p) {
99                 if (*p == c)
100                         return (s_char *)p;
101                 p++;
102         }
103         return (s_char *)0;
104 }
105
106 bzero(ptr, size)
107 s_char *ptr;
108 int size;
109 {
110         int i;
111
112         for (i = 0; i < size; i++)
113                 ptr[i] = 0;
114 }
115
116 bcopy(src, dest, size)
117 unsigned char *src, *dest;
118 int size;
119 {
120         int i;
121         unsigned char *d = dest,
122                    *s = src;
123
124         for (i = 0; i < size; i++)
125                 *d++ = *s++;
126 }
127 #endif
128
129 int
130 main(ac, av)
131         int     ac;
132         s_char  *av[];
133 {
134 #ifdef _WIN32
135         WSADATA WsaData;
136         int err;
137         fd_set  readfds;
138         struct timeval tm;
139         INPUT_RECORD InpBuffer[10];
140         DWORD numevents;
141         DWORD stdinmode;
142         SECURITY_ATTRIBUTES security;
143         void intr(void);
144 #endif
145         extern  s_char *getenv();
146         extern  s_char empireport[];
147         extern  s_char empirehost[];
148         bit_fdmask mask;
149         bit_fdmask savemask;
150         struct  ioqueue server;
151         s_char  *argv[128];
152         int     i, j;
153         s_char  *ptr;
154         s_char  *auxout_fname;
155         FILE    *auxout_fp;
156 #ifndef _WIN32
157         struct  passwd *pwd;
158         void    intr();
159 #endif
160         struct  sockaddr_in sin;
161         int     n;
162         s_char  *cname;
163         s_char  *pname;
164         int     retry = 0;
165         int     send_kill = 0;
166
167 #ifdef _WIN32
168         err = WSAStartup (0x0101, &WsaData);
169         if (err == SOCKET_ERROR) {
170                 printf ("WSAStartup Failed\n");
171                 return FALSE;
172         }
173 #else
174         mask = bit_newfdmask();
175         savemask = bit_newfdmask();
176 #endif
177         bzero((s_char *)argv, sizeof(argv));
178         saveargv(ac, av, argv);
179         auxout_fname = 0;
180         auxout_fp = 0;
181         for (i = j = 1; i < ac; ++i) {
182                 ptr = argv[i];
183                 if (strcmp(ptr, "-2") == 0) {
184                         if (i + 1 >= ac) {
185                                 fprintf(stderr, "-2: Missing filename!\n");
186                                 exit(1);
187                         }
188                         auxout_fname = argv[i+1];
189                         ++i;
190                         continue;
191                 }
192                 else if (strcmp(ptr, "-k") == 0) {
193                         send_kill = 1;
194                         continue;
195                 }
196                 argv[j] = argv[i];
197                 ++j;
198         }
199         ac = j;
200         if (auxout_fname && (auxout_fp = fopen(auxout_fname, "a")) == NULL) {
201                 fprintf(stderr, "Unable to open %s for append\n", auxout_fname);
202                 exit(1);
203         }
204 #ifndef _WIN32
205         pwd = getpwuid(getuid());
206         if (pwd == NULL) {
207                 fprintf(stderr, "You don't exist.  Go away\n");
208                 exit(1);
209         }
210 #endif
211         getsose();
212         if (!hostport(getenv("EMPIREPORT"), &sin) &&
213             !hostport("empire", &sin) &&
214             !hostport(empireport, &sin)) {
215                 fprintf(stderr, "No empire port\n");
216                 exit(1);
217         }
218         if (!hostaddr(getenv("EMPIREHOST"), &sin) && 
219             !hostaddr(empirehost, &sin)) {
220                 fprintf(stderr, "No empire host\n");
221                 exit(1);
222         }
223         if ((sock = hostconnect(&sin)) < 0)
224                 exit(1);
225         cname = getenv("COUNTRY");
226         pname = getenv("PLAYER");
227         if (ac > 1)
228                 cname = argv[1];
229         if (ac > 2)
230                 pname = argv[2];
231 #ifndef _WIN32
232         if (!login(sock, pwd->pw_name, cname, pname, send_kill)) {
233 #else
234         if (!login(sock, "win-empcl2.8", cname, pname, send_kill)) {
235 #endif
236                 close(sock);
237                 exit(1);
238         }
239         ioq_init(&server, 2048);
240         io_init();
241         mask = bit_newfdmask();
242 #ifndef _WIN32
243         BIT_SETB(0, savemask);
244         BIT_SETB(sock, savemask);
245 #endif
246         (void) signal(SIGINT, intr);
247 #ifndef _WIN32
248         (void) signal(SIGPIPE, SIG_IGN);
249         while (BIT_ISSETB(sock, savemask)) {
250                 bit_copy(savemask, mask);
251                 n = select(sock+1, (fd_set *)mask, (fd_set *)0, (fd_set *)0,
252                         (struct timeval *)0);
253                 if (interrupt) {
254                         if (!handleintr(sock))
255                                 break;
256                         errno = 0;
257                 }
258                 if (n <= 0) {
259                         if (errno == EINTR) {
260                                 perror("select");
261                                 (void) close(sock);
262                                 BIT_CLRB(sock, savemask);
263                         }
264                 } else {
265                         if (BIT_ISSETB(0, mask)) {
266                                 if (!termio(0, sock, auxout_fp)) {
267                                         if (retry++ >= RETRY)  {
268                                                 BIT_CLRB(0, savemask);
269                                         }
270                                 } else {
271                                         retry = 0;
272                                 }
273                         }
274                         if (BIT_ISSETB(sock, mask)) {
275                                 if (!serverio(sock, &server))
276                                         BIT_CLRB(sock, savemask);
277                                 else
278                                         servercmd(&server, auxout_fp);
279                         }
280                 }
281         }
282 #else
283         tm.tv_sec = 0;
284         tm.tv_usec = 1000;
285
286         security.nLength = sizeof(SECURITY_ATTRIBUTES);
287         security.lpSecurityDescriptor = NULL;
288         security.bInheritHandle = TRUE;
289         hStdIn = CreateFile("CONIN$",
290                                                 GENERIC_READ | GENERIC_WRITE,
291                                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
292                                                 &security,
293                                                 OPEN_EXISTING,
294                                                 (DWORD)NULL,
295                                                 NULL);
296
297         if (hStdIn == INVALID_HANDLE_VALUE) {
298                 printf("Error getting hStdIn.\n");
299                 fflush(stdout);
300         }
301         err = GetConsoleMode(hStdIn, &stdinmode);
302         if (!err) {
303                 printf("Error getting console mode.\n");
304                 fflush(stdout);
305         }
306         stdinmode |= ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT;
307         err = SetConsoleMode(hStdIn, stdinmode);
308         if (!err) {
309                 printf("Error setting console mode.\n");
310                 fflush(stdout);
311         }
312         while (1) {
313                 FD_ZERO(&readfds);
314                 FD_SET(sock, &readfds);
315                 n = select(sock+1, &readfds, (fd_set *)0, (fd_set *)0,
316                                    (struct timeval *)&tm);
317                 if (n < 0) {
318                         if (errno == EINTR) {
319                                 errno = WSAGetLastError();
320                                 perror("select");
321                                 (void) close(sock);
322                                 break;
323                         }
324                 } else {
325                         if (WaitForSingleObject(hStdIn, 10) != WAIT_TIMEOUT) {
326                                 if (!termio(-1, sock, auxout_fp)) {
327                                         if (retry++ >= RETRY)  {
328                                                 ;
329                                         }
330                                 } else {
331                                         retry = 0;
332                                 }
333                                 FlushConsoleInputBuffer(hStdIn);
334                         }
335                         if (FD_ISSET(sock, &readfds)) {
336                                 if (!serverio(sock, &server))
337                                         break;
338                                 else
339                                         servercmd(&server, auxout_fp);
340                         }
341                 }
342         }
343         CloseHandle(hStdIn);
344 #endif
345         ioq_drain(&server);
346         (void) close(sock);
347         exit(0);
348         return 0; /* Shut the compiler up */
349 }
350
351 void
352 #ifdef _WIN32
353 intr(void)
354 #else
355 intr()
356 #endif
357 {
358         interrupt++;
359 #ifdef hpux
360         signal(SIGINT, intr);
361 #endif
362 }