]> git.pond.sub.org Git - empserver/blob - src/lib/player/login.c
Import of Empire 4.2.12
[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         }
111         player_delete(player); 
112         empth_exit();
113         /*NOTREACHED*/
114 }
115
116 int
117 client_cmd(struct player *player, int ac, char **av)
118 {
119         int i;
120
121         if (ac < 1 || av[1] == '\0')
122                 return RET_SYN;
123
124         for (i = 1; i < ac; ++i) {
125                 if (i > 1)
126                         (void) strncat(player->client, " ", sizeof(player->client)-1);
127                 (void) strncat(player->client, av[i], sizeof(player->client)-1);
128         }
129         player->client[sizeof(player->client)-1] = '\0';
130         pr_id(player, C_CMDOK, "talking to %s\n", player->client);
131         return RET_OK;
132 }
133
134 int
135 user_cmd(struct player *player, int ac, char **av)
136 {
137         if (ac < 1 || av[1] == '\0')
138                 return RET_SYN;
139         (void) strncpy(player->userid, av[1], sizeof(player->userid)-1);
140         player->userid[sizeof(player->userid)-1] = '\0';
141         pr_id(player, C_CMDOK, "hello %s\n", player->userid);
142         return RET_OK;
143 }
144
145 int
146 sanc_cmd(struct player *player, int ac, char **av)
147 {
148         struct  nstr_item ni;
149         struct  natstr nat;
150         int     first = 1;
151
152         if (!opt_BLITZ) {
153                 pr_id(player, C_BADCMD, "Command %s not found\n", av[0]);
154                 return RET_FAIL;
155         }
156
157         snxtitem_all(&ni, EF_NATION);
158         while (nxtitem(&ni, (s_char *)&nat)) {
159                 if (nat.nat_stat != (STAT_INUSE|STAT_SANCT))
160                         continue;
161                 if (first) {
162                         pr_id(player, C_DATA, "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",
246                         praddr(other));
247                 } else {
248                   pr_id(player, C_EXIT, "country in use\n");
249                 }
250                 return RET_FAIL;
251         }
252         if (match_user(banfil, player)) {
253                 logerror("Attempted login by BANNED host %s",
254                          praddr(player));
255                 pr("Your login has been banned from this game\n");
256                 io_shutdown(player->iop, IO_READ);
257                 return RET_FAIL;
258         }
259         player_main(player);
260         player->state = PS_SHUTDOWN;
261         return RET_OK;
262 }
263
264 /*ARGSUSED*/
265 int
266 kill_cmd(struct player *player, int ac, char **av)
267 {
268         struct  player *other;
269
270         if (player->cnum == 255 || !player->validated) {
271                 pr_id(player, C_CMDERR, "need country and password\n");
272                 return RET_FAIL;
273         }
274         /* XXX find cnum other than us */
275         if ((other = player_find_other(player, player->cnum)) == 0) {
276                 pr_id(player, C_EXIT, "country not in use\n");
277                 return RET_FAIL;
278         }
279         io_shutdown(other->iop, IO_READ|IO_WRITE);
280         pr_id(player, C_EXIT, "closed socket of offending job\n");
281         return RET_OK;
282 }
283
284 /*ARGSUSED*/
285 int
286 list_cmd(struct player *player, int ac, char **av)
287 {
288         struct  player *lp;
289         int     first = 1;
290
291         if (player->cnum != 0 || !player->validated) {
292                 pr_id(player, C_CMDERR, "Permission denied\n");
293                 return 0;
294         }
295         for (lp = player_next(0); lp != 0; lp = player_next(lp)) {
296                 if (first) {
297                         pr_id(player, C_DATA, "user@host\tcountry\tpid\n");
298                         first = 0;
299                 }
300                 pr_id(player, C_DATA, "%s\t%d\n", praddr(lp), lp->cnum);
301         }
302         if (first == 0)
303                 pr_id(player, C_DATA, "\n");
304         return 0;
305 }
306
307 /*ARGSUSED*/
308 int
309 quit_cmd(struct player *player, int ac, char **av)
310 {
311         pr_id(player, C_EXIT, "so long\n");
312         io_shutdown(player->iop, IO_READ);
313         return RET_OK;
314 }
315
316 struct cmndstr login_coms[] = {
317         { "list",                               0, list_cmd, 0, 0 },
318         { "client clientname [version info]", 0, client_cmd, 0, 0 },
319         { "user username",              0, user_cmd, 0, 0 },
320         { "sanc",                               0, sanc_cmd, 0, 0 },
321         { "coun countryname",           0, coun_cmd, 0, 0 },
322         { "pass password",              0, pass_cmd, 0, 0 },
323         { "play [user country pass]",   0, play_cmd, 0, 0 },
324         { "quit ",                      0, quit_cmd, 0, 0 },
325         { "kill {self}",                        0, kill_cmd, 0, 0 },
326         { 0,                            0, 0, 0, 0 }
327 };