]> git.pond.sub.org Git - empserver/blob - src/client/main.c
ecc952be5b7f1a27db6ad5f6a6f1747f377d3439
[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 #define RETRY   3
67
68 int interrupt;
69 int sock;
70
71 void saveargv();
72 void getsose();
73 int hostport();
74 int hostaddr();
75 int hostconnect();
76 int login();
77 void ioq_init();
78 void io_init();
79 void bit_copy();
80 int handleintr();
81 int termio();
82 int serverio();
83 void servercmd();
84 void ioq_drain();
85
86
87 int
88 main(ac, av)
89 int ac;
90 s_char *av[];
91 {
92 #ifdef _WIN32
93     WSADATA WsaData;
94     int err;
95     fd_set readfds;
96     struct timeval tm;
97     INPUT_RECORD InpBuffer[10];
98     DWORD numevents;
99     DWORD stdinmode;
100     SECURITY_ATTRIBUTES security;
101     void intr(void);
102 #endif
103     extern s_char *getenv();
104     extern s_char empireport[];
105     extern s_char empirehost[];
106     bit_fdmask mask;
107     bit_fdmask 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     mask = bit_newfdmask();
133     savemask = bit_newfdmask();
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     mask = bit_newfdmask();
198 #ifndef _WIN32
199     BIT_SETB(0, savemask);
200     BIT_SETB(sock, savemask);
201 #endif
202     (void)signal(SIGINT, intr);
203 #ifndef _WIN32
204     (void)signal(SIGPIPE, SIG_IGN);
205     while (BIT_ISSETB(sock, savemask)) {
206         bit_copy(savemask, mask);
207         n = select(sock + 1, (fd_set *) 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                 BIT_CLRB(sock, savemask);
219             }
220         } else {
221             if (BIT_ISSETB(0, mask)) {
222                 if (!termio(0, sock, auxout_fp)) {
223                     if (retry++ >= RETRY) {
224                         BIT_CLRB(0, savemask);
225                     }
226                 } else {
227                     retry = 0;
228                 }
229             }
230             if (BIT_ISSETB(sock, mask)) {
231                 if (!serverio(sock, &server))
232                     BIT_CLRB(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 }