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