/[LeafOK_CVS]/pvpgn-1.7.4/src/client/bnchat.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/client/bnchat.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 /*
2 * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu)
3 * Copyright (C) 1999 Oleg Drokin (green@ccssu.ccssu.crimea.ua)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include "common/setup_before.h"
20 #include <stdio.h>
21 #ifdef HAVE_STDDEF_H
22 # include <stddef.h>
23 #else
24 # ifndef NULL
25 # define NULL ((void *)0)
26 # endif
27 #endif
28 #include "compat/exitstatus.h"
29 #ifdef HAVE_STRING_H
30 # include <string.h>
31 #else
32 # ifdef HAVE_STRINGS_H
33 # include <strings.h>
34 # endif
35 #endif
36 #include "compat/strchr.h"
37 #include "compat/strdup.h"
38 #include "compat/strcasecmp.h"
39 #include "compat/vargs.h"
40 #include <ctype.h>
41 #include <errno.h>
42 #include "compat/strerror.h"
43 #ifdef TIME_WITH_SYS_TIME
44 # include <sys/time.h>
45 # include <time.h>
46 #else
47 # ifdef HAVE_SYS_TIME_H
48 # include <sys/time.h>
49 # else
50 # include <time.h>
51 # endif
52 #endif
53 #ifdef HAVE_UNISTD_H
54 # include <unistd.h>
55 #endif
56 #ifdef HAVE_FCNTL_H
57 # include <fcntl.h>
58 #else
59 # ifdef HAVE_SYS_FILE_H
60 # include <sys/file.h>
61 # endif
62 #endif
63 #ifdef HAVE_TERMIOS_H
64 # include <termios.h>
65 #endif
66 #include "compat/termios.h"
67 #ifdef HAVE_SYS_TYPES_H
68 # include <sys/types.h>
69 #endif
70 #ifdef HAVE_SIGACTION
71 # include <signal.h>
72 # include "compat/signal.h"
73 #endif
74 #ifdef HAVE_SYS_SELECT_H
75 # include <sys/select.h>
76 #endif
77 #ifdef HAVE_SYS_SOCKET_H
78 # include <sys/socket.h>
79 #endif
80 #include "compat/socket.h"
81 #ifdef HAVE_SYS_PARAM_H
82 # include <sys/param.h>
83 #endif
84 #ifdef HAVE_NETINET_IN_H
85 # include <netinet/in.h>
86 #endif
87 #include "compat/netinet_in.h"
88 #ifdef HAVE_ARPA_INET_H
89 # include <arpa/inet.h>
90 #endif
91 #include "compat/inet_ntoa.h"
92 #include "compat/psock.h"
93 #include "common/packet.h"
94 #include "common/init_protocol.h"
95 #include "common/udp_protocol.h"
96 #include "common/bnet_protocol.h"
97 #include "common/file_protocol.h"
98 #include "common/tag.h"
99 #include "common/bn_type.h"
100 #include "common/field_sizes.h"
101 #include "common/network.h"
102 #include "common/bnethash.h"
103 #include "common/bnethashconv.h"
104 #include "ansi_term.h"
105 #include "common/version.h"
106 #include "common/util.h"
107 #include "common/xalloc.h"
108 #include "common/hexdump.h"
109 #ifdef CLIENTDEBUG
110 # include "common/eventlog.h"
111 #endif
112 #include "client.h"
113 #include "udptest.h"
114 #include "client_connect.h"
115 #ifdef WIN32
116 # include <conio.h> /* for kbhit() and getch() */
117 #endif
118 #include "compat/vsnprintf.h"
119 #include "common/setup_after.h"
120
121
122 #ifdef CLIENTDEBUG
123 # define dprintf printf
124 #else
125 # define dprintf if (0) printf
126 #endif
127
128 #define CHANNEL_BNCHATBOT "Chat"
129 #define CHANNEL_STARCRAFT "Starcraft"
130 #define CHANNEL_BROODWARS "Brood War"
131 #define CHANNEL_SHAREWARE "Starcraft Shareware"
132 #define CHANNEL_DIABLORTL "Diablo Retail"
133 #define CHANNEL_DIABLOSHR "Diablo Shareware" /* FIXME: is this one right? */
134 #define CHANNEL_WARCIIBNE "War2BNE"
135 #define CHANNEL_DIABLO2DV "Diablo II"
136 #define CHANNEL_DIABLO2XP "Diablo II"
137 #define CHANNEL_WARCRAFT3 "W3"
138 #define CHANNEL_WAR3XP "W3"
139
140
141 volatile int handle_winch=0;
142
143 typedef enum {
144 mode_chat,
145 mode_command,
146 mode_waitstat,
147 mode_waitgames,
148 mode_waitladder,
149 mode_gamename,
150 mode_gamepass,
151 mode_gamewait,
152 mode_gamestop,
153 mode_claninvite
154 } t_mode;
155
156 typedef struct _client_state
157 {
158 int useansi;
159 int sd;
160 struct sockaddr_in saddr;
161 unsigned int sessionkey;
162 unsigned int sessionnum;
163 unsigned int currsize;
164 unsigned int commpos;
165 struct termios in_attr_old;
166 struct termios in_attr_new;
167 int changed_in;
168 int fd_stdin;
169 unsigned int screen_width,screen_height;
170 int munged;
171 t_mode mode;
172 char text[MAX_MESSAGE_LEN];
173 } t_client_state;
174
175 typedef struct _user_info
176 {
177 char const * clienttag;
178 char player[MAX_MESSAGE_LEN];
179 char const * cdowner;
180 char const * cdkey;
181 char const * channel;
182 char curr_gamename[GAME_NAME_LEN];
183 char curr_gamepass[GAME_PASS_LEN];
184 int count, clantag;
185 char const * inviter;
186
187 } t_user_info;
188
189
190 static char const * mflags_get_str(unsigned int flags);
191 static char const * cflags_get_str(unsigned int flags);
192 static char const * mode_get_prompt(t_mode mode);
193 static int print_file(struct sockaddr_in * saddr, char const * filename, char const * progname, char const * clienttag);
194 static void usage(char const * progname);
195 #ifdef HAVE_SIGACTION
196 static void winch_sig_handle(int unused);
197 #endif
198
199
200 #ifdef HAVE_SIGACTION
201 static void winch_sig_handle(int unused)
202 {
203 handle_winch = 1;
204 }
205 #endif
206
207
208 static char const * mflags_get_str(unsigned int flags)
209 {
210 static char buffer[32];
211
212 buffer[0]=buffer[1] = '\0';
213 if (flags&MF_BLIZZARD)
214 strcat(buffer,",Blizzard");
215 if (flags&MF_GAVEL)
216 strcat(buffer,",Gavel");
217 if (flags&MF_VOICE)
218 strcat(buffer,",Megaphone");
219 if (flags&MF_BNET)
220 strcat(buffer,",BNET");
221 if (flags&MF_PLUG)
222 strcat(buffer,",Plug");
223 if (flags&MF_X)
224 strcat(buffer,",X");
225 if (flags&MF_SHADES)
226 strcat(buffer,",Shades");
227 if (flags&MF_PGLPLAY)
228 strcat(buffer,",PGL_Player");
229 if (flags&MF_PGLOFFL)
230 strcat(buffer,",PGL_Official");
231 buffer[0] = '[';
232 strcat(buffer,"]");
233
234 return buffer;
235 }
236
237
238 static char const * cflags_get_str(unsigned int flags)
239 {
240 static char buffer[32];
241
242 buffer[0]=buffer[1] = '\0';
243 if (flags&CF_PUBLIC)
244 strcat(buffer,",Public");
245 if (flags&CF_MODERATED)
246 strcat(buffer,",Moderated");
247 if (flags&CF_RESTRICTED)
248 strcat(buffer,",Restricted");
249 if (flags&CF_THEVOID)
250 strcat(buffer,",The Void");
251 if (flags&CF_SYSTEM)
252 strcat(buffer,",System");
253 if (flags&CF_OFFICIAL)
254 strcat(buffer,",Official");
255 buffer[0] = '[';
256 strcat(buffer,"]");
257
258 return buffer;
259 }
260
261
262 static char const * mode_get_prompt(t_mode mode)
263 {
264 switch (mode)
265 {
266 case mode_chat:
267 return "] ";
268 case mode_command:
269 return "command> ";
270 case mode_waitstat:
271 case mode_waitgames:
272 case mode_waitladder:
273 case mode_gamewait:
274 return "*please wait* ";
275 case mode_gamename:
276 return "Name: ";
277 case mode_gamepass:
278 return "Password: ";
279 case mode_gamestop:
280 return "[Return to kill game] ";
281 default:
282 return "? ";
283 }
284 }
285
286
287 static int print_file(struct sockaddr_in * saddr, char const * filename, char const * progname, char const * clienttag)
288 {
289 int sd;
290 t_packet * ipacket;
291 t_packet * packet;
292 t_packet * rpacket;
293 t_packet * fpacket;
294 unsigned int currsize;
295 unsigned int filelen;
296
297 if (!saddr || !filename || !progname)
298 return -1;
299
300 if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0)
301 {
302 fprintf(stderr,"%s: could not create socket (psock_socket: %s)\n",progname,pstrerror(psock_errno()));
303 return -1;
304 }
305
306 if (psock_connect(sd,(struct sockaddr *)saddr,sizeof(*saddr))<0)
307 {
308 fprintf(stderr,"%s: could not connect to server (psock_connect: %s)\n",progname,pstrerror(psock_errno()));
309 return -1;
310 }
311
312 if (!(ipacket = packet_create(packet_class_init)))
313 {
314 fprintf(stderr,"%s: could not create packet\n",progname);
315 return -1;
316 }
317 bn_byte_set(&ipacket->u.client_initconn.class,CLIENT_INITCONN_CLASS_FILE);
318 client_blocksend_packet(sd,ipacket);
319 packet_del_ref(ipacket);
320
321 if (!(rpacket = packet_create(packet_class_file)))
322 {
323 fprintf(stderr,"%s: could not create packet\n",progname);
324 return -1;
325 }
326
327 if (!(fpacket = packet_create(packet_class_raw)))
328 {
329 fprintf(stderr,"%s: could not create packet\n",progname);
330 return -1;
331 }
332
333 if (!(packet = packet_create(packet_class_file)))
334 {
335 fprintf(stderr,"%s: could not create packet\n",progname);
336 return -1;
337 }
338 packet_set_size(packet,sizeof(t_client_file_req));
339 packet_set_type(packet,CLIENT_FILE_REQ);
340 bn_int_tag_set(&packet->u.client_file_req.archtag,ARCHTAG_WINX86);
341 bn_int_tag_set(&packet->u.client_file_req.clienttag,clienttag);
342 bn_int_set(&packet->u.client_file_req.adid,0);
343 bn_int_set(&packet->u.client_file_req.extensiontag,0);
344 bn_int_set(&packet->u.client_file_req.startoffset,0);
345 bn_long_set_a_b(&packet->u.client_file_req.timestamp,0x00000000,0x00000000);
346 packet_append_string(packet,filename);
347 client_blocksend_packet(sd,packet);
348 packet_del_ref(packet);
349
350 do
351 if (client_blockrecv_packet(sd,rpacket)<0)
352 {
353 fprintf(stderr,"%s: server closed file connection\n",progname);
354 packet_del_ref(fpacket);
355 packet_del_ref(rpacket);
356 return -1;
357 }
358 while (packet_get_type(rpacket)!=SERVER_FILE_REPLY);
359
360 filelen = bn_int_get(rpacket->u.server_file_reply.filelen);
361 packet_del_ref(rpacket);
362
363 for (currsize=0; currsize+MAX_PACKET_SIZE<=filelen; currsize+=MAX_PACKET_SIZE)
364 {
365 if (client_blockrecv_raw_packet(sd,fpacket,MAX_PACKET_SIZE)<0)
366 {
367 fflush(stdout);
368 fprintf(stderr,"%s: server closed file connection\n",progname);
369 packet_del_ref(fpacket);
370 return -1;
371 }
372 str_print_term(stdout,packet_get_raw_data_const(fpacket,0),MAX_PACKET_SIZE,1);
373 }
374 filelen -= currsize;
375 if (filelen)
376 {
377 if (client_blockrecv_raw_packet(sd,fpacket,filelen)<0)
378 {
379 fflush(stdout);
380 fprintf(stderr,"%s: server closed file connection\n",progname);
381 packet_del_ref(fpacket);
382 return -1;
383 }
384 str_print_term(stdout,packet_get_raw_data_const(fpacket,0),filelen,1);
385 }
386 fflush(stdout);
387
388 psock_close(sd);
389
390 packet_del_ref(fpacket);
391
392 return 0;
393 }
394
395
396 static void usage(char const * progname)
397 {
398 fprintf(stderr,"usage: %s [<options>] [<servername> [<TCP portnumber>]]\n",progname);
399 fprintf(stderr,
400 " -a, --ansi-color use ANSI colors\n"
401 " -n, --new-account create a new account\n"
402 " -c, --change-password change account password\n"
403 " --client=CHAT report client as a chat bot\n"
404 " -b, --client=SEXP report client as Brood Wars\n"
405 " -d, --client=DRTL report client as Diablo Retail\n"
406 " --client=DSHR report client as Diablo Shareware\n");
407 fprintf(stderr,
408 " -s, --client=STAR report client as Starcraft (default)\n"
409 " --client=SSHR report client as Starcraft Shareware\n"
410 " -w, --client=W2BN report client as Warcraft II BNE\n"
411 " --client=D2DV report client as Diablo II\n"
412 " --client=D2XP report client as Diablo II: LoD\n"
413 " --client=WAR3 report client as Warcraft III\n"
414 " --client=W3XP report client as Warcraft III Frozen Throne\n");
415 fprintf(stderr,
416 " -o NAME, --owner=NAME report CD owner as NAME\n"
417 " -k KEY, --cdkey=KEY report CD key as KEY\n"
418 " -h, --help, --usage show this information and exit\n"
419 " -v, --version print version number and exit\n");
420 exit(STATUS_FAILURE);
421 }
422
423 int read_commandline(int argc, char * * argv,
424 char const * * servname, unsigned short * servport,
425 char const * * clienttag,
426 int * changepass, int * newacct,
427 char const * * channel,
428 char const * * cdowner,
429 char const * * cdkey,
430 int * useansi)
431 {
432 int a;
433
434 if (argc<1 || !argv || !argv[0])
435 {
436 fprintf(stderr,"bad arguments\n");
437 return STATUS_FAILURE;
438 }
439
440 for (a=1; a<argc; a++)
441 if (*servname && isdigit((int)argv[a][0]) && a+1>=argc)
442 {
443 if (str_to_ushort(argv[a],servport)<0)
444 {
445 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]);
446 usage(argv[0]);
447 }
448 }
449 else if (!(*servname) && argv[a][0]!='-' && a+2>=argc)
450 *servname = argv[a];
451 else if (strcmp(argv[a],"-a")==0 || strcmp(argv[a],"--use-ansi")==0)
452 *useansi = 1;
453 else if (strcmp(argv[a],"-n")==0 || strcmp(argv[a],"--new-account")==0)
454 {
455 if (*changepass)
456 {
457 fprintf(stderr,"%s: can not create new account when changing passwords\n",argv[0]);
458 usage(argv[0]);
459 }
460 *newacct = 1;
461 }
462 else if (strcmp(argv[a],"-c")==0 || strcmp(argv[a],"--change-password")==0)
463 {
464 if (*newacct)
465 {
466 fprintf(stderr,"%s: can not change passwords when creating a new account\n",argv[0]);
467 usage(argv[0]);
468 }
469 *changepass = 1;
470 }
471 else if (strcmp(argv[a],"--client=CHAT")==0)
472 {
473 if (*clienttag)
474 {
475 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
476 usage(argv[0]);
477 }
478 *clienttag = CLIENTTAG_BNCHATBOT;
479 *channel = CHANNEL_BNCHATBOT;
480 }
481 else if (strcmp(argv[a],"-b")==0 || strcmp(argv[a],"--client=SEXP")==0)
482 {
483 if (*clienttag)
484 {
485 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
486 usage(argv[0]);
487 }
488 *clienttag = CLIENTTAG_BROODWARS;
489 *channel = CHANNEL_BROODWARS;
490 }
491 else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--client=DRTL")==0)
492 {
493 if (*clienttag)
494 {
495 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
496 usage(argv[0]);
497 }
498 *clienttag = CLIENTTAG_DIABLORTL;
499 *channel = CHANNEL_DIABLORTL;
500 }
501 else if (strcmp(argv[a],"--client=DSHR")==0)
502 {
503 if (*clienttag)
504 {
505 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
506 usage(argv[0]);
507 }
508 *clienttag = CLIENTTAG_DIABLOSHR;
509 *channel = CHANNEL_DIABLOSHR;
510 }
511 else if (strcmp(argv[a],"-s")==0 || strcmp(argv[a],"--client=STAR")==0)
512 {
513 if (*clienttag)
514 {
515 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
516 usage(argv[0]);
517 }
518 *clienttag = CLIENTTAG_STARCRAFT;
519 *channel = CHANNEL_STARCRAFT;
520 }
521 else if (strcmp(argv[a],"--client=SSHR")==0)
522 {
523 if (*clienttag)
524 {
525 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
526 usage(argv[0]);
527 }
528 *clienttag = CLIENTTAG_SHAREWARE;
529 *channel = CHANNEL_SHAREWARE;
530 }
531 else if (strcmp(argv[a],"-w")==0 || strcmp(argv[a],"--client=W2BN")==0)
532 {
533 if (*clienttag)
534 {
535 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
536 usage(argv[0]);
537 }
538 *clienttag = CLIENTTAG_WARCIIBNE;
539 *channel = CHANNEL_WARCIIBNE;
540 }
541 else if (strcmp(argv[a],"--client=D2DV")==0)
542 {
543 if (*clienttag)
544 {
545 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
546 usage(argv[0]);
547 }
548 *clienttag = CLIENTTAG_DIABLO2DV;
549 *channel = CHANNEL_DIABLO2DV;
550 }
551 else if (strcmp(argv[a],"--client=D2XP")==0)
552 {
553 if (*clienttag)
554 {
555 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
556 usage(argv[0]);
557 }
558 *clienttag = CLIENTTAG_DIABLO2XP;
559 *channel = CHANNEL_DIABLO2XP;
560 }
561 else if (strcmp(argv[a],"--client=WAR3")==0)
562 {
563 if (*clienttag)
564 {
565 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
566 usage(argv[0]);
567 }
568 *clienttag = CLIENTTAG_WARCRAFT3;
569 *channel = CHANNEL_WARCRAFT3;
570 }
571 else if (strcmp(argv[a],"--client=W3XP")==0)
572 {
573 if (*clienttag)
574 {
575 fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],*clienttag);
576 usage(argv[0]);
577 }
578 *clienttag = CLIENTTAG_WAR3XP;
579 *channel = CHANNEL_WAR3XP;
580 }
581 else if (strncmp(argv[a],"--client=",9)==0)
582 {
583 fprintf(stderr,"%s: unknown client tag \"%s\"\n",argv[0],&argv[a][9]);
584 usage(argv[0]);
585 }
586 else if (strcmp(argv[a],"-o")==0)
587 {
588 if (a+1>=argc)
589 {
590 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
591 usage(argv[0]);
592 }
593 if (*cdowner)
594 {
595 fprintf(stderr,"%s: CD owner was already specified as \"%s\"\n",argv[0],*cdowner);
596 usage(argv[0]);
597 }
598 *cdowner = argv[++a];
599 }
600 else if (strncmp(argv[a],"--owner=",8)==0)
601 {
602 if (*cdowner)
603 {
604 fprintf(stderr,"%s: CD owner was already specified as \"%s\"\n",argv[0],*cdowner);
605 usage(argv[0]);
606 }
607 *cdowner = &argv[a][8];
608 }
609 else if (strcmp(argv[a],"-k")==0)
610 {
611 if (a+1>=argc)
612 {
613 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
614 usage(argv[0]);
615 }
616 if (*cdkey)
617 {
618 fprintf(stderr,"%s: CD key was already specified as \"%s\"\n",argv[0],*cdkey);
619 usage(argv[0]);
620 }
621 *cdkey = argv[++a];
622 }
623 else if (strncmp(argv[a],"--cdkey=",8)==0)
624 {
625 if (*cdkey)
626 {
627 fprintf(stderr,"%s: CD key was already specified as \"%s\"\n",argv[0],*cdkey);
628 usage(argv[0]);
629 }
630 *cdkey = &argv[a][8];
631 }
632 else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0)
633 {
634 printf("version "PVPGN_VERSION"\n");
635 return STATUS_SUCCESS;
636 }
637 else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0)
638 usage(argv[0]);
639 else if (strcmp(argv[a],"--client")==0 || strcmp(argv[a],"--owner")==0 || strcmp(argv[a],"--cdkey")==0)
640 {
641 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
642 usage(argv[0]);
643 }
644 else
645 {
646 fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]);
647 usage(argv[0]);
648 }
649
650 if (*servport==0)
651 *servport = BNETD_SERV_PORT;
652 if (!(*cdowner))
653 *cdowner = BNETD_DEFAULT_OWNER;
654 if (!(*cdkey))
655 *cdkey = BNETD_DEFAULT_KEY;
656 if (!(*clienttag))
657 {
658 *clienttag = CLIENTTAG_STARCRAFT;
659 *channel = CHANNEL_STARCRAFT;
660 }
661 if (!(*servname))
662 *servname = BNETD_DEFAULT_HOST;
663
664 return 0;
665 }
666
667 void munge(t_client_state * client)
668 {
669 int i;
670
671 if (!client->munged)
672 {
673 printf("\r");
674 for (i=0; i<strlen(mode_get_prompt(client->mode)); i++)
675 printf(" ");
676 for (i=0; i<strlen(client->text) && i<client->screen_width-strlen(mode_get_prompt(client->mode)); i++)
677 printf(" ");
678 printf("\r");
679 client->munged = 1;
680 }
681 }
682
683 void ansi_printf(t_client_state * client,int color, char const * fmt, ...)
684 {
685 va_list args;
686 char buffer[2048];
687
688 if (!(client))
689 return;
690
691 if (!(fmt))
692 return;
693
694 if (client->useansi)
695 ansi_text_color_fore(color);
696
697 VA_START(args,fmt);
698 vsnprintf(buffer,2048,fmt,args);
699 va_end(args);
700
701 str_print_term(stdout,buffer,0,1);
702
703 if (client->useansi)
704 ansi_text_reset();
705
706 fflush(stdout);
707
708 }
709
710 extern int main(int argc, char * argv[])
711 {
712 int newacct=0;
713 int changepass=0;
714 t_client_state client;
715 t_user_info user;
716 t_packet * packet;
717 t_packet * rpacket;
718 char const * servname=NULL;
719 unsigned short servport=0;
720 char const * * channellist;
721 unsigned int statsmatch=24; /* any random number that is rare in uninitialized fields */
722
723 memset(&user,0,sizeof(t_user_info));
724 memset(&client,0,sizeof(t_client_state));
725
726 read_commandline(argc,argv,&servname,&servport,&user.clienttag,&changepass,&newacct,&user.channel,
727 &user.cdowner,&user.cdkey,&client.useansi);
728
729 client.fd_stdin = fileno(stdin);
730 if (tcgetattr(client.fd_stdin,&client.in_attr_old)>=0)
731 {
732 client.in_attr_new = client.in_attr_old;
733 client.in_attr_new.c_lflag &= ~(ECHO | ICANON); /* turn off ECHO and ICANON */
734 client.in_attr_new.c_cc[VMIN] = 0; /* don't require reads to return data */
735 client.in_attr_new.c_cc[VTIME] = 1; /* timeout = .1 seconds */
736 tcsetattr(client.fd_stdin,TCSANOW,&client.in_attr_new);
737 client.changed_in = 1;
738 }
739 else
740 {
741 fprintf(stderr,"%s: could not set terminal attributes for stdin\n",argv[0]);
742 client.changed_in = 0;
743 }
744
745 #ifdef HAVE_SIGACTION
746 {
747 struct sigaction winch_action;
748
749 winch_action.sa_handler = winch_sig_handle;
750 sigemptyset(&winch_action.sa_mask);
751 winch_action.sa_flags = SA_RESTART;
752
753 sigaction(SIGWINCH,&winch_action,NULL);
754 }
755 #endif
756
757
758 if (client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height)<0)
759 {
760 fprintf(stderr,"%s: could not determine screen size\n",argv[0]);
761 if (client.changed_in)
762 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
763 return STATUS_FAILURE;
764 }
765
766 if (client.useansi)
767 {
768 ansi_text_reset();
769 ansi_screen_clear();
770 ansi_cursor_move_home();
771 fflush(stdout);
772 }
773
774 if ((client.sd = client_connect(argv[0],
775 servname,servport,user.cdowner,user.cdkey,user.clienttag,
776 &client.saddr,&client.sessionkey,&client.sessionnum,ARCHTAG_WINX86))<0)
777 {
778 fprintf(stderr,"%s: fatal error during handshake\n",argv[0]);
779 if (client.changed_in)
780 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
781 return STATUS_FAILURE;
782 }
783
784 /* reuse this same packet over and over */
785 if (!(rpacket = packet_create(packet_class_bnet)))
786 {
787 fprintf(stderr,"%s: could not create packet\n",argv[0]);
788 psock_close(client.sd);
789 if (client.changed_in)
790 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
791 return STATUS_FAILURE;
792 }
793
794 if (!(packet = packet_create(packet_class_bnet)))
795 {
796 fprintf(stderr,"%s: could not create packet\n",argv[0]);
797 psock_close(client.sd);
798 if (client.changed_in)
799 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
800 return STATUS_FAILURE;
801 }
802 packet_set_size(packet,sizeof(t_client_fileinforeq));
803 packet_set_type(packet,CLIENT_FILEINFOREQ);
804 bn_int_set(&packet->u.client_fileinforeq.type,CLIENT_FILEINFOREQ_TYPE_TOS);
805 bn_int_set(&packet->u.client_fileinforeq.unknown2,CLIENT_FILEINFOREQ_UNKNOWN2);
806
807 if ((user.clienttag == CLIENTTAG_DIABLO2DV) || (user.clienttag == CLIENTTAG_DIABLO2XP))
808 packet_append_string(packet,CLIENT_FILEINFOREQ_FILE_TOSUNICODEUSA);
809 else
810 packet_append_string(packet,CLIENT_FILEINFOREQ_FILE_TOSUSA);
811
812 client_blocksend_packet(client.sd,packet);
813 packet_del_ref(packet);
814 do
815 if (client_blockrecv_packet(client.sd,rpacket)<0)
816 {
817 fprintf(stderr,"%s: server closed connection\n",argv[0]);
818 psock_close(client.sd);
819 if (client.changed_in)
820 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
821 return STATUS_FAILURE;
822 }
823 while (packet_get_type(rpacket)!=SERVER_FILEINFOREPLY);
824
825 /* real client would also send statsreq on past logins here */
826
827 printf("----\n");
828 if (newacct)
829 {
830 if (client.useansi)
831 ansi_text_color_fore(ansi_text_color_red);
832 printf("###### Terms Of Service ######\n");
833 print_file(&client.saddr,packet_get_str_const(rpacket,sizeof(t_server_fileinforeply),1024),argv[0],user.clienttag);
834 printf("##############################\n\n");
835 if (client.useansi)
836 ansi_text_reset();
837 }
838
839 for (;;)
840 {
841 char password[MAX_MESSAGE_LEN];
842 unsigned int i;
843 int status;
844
845 if (newacct)
846 {
847 char passwordvrfy[MAX_MESSAGE_LEN];
848 t_hash passhash1;
849
850 printf("Enter information for your new account\n");
851 client.munged = 1;
852 client.commpos = 0;
853 user.player[0] = '\0';
854 while ((status = client_get_comm("Username: ",user.player,MAX_MESSAGE_LEN,&client.commpos,
855 1,client.munged,client.screen_width))==0)
856 if (handle_winch)
857 {
858 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
859 printf(" \r");
860 client.munged = 1;
861 handle_winch = 0;
862 }
863 else
864 client.munged = 0;
865 printf("\n");
866 if (status<0)
867 continue;
868 if (strchr(user.player,' ') || strchr(user.player,'\t') ||
869 strchr(user.player,'\r') || strchr(user.player,'\n') )
870 {
871 printf("Spaces are not allowed in usernames. Try again.\n");
872 continue;
873 }
874 /* we could use strcspn() but it doesn't exist everywhere */
875 if (strchr(user.player,'#') ||
876 strchr(user.player,'%') ||
877 strchr(user.player,'&') ||
878 strchr(user.player,'*') ||
879 strchr(user.player,'\\') ||
880 strchr(user.player,'"') ||
881 strchr(user.player,',') ||
882 strchr(user.player,'<') ||
883 strchr(user.player,'/') ||
884 strchr(user.player,'>') ||
885 strchr(user.player,'?'))
886 {
887 printf("The special characters #%%&*\\\",</>? are allowed in usernames. Try again.\n");
888 }
889 if (strlen(user.player)>=USER_NAME_MAX)
890 {
891 printf("Usernames must not be more than %u characters long. Try again.\n",USER_NAME_MAX-1);
892 continue;
893 }
894
895 client.munged = 1;
896 client.commpos = 0;
897 password[0] = '\0';
898 while ((status = client_get_comm("Password: ",password,MAX_MESSAGE_LEN,&client.commpos,0,
899 client.munged,client.screen_width))==0)
900 if (handle_winch)
901 {
902 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
903 printf(" \r");
904 client.munged = 1;
905 handle_winch = 0;
906 }
907 else
908 client.munged = 0;
909 printf("\n");
910 if (status<0)
911 continue;
912 if (strlen(password)>USER_PASS_MAX)
913 {
914 printf("password must not be more than %u characters long. Try again.\n",USER_PASS_MAX);
915 continue;
916 }
917 for (i=0; i<strlen(password); i++)
918 if (isupper((int)password[i]))
919 password[i] = tolower((int)password[i]);
920
921 client.munged = 1;
922 client.commpos = 0;
923 passwordvrfy[0] = '\0';
924 while ((status = client_get_comm("Retype password: ",passwordvrfy,MAX_MESSAGE_LEN,&client.commpos,0,
925 client.munged,client.screen_width))==0)
926 if (handle_winch)
927 {
928 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
929 printf(" \r");
930 client.munged = 1;
931 handle_winch = 0;
932 }
933 else
934 client.munged = 0;
935 printf("\n");
936 if (status<0)
937 continue;
938 for (i=0; i<strlen(passwordvrfy); i++)
939 passwordvrfy[i] = tolower((int)passwordvrfy[i]);
940
941 if (strcmp(password,passwordvrfy)!=0)
942 {
943 printf("Passwords do not match. Try again.\n");
944 continue;
945 }
946
947 bnet_hash(&passhash1,strlen(password),password); /* do the single hash */
948
949 if (!(packet = packet_create(packet_class_bnet)))
950 {
951 fprintf(stderr,"%s: could not create packet\n",argv[0]);
952 psock_close(client.sd);
953 if (client.changed_in)
954 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
955 return STATUS_FAILURE;
956 }
957 packet_set_size(packet,sizeof(t_client_createacctreq1));
958 packet_set_type(packet,CLIENT_CREATEACCTREQ1);
959 hash_to_bnhash((t_hash const *)&passhash1,packet->u.client_createacctreq1.password_hash1); /* avoid warning */
960 packet_append_string(packet,user.player);
961 client_blocksend_packet(client.sd,packet);
962 packet_del_ref(packet);
963
964 do
965 if (client_blockrecv_packet(client.sd,rpacket)<0)
966 {
967 fprintf(stderr,"%s: server closed connection\n",argv[0]);
968 psock_close(client.sd);
969 if (client.changed_in)
970 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
971 return STATUS_FAILURE;
972 }
973 while (packet_get_type(rpacket)!=SERVER_CREATEACCTREPLY1);
974 dprintf("Got CREATEACCTREPLY1\n");
975 if (bn_int_get(rpacket->u.server_createacctreply1.result)==SERVER_CREATEACCTREPLY1_RESULT_NO)
976 {
977 printf("Could not create an account under that name. Try another one.\n");
978 continue;
979 }
980 printf("Account created.\n");
981 }
982 else if (changepass)
983 {
984 char passwordprev[MAX_MESSAGE_LEN];
985 char passwordvrfy[MAX_MESSAGE_LEN];
986 struct
987 {
988 bn_int ticks;
989 bn_int sessionkey;
990 bn_int passhash1[5];
991 } temp;
992 t_hash oldpasshash1;
993 t_hash oldpasshash2;
994 t_hash newpasshash1;
995 unsigned int ticks;
996
997 printf("Enter your old and new login information\n");
998
999 client.munged = 1;
1000 client.commpos = 0;
1001 user.player[0] = '\0';
1002 while ((status = client_get_comm("Username: ",user.player,MAX_MESSAGE_LEN,&client.commpos,1,
1003 client.munged,client.screen_width))==0)
1004 if (handle_winch)
1005 {
1006 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1007 printf(" \r");
1008 client.munged = 1;
1009 handle_winch = 0;
1010 }
1011 else
1012 client.munged = 0;
1013 printf("\n");
1014 if (status<0)
1015 continue;
1016 if (strchr(user.player,' '))
1017 {
1018 printf("Spaces not allowed in username. Try again.\n");
1019 continue;
1020 }
1021 if (strlen(user.player)>=USER_NAME_MAX)
1022 {
1023 printf("Usernames must not be more than %u characters long. Try again.\n",USER_NAME_MAX-1);
1024 continue;
1025 }
1026
1027 client.munged = 1;
1028 client.commpos = 0;
1029 passwordprev[0] = '\0';
1030 while ((status = client_get_comm("Old password: ",passwordprev,MAX_MESSAGE_LEN,&client.commpos,0,
1031 client.munged,client.screen_width))==0)
1032 if (handle_winch)
1033 {
1034 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1035 printf(" \r");
1036 client.munged = 1;
1037 handle_winch = 0;
1038 }
1039 else
1040 client.munged = 0;
1041 printf("\n");
1042 if (status<0)
1043 continue;
1044 for (i=0; i<strlen(passwordprev); i++)
1045 passwordprev[i] = tolower((int)passwordprev[i]);
1046
1047 client.munged = 1;
1048 client.commpos = 0;
1049 password[0] = '\0';
1050 while ((status = client_get_comm("New password: ",password,MAX_MESSAGE_LEN,&client.commpos,0,
1051 client.munged,client.screen_width))==0)
1052 if (handle_winch)
1053 {
1054 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1055 printf(" \r");
1056 client.munged = 1;
1057 handle_winch = 0;
1058 }
1059 else
1060 client.munged = 0;
1061 printf("\n");
1062 if (status<0)
1063 continue;
1064 for (i=0; i<strlen(password); i++)
1065 password[i] = tolower((int)password[i]);
1066
1067 client.munged = 1;
1068 client.commpos = 0;
1069 passwordvrfy[0] = '\0';
1070 while ((status = client_get_comm("Retype new password: ",passwordvrfy,MAX_MESSAGE_LEN,&client.commpos,0,
1071 client.munged,client.screen_width))==0)
1072 if (handle_winch)
1073 {
1074 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1075 printf(" \r");
1076 client.munged = 1;
1077 handle_winch = 0;
1078 }
1079 else
1080 client.munged = 0;
1081 printf("\n");
1082 if (status<0)
1083 continue;
1084 for (i=0; i<strlen(passwordvrfy); i++)
1085 passwordvrfy[i] = tolower((int)passwordvrfy[i]);
1086
1087 if (strcmp(password,passwordvrfy)!=0)
1088 {
1089 printf("New passwords do not match. Try again.\n");
1090 continue;
1091 }
1092
1093 ticks = 0; /* FIXME: what to use here? */
1094 bn_int_set(&temp.ticks,ticks);
1095 bn_int_set(&temp.sessionkey,client.sessionkey);
1096 bnet_hash(&oldpasshash1,strlen(passwordprev),passwordprev); /* do the single hash for old */
1097 hash_to_bnhash((t_hash const *)&oldpasshash1,temp.passhash1); /* avoid warning */
1098 bnet_hash(&oldpasshash2,sizeof(temp),&temp); /* do the double hash for old */
1099 bnet_hash(&newpasshash1,strlen(password),password); /* do the single hash for new */
1100
1101 if (!(packet = packet_create(packet_class_bnet)))
1102 {
1103 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1104 psock_close(client.sd);
1105 if (client.changed_in)
1106 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1107 return STATUS_FAILURE;
1108 }
1109 packet_set_size(packet,sizeof(t_client_changepassreq));
1110 packet_set_type(packet,CLIENT_CHANGEPASSREQ);
1111 bn_int_set(&packet->u.client_changepassreq.ticks,ticks);
1112 bn_int_set(&packet->u.client_changepassreq.sessionkey,client.sessionkey);
1113 hash_to_bnhash((t_hash const *)&oldpasshash2,packet->u.client_changepassreq.oldpassword_hash2); /* avoid warning */
1114 hash_to_bnhash((t_hash const *)&newpasshash1,packet->u.client_changepassreq.newpassword_hash1); /* avoid warning */
1115 packet_append_string(packet,user.player);
1116 client_blocksend_packet(client.sd,packet);
1117 packet_del_ref(packet);
1118
1119 do
1120 if (client_blockrecv_packet(client.sd,rpacket)<0)
1121 {
1122 fprintf(stderr,"%s: server closed connection\n",argv[0]);
1123 psock_close(client.sd);
1124 if (client.changed_in)
1125 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1126 return STATUS_FAILURE;
1127 }
1128 while (packet_get_type(rpacket)!=SERVER_CHANGEPASSACK);
1129 dprintf("Got CHANGEPASSACK\n");
1130 if (bn_int_get(rpacket->u.server_changepassack.message)==SERVER_CHANGEPASSACK_MESSAGE_FAIL)
1131 {
1132 printf("Could not change password. Try again.\n");
1133 continue;
1134 }
1135 printf("Password changed.\n");
1136 }
1137 else
1138 {
1139 printf("Enter your login information\n");
1140
1141 client.munged = 1;
1142 client.commpos = 0;
1143 user.player[0] = '\0';
1144 while ((status = client_get_comm("Username: ",user.player,MAX_MESSAGE_LEN,&client.commpos,1,
1145 client.munged,client.screen_width))==0)
1146 if (handle_winch)
1147 {
1148 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1149 printf(" \r");
1150 client.munged = 1;
1151 handle_winch = 0;
1152 }
1153 else
1154 client.munged = 0;
1155 printf("\n");
1156 if (status<0)
1157 continue;
1158 if (strchr(user.player,' '))
1159 {
1160 printf("Spaces not allowed in username. Try again.\n");
1161 continue;
1162 }
1163 if (strlen(user.player)>=USER_NAME_MAX)
1164 {
1165 printf("Usernames must not be more than %u characters long. Try again.\n",USER_NAME_MAX-1);
1166 continue;
1167 }
1168
1169 client.munged = 1;
1170 client.commpos = 0;
1171 password[0] = '\0';
1172 while ((status = client_get_comm("Password: ",password,MAX_MESSAGE_LEN,&client.commpos,0,
1173 client.munged,client.screen_width))==0)
1174 if (handle_winch)
1175 {
1176 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1177 printf(" \r");
1178 client.munged = 1;
1179 handle_winch = 0;
1180 }
1181 else
1182 client.munged = 0;
1183 printf("\n");
1184 if (status<0)
1185 continue;
1186 for (i=0; i<strlen(password); i++)
1187 password[i] = tolower((int)password[i]);
1188 }
1189
1190 /* now login */
1191 {
1192 struct
1193 {
1194 bn_int ticks;
1195 bn_int sessionkey;
1196 bn_int passhash1[5];
1197 } temp;
1198 t_hash passhash1;
1199 t_hash passhash2;
1200 unsigned int ticks;
1201
1202 ticks = 0; /* FIXME: what to use here? */
1203 bn_int_set(&temp.ticks,ticks);
1204 bn_int_set(&temp.sessionkey,client.sessionkey);
1205 bnet_hash(&passhash1,strlen(password),password); /* do the single hash */
1206 hash_to_bnhash((t_hash const *)&passhash1,temp.passhash1); /* avoid warning */
1207 bnet_hash(&passhash2,sizeof(temp),&temp); /* do the double hash */
1208
1209 if (!(packet = packet_create(packet_class_bnet)))
1210 {
1211 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1212 psock_close(client.sd);
1213 if (client.changed_in)
1214 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1215 return STATUS_FAILURE;
1216 }
1217 packet_set_size(packet,sizeof(t_client_loginreq1));
1218 packet_set_type(packet,CLIENT_LOGINREQ1);
1219 bn_int_set(&packet->u.client_loginreq1.ticks,ticks);
1220 bn_int_set(&packet->u.client_loginreq1.sessionkey,client.sessionkey);
1221 hash_to_bnhash((t_hash const *)&passhash2,packet->u.client_loginreq1.password_hash2); /* avoid warning */
1222 packet_append_string(packet,user.player);
1223 client_blocksend_packet(client.sd,packet);
1224 packet_del_ref(packet);
1225 }
1226
1227 do
1228 if (client_blockrecv_packet(client.sd,rpacket)<0)
1229 {
1230 fprintf(stderr,"%s: server closed connection\n",argv[0]);
1231 psock_close(client.sd);
1232 if (client.changed_in)
1233 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1234 return STATUS_FAILURE;
1235 }
1236 while (packet_get_type(rpacket)!=SERVER_LOGINREPLY1);
1237 if (bn_int_get(rpacket->u.server_loginreply1.message)==SERVER_LOGINREPLY1_MESSAGE_SUCCESS)
1238 break;
1239 fprintf(stderr,"Login incorrect.\n");
1240 }
1241
1242 fprintf(stderr,"Logged in.\n");
1243 printf("----\n");
1244
1245 if (newacct && (strcmp(user.clienttag,CLIENTTAG_DIABLORTL)==0 ||
1246 strcmp(user.clienttag,CLIENTTAG_DIABLOSHR)==0))
1247 {
1248 if (!(packet = packet_create(packet_class_bnet)))
1249 {
1250 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1251 if (client.changed_in)
1252 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1253 }
1254 else
1255 {
1256 packet_set_size(packet,sizeof(t_client_playerinforeq));
1257 packet_set_type(packet,CLIENT_PLAYERINFOREQ);
1258 packet_append_string(packet,user.player);
1259 packet_append_string(packet,"LTRD 1 2 0 20 25 15 20 100 0"); /* FIXME: don't hardcode */
1260 client_blocksend_packet(client.sd,packet);
1261 packet_del_ref(packet);
1262 }
1263 }
1264
1265 if (!(packet = packet_create(packet_class_bnet)))
1266 {
1267 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1268 psock_close(client.sd);
1269 if (client.changed_in)
1270 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1271 return STATUS_FAILURE;
1272 }
1273 packet_set_size(packet,sizeof(t_client_progident2));
1274 packet_set_type(packet,CLIENT_PROGIDENT2);
1275 bn_int_tag_set(&packet->u.client_progident2.clienttag,user.clienttag);
1276 client_blocksend_packet(client.sd,packet);
1277 packet_del_ref(packet);
1278
1279 do
1280 if (client_blockrecv_packet(client.sd,rpacket)<0)
1281 {
1282 fprintf(stderr,"%s: server closed connection\n",argv[0]);
1283 psock_close(client.sd);
1284 if (client.changed_in)
1285 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1286 return STATUS_FAILURE;
1287 }
1288 while (packet_get_type(rpacket)!=SERVER_CHANNELLIST);
1289
1290 {
1291 unsigned int i;
1292 unsigned int chann_off;
1293 char const * chann;
1294
1295 channellist = xmalloc(sizeof(char const *)*1);
1296 for (i=0,chann_off=sizeof(t_server_channellist);
1297 (chann = packet_get_str_const(rpacket,chann_off,128));
1298 i++,chann_off+=strlen(chann)+1)
1299 {
1300 if (chann[0] == '\0') break; /* channel list ends with a "" */
1301
1302 channellist = xrealloc(channellist,sizeof(char const *)*(i+2));
1303 channellist[i] = xstrdup(chann);
1304 }
1305 channellist[i] = NULL;
1306 }
1307
1308 if (!(packet = packet_create(packet_class_bnet)))
1309 {
1310 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1311 psock_close(client.sd);
1312 if (client.changed_in)
1313 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1314 return STATUS_FAILURE;
1315 }
1316 packet_set_size(packet,sizeof(t_client_joinchannel));
1317 packet_set_type(packet,CLIENT_JOINCHANNEL);
1318 bn_int_set(&packet->u.client_joinchannel.channelflag,CLIENT_JOINCHANNEL_GENERIC);
1319 packet_append_string(packet,user.channel);
1320 client_blocksend_packet(client.sd,packet);
1321 packet_del_ref(packet);
1322
1323 if (psock_ctl(client.sd,PSOCK_NONBLOCK)<0)
1324 fprintf(stderr,"%s: could not set TCP socket to non-blocking mode (psock_ctl: %s)\n",argv[0],pstrerror(psock_errno()));
1325
1326 client.mode = mode_chat;
1327
1328 {
1329 unsigned int i;
1330 int highest_fd;
1331 t_psock_fd_set rfds;
1332 #ifdef WIN32
1333 static struct timeval tv;
1334
1335 tv.tv_sec = 50 / 1000;
1336 tv.tv_usec = 50 % 1000;
1337 #endif
1338
1339 PSOCK_FD_ZERO(&rfds);
1340
1341 #ifndef WIN32
1342 highest_fd = client.fd_stdin;
1343 if (client.sd>highest_fd)
1344 #endif
1345 highest_fd = client.sd;
1346
1347 client.currsize = 0;
1348
1349 client.munged = 1; /* == need to draw prompt */
1350 client.commpos = 0;
1351 client.text[0] = '\0';
1352
1353 for (;;)
1354 {
1355
1356
1357 if (handle_winch)
1358 {
1359 client_get_termsize(client.fd_stdin,&client.screen_width,&client.screen_height);
1360 handle_winch = 0;
1361 printf(" \r");
1362 client.munged = 1;
1363 }
1364
1365 if (client.munged)
1366 {
1367 printf("%s%s",mode_get_prompt(client.mode),client.text + ((client.screen_width <= strlen(mode_get_prompt(client.mode)) + client.commpos ) ? strlen(mode_get_prompt(client.mode)) + client.commpos + 1 - client.screen_width : 0));
1368 fflush(stdout);
1369 client.munged = 0;
1370 }
1371 PSOCK_FD_ZERO(&rfds);
1372 #ifndef WIN32
1373 PSOCK_FD_SET(client.fd_stdin,&rfds);
1374 #endif
1375 PSOCK_FD_SET(client.sd,&rfds);
1376 errno = 0;
1377
1378 #ifndef WIN32
1379 if (psock_select(highest_fd+1,&rfds,NULL,NULL,NULL)<0)
1380 #else
1381 if (psock_select(highest_fd+1,&rfds,NULL,NULL,&tv)<0)
1382 #endif
1383 {
1384 if (psock_errno()!=PSOCK_EINTR)
1385 {
1386 munge(&client);
1387 printf("Select failed (select: %s)\n",pstrerror(psock_errno()));
1388 }
1389 continue;
1390 }
1391 #ifndef WIN32
1392 if (PSOCK_FD_ISSET(client.fd_stdin,&rfds)) /* got keyboard data */
1393 #else
1394 if (kbhit())
1395 #endif
1396 {
1397 client.munged = 0;
1398
1399 switch (client_get_comm(mode_get_prompt(client.mode),client.text,MAX_MESSAGE_LEN,&client.commpos,1,
1400 0,client.screen_width))
1401 {
1402 case -1: /* cancel */
1403 munge(&client);
1404 if (client.mode==mode_command)
1405 client.mode = mode_chat;
1406 else
1407 client.mode = mode_command;
1408 client.commpos = 0;
1409 client.text[0] = '\0';
1410 break;
1411
1412 case 0: /* timeout */
1413 break;
1414
1415 case 1:
1416 switch (client.mode)
1417 {
1418 case mode_claninvite:
1419
1420 printf("\n");
1421 client.munged = 1;
1422
1423 if ((client.text[0]!='\0') && strcasecmp(client.text,"yes") && strcasecmp(client.text,"no"))
1424 {
1425 printf("Do you want to accept invitation (yes/no) ? [yes] ");
1426 break;
1427 }
1428
1429 if (!(packet = packet_create(packet_class_bnet)))
1430 {
1431 printf("Packet creation failed.\n");
1432 }
1433 else
1434 {
1435 char result;
1436
1437 packet_set_size(packet,sizeof(t_client_w3xp_clan_invitereply));
1438 packet_set_type(packet,CLIENT_W3XP_CLAN_INVITEREPLY);
1439 bn_int_set(&packet->u.client_w3xp_clan_invitereply.count,user.count);
1440 bn_int_set(&packet->u.client_w3xp_clan_invitereply.clantag,user.clantag);
1441 packet_append_string(packet,user.inviter);
1442
1443 if (!strcasecmp(client.text,"no"))
1444 result = W3XP_CLAN_INVITEREPLY_DECLINE;
1445 else
1446 result = W3XP_CLAN_INVITEREPLY_ACCEPT;
1447
1448 packet_append_data(packet,&result,1);
1449
1450 client_blocksend_packet(client.sd,packet);
1451 packet_del_ref(packet);
1452
1453 if (user.inviter)
1454 xfree((void *)user.inviter);
1455 user.inviter = NULL;
1456
1457 }
1458
1459
1460 client.mode = mode_chat;
1461 break;
1462
1463 case mode_gamename:
1464 if (client.text[0]=='\0')
1465 {
1466 munge(&client);
1467 printf("Games must have a name.\n");
1468 break;
1469 }
1470 printf("\n");
1471 client.munged = 1;
1472 strncpy(user.curr_gamename,client.text,sizeof(user.curr_gamename));
1473 user.curr_gamename[sizeof(user.curr_gamename)-1] = '\0';
1474 client.mode = mode_gamepass;
1475 break;
1476 case mode_gamepass:
1477 printf("\n");
1478 client.munged = 1;
1479 strncpy(user.curr_gamepass,client.text,sizeof(user.curr_gamepass));
1480 user.curr_gamepass[sizeof(user.curr_gamepass)-1] = '\0';
1481
1482 if (!(packet = packet_create(packet_class_bnet)))
1483 {
1484 printf("Packet creation failed.\n");
1485 client.mode = mode_command;
1486 }
1487 else
1488 {
1489 packet_set_size(packet,sizeof(t_client_startgame4));
1490 packet_set_type(packet,CLIENT_STARTGAME4);
1491 bn_short_set(&packet->u.client_startgame4.status,CLIENT_STARTGAME4_STATUS_INIT);
1492 bn_short_set(&packet->u.client_startgame4.flag,0x0000);
1493 bn_int_set(&packet->u.client_startgame4.unknown2,CLIENT_STARTGAME4_UNKNOWN2);
1494 bn_short_set(&packet->u.client_startgame4.gametype,CLIENT_GAMELISTREQ_MELEE);
1495 bn_short_set(&packet->u.client_startgame4.option,CLIENT_STARTGAME4_OPTION_MELEE_NORMAL);
1496 bn_int_set(&packet->u.client_startgame4.unknown4,CLIENT_STARTGAME4_UNKNOWN4);
1497 bn_int_set(&packet->u.client_startgame4.unknown5,CLIENT_STARTGAME4_UNKNOWN5);
1498 packet_append_string(packet,user.curr_gamename);
1499 packet_append_string(packet,user.curr_gamepass);
1500 packet_append_string(packet,",,,,1,3,1,3e37a84c,7,Player\rAshrigo\r");
1501 client_blocksend_packet(client.sd,packet);
1502 packet_del_ref(packet);
1503 client.mode = mode_gamewait;
1504 }
1505 break;
1506 case mode_gamestop:
1507 printf("\n");
1508 client.munged = 1;
1509
1510 if (!(packet = packet_create(packet_class_bnet)))
1511 printf("Packet creation failed.\n");
1512 else
1513 {
1514 packet_set_size(packet,sizeof(t_client_closegame));
1515 packet_set_type(packet,CLIENT_CLOSEGAME);
1516 client_blocksend_packet(client.sd,packet);
1517 packet_del_ref(packet);
1518 printf("Game closed.\n");
1519 client.mode = mode_command;
1520 }
1521 break;
1522 case mode_command:
1523 if (client.text[0]=='\0')
1524 break;
1525 printf("\n");
1526 client.munged = 1;
1527 if (strstart(client.text,"channel")==0)
1528 {
1529 printf("Available channels:\n");
1530 if (client.useansi)
1531 ansi_text_color_fore(ansi_text_color_yellow);
1532 for (i=0; channellist[i]; i++)
1533 printf(" %s\n",channellist[i]);
1534 if (client.useansi)
1535 ansi_text_reset();
1536 }
1537 else if (strstart(client.text,"create")==0)
1538 {
1539 printf("Enter new game information\n");
1540 client.mode = mode_gamename;
1541 }
1542 else if (strstart(client.text,"join")==0)
1543 {
1544 printf("Not implemented yet.\n");
1545 }
1546 else if (strstart(client.text,"ladder")==0)
1547 {
1548 printf("Not implemented yet.\n");
1549 }
1550 else if (strstart(client.text,"stats")==0)
1551 {
1552 printf("Not implemented yet.\n");
1553 }
1554 else if (strstart(client.text,"help")==0 || strcmp(client.text,"?")==0)
1555 {
1556 printf("Available commands:\n"
1557 " channel - join or create a channel\n"
1558 " create - create a new game\n"
1559 " join - list current games\n"
1560 " ladder - list ladder rankings\n"
1561 " help - show this text\n"
1562 " info <PLAYER> - print a player's profile\n"
1563 " chinfo - modify your profile\n"
1564 " quit - exit bnchat\n"
1565 " stats <PLAYER> - print a player's game record\n"
1566 "Use the escape key to toggle between chat and command modes.\n");
1567 }
1568 else if (strstart(client.text,"info")==0)
1569 {
1570 for (i=4; client.text[i]==' ' || client.text[i]=='\t'; i++);
1571 if (client.text[i]=='\0')
1572 {
1573 ansi_printf(&client,ansi_text_color_red,"You must specify the player.\n");
1574 }
1575 else
1576 {
1577 if (!(packet = packet_create(packet_class_bnet)))
1578 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1579 else
1580 {
1581 printf("Profile info for %s:\n",&client.text[i]);
1582 packet_set_size(packet,sizeof(t_client_statsreq));
1583 packet_set_type(packet,CLIENT_STATSREQ);
1584 bn_int_set(&packet->u.client_statsreq.name_count,1);
1585 bn_int_set(&packet->u.client_statsreq.key_count,4);
1586 statsmatch = (unsigned int)time(NULL);
1587 bn_int_set(&packet->u.client_statsreq.requestid,statsmatch);
1588 packet_append_string(packet,&client.text[i]);
1589 #if 0
1590 packet_append_string(packet,"BNET\\acct\\username");
1591 packet_append_string(packet,"BNET\\acct\\userid");
1592 #endif
1593 packet_append_string(packet,"profile\\sex");
1594 packet_append_string(packet,"profile\\age");
1595 packet_append_string(packet,"profile\\location");
1596 packet_append_string(packet,"profile\\description");
1597 client_blocksend_packet(client.sd,packet);
1598 packet_del_ref(packet);
1599
1600 client.mode = mode_waitstat;
1601 }
1602 }
1603 }
1604 else if (strstart(client.text,"chinfo")==0)
1605 {
1606 printf("Not implemented yet.\n");
1607 }
1608 else if (strstart(client.text,"quit")==0)
1609 {
1610 psock_close(client.sd);
1611 if (client.changed_in)
1612 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1613 return STATUS_SUCCESS;
1614 }
1615 else
1616 {
1617 ansi_printf(&client,ansi_text_color_red,"Unknown local command \"%s\".\n",client.text);
1618 }
1619 break;
1620
1621 case mode_chat:
1622 if (client.text[0]=='\0')
1623 break;
1624 if (client.text[0]=='/')
1625 {
1626 munge(&client);
1627 }
1628 else
1629 {
1630 ansi_printf(&client,ansi_text_color_blue,"\r<%s>",user.player);
1631 printf(" ");
1632 str_print_term(stdout,client.text,0,0);
1633 printf("\n");
1634 client.munged = 1;
1635 }
1636
1637 if (!(packet = packet_create(packet_class_bnet)))
1638 {
1639 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1640 psock_close(client.sd);
1641 if (client.changed_in)
1642 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1643 return STATUS_FAILURE;
1644 }
1645 packet_set_size(packet,sizeof(t_client_message));
1646 packet_set_type(packet,CLIENT_MESSAGE);
1647 packet_append_string(packet,client.text);
1648 client_blocksend_packet(client.sd,packet);
1649 packet_del_ref(packet);
1650 break;
1651
1652 default:
1653 /* one of the wait states; erase what they typed */
1654 munge(&client);
1655 break;
1656 }
1657
1658 client.commpos = 0;
1659 client.text[0] = '\0';
1660 break;
1661 }
1662 }
1663
1664 if (PSOCK_FD_ISSET(client.sd,&rfds)) /* got network data */
1665 {
1666 /* rpacket is from server, packet is from client */
1667 switch (net_recv_packet(client.sd,rpacket,&client.currsize))
1668 {
1669 case 0: /* nothing */
1670 break;
1671
1672 case 1:
1673 switch (packet_get_type(rpacket))
1674 {
1675 case SERVER_ECHOREQ: /* might as well support it */
1676 if (packet_get_size(rpacket)<sizeof(t_server_echoreq))
1677 {
1678 munge(&client);
1679 printf("Got bad SERVER_ECHOREQ packet (expected %u bytes, got %u)\n",sizeof(t_server_echoreq),packet_get_size(rpacket));
1680 break;
1681 }
1682
1683 if (!(packet = packet_create(packet_class_bnet)))
1684 {
1685 munge(&client);
1686 fprintf(stderr,"%s: could not create packet\n",argv[0]);
1687 psock_close(client.sd);
1688 if (client.changed_in)
1689 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
1690 return STATUS_FAILURE;
1691 }
1692 packet_set_size(packet,sizeof(t_client_echoreply));
1693 packet_set_type(packet,CLIENT_ECHOREPLY);
1694 bn_int_set(&packet->u.client_echoreply.ticks,bn_int_get(rpacket->u.server_echoreq.ticks));
1695 client_blocksend_packet(client.sd,packet);
1696 packet_del_ref(packet);
1697
1698 break;
1699
1700 case SERVER_STARTGAME4_ACK:
1701 if (client.mode==mode_gamewait)
1702 {
1703 munge(&client);
1704
1705 if (bn_int_get(rpacket->u.server_startgame4_ack.reply)==SERVER_STARTGAME4_ACK_OK)
1706 {
1707 printf("Game created.\n");
1708 client.mode = mode_gamestop;
1709 }
1710 else
1711 {
1712 printf("Game could not be created, try another name.\n");
1713 client.mode = mode_gamename;
1714 }
1715 }
1716 break;
1717
1718 case SERVER_W3XP_CLAN_INVITEREQ:
1719 if (packet_get_size(rpacket)<sizeof(t_server_w3xp_clan_invitereq))
1720 {
1721 munge(&client);
1722 printf("Got bad SERVER_W3XP_CLAN_INVITEREQ packet (expected %u bytes, got %u)\n",sizeof(t_server_w3xp_clan_invitereq),packet_get_size(rpacket));
1723 break;
1724 }
1725
1726 {
1727 char const * clan;
1728 char const * inviter;
1729 int offset;
1730
1731 offset = sizeof(t_server_w3xp_clan_invitereq);
1732 if (!(clan = packet_get_str_const(rpacket,offset,MAX_CLANNAME_LEN)))
1733 {
1734 munge(&client);
1735 printf("Got SERVER_W3XP_CLAN_INVITEREQ with bad or missing clanname\n");
1736 break;
1737 }
1738 offset+=strlen(clan)+1;
1739 if (!(inviter = packet_get_str_const(rpacket,offset,USER_NAME_MAX)))
1740 {
1741 munge(&client);
1742 printf("Got SERVER_W3XP_CLAN_INVITEREQ with bad or missing inviter\n");
1743 break;
1744 }
1745 user.count = bn_int_get(rpacket->u.server_w3xp_clan_invitereq.count);
1746 user.clantag = bn_int_get(rpacket->u.server_w3xp_clan_invitereq.clantag);
1747 if (user.inviter)
1748 xfree((void *)user.inviter);
1749 user.inviter = xstrdup(inviter);
1750
1751 munge(&client);
1752 printf("%s invited you to Clan %s\n",inviter,clan);
1753 printf("Do you want to accept invitation (yes/no) ? [yes] ");
1754
1755 client.mode = mode_claninvite;
1756 }
1757
1758
1759
1760 case SERVER_W3XP_CLANMEMBERUPDATE:
1761 if (packet_get_size(rpacket)<sizeof(t_server_w3xp_clanmemberupdate))
1762 {
1763 munge(&client);
1764 printf("Got bad SERVER_W3XP_CLANMEMBERUPDATE packet (expected %u bytes, got %u)\n",sizeof(t_server_w3xp_clanmemberupdate),packet_get_size(rpacket));
1765 break;
1766 }
1767
1768 if (client.mode == mode_claninvite)
1769 break;
1770
1771 {
1772 char const * member;
1773 char rank, online;
1774 char const * rank_p;
1775 char const * online_p;
1776 char const * append_str;
1777 int offset;
1778 char const * rank_str;
1779 char const * online_str;
1780
1781 offset = sizeof(t_server_w3xp_clanmemberupdate);
1782 if (!(member = packet_get_str_const(rpacket,offset,USER_NAME_MAX)))
1783 {
1784 munge(&client);
1785 printf("Got SERVER_W3XP_CLANMEMBERUPDATE with bad or missing member\n");
1786 break;
1787 }
1788 offset+=strlen(member)+1;
1789 if (!(rank_p = (char *)packet_get_data_const(rpacket,offset,1)))
1790 {
1791 munge(&client);
1792 printf("Got SERVER_W3XP_CLANMEMBERUPDATE with bad or missing rank\n");
1793 break;
1794 }
1795 rank = *rank_p;
1796 offset+=1;
1797 if (!(online_p = (char *)packet_get_data_const(rpacket,offset,1)))
1798 {
1799 munge(&client);
1800 printf("Got SERVER_W3XP_CLAN_MEMBERUPDATE with bad or missing online status\n");
1801 break;
1802 }
1803 online = *online_p;
1804 offset+=1;
1805 if (!(append_str = packet_get_str_const(rpacket,offset,USER_NAME_MAX)))
1806 {
1807 munge(&client);
1808 printf("Got SERVER_W3XP_CLANMEMBERUPDATE with bad or missing append_str\n");
1809 break;
1810 }
1811
1812 switch (rank)
1813 {
1814 case SERVER_W3XP_CLAN_MEMBER_NEW:
1815 rank_str = "New clan member";
1816 break;
1817 case SERVER_W3XP_CLAN_MEMBER_PEON:
1818 rank_str = "Peon";
1819 break;
1820 case SERVER_W3XP_CLAN_MEMBER_GRUNT:
1821 rank_str = "Grunt";
1822 break;
1823 case SERVER_W3XP_CLAN_MEMBER_SHAMAN:
1824 rank_str = "Shaman";
1825 break;
1826 case SERVER_W3XP_CLAN_MEMBER_CHIEFTAIN:
1827 rank_str = "Chieftain";
1828 break;
1829 default:
1830 rank_str = "";
1831
1832 }
1833
1834 switch (online)
1835 {
1836 case SERVER_W3XP_CLAN_MEMBER_OFFLINE:
1837 online_str = "offline";
1838 break;
1839 case SERVER_W3XP_CLAN_MEMBER_ONLINE:
1840 online_str = "online";
1841 break;
1842 case SERVER_W3XP_CLAN_MEMBER_CHANNEL:
1843 online_str = "in channel";
1844 break;
1845 case SERVER_W3XP_CLAN_MEMBER_GAME:
1846 online_str = "in game";
1847 break;
1848 case SERVER_W3XP_CLAN_MEMBER_PRIVATE_GAME:
1849 online_str = "in private game";
1850 break;
1851 default:
1852 online_str = "";
1853 }
1854
1855 munge(&client);
1856 printf("%s %s is now %s %s\n",rank_str,member,online_str,append_str);
1857 }
1858
1859
1860 case SERVER_STATSREPLY:
1861 if (client.mode==mode_waitstat)
1862 {
1863 unsigned int names,keys;
1864 unsigned int match;
1865 unsigned int strpos;
1866 char const * temp;
1867
1868 munge(&client);
1869
1870 names = bn_int_get(rpacket->u.server_statsreply.name_count);
1871 keys = bn_int_get(rpacket->u.server_statsreply.key_count);
1872 match = bn_int_get(rpacket->u.server_statsreply.requestid);
1873
1874 if (names!=1 || keys!=4 || match!=statsmatch)
1875 printf("mangled reply (name_count=%u key_count=%u unknown1=%u)\n",
1876 names,keys,match);
1877
1878 strpos = sizeof(t_server_statsreply);
1879 if ((temp = packet_get_str_const(rpacket,strpos,256)))
1880 {
1881 printf(" Sex: ");
1882 ansi_printf(&client,ansi_text_color_yellow,"%s\n",temp);
1883 strpos += strlen(temp)+1;
1884 }
1885 if ((temp = packet_get_str_const(rpacket,strpos,256)))
1886 {
1887 printf(" Age: ");
1888 ansi_printf(&client,ansi_text_color_yellow,"%s\n",temp);
1889 strpos += strlen(temp)+1;
1890 }
1891 if ((temp = packet_get_str_const(rpacket,strpos,256)))
1892 {
1893 printf(" Location: ");
1894 ansi_printf(&client,ansi_text_color_yellow,"%s\n",temp);
1895 strpos += strlen(temp)+1;
1896 }
1897 if ((temp = packet_get_str_const(rpacket,strpos,256)))
1898 {
1899 char msgtemp[1024];
1900 char * tok;
1901
1902 printf(" Description: \n");
1903 if (client.useansi)
1904 ansi_text_color_fore(ansi_text_color_yellow);
1905 strncpy(msgtemp,temp,sizeof(msgtemp));
1906 msgtemp[sizeof(msgtemp)-1] = '\0';
1907 for (tok=strtok(msgtemp,"\r\n"); tok; tok=strtok(NULL,"\r\n"))
1908 printf(" %s\n",tok);
1909 if (client.useansi)
1910 ansi_text_reset();
1911 strpos += strlen(temp)+1;
1912 }
1913
1914 if (match==statsmatch)
1915 client.mode = mode_command;
1916 }
1917 break;
1918
1919 case SERVER_PLAYERINFOREPLY: /* hmm. we didn't ask for one... */
1920 break;
1921
1922 case SERVER_MESSAGE:
1923 if (packet_get_size(rpacket)<sizeof(t_server_message))
1924 {
1925 munge(&client);
1926 printf("Got bad SERVER_MESSAGE packet (expected %u bytes, got %u)",sizeof(t_server_message),packet_get_size(rpacket));
1927 break;
1928 }
1929
1930 {
1931 char const * speaker;
1932 char const * message;
1933
1934 if (!(speaker = packet_get_str_const(rpacket,sizeof(t_server_message),32)))
1935 {
1936 munge(&client);
1937 printf("Got SERVER_MESSAGE packet with bad or missing speaker\n");
1938 break;
1939 }
1940 if (!(message = packet_get_str_const(rpacket,sizeof(t_server_message)+strlen(speaker)+1,1024)))
1941 {
1942 munge(&client);
1943 printf("Got SERVER_MESSAGE packet with bad or missing message (speaker=\"%s\" start=%u len=%u)\n",speaker,sizeof(t_server_message)+strlen(speaker)+1,packet_get_size(rpacket));
1944 break;
1945 }
1946
1947 switch (bn_int_get(rpacket->u.server_message.type))
1948 {
1949 case SERVER_MESSAGE_TYPE_JOIN:
1950 munge(&client);
1951 ansi_printf(&client,ansi_text_color_green,"\"%s\" %s enters\n",speaker,
1952 mflags_get_str(bn_int_get(rpacket->u.server_message.flags)));
1953 break;
1954 case SERVER_MESSAGE_TYPE_CHANNEL:
1955 munge(&client);
1956 ansi_printf(&client,ansi_text_color_green,"Joining channel :\"%s\" %s\n",message,
1957 cflags_get_str(bn_int_get(rpacket->u.server_message.flags)));
1958 break;
1959 case SERVER_MESSAGE_TYPE_ADDUSER:
1960 munge(&client);
1961 ansi_printf(&client,ansi_text_color_green,"\"%s\" %s is here\n",speaker,
1962 mflags_get_str(bn_int_get(rpacket->u.server_message.flags)));
1963 break;
1964 case SERVER_MESSAGE_TYPE_USERFLAGS:
1965 break;
1966 case SERVER_MESSAGE_TYPE_PART:
1967 munge(&client);
1968 ansi_printf(&client,ansi_text_color_green,"\"%s\" %s leaves\n",speaker,
1969 mflags_get_str(bn_int_get(rpacket->u.server_message.flags)));
1970 break;
1971 case SERVER_MESSAGE_TYPE_WHISPER:
1972 munge(&client);
1973 ansi_printf(&client,ansi_text_color_blue,"<From: %s>",speaker);
1974 printf(" ");
1975 str_print_term(stdout,message,0,0);
1976 printf("\n");
1977 break;
1978 case SERVER_MESSAGE_TYPE_WHISPERACK:
1979 munge(&client);
1980 ansi_printf(&client,ansi_text_color_blue,"<To: %s>",speaker);
1981 printf(" ");
1982 str_print_term(stdout,message,0,0);
1983 printf("\n");
1984 break;
1985 case SERVER_MESSAGE_TYPE_BROADCAST:
1986 munge(&client);
1987 ansi_printf(&client,ansi_text_color_yellow,"<Broadcast %s> %s\n",speaker,message);
1988 break;
1989 case SERVER_MESSAGE_TYPE_ERROR:
1990 munge(&client);
1991 ansi_printf(&client,ansi_text_color_red,"<Error> %s\n",message);
1992 break;
1993 case SERVER_MESSAGE_TYPE_INFO:
1994 munge(&client);
1995 ansi_printf(&client,ansi_text_color_yellow,"<Info> %s\n",message);
1996 break;
1997 case SERVER_MESSAGE_TYPE_EMOTE:
1998 munge(&client);
1999 ansi_printf(&client,ansi_text_color_yellow,"<%s %s>\n",speaker,message);
2000 break;
2001 default:
2002 case SERVER_MESSAGE_TYPE_TALK:
2003 munge(&client);
2004 ansi_printf(&client,ansi_text_color_yellow,"<%s>",speaker);
2005 printf(" ");
2006 str_print_term(stdout,message,0,0);
2007 printf("\n");
2008 }
2009 }
2010 break;
2011
2012 default:
2013 munge(&client);
2014 printf("Unsupported server packet type 0x%04x\n",packet_get_type(rpacket));
2015 hexdump(stdout,packet_get_data_const(rpacket,0,packet_get_size(rpacket)),packet_get_size(rpacket));
2016 printf("\n");
2017 }
2018
2019 client.currsize = 0;
2020 break;
2021
2022 case -1: /* error (probably connection closed) */
2023 default:
2024 munge(&client);
2025 printf("----\nConnection closed by server.\n");
2026 psock_close(client.sd);
2027 if (client.changed_in)
2028 tcsetattr(client.fd_stdin,TCSAFLUSH,&client.in_attr_old);
2029 return STATUS_SUCCESS;
2030 }
2031 }
2032 }
2033 }
2034
2035 /* not reached */
2036 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1