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