micq.c
资源名称:micq.tgz [点击查看]
上传用户:ai20ln
上传日期:2007-01-05
资源大小:79k
文件大小:12k
源码类别:
ICQ/即时通讯
开发平台:
Unix_Linux
- /*********************************************
- **********************************************
- This is the main ICQ file. Currently it
- logs in and sits in a loop. It can receive
- messages and keeps the connection alive.
- Use crtl-break to exit.
- This software is provided AS IS to be used in
- whatever way you see fit and is placed in the
- public domain.
- Author : Matthew Smith April 19, 1998
- Contributors : Nicolas Sahlqvist April 27, 1998
- Ulf Hedlund (guru@slideware.com) April 28, 1998
- Michael Ivey May 4, 1998
- Michael Holzt May 5, 1998
- Changes :
- 4-28-98 support for WIN32 [UH]
- 4-20-98 added variable time_delay between keep_alive packets mds
- 4-20-98 added instant message from server support mds
- 4-21-98 changed so that long ( 250+ characters ) messages work
- new maximum is ~900 which is hopefully big enough.
- When I know more about udp maybe I can come up with
- a general solution. mds I now think ICQ has a max that is
- smaller than this so everything is ok mds I now think that
- the icq client's maximum is arbitrary and can be ignored :)
- 4-23-98 Added beginnings of a user interface
- 4-26-98 Changed the version to 0.2a :)
- 4-27-98 Nicco added feature to use nick names to log in
- 5-05-98 Authorization Messages
- 5-13-98 Added time stamps for most things.
- 6-17-98 Changed condition on which we should send auto_reply message. Fryslan
- 6-18-98 Added different auto reply messages for different status types see also ui.c and util.c Fryslan
- 6-20-98 Added an alter command to alter your command names online. Fryslan
- **********************************************
- **********************************************/
- #include "micq.h"
- #include "datatype.h"
- #include "msg_queue.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <limits.h>
- #ifdef _WIN32
- #include <conio.h>
- #include <io.h>
- #include <winsock2.h>
- #include <time.h>
- #else
- #include <unistd.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #endif
- #include <fcntl.h>
- #include <time.h>
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #include <assert.h>
- BYTE Sound = SOUND_ON; /* Beeps on by default */
- BYTE Sound_Str[150]; /* the command to run from the shell to play sound files */
- BOOL Russian = FALSE; /* Do we do kio8-r <->Cp1251 codeset translation? */
- BOOL Logging = TRUE; /* Do we log messages to ~/micq_log? This should probably have different levels */
- BOOL Color = TRUE; /* Do we use ANSI color? */
- BOOL Quit = FALSE; /* set when it's time to exit the program */
- BOOL Verbose = FALSE; /* this is displays extra debuging info */
- BOOL serv_mess[ 1024 ]; /* used so that we don't get duplicate messages with the same SEQ */
- WORD last_cmd[ 1024 ]; /* command issued for the first 1024 SEQ #'s */
- /******************** if we have more than 1024 SEQ this will need some hacking */
- WORD seq_num = 1; /* current sequence number */
- DWORD our_ip = 0x0100007f; /* localhost for some reason */
- DWORD our_port; /* the port to make tcp connections on */
- /************ We don't make tcp connections yet though :( */
- DWORD UIN; /* current User Id Number */
- BOOL Contact_List = FALSE; /* I think we always have a contact list now */
- Contact_Member Contacts[ 100 ]; /* no more than 100 contacts max */
- int Num_Contacts=0;
- DWORD Current_Status=STATUS_OFFLINE;
- DWORD last_recv_uin=0;
- char passwd[100];
- char server[100];
- DWORD set_status;
- DWORD remote_port;
- BOOL Done_Login=FALSE;
- BOOL auto_resp=FALSE;
- char auto_rep_str_dnd[450] = { "Don't page me, my head is hurting!" };
- char auto_rep_str_away[450] = { "I told you I wasn't here!" };
- char auto_rep_str_na[450] = { "Working, working always working..." };
- char auto_rep_str_occ[450] = { "I am working on opening this beer so I am busy." };
- char auto_rep_str_inv[450] = { "So you can see me, so you can't!" };
- char message_cmd[16];
- char info_cmd[16];
- char quit_cmd[16];
- char reply_cmd[16];
- char again_cmd[16];
- char add_cmd[16];
- char list_cmd[16];
- char away_cmd[16];
- char na_cmd[16];
- char dnd_cmd[16];
- char online_cmd[16];
- char occ_cmd[16];
- char ffc_cmd[16];
- char inv_cmd[16];
- char status_cmd[16];
- char auth_cmd[16];
- char auto_cmd[16];
- char change_cmd[16];
- char search_cmd[16];
- char save_cmd[16];
- char alter_cmd[16];
- char msga_cmd[16];
- char url_cmd[16];
- char update_cmd[16];
- unsigned int next_resend;
- /*/////////////////////////////////////////////
- // Connects to hostname on port port
- // hostname can be DNS or nnn.nnn.nnn.nnn
- // write out messages to the FD aux */
- int Connect_Remote( char *hostname, int port, FD_T aux )
- {
- int conct, length;
- int sok;
- struct sockaddr_in sin; /* used to store inet addr stuff */
- struct hostent *host_struct; /* used in DNS lookup */
- #if 1
- sin.sin_addr.s_addr = inet_addr( hostname );
- if ( sin.sin_addr.s_addr == -1 ) /* name isn't n.n.n.n so must be DNS */
- #else
- if ( inet_aton( hostname, &sin.sin_addr ) == 0 ) /* checks for n.n.n.n notation */
- #endif
- {
- host_struct = gethostbyname( hostname );/* name isn't n.n.n.n so must be DNS */
- if ( host_struct == NULL )
- {
- if ( Verbose )
- {
- M_fdprint( aux, "Shakespeare couldn't spell why should I?n" );
- M_fdprint( aux, " Especially something like %sn", hostname );
- /*herror( "Can't find hostname" );*/
- }
- return 0;
- }
- sin.sin_addr = *((struct in_addr *)host_struct->h_addr);
- }
- sin.sin_family = AF_INET; /* we're using the inet not appletalk*/
- sin.sin_port = htons( port ); /* port */
- sok = socket( AF_INET, SOCK_DGRAM, 0 );/* create the unconnected socket*/
- if ( sok == -1 )
- {
- perror( "Socket creation failed" );
- exit( 1 );
- }
- if ( Verbose )
- {
- M_fdprint( aux, "Socket created attempting to connectn" );
- }
- conct = connect( sok, (struct sockaddr *) &sin, sizeof( sin ) );
- if ( conct == -1 )/* did we connect ?*/
- {
- if ( Verbose )
- {
- M_fdprint( aux, " Conection Refused on port %d at %sn", port, hostname );
- #ifdef FUNNY_MSGS
- M_fdprint( aux, " D'oh!n" );
- #endif
- perror( "connect" );
- }
- return 0;
- }
- length = sizeof( sin ) ;
- getsockname( sok, (struct sockaddr *) &sin, &length );
- our_ip = sin.sin_addr.s_addr;
- our_port = sin.sin_port;
- if (Verbose )
- {
- #ifdef FUNNY_MSGS
- M_fdprint( aux, "Our port is %d, take her to sea Mr. Mordoch.n", ntohs( sin.sin_port ) );
- #else
- M_fdprint( aux, "The port that will be used for tcp ( not yet implemented ) is %dn", ntohs( sin.sin_port ) );
- #endif
- }
- if ( Verbose )
- {
- M_fdprint( aux, "Connected to %s, waiting for responsen", hostname );
- }
- return sok;
- }
- /******************************************
- Handles packets that the server sends to us.
- *******************************************/
- void Handle_Server_Response( SOK_T sok )
- {
- srv_net_icq_pak pak;
- int s;
- s = SOCKREAD( sok, &pak.head.ver, sizeof( pak ) - 2 );
- if ( s < 0 )
- return;
- #if 0 /* V4 testing */
- M_print( CLIENTCOL "nThe response was %04Xt", Chars_2_Word( pak.head.cmd ) );
- M_print( "The version was %Xt", Chars_2_Word( pak.head.ver ) );
- Time_Stamp();
- M_print( "nThe SEQ was %04Xt", Chars_2_Word( pak.head.seq ) );
- len = s - ( sizeof( pak.head ) - 2 );
- M_print( "The size was %dn", len );
- if ( Verbose )
- {
- Hex_Dump( pak.data, len );
- }
- M_print( NOCOL "n" );
- Prompt();
- ack_srv( sok, Chars_2_Word( pak.head.seq ) ); /* fake like we know what we're doing*/
- return;
- #endif
- if ( ( serv_mess[ Chars_2_Word( pak.head.seq ) ] ) &&
- ( Chars_2_Word( pak.head.cmd ) != SRV_NEW_UIN ) )
- {
- if ( Chars_2_Word( pak.head.cmd ) != SRV_ACK ) /* ACKs don't matter */
- {
- if ( Verbose )
- M_print( "nIgnored a message cmd %04xn", Chars_2_Word( pak.head.cmd ) );
- ack_srv( sok, Chars_2_Word( pak.head.seq ) ); /* LAGGGGG!! */
- return;
- }
- }
- if ( Chars_2_Word( pak.head.cmd ) != SRV_ACK )
- {
- serv_mess[ Chars_2_Word( pak.head.seq ) ] = TRUE;
- ack_srv( sok, Chars_2_Word( pak.head.seq ) );
- }
- Server_Response( sok, pak.data, s - ( sizeof( pak.head ) - 2 ),
- Chars_2_Word( pak.head.cmd ), Chars_2_Word( pak.head.ver ),
- Chars_2_Word( pak.head.seq ), Chars_2_DW( pak.head.UIN ) );
- }
- /**********************************************
- Verifies that we are in the correct endian
- ***********************************************/
- void Check_Endian( void )
- {
- int i;
- char passwd[10];
- passwd[0] = 1;
- passwd[1] = 0;
- passwd[2] = 0;
- passwd[3] = 0;
- passwd[4] = 0;
- passwd[5] = 0;
- passwd[6] = 0;
- passwd[7] = 0;
- passwd[8] = 0;
- passwd[9] = 0;
- i = * ( DWORD *) passwd;
- if ( i == 1 )
- {
- M_print( "Using intel byte ordering.n" );
- }
- else
- {
- M_print( "Using motorola byte ordering.n" );
- }
- }
- /******************************
- Main function connects gets UIN
- and passwd and logins in and sits
- in a loop waiting for server responses.
- ******************************/
- int main( int argc, char *argv[] )
- {
- int sok;
- int i;
- int next;
- int time_delay = 120;
- struct timeval tv;
- fd_set readfds;
- #ifdef _WIN32
- WSADATA wsaData;
- #endif
- M_print( SERVCOL "Matt's ICQ clone " NOCOL "compiled on %s %sn" SERVCOL " Version " MICQ_VERSION NOCOL "n", __TIME__, __DATE__ );
- #ifdef FUNNY_MSGS
- M_print( "No Mirabilis client was maimed, hacked, tortured, sodomized or otherwise harmednin the making of this utility.n" );
- #else
- M_print( "This program was made without any help from Mirabilis or their consent.n" );
- M_print( "No reverse engineering or decompilation of any Mirabilis code took placento make this program.n" );
- #endif
- Get_Config_Info();
- if ( !strcmp( passwd,"" ) )
- {
- M_print( "Enter password : " );
- fflush( stdout );
- Echo_Off();
- M_fdnreadln(STDIN, passwd, sizeof(passwd));
- Echo_On();
- }
- memset( serv_mess, FALSE, 1024 );
- Initialize_Msg_Queue();
- if (argc > 1 )
- {
- for ( i=1; i< argc; i++ )
- {
- if ( argv[i][0] != '-' )
- ;
- else if ( (argv[i][1] == 'v' ) || (argv[i][1] == 'V' ) )
- {
- Verbose++;
- }
- }
- }
- Check_Endian();
- #ifdef _WIN32
- i = WSAStartup( 0x0101, &wsaData );
- if ( i != 0 ) {
- #ifdef FUNNY_MSGS
- perror("Windows Sockets broken blame Bill -");
- #else
- perror("Sorry, can't initialize Windows Sockets...");
- #endif
- exit(1);
- }
- #endif
- sok = Connect_Remote( server, remote_port, STDERR );
- if ( ( sok == -1 ) || ( sok == 0 ) )
- {
- M_print( "Couldn't establish connectionn" );
- exit( 1 );
- }
- Login( sok, UIN, &passwd[0], our_ip, our_port, set_status );
- next = time( NULL );
- next += 120;
- next_resend = 10;
- Prompt();
- for ( ; !Quit; )
- {
- #ifdef UNIX
- tv.tv_sec = 2;
- tv.tv_usec = 500000;
- #else
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
- #endif
- FD_ZERO(&readfds);
- FD_SET(sok, &readfds);
- #ifndef _WIN32
- FD_SET(STDIN, &readfds);
- #endif
- /* don't care about writefds and exceptfds: */
- select(sok+1, &readfds, NULL, NULL, &tv);
- if (FD_ISSET(sok, &readfds))
- Handle_Server_Response( sok );
- #if _WIN32
- else if (_kbhit()) /* sorry, this is a bit ugly... [UH]*/
- #else
- else if (FD_ISSET( STDIN, &readfds ) )
- #endif
- {
- Get_Input( sok );
- }
- if ( time( NULL ) > next )
- {
- next = time( NULL ) + time_delay;
- Keep_Alive( sok );
- }
- if ( time( NULL ) > next_resend )
- {
- Do_Resend( sok );
- }
- #ifdef UNIX
- while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up child processes */
- #endif
- }
- Quit_ICQ( sok );
- return 0;
- }