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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
CVS Tags: pvpgn_1-7-4-0_MIL
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

1 sysadm 1.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