]> git.pond.sub.org Git - empserver/blob - src/lib/player/login.c
Indented with src/scripts/indent-emp.
[empserver] / src / lib / player / login.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  *  login.c: Allow the player to login
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1994
32  *     Steve McClure, 2000
33  */
34
35 #ifdef Rel4
36 #include <string.h>
37 #endif /* Rel4 */
38 #include "prototypes.h"
39 #include "misc.h"
40 #include "proto.h"
41 #include "player.h"
42 #include "com.h"
43 #include "empthread.h"
44 #include "empio.h"
45 #include "nsc.h"
46 #include "nat.h"
47 #include "optlist.h"
48 #include "file.h"
49 #include "subs.h"
50 #include "common.h"
51 #include "gen.h"
52
53 #ifdef aix
54 #include <unistd.h>
55 #endif /* aix */
56 #if !defined(_WIN32)
57 #include <netinet/in.h>
58 #endif
59 #include <errno.h>
60
61 struct cmndstr login_coms[];
62
63
64 /*ARGSUSED*/
65 void
66 player_login(void *ud)
67 {
68     s_char buf[128];
69     s_char space[512];
70     s_char *av[64];
71     int ac;
72     int cmd;
73
74     player->proc = empth_self();
75
76     pr_id(player, C_INIT, "Empire server ready\n");
77
78     while (!io_eof(player->iop) && !io_error(player->iop)) {
79         io_output(player->iop, IO_WAIT);
80         if (io_gets(player->iop, buf, sizeof(buf)) < 0) {
81             io_input(player->iop, IO_WAIT);
82             continue;
83         }
84         ac = parse(buf, av, 0, space, 0);
85         cmd = comtch(av[0], login_coms, 0, 0);
86         if (cmd < 0) {
87             pr_id(player, C_BADCMD, "Command %s not found\n", av[0]);
88             continue;
89         }
90         switch (login_coms[cmd].c_addr(player, ac, av)) {
91         case RET_OK:
92             break;
93         case RET_FAIL:
94             break;
95         case RET_SYN:
96             pr_id(player, C_BADCMD, "Usage %s\n", login_coms[cmd].c_form);
97             break;
98         default:
99             break;
100         }
101         if (player->state >= PS_SHUTDOWN)
102             break;
103     }
104     player->state = PS_SHUTDOWN;
105     if (!io_eof(player->iop)) {
106         (void)pr_player(player, C_EXIT, "so long...\n");
107         io_noblocking(player->iop, 0);
108         while (io_output(player->iop, IO_WAIT) > 0) ;
109     }
110     player_delete(player);
111     empth_exit();
112     /*NOTREACHED*/
113 }
114
115 int
116 client_cmd(struct player *player, int ac, char **av)
117 {
118     int i;
119
120     if (ac < 1 || av[1] == '\0')
121         return RET_SYN;
122
123     for (i = 1; i < ac; ++i) {
124         if (i > 1)
125             (void)strncat(player->client, " ", sizeof(player->client) - 1);
126         (void)strncat(player->client, av[i], sizeof(player->client) - 1);
127     }
128     player->client[sizeof(player->client) - 1] = '\0';
129     pr_id(player, C_CMDOK, "talking to %s\n", player->client);
130     return RET_OK;
131 }
132
133 int
134 user_cmd(struct player *player, int ac, char **av)
135 {
136     if (ac < 1 || av[1] == '\0')
137         return RET_SYN;
138     (void)strncpy(player->userid, av[1], sizeof(player->userid) - 1);
139     player->userid[sizeof(player->userid) - 1] = '\0';
140     pr_id(player, C_CMDOK, "hello %s\n", player->userid);
141     return RET_OK;
142 }
143
144 int
145 sanc_cmd(struct player *player, int ac, char **av)
146 {
147     struct nstr_item ni;
148     struct natstr nat;
149     int first = 1;
150
151     if (!opt_BLITZ) {
152         pr_id(player, C_BADCMD, "Command %s not found\n", av[0]);
153         return RET_FAIL;
154     }
155
156     snxtitem_all(&ni, EF_NATION);
157     while (nxtitem(&ni, (s_char *)&nat)) {
158         if (nat.nat_stat != (STAT_INUSE | STAT_SANCT))
159             continue;
160         if (first) {
161             pr_id(player, C_DATA,
162                   "The following countries are still in sanctuary:\n");
163             first = 0;
164         }
165         pr_id(player, C_DATA, "%s\n", nat.nat_cnam);
166     }
167     if (first)
168         pr_id(player, C_CMDOK, "There are no countries in sanctuary\n");
169     else
170         pr_id(player, C_CMDOK, "\n");
171     return RET_OK;
172 }
173
174 int
175 coun_cmd(struct player *player, int ac, char **av)
176 {
177     natid cnum;
178
179     if (ac < 1 || av[1] == '\0')
180         return RET_SYN;
181     if (natbyname(av[1], &cnum) < 0) {
182         pr_id(player, C_CMDERR, "country %s does not exist\n", av[1]);
183         return 0;
184     }
185     player->cnum = cnum;
186     player->validated = 0;
187     pr_id(player, C_CMDOK, "country name %s\n", av[1]);
188     return 0;
189 }
190
191 int
192 pass_cmd(struct player *player, int ac, char **av)
193 {
194     if (ac < 1 || av[1] == '\0')
195         return RET_SYN;
196     if (player->cnum == 255) {
197         pr_id(player, C_CMDERR, "need country first\n");
198         return RET_FAIL;
199     }
200     if (!natpass(player->cnum, av[1])) {
201         pr_id(player, C_CMDERR, "password bad, logging entry\n");
202         logerror("%s tried country #%d with %s",
203                  praddr(player), player->cnum, av[1]);
204         return RET_FAIL;
205     }
206     player->validated++;
207     pr_id(player, C_CMDOK, "password ok\n");
208     logerror("%s using country #%d", praddr(player), player->cnum);
209     return RET_OK;
210 }
211
212 /*ARGSUSED*/
213 int
214 play_cmd(struct player *player, int ac, char **av)
215 {
216     extern char *banfil;
217     struct player *other;
218     natid cnum;
219     struct natstr *natp;
220
221     if (ac == 4) {
222         (void)strncpy(player->userid, av[1], sizeof(player->userid) - 1);
223         player->userid[sizeof(player->userid) - 1] = '\0';
224         player->validated = 0;
225         if (natbyname(av[2], &cnum) < 0) {
226             pr_id(player, C_CMDERR, "country %s does not exist\n", av[2]);
227             return 0;
228         }
229         if (!natpass(cnum, av[3])) {
230             pr_id(player, C_CMDERR, "password bad, logging entry\n");
231             logerror("%s tried country #%d with %s",
232                      praddr(player), cnum, av[3]);
233             return RET_FAIL;
234         }
235         player->cnum = cnum;
236         player->validated++;
237     }
238     if (player->cnum == 255 || !player->validated) {
239         pr_id(player, C_CMDERR, "need country and password\n");
240         return RET_FAIL;
241     }
242     if ((other = player_find_other(player, (natid)player->cnum)) != 0) {
243         natp = getnatp(player->cnum);
244         if (natp->nat_stat != VIS) {
245             pr_id(player, C_EXIT, "country in use by %s\n", praddr(other));
246         } else {
247             pr_id(player, C_EXIT, "country in use\n");
248         }
249         return RET_FAIL;
250     }
251     if (match_user(banfil, player)) {
252         logerror("Attempted login by BANNED host %s", praddr(player));
253         pr("Your login has been banned from this game\n");
254         io_shutdown(player->iop, IO_READ);
255         return RET_FAIL;
256     }
257     player_main(player);
258     player->state = PS_SHUTDOWN;
259     return RET_OK;
260 }
261
262 /*ARGSUSED*/
263 int
264 kill_cmd(struct player *player, int ac, char **av)
265 {
266     struct player *other;
267
268     if (player->cnum == 255 || !player->validated) {
269         pr_id(player, C_CMDERR, "need country and password\n");
270         return RET_FAIL;
271     }
272     /* XXX find cnum other than us */
273     if ((other = player_find_other(player, player->cnum)) == 0) {
274         pr_id(player, C_EXIT, "country not in use\n");
275         return RET_FAIL;
276     }
277     io_shutdown(other->iop, IO_READ | IO_WRITE);
278     pr_id(player, C_EXIT, "closed socket of offending job\n");
279     return RET_OK;
280 }
281
282 /*ARGSUSED*/
283 int
284 list_cmd(struct player *player, int ac, char **av)
285 {
286     struct player *lp;
287     int first = 1;
288
289     if (player->cnum != 0 || !player->validated) {
290         pr_id(player, C_CMDERR, "Permission denied\n");
291         return 0;
292     }
293     for (lp = player_next(0); lp != 0; lp = player_next(lp)) {
294         if (first) {
295             pr_id(player, C_DATA, "user@host\tcountry\tpid\n");
296             first = 0;
297         }
298         pr_id(player, C_DATA, "%s\t%d\n", praddr(lp), lp->cnum);
299     }
300     if (first == 0)
301         pr_id(player, C_DATA, "\n");
302     return 0;
303 }
304
305 /*ARGSUSED*/
306 int
307 quit_cmd(struct player *player, int ac, char **av)
308 {
309     pr_id(player, C_EXIT, "so long\n");
310     io_shutdown(player->iop, IO_READ);
311     return RET_OK;
312 }
313
314 struct cmndstr login_coms[] = {
315     {"list", 0, list_cmd, 0, 0},
316     {"client clientname [version info]", 0, client_cmd, 0, 0},
317     {"user username", 0, user_cmd, 0, 0},
318     {"sanc", 0, sanc_cmd, 0, 0},
319     {"coun countryname", 0, coun_cmd, 0, 0},
320     {"pass password", 0, pass_cmd, 0, 0},
321     {"play [user country pass]", 0, play_cmd, 0, 0},
322     {"quit ", 0, quit_cmd, 0, 0},
323     {"kill {self}", 0, kill_cmd, 0, 0},
324     {0, 0, 0, 0, 0}
325 };