1 /*
2 * Support for the "remote console". It lets the server admin
3 * perform server maintenance without requiring that the server
4 * have a devoted tty.
5 */
6
7 /* added this for consistency in some (unrelated) header-inclusion,
8 it IS a server file, isn't it? */
9 #define SERVER
10
11 #include <stdarg.h>
12 #include "angband.h"
13 #include "control.h"
14
15 #ifdef MINGW
16 #define EWOULDBLOCK WSAEWOULDBLOCK
17 #endif
18
19 #ifdef SERVER_GWPORT
20 #if 0
21 /* Server gateway stuff */
22 void SGWHit(int read_fd, int arg){
23 int newsock = 0;
24 char *sdb;
25 int size = 0;
26 time_t now;
27
28 /* read_fd always the main socket, because we
29 never install_input on any others. */
30 /* Order: connection, s->send, s->shutdown socket */
31
32 if ((newsock = SocketAccept(read_fd)) != -1) {
33 /* Send some crap here */
34 sdb = C_NEW(4096, char);
35 if (sdb != (char*)NULL) {
36 int i;
37 time(&now);
38 size += sprintf(sdb, "runtime=%d\n", (int)(now - cfg.runtime));
39 size += sprintf(&sdb[size], "turn=%d\n", turn);
40 size += sprintf(&sdb[size], "day=%d\n", DAY); /* day const */
41 size += sprintf(&sdb[size], "year=%d\n", bst(YEAR, turn)); /* starting year const */
42 /* let the script count or we'll give away
43 the dungeon masters. */
44 /* size+=sprintf(&sdb[size],"num=%d\n", NumPlayers);*/
45 for (i = 1; i <= NumPlayers; i++) {
46 if (Players[i]->admin_dm && cfg.secret_dungeon_master) continue;
47 size += sprintf(&sdb[size], "player=%s\n", Players[i]->name);
48 size += sprintf(&sdb[size], "level=%d\n", Players[i]->lev);
49 size += sprintf(&sdb[size], "race=%s\n", race_info[Players[i]->prace].title);
50 size += sprintf(&sdb[size], "born=%d\n", Players[i]->turn);
51 }
52 size += highscore_send(&sdb[size], 4096 - size);
53 DgramWrite(newsock, sdb, size);
54 C_FREE(sdb, 4096, char);
55 }
56 close(newsock); /* oops */
57 }
58 else
59 s_printf("Web server request failed: %d\n", errno);
60 }
61 #else
62 /* Server gateway stuff */
63
64 gw_connection_t gw_conns[MAX_GW_CONNS];
65 int gw_conns_num;
66
67 /* Copy the first line from the socket buffer into buf */
Packet_getln(sockbuf_t * s,char * buf)68 static int Packet_getln(sockbuf_t *s, char *buf) {
69 char *scan;
70 int len;
71
72 for (scan = s->ptr; scan < s->buf + s->len; scan++) {
73 if (*scan == '\n') {
74 /* Calculate the length and limit to MSG_LEN - 1 */
75 len = MIN(scan - s->ptr, MSG_LEN - 1);
76
77 /* Copy the line */
78 memcpy(buf, s->ptr, len);
79
80 /* Terminate */
81 buf[len] = '\0';
82
83 /* Move the socket buffer pointer forward */
84 s->ptr = scan + 1;
85
86 return len;
87 }
88 }
89
90 return 0;
91 }
92
93 /* Write formatted ouput terminated with a newline into a socket buffer */
Packet_println(sockbuf_t * s,cptr fmt,...)94 static int Packet_println(sockbuf_t *s, cptr fmt, ...) {
95 va_list ap;
96 char buf[4096];
97 int n;
98 int rval;
99
100 va_start(ap, fmt);
101
102 /* Use vsnprintf to do the formatting */
103 n = vsnprintf(buf, 4095, fmt, ap);
104
105 if (n >= 0) {
106 /* Write the output to the socket buffer */
107 buf[n++] = '\n';
108 rval = Sockbuf_write(s, buf, n);
109 } else {
110 /* Some error */
111 rval = 0;
112 }
113
114 va_end(ap);
115
116 return rval;
117 }
118
119 /* GW connection handler */
SGWHit(int read_fd,int arg)120 void SGWHit(int read_fd, int arg) {
121 int i, sock, bytes;
122 gw_connection_t *gw_conn = NULL;
123 char buf[MSG_LEN];
124
125 /* Check if it's a new client */
126 if (read_fd == SGWSocket) {
127 /* Accept it */
128 sock = SocketAccept(read_fd);
129
130 if (sock == -1) {
131 s_printf("Failed to accept GW port connection (errno=%d)\n", errno);
132 return;
133 }
134
135 /* Check if we have room for it */
136 if (gw_conns_num < MAX_GW_CONNS) {
137
138 /* Find a free connection */
139 for (i = 0; i < MAX_GW_CONNS; i++) {
140 gw_conn = &gw_conns[i];
141
142 if (gw_conn->state == CONN_FREE)
143 break;
144 }
145
146 gw_conn->sock = sock;
147 gw_conn->state = CONN_CONNECTED;
148 gw_conn->last_activity = time(NULL);
149
150 #if 0 /* prevents sending lots of data */
151 if (SetSocketNonBlocking(sock, 1) == -1) {
152 plog("Cannot make GW client socket non-blocking");
153 }
154 #endif
155
156 /* Initialize socket buffers */
157 Sockbuf_init(&gw_conn->r, sock, 8192, SOCKBUF_READ);
158 Sockbuf_init(&gw_conn->w, sock, 8192, SOCKBUF_WRITE);
159
160 install_input(SGWHit, sock, 2);
161
162 gw_conns_num++;
163 } else {
164 /* No room, close the connection */
165 DgramClose(sock);
166 }
167
168 /* The connection has either been accepted or not, we're done */
169 return;
170 }
171
172 /* Find the matching connection */
173 for (i = 0; i < MAX_GW_CONNS; i++) {
174 gw_connection_t *gw_conn2 = &gw_conns[i];
175
176 if (gw_conn2->state == CONN_CONNECTED && gw_conn2->sock == read_fd) {
177 gw_conn = gw_conn2;
178 break;
179 }
180 }
181
182 if (!gw_conn) {
183 s_printf("No GW connection found for socket number %d\n", read_fd);
184 DgramClose(read_fd);
185 return;
186 }
187
188 /* Read the message */
189 bytes = DgramReceiveAny(read_fd, gw_conn->r.buf + gw_conn->r.len, gw_conn->r.size - gw_conn->r.len);
190
191 /* Check for errors or our TCP connection closing */
192 if (bytes <= 0) {
193 /* If 0 bytes have been sent than the client has probably closed
194 * the connection
195 */
196 if (bytes == 0) {
197 gw_conn->state = CONN_FREE;
198 Sockbuf_cleanup(&gw_conn->r);
199 Sockbuf_cleanup(&gw_conn->w);
200 DgramClose(read_fd);
201 remove_input(read_fd);
202 gw_conns_num--;
203 }
204 else if (bytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN &&
205 errno != EINTR)
206 {
207 /* Clear the error condition for the contact socket */
208 GetSocketError(read_fd);
209
210 s_printf("Failed to read from GW client!\n");
211 }
212 return;
213 }
214
215 /* Set length */
216 gw_conn->r.len = bytes;
217
218 gw_conn->last_activity = time(NULL);
219
220 /* Prepare to send a new reply */
221 Sockbuf_clear(&gw_conn->w);
222
223 /* Try to read the request */
224 while (Packet_getln(&gw_conn->r, buf) > 0) {
225 /* Basic server info */
226 if (!strcmp(buf, "INFO")) {
227 time_t now;
228 player_type *p_ptr;
229 int players = 0;
230 int day = bst(DAY, turn);
231 now = time(NULL);
232
233 /* Count players */
234 for (i = 1; i <= NumPlayers; i++) {
235 p_ptr = Players[i];
236 if (p_ptr->admin_dm && cfg.secret_dungeon_master) continue;
237 players++;
238 }
239
240 Packet_println(&gw_conn->w, "INFO REPLY");
241 Packet_println(&gw_conn->w, "uptime=%d", now - cfg.runtime);
242 Packet_println(&gw_conn->w, "turn=%d", turn);
243 Packet_println(&gw_conn->w, "ingameday=%s of the %s year", get_month_name(day, FALSE, FALSE), get_day(bst(YEAR, turn)));
244 Packet_println(&gw_conn->w, "fps=%d", cfg.fps);
245 Packet_println(&gw_conn->w, "players=%d", players);
246 Packet_println(&gw_conn->w, "INFO REPLY END");
247 }
248
249 /* List of players */
250 else if (!strcmp(buf, "PLAYERS")) {
251 player_type *p_ptr;
252 Packet_println(&gw_conn->w, "PLAYERS REPLY");
253 for (i = 1; i <= NumPlayers; i++) {
254 p_ptr = Players[i];
255 if (p_ptr->admin_dm && cfg.secret_dungeon_master) continue;
256 Packet_println(&gw_conn->w, "name=%s", p_ptr->name);
257 Packet_println(&gw_conn->w, "account=%s", p_ptr->accountname);
258 Packet_println(&gw_conn->w, "host=%s", p_ptr->hostname);
259 Packet_println(&gw_conn->w, "level=%d", p_ptr->lev);
260 Packet_println(&gw_conn->w, "race=%s", race_info[p_ptr->prace].title);
261 Packet_println(&gw_conn->w, "class=%s", class_info[p_ptr->pclass].title);
262 Packet_println(&gw_conn->w, "gender=%s", (p_ptr->male) ? "male" : "female");
263 }
264 Packet_println(&gw_conn->w, "PLAYERS REPLY END");
265 }
266
267 /* Highscore list */
268 else if (!strcmp(buf, "SCORES")) {
269 char *buf2;
270 int len;
271 int amount, sent = 0, rval, fail = 0;
272
273 Packet_println(&gw_conn->w, "SCORES REPLY");
274
275 /* Send the contents of the socket buffer before sending buf2 */
276 Sockbuf_flush(&gw_conn->w);
277 Sockbuf_clear(&gw_conn->w);
278
279 C_MAKE(buf2, 81920, char);
280 len = highscore_send(buf2, 81920);
281
282 /* Send buf2 in pieces */
283 /* XXX - Blocking send loop */
284 while (sent < len) {
285 /* Try to send a full socket buffer */
286 amount = MIN(8192, len - sent);
287 Sockbuf_write(&gw_conn->w, &buf2[sent], amount);
288 rval = Sockbuf_flush(&gw_conn->w);
289
290 if (rval <= 0) {
291 /* Failure */
292 if (++fail >= 3) {
293 /* Give up */
294 break;
295 }
296 }
297 else {
298 sent += rval;
299 }
300
301 Sockbuf_clear(&gw_conn->w);
302 }
303
304 C_KILL(buf2, 81920, char);
305 Packet_println(&gw_conn->w, "SCORES REPLY END");
306 }
307
308 /* House list */
309 else if (!strcmp(buf, "HOUSES")) {
310 char *buf2;
311 int len, alloc = 128 * num_houses;
312 int amount, sent = 0, rval, fail = 0;
313
314 C_MAKE(buf2, alloc, char);
315 Packet_println(&gw_conn->w, "HOUSES REPLY");
316
317 len = houses_send(buf2, alloc);
318
319 /* Send the contents of the socket buffer before sending buf2 */
320 Sockbuf_flush(&gw_conn->w);
321 Sockbuf_clear(&gw_conn->w);
322
323 /* Send buf2 in pieces */
324 /* XXX - Blocking send loop */
325 while (sent < len) {
326 /* Try to send a full socket buffer */
327 amount = MIN(8192, len - sent);
328 Sockbuf_write(&gw_conn->w, &buf2[sent], amount);
329 rval = Sockbuf_flush(&gw_conn->w);
330
331 if (rval <= 0) {
332 /* Failure */
333 if (++fail >= 3) {
334 /* Give up */
335 break;
336 }
337 }
338 else {
339 sent += rval;
340 }
341
342 Sockbuf_clear(&gw_conn->w);
343 }
344
345 Packet_println(&gw_conn->w, "HOUSES REPLY END");
346 C_KILL(buf2, alloc, char);
347 }
348
349 /* Player stores list */
350 else if (!strcmp(buf, "PSTORES")) {
351 //MAX_HOUSES (65536), STORE_INVEN_MAX (120)
352 #if 0 /* todo: implement (this is a copy/paste of above 'HOUSES') */
353 char *buf2;
354 int len, alloc = 128 * num_houses;
355 int amount, sent = 0, rval, fail = 0;
356
357 C_MAKE(buf2, alloc, char);
358 Packet_println(&gw_conn->w, "PSTORES REPLY");
359
360 len = pstores_send(buf2, alloc);
361
362 /* Send the contents of the socket buffer before sending buf2 */
363 Sockbuf_flush(&gw_conn->w);
364 Sockbuf_clear(&gw_conn->w);
365
366 /* Send buf2 in pieces */
367 /* XXX - Blocking send loop */
368 while (sent < len) {
369 /* Try to send a full socket buffer */
370 amount = MIN(8192, len - sent);
371 Sockbuf_write(&gw_conn->w, &buf2[sent], amount);
372 rval = Sockbuf_flush(&gw_conn->w);
373
374 if (rval <= 0) {
375 /* Failure */
376 if (++fail >= 3) {
377 /* Give up */
378 break;
379 }
380 }
381 else {
382 sent += rval;
383 }
384
385 Sockbuf_clear(&gw_conn->w);
386 }
387
388 Packet_println(&gw_conn->w, "PSTORES REPLY END");
389 C_KILL(buf2, alloc, char);
390 #endif
391 }
392
393 /* Default reply */
394 else {
395 Packet_println(&gw_conn->w, "ERROR UNKNOWN REQUEST");
396 }
397
398 if (gw_conn->w.len) {
399 /* Send our reply */
400 Sockbuf_flush(&gw_conn->w);
401
402 /* Make room for more */
403 Sockbuf_clear(&gw_conn->w);
404 }
405 }
406
407 /* Advance the read buffer */
408 Sockbuf_advance(&gw_conn->r, gw_conn->r.ptr - gw_conn->r.buf);
409 }
410
411 /* Checks whether GW connections should timeout */
SGWTimeout()412 void SGWTimeout() {
413 int i;
414 gw_connection_t *gw_conn;
415 time_t now;
416
417 now = time(NULL);
418
419 /* Go through all gateway connections */
420 for (i = 0; i < MAX_GW_CONNS; i++) {
421 gw_conn = &gw_conns[i];
422 if (gw_conn->state == CONN_CONNECTED) {
423 /* Check for timeout */
424 if (gw_conn->last_activity + GW_CONN_TIMEOUT < now) {
425 s_printf("GW client timeout\n");
426
427 /* Close the connection */
428 gw_conn->state = CONN_FREE;
429 Sockbuf_cleanup(&gw_conn->r);
430 Sockbuf_cleanup(&gw_conn->w);
431 DgramClose(gw_conn->sock);
432 remove_input(gw_conn->sock);
433 gw_conns_num--;
434 }
435 }
436 }
437 }
438 #endif
439 #endif
440
441 #ifdef NEW_SERVER_CONSOLE
442
443 static sockbuf_t console_buf;
444
445 /*
446 * Return the list of players
447 */
console_status()448 static void console_status()
449 {
450 int k;
451
452 /* Packet header */
453 Packet_printf(&console_buf, "%c%d", CONSOLE_STATUS, NumPlayers);
454
455 /* Scan the player list */
456 for (k = 1; k <= NumPlayers; k++)
457 {
458 player_type *p_ptr = Players[k];
459
460 /* Skip disconnected players */
461 if (p_ptr->conn == NOT_CONNECTED) continue;
462
463 /* Add an entry */
464 Packet_printf(&console_buf, "%s%s%s%d%d%d%d",
465 p_ptr->name, race_info[p_ptr->prace].title,
466 class_info[p_ptr->pclass].title, p_ptr->lev,
467 p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
468 }
469 }
470
console_player_info(int player)471 static void console_player_info(int player)
472 {
473 }
474
console_artifacts()475 static void console_artifacts()
476 {
477 int i, count = 0, z;
478 bool okay[MAX_A_IDX];
479 char base_name[ONAME_LEN];
480
481 /* Packet header */
482 Packet_printf(&console_buf, "%c", CONSOLE_ARTIFACT_LIST);
483
484 /* Scan the artifacts */
485 for (i = 0; i < MAX_A_IDX; i++) {
486 artifact_type *a_ptr = &a_info[i];
487
488 /* Default */
489 okay[i] = FALSE;
490
491 /* Skip "empty" artifacts */
492 if (!a_ptr->name) continue;
493
494 /* Skip "uncreated" artifacts */
495 if (!a_ptr->cur_num) continue;
496
497 /* Assume OK */
498 okay[i] = TRUE;
499
500 /* One more artifact */
501 count++;
502 }
503
504 /* Write the number */
505 Packet_printf(&console_buf, "%d", count);
506
507 /* Write each artifact info */
508 for (i = 0; i < MAX_A_IDX; i++) {
509 artifact_type *a_ptr = &a_info[i];
510
511 /* List "dead" ones */
512 if (!okay[i]) continue;
513
514 /* Paranoia */
515 strcpy(base_name, "Unknown Artifact");
516
517 /* Obtain the base object type */
518 z = lookup_kind(a_ptr->tval, a_ptr->sval);
519
520 /* Real object */
521 if (z) {
522 object_type forge;
523
524 /* Create the object */
525 invcopy(&forge, z);
526
527 /* Create the artifact */
528 forge.name1 = i;
529
530 /* Describe the artifact */
531 object_desc_store(0, base_name, &forge, FALSE, 0);
532 }
533
534 /* Output this artifact's number and name */
535 Packet_printf(&console_buf, "%d%s", i, base_name);
536 }
537 }
538
console_uniques()539 static void console_uniques()
540 {
541 int k, count = 0;
542 char buf[1024];
543
544 /* Packet header */
545 Packet_printf(&console_buf, "%c", CONSOLE_UNIQUE_LIST);
546
547 /* Scan the monster races */
548 for (k = 1; k < MAX_R_IDX - 1; k++) {
549 monster_race *r_ptr = &r_info[k];
550
551 /* Only process uniques */
552 if (r_ptr->flags1 & RF1_UNIQUE) {
553 bool dead = (r_ptr->max_num == 0);
554
555 /* Only count known uniques */
556 if (dead || r_ptr->r_sights) {
557 /* One more */
558 count++;
559 }
560 }
561 }
562
563 /* Write the number of uniques */
564 Packet_printf(&console_buf, "%d", count);
565
566 /* Scan the monster races */
567 for (k = 1; k < MAX_R_IDX - 1; k++) {
568 monster_race *r_ptr = &r_info[k];
569
570 /* Only process uniques */
571 if (r_ptr->flags1 & RF1_UNIQUE) {
572 /* Only display known uniques */
573 if (r_ptr->r_sights) {
574 int i;
575 byte ok = FALSE;
576
577 /* Format message */
578 sprintf(buf, "%s has been killed by:\n", r_name + r_ptr->name);
579
580 for (i = 1; i <= NumPlayers; i++) {
581 player_type *q_ptr = Players[i];
582
583 if (q_ptr->r_killed[k] == 1) {
584 sprintf(buf, " %s\n", q_ptr->name);
585 ok = TRUE;
586 }
587 }
588 if (!ok) sprintf(buf, " Nobody\n");
589
590
591 /* Add info */
592 Packet_printf(&console_buf, "%d%s", k, buf);
593 }
594 }
595 }
596 }
597
console_change_artifact(int artifact,int status)598 static void console_change_artifact(int artifact, int status) {
599 /* Check bounds */
600 if (artifact <= 0 || artifact > MAX_A_IDX) {
601 /* Failed */
602 Packet_printf(&console_buf, "%c%c", CONSOLE_CHANGE_ARTIFACT, 0);
603 return;
604 }
605
606 /* Set the artifact's status */
607 if (status) {
608 /* Make found */
609 handle_art_inum(artifact);
610 } else {
611 /* Make unfound */
612 handle_art_dnum(artifact);
613 }
614
615 /* Succeeded */
616 Packet_printf(&console_buf, "%c%c", CONSOLE_CHANGE_ARTIFACT, 1);
617 }
618
console_change_unique(int unique,cptr killer)619 static void console_change_unique(int unique, cptr killer)
620 {
621 monster_race *r_ptr;
622 int kill_idx;
623 char buf[80];
624
625 /* Check bounds */
626 if (unique <= 0 || unique > MAX_R_IDX - 1) {
627 /* Failed */
628 Packet_printf(&console_buf, "%c%c", CONSOLE_CHANGE_UNIQUE, 0);
629
630 return;
631 }
632
633 /* Get killer index */
634 if (killer) {
635 /* Lookup player by name */
636 kill_idx = lookup_player_id(killer);
637 } else {
638 /* No killer */
639 kill_idx = 0;
640 }
641
642 /* Set pointer */
643 r_ptr = &r_info[unique];
644
645 /* Check for uniqueness */
646 if (!r_ptr->flags1 & RF1_UNIQUE) {
647 /* Failed */
648 Packet_printf(&console_buf, "%c%c", CONSOLE_CHANGE_UNIQUE, 0);
649
650 return;
651 }
652
653 /* Set death flag */
654 if (kill_idx) {
655 /* Dead */
656 r_ptr->max_num = 0;
657 } else {
658 /* Alive */
659
660 /* Tell people if the monster is respawning */
661 if (!r_ptr->max_num)
662 { /* the_sandman: added colour */
663 snprintf(buf, 80, "\377v%s rises from the dead!",(r_name + r_ptr->name));
664
665 /* Tell every player */
666 msg_broadcast(0,buf);
667 }
668 r_ptr->max_num = 1;
669 }
670
671 /* Succeeded */
672 Packet_printf(&console_buf, "%c%c", CONSOLE_CHANGE_UNIQUE, 1);
673 }
674
console_message(char * buf)675 static void console_message(char *buf)
676 {
677 /* Send the message */
678 player_talk(0, buf);
679
680 /* Reply */
681 Packet_printf(&console_buf, "%c", CONSOLE_MESSAGE);
682 }
683
console_kick_player(char * name)684 static void console_kick_player(char *name)
685 {
686 int i;
687
688 /* Check the players in the game */
689 for (i = 1; i <= NumPlayers; i++) {
690 /* Check name */
691 if (!strcmp(name, Players[i]->name)) {
692 /* Kick him */
693 Destroy_connection(Players[i]->conn, "Kicked out");
694
695 /* Success */
696 Packet_printf(&console_buf, "%c%c", CONSOLE_KICK_PLAYER, 1);
697
698 return;
699 }
700 }
701
702 /* Failure */
703 Packet_printf(&console_buf, "%c%c", CONSOLE_KICK_PLAYER, 0);
704 }
705
console_reload_server_preferences(void)706 static void console_reload_server_preferences(void)
707 {
708 /* Reload the server preferences */
709 load_server_cfg();
710
711 /* Let mangconsole know that the command was a success */
712 /* Packet header */
713 Packet_printf(&console_buf, "%c", CONSOLE_RELOAD_SERVER_PREFERENCES);
714
715 /* Write the output */
716 DgramReply(console_buf.sock, console_buf.ptr, console_buf.len);
717 }
console_shutdown(void)718 static void console_shutdown(void)
719 {
720 /* Packet header */
721 Packet_printf(&console_buf, "%c", CONSOLE_SHUTDOWN);
722
723 /* Write the output */
724 DgramReply(console_buf.sock, console_buf.ptr, console_buf.len);
725
726 /* Shutdown */
727 shutdown_server();
728 }
729
730 /*
731 * This is the response function when incoming data is received on the
732 * control pipe.
733 */
NewConsole(int read_fd,int arg)734 void NewConsole(int read_fd, int arg)
735 {
736 char ch, passwd[80], buf[1024];
737 int i, j, bytes;
738 static int newsock = 0;
739
740 /* Make a TCP connection */
741 /* Hack -- check if this data has arrived on the contact socket or not.
742 * If it has, then we have not created a connection with the client yet,
743 * and so we must do so.
744 */
745 if (read_fd == ConsoleSocket)
746 {
747 /* Hack -- make sure that two people haven't tried to use mangconsole
748 * at the same time. Since I am currently too lazy to support this,
749 * we will remove the input of the first person when the second person
750 * connects.
751 */
752 if (newsock) remove_input(newsock);
753 if ((newsock = SocketAccept(read_fd)) == -1)
754 {
755 /* Clear socket if it failed */
756 newsock = 0;
757 quit("Couldn't accept console TCP connection.\n");
758 }
759 console_buf.sock = newsock;
760 install_input(NewConsole, newsock, 2);
761 return;
762 }
763
764
765 /* Clear the buffer */
766 Sockbuf_clear(&console_buf);
767 /* Read the message */
768 bytes = DgramReceiveAny(read_fd, console_buf.buf, console_buf.size);
769
770 /* Check for errors or our TCP connection closing */
771 if (bytes <= 0)
772 {
773 /* If this happens our TCP connection has probably been severed.
774 * Remove the input.
775 */
776 close(newsock);
777 remove_input(newsock);
778 newsock = 0;
779
780 return;
781 }
782
783 /* Set length */
784 console_buf.len = bytes;
785
786 /* Get the password */
787 Packet_scanf(&console_buf, "%s",passwd);
788
789 if (strcmp(passwd, cfg.console_password))
790 {
791 /* Clear buffer */
792 Sockbuf_clear(&console_buf);
793
794 /* Put an "illegal access" reply in the buffer */
795 Packet_printf(&console_buf, "%c", CONSOLE_DENIED);
796
797 /* Send it */
798 DgramWrite(read_fd, console_buf.buf, console_buf.len);
799
800 /* Log this to the local console */
801 s_printf("Illegal console command from %s.\n", DgramLastname(read_fd));
802
803 return;
804 }
805 else s_printf("Valid console command from %s.\n", DgramLastname(read_fd));
806
807 /* Acquire command */
808 Packet_scanf(&console_buf, "%c", &ch);
809
810 /* Determine what the command is */
811 switch(ch)
812 {
813 /* Wants to see the player list */
814 case CONSOLE_STATUS:
815 console_status();
816 break;
817
818 /* Wants to see detailed player info */
819 case CONSOLE_PLAYER_INFO:
820 Packet_scanf(&console_buf, "%d", &i);
821 console_player_info(i);
822 break;
823
824 /* Wants to see the artifact list */
825 case CONSOLE_ARTIFACT_LIST:
826 console_artifacts();
827 break;
828
829 /* Wants to see the unique list */
830 case CONSOLE_UNIQUE_LIST:
831 console_uniques();
832 break;
833
834 /* Wants to change artifact status */
835 case CONSOLE_CHANGE_ARTIFACT:
836 Packet_scanf(&console_buf, "%d%d", &i, &j);
837 console_change_artifact(i, j);
838 break;
839
840 /* Wants to change unique status */
841 case CONSOLE_CHANGE_UNIQUE:
842 Packet_scanf(&console_buf, "%d%s", &i, buf);
843 console_change_unique(i, buf);
844 break;
845
846 /* Wants to send a message */
847 case CONSOLE_MESSAGE:
848 Packet_scanf(&console_buf, "%s", buf);
849 console_message(buf);
850 break;
851
852 /* Wants to kick a player */
853 case CONSOLE_KICK_PLAYER:
854 Packet_scanf(&console_buf, "%s", buf);
855 console_kick_player(buf);
856 break;
857
858 /* Wants to reload the server preferences */
859 case CONSOLE_RELOAD_SERVER_PREFERENCES:
860 console_reload_server_preferences();
861 break;
862
863 /* Wants to shut the server down */
864 case CONSOLE_SHUTDOWN:
865 console_shutdown();
866 break;
867
868 /* Strangeness */
869 default:
870 s_printf("Bizarre input on server console; ignoring.\n");
871 return;
872 }
873
874 /* Write the response */
875 DgramWrite(console_buf.sock, console_buf.ptr, console_buf.len);
876 }
877
878 /*
879 * Initialize the stuff for the new console
880 */
InitNewConsole(int write_fd)881 bool InitNewConsole(int write_fd)
882 {
883 /* Initialize buffer */
884 if (Sockbuf_init(&console_buf, write_fd, 8192, SOCKBUF_READ | SOCKBUF_WRITE))
885 {
886 /* Failed */
887 s_printf("No memory for console buffer.\n");
888
889 return FALSE;
890 }
891
892 return TRUE;
893 }
894
895 #endif
896