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