]> git.pond.sub.org Git - empserver/blob - src/client/main.c
Indented with src/scripts/indent-emp.
[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, *s = src;
122
123     for (i = 0; i < size; i++)
124         *d++ = *s++;
125 }
126 #endif
127
128 int
129 main(ac, av)
130 int ac;
131 s_char *av[];
132 {
133 #ifdef _WIN32
134     WSADATA WsaData;
135     int err;
136     fd_set readfds;
137     struct timeval tm;
138     INPUT_RECORD InpBuffer[10];
139     DWORD numevents;
140     DWORD stdinmode;
141     SECURITY_ATTRIBUTES security;
142     void intr(void);
143 #endif
144     extern s_char *getenv();
145     extern s_char empireport[];
146     extern s_char empirehost[];
147     bit_fdmask mask;
148     bit_fdmask savemask;
149     struct ioqueue server;
150     s_char *argv[128];
151     int i, j;
152     s_char *ptr;
153     s_char *auxout_fname;
154     FILE *auxout_fp;
155 #ifndef _WIN32
156     struct passwd *pwd;
157     void intr();
158 #endif
159     struct sockaddr_in sin;
160     int n;
161     s_char *cname;
162     s_char *pname;
163     int retry = 0;
164     int send_kill = 0;
165
166 #ifdef _WIN32
167     err = WSAStartup(0x0101, &WsaData);
168     if (err == SOCKET_ERROR) {
169         printf("WSAStartup Failed\n");
170         return FALSE;
171     }
172 #else
173     mask = bit_newfdmask();
174     savemask = bit_newfdmask();
175 #endif
176     bzero((s_char *)argv, sizeof(argv));
177     saveargv(ac, av, argv);
178     auxout_fname = 0;
179     auxout_fp = 0;
180     for (i = j = 1; i < ac; ++i) {
181         ptr = argv[i];
182         if (strcmp(ptr, "-2") == 0) {
183             if (i + 1 >= ac) {
184                 fprintf(stderr, "-2: Missing filename!\n");
185                 exit(1);
186             }
187             auxout_fname = argv[i + 1];
188             ++i;
189             continue;
190         } else if (strcmp(ptr, "-k") == 0) {
191             send_kill = 1;
192             continue;
193         }
194         argv[j] = argv[i];
195         ++j;
196     }
197     ac = j;
198     if (auxout_fname && (auxout_fp = fopen(auxout_fname, "a")) == NULL) {
199         fprintf(stderr, "Unable to open %s for append\n", auxout_fname);
200         exit(1);
201     }
202 #ifndef _WIN32
203     pwd = getpwuid(getuid());
204     if (pwd == NULL) {
205         fprintf(stderr, "You don't exist.  Go away\n");
206         exit(1);
207     }
208 #endif
209     getsose();
210     if (!hostport(getenv("EMPIREPORT"), &sin) &&
211         !hostport("empire", &sin) && !hostport(empireport, &sin)) {
212         fprintf(stderr, "No empire port\n");
213         exit(1);
214     }
215     if (!hostaddr(getenv("EMPIREHOST"), &sin) &&
216         !hostaddr(empirehost, &sin)) {
217         fprintf(stderr, "No empire host\n");
218         exit(1);
219     }
220     if ((sock = hostconnect(&sin)) < 0)
221         exit(1);
222     cname = getenv("COUNTRY");
223     pname = getenv("PLAYER");
224     if (ac > 1)
225         cname = argv[1];
226     if (ac > 2)
227         pname = argv[2];
228 #ifndef _WIN32
229     if (!login(sock, pwd->pw_name, cname, pname, send_kill)) {
230 #else
231     if (!login(sock, "win-empcl2.8", cname, pname, send_kill)) {
232 #endif
233         close(sock);
234         exit(1);
235     }
236     ioq_init(&server, 2048);
237     io_init();
238     mask = bit_newfdmask();
239 #ifndef _WIN32
240     BIT_SETB(0, savemask);
241     BIT_SETB(sock, savemask);
242 #endif
243     (void)signal(SIGINT, intr);
244 #ifndef _WIN32
245     (void)signal(SIGPIPE, SIG_IGN);
246     while (BIT_ISSETB(sock, savemask)) {
247         bit_copy(savemask, mask);
248         n = select(sock + 1, (fd_set *) mask, (fd_set *) 0, (fd_set *) 0,
249                    (struct timeval *)0);
250         if (interrupt) {
251             if (!handleintr(sock))
252                 break;
253             errno = 0;
254         }
255         if (n <= 0) {
256             if (errno == EINTR) {
257                 perror("select");
258                 (void)close(sock);
259                 BIT_CLRB(sock, savemask);
260             }
261         } else {
262             if (BIT_ISSETB(0, mask)) {
263                 if (!termio(0, sock, auxout_fp)) {
264                     if (retry++ >= RETRY) {
265                         BIT_CLRB(0, savemask);
266                     }
267                 } else {
268                     retry = 0;
269                 }
270             }
271             if (BIT_ISSETB(sock, mask)) {
272                 if (!serverio(sock, &server))
273                     BIT_CLRB(sock, savemask);
274                 else
275                     servercmd(&server, auxout_fp);
276             }
277         }
278     }
279 #else
280     tm.tv_sec = 0;
281     tm.tv_usec = 1000;
282
283     security.nLength = sizeof(SECURITY_ATTRIBUTES);
284     security.lpSecurityDescriptor = NULL;
285     security.bInheritHandle = TRUE;
286     hStdIn = CreateFile("CONIN$",
287                         GENERIC_READ | GENERIC_WRITE,
288                         FILE_SHARE_READ | FILE_SHARE_WRITE,
289                         &security, OPEN_EXISTING, (DWORD) NULL, NULL);
290
291     if (hStdIn == INVALID_HANDLE_VALUE) {
292         printf("Error getting hStdIn.\n");
293         fflush(stdout);
294     }
295     err = GetConsoleMode(hStdIn, &stdinmode);
296     if (!err) {
297         printf("Error getting console mode.\n");
298         fflush(stdout);
299     }
300     stdinmode |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
301     err = SetConsoleMode(hStdIn, stdinmode);
302     if (!err) {
303         printf("Error setting console mode.\n");
304         fflush(stdout);
305     }
306     while (1) {
307         FD_ZERO(&readfds);
308         FD_SET(sock, &readfds);
309         n = select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0,
310                    (struct timeval *)&tm);
311         if (n < 0) {
312             if (errno == EINTR) {
313                 errno = WSAGetLastError();
314                 perror("select");
315                 (void)close(sock);
316                 break;
317             }
318         } else {
319             if (WaitForSingleObject(hStdIn, 10) != WAIT_TIMEOUT) {
320                 if (!termio(-1, sock, auxout_fp)) {
321                     if (retry++ >= RETRY) {
322                         ;
323                     }
324                 } else {
325                     retry = 0;
326                 }
327                 FlushConsoleInputBuffer(hStdIn);
328             }
329             if (FD_ISSET(sock, &readfds)) {
330                 if (!serverio(sock, &server))
331                     break;
332                 else
333                     servercmd(&server, auxout_fp);
334             }
335         }
336     }
337     CloseHandle(hStdIn);
338 #endif
339     ioq_drain(&server);
340     (void)close(sock);
341     exit(0);
342     return 0;                   /* Shut the compiler up */
343 }
344
345 void
346 #ifdef _WIN32
347 intr(void)
348 #else
349 intr()
350 #endif
351 {
352     interrupt++;
353 #ifdef hpux
354     signal(SIGINT, intr);
355 #endif
356 }