]> git.pond.sub.org Git - empserver/blob - src/client/main.c
(main): Portability bug: code passed bit_fdmask to select(). This
[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
44 #include <stdio.h>
45 #ifndef _WIN32
46 #include <pwd.h>
47 #endif
48 #include <signal.h>
49 #include <errno.h>
50 #include <time.h>
51 #ifndef _WIN32
52 #include <sys/socket.h>
53 #include <netinet/in.h>
54 #include <unistd.h>
55 #else
56 #include <windows.h>
57 #include <winsock.h>
58 #include <conio.h>
59 #endif
60
61 #ifdef _WIN32
62 HANDLE hStdIn;
63 #endif
64
65 #define RETRY   3
66
67 int interrupt;
68 int sock;
69
70 void saveargv();
71 void getsose();
72 int hostport();
73 int hostaddr();
74 int hostconnect();
75 int login();
76 void ioq_init();
77 void io_init();
78 int handleintr();
79 int termio();
80 int serverio();
81 void servercmd();
82 void ioq_drain();
83
84
85 int
86 main(ac, av)
87 int ac;
88 s_char *av[];
89 {
90 #ifdef _WIN32
91     WSADATA WsaData;
92     int err;
93     fd_set readfds;
94     struct timeval tm;
95     INPUT_RECORD InpBuffer[10];
96     DWORD numevents;
97     DWORD stdinmode;
98     SECURITY_ATTRIBUTES security;
99     void intr(void);
100 #endif
101     extern s_char *getenv();
102     extern s_char empireport[];
103     extern s_char empirehost[];
104     fd_set mask;
105     fd_set savemask;
106     struct ioqueue server;
107     s_char *argv[128];
108     int i, j;
109     s_char *ptr;
110     s_char *auxout_fname;
111     FILE *auxout_fp;
112 #ifndef _WIN32
113     struct passwd *pwd;
114     void intr();
115 #endif
116     struct sockaddr_in sin;
117     int n;
118     s_char *cname;
119     s_char *pname;
120     int retry = 0;
121     int send_kill = 0;
122
123 #ifdef _WIN32
124     err = WSAStartup(0x0101, &WsaData);
125     if (err == SOCKET_ERROR) {
126         printf("WSAStartup Failed\n");
127         return FALSE;
128     }
129 #else
130     FD_ZERO(&mask);
131     FD_ZERO(&savemask);
132 #endif
133     memset(argv, 0, sizeof(argv));
134     saveargv(ac, av, argv);
135     auxout_fname = 0;
136     auxout_fp = 0;
137     for (i = j = 1; i < ac; ++i) {
138         ptr = argv[i];
139         if (strcmp(ptr, "-2") == 0) {
140             if (i + 1 >= ac) {
141                 fprintf(stderr, "-2: Missing filename!\n");
142                 exit(1);
143             }
144             auxout_fname = argv[i + 1];
145             ++i;
146             continue;
147         } else if (strcmp(ptr, "-k") == 0) {
148             send_kill = 1;
149             continue;
150         }
151         argv[j] = argv[i];
152         ++j;
153     }
154     ac = j;
155     if (auxout_fname && (auxout_fp = fopen(auxout_fname, "a")) == NULL) {
156         fprintf(stderr, "Unable to open %s for append\n", auxout_fname);
157         exit(1);
158     }
159 #ifndef _WIN32
160     pwd = getpwuid(getuid());
161     if (pwd == NULL) {
162         fprintf(stderr, "You don't exist.  Go away\n");
163         exit(1);
164     }
165 #endif
166     getsose();
167     if (!hostport(getenv("EMPIREPORT"), &sin) &&
168         !hostport("empire", &sin) && !hostport(empireport, &sin)) {
169         fprintf(stderr, "No empire port\n");
170         exit(1);
171     }
172     if (!hostaddr(getenv("EMPIREHOST"), &sin) &&
173         !hostaddr(empirehost, &sin)) {
174         fprintf(stderr, "No empire host\n");
175         exit(1);
176     }
177     if ((sock = hostconnect(&sin)) < 0)
178         exit(1);
179     cname = getenv("COUNTRY");
180     pname = getenv("PLAYER");
181     if (ac > 1)
182         cname = argv[1];
183     if (ac > 2)
184         pname = argv[2];
185 #ifndef _WIN32
186     if (!login(sock, pwd->pw_name, cname, pname, send_kill)) {
187 #else
188     if (!login(sock, "win-empcl2.8", cname, pname, send_kill)) {
189 #endif
190         close(sock);
191         exit(1);
192     }
193     ioq_init(&server, 2048);
194     io_init();
195     FD_ZERO(&mask);
196 #ifndef _WIN32
197     FD_SET(0, &savemask);
198     FD_SET(sock, &savemask);
199 #endif
200     (void)signal(SIGINT, intr);
201 #ifndef _WIN32
202     (void)signal(SIGPIPE, SIG_IGN);
203     while (FD_ISSET(sock, &savemask)) {
204         mask = savemask;
205         n = select(sock + 1, &mask, (fd_set *)0, (fd_set *)0,
206                    (struct timeval *)0);
207         if (interrupt) {
208             if (!handleintr(sock))
209                 break;
210             errno = 0;
211         }
212         if (n <= 0) {
213             if (errno == EINTR) {
214                 perror("select");
215                 (void)close(sock);
216                 FD_CLR(sock, &savemask);
217             }
218         } else {
219             if (FD_ISSET(0, &mask)) {
220                 if (!termio(0, sock, auxout_fp)) {
221                     if (retry++ >= RETRY) {
222                         FD_CLR(0, &savemask);
223                     }
224                 } else {
225                     retry = 0;
226                 }
227             }
228             if (FD_ISSET(sock, &mask)) {
229                 if (!serverio(sock, &server))
230                     FD_CLR(sock, &savemask);
231                 else
232                     servercmd(&server, auxout_fp);
233             }
234         }
235     }
236 #else
237     tm.tv_sec = 0;
238     tm.tv_usec = 1000;
239
240     security.nLength = sizeof(SECURITY_ATTRIBUTES);
241     security.lpSecurityDescriptor = NULL;
242     security.bInheritHandle = TRUE;
243     hStdIn = CreateFile("CONIN$",
244                         GENERIC_READ | GENERIC_WRITE,
245                         FILE_SHARE_READ | FILE_SHARE_WRITE,
246                         &security, OPEN_EXISTING, (DWORD) NULL, NULL);
247
248     if (hStdIn == INVALID_HANDLE_VALUE) {
249         printf("Error getting hStdIn.\n");
250         fflush(stdout);
251     }
252     err = GetConsoleMode(hStdIn, &stdinmode);
253     if (!err) {
254         printf("Error getting console mode.\n");
255         fflush(stdout);
256     }
257     stdinmode |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
258     err = SetConsoleMode(hStdIn, stdinmode);
259     if (!err) {
260         printf("Error setting console mode.\n");
261         fflush(stdout);
262     }
263     while (1) {
264         FD_ZERO(&readfds);
265         FD_SET(sock, &readfds);
266         n = select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0,
267                    (struct timeval *)&tm);
268         if (n < 0) {
269             if (errno == EINTR) {
270                 errno = WSAGetLastError();
271                 perror("select");
272                 (void)close(sock);
273                 break;
274             }
275         } else {
276             if (WaitForSingleObject(hStdIn, 10) != WAIT_TIMEOUT) {
277                 if (!termio(-1, sock, auxout_fp)) {
278                     if (retry++ >= RETRY) {
279                         ;
280                     }
281                 } else {
282                     retry = 0;
283                 }
284                 FlushConsoleInputBuffer(hStdIn);
285             }
286             if (FD_ISSET(sock, &readfds)) {
287                 if (!serverio(sock, &server))
288                     break;
289                 else
290                     servercmd(&server, auxout_fp);
291             }
292         }
293     }
294     CloseHandle(hStdIn);
295 #endif
296     ioq_drain(&server);
297     (void)close(sock);
298     exit(0);
299     return 0;                   /* Shut the compiler up */
300 }
301
302 void
303 #ifdef _WIN32
304 intr(void)
305 #else
306 intr()
307 #endif
308 {
309     interrupt++;
310 #ifdef hpux
311     signal(SIGINT, intr);
312 #endif
313 }