/*
by hkpco (ChanAm Park)
hkpco@korea.com
http://hkpco.kr/
irc bot program
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdarg.h>
void pong( int sockfd, char *ping, int sz );
// keep-alive를 위한 함수
int irc_req( int sockfd, char *req, ... );
// request를 보내기 위한 함수
int main( int argc , char **argv )
{
pid_t pid;
int sockfd, port, status;
struct sockaddr_in sock;
struct hostent *host_st;
char nickname[64] = {0x00,}, channel[64] = {0x00,};
char rcv_data[4096] = {0x00,}, tmp_buf[64+2] = {0x00,}, *strp;
if( argc < 5 ) {
fprintf( stderr, "%s <irc_server> <port> <nickname> <channel>\n", argv[0] );
return -1;
}
/******* 데몬 프로그램을 위한 세팅 *******/
pid = fork();
if( pid < 0 ) {
perror( "fork()" );
return -1;
}
else if( pid != 0 ) {
return 0;
}
else {
setsid();
}
/******* 세팅 끝 *******/
printf( "\n\n<code by hkpco>\n\n" );
/******* 접속 정보 저장 *******/
port = atoi(argv[2]);
strncpy( nickname, argv[3], sizeof(nickname) -1 );
strncpy( channel, "#", 1 );
strncat( channel, argv[4], sizeof(channel) -2 );
/******* 접속 정보 저장 끝 *******/
host_st = gethostbyname(argv[1]);
if( host_st == NULL ) {
perror( "gethostbyname()" );
return -1;
}
if( argc > 2 )
port = atoi(argv[2]);
sockfd = socket( PF_INET, SOCK_STREAM, 0 );
if( sockfd < 0 ) {
perror( "socket()" );
return -1;
}
bzero( sock.sin_zero, sizeof(sock.sin_zero) );
sock.sin_family = AF_INET;
sock.sin_port = htons(port);
sock.sin_addr = *((struct in_addr *)host_st->h_addr);
if( connect( sockfd, (struct sockaddr *)&sock, sizeof(sock) ) < 0 ) {
perror( "connect()" );
return -1;
}
/******* IRC 초기 접속 *******/
irc_req( sockfd, "NICK", nickname, NULL );
read( sockfd, rcv_data, sizeof(rcv_data) );
printf( "Response:\n%s\n\n", rcv_data );
memset( rcv_data, 0x0, sizeof(rcv_data) );
memset( tmp_buf , 0x0, sizeof(tmp_buf));
snprintf( tmp_buf, sizeof(tmp_buf) -1, ":%s\n", nickname );
irc_req( sockfd, "USER", nickname, ". ." , tmp_buf , NULL );
read( sockfd, rcv_data, sizeof(rcv_data) );
printf( "Response:\n%s\n\n", rcv_data );
if( (strp = strstr( rcv_data, "PING" )) == NULL ) {
memset( rcv_data, 0x0, sizeof(rcv_data) );
read( sockfd, rcv_data, sizeof(rcv_data) );
strp = strstr( rcv_data, "PING" );
pong( sockfd, strp, strlen(strp) );
}
else {
pong( sockfd, strp, strlen(strp) );
}
memset( rcv_data, 0x0, sizeof(rcv_data) );
read( sockfd, rcv_data, sizeof(rcv_data) );
printf( "Response:\n%s\n\n", rcv_data );
irc_req( sockfd, "USERHOST", nickname, NULL );
read( sockfd, rcv_data, sizeof(rcv_data) );
printf( "Response:\n%s\n\n", rcv_data );
memset( rcv_data, 0x0, sizeof(rcv_data) );
irc_req( sockfd, "JOIN", channel, NULL );
read( sockfd, rcv_data, sizeof(rcv_data) );
printf( "Response:\n%s\n\n", rcv_data );
memset( rcv_data, 0x0, sizeof(rcv_data) );
irc_req( sockfd, "PRIVMSG", channel, ":상호의 봇이 접속했다예요.", NULL );
read( sockfd, rcv_data, sizeof(rcv_data) );
memset( rcv_data, 0x0, sizeof(rcv_data) );
/******* IRC 초기 접속 끝 *******/
/******* 메시지 처리 *******/
while(1)
{
fd_set fds;
int cmd_pps[2];
pid_t cmd_prcs;
char cmd_buf[1024] = {0x00,}, buf_snd[2048] = {0x00,};;
char buf[1024] = {0x00,}, *p;
FD_ZERO(&fds);
FD_SET( sockfd, &fds );
if( (select( sockfd +1, &fds, (fd_set *)NULL, (fd_set *)NULL, (struct timeval*)NULL )) < 0 ) {
perror( "select()" );
return -1;
}
if( FD_ISSET( sockfd, &fds ) ) {
read( sockfd, buf, sizeof(buf) -1 );
if( (p = strstr( buf, "PING" )) ) {
pong( sockfd, p, strlen(p) );
}
else if( strstr( buf, "whoareyou?" ) ) {
if( pipe(cmd_pps) < 0 ) {
perror( "pipe()" );
continue;
}
// 자식 프로세스와의 통신을 위한 pipe 생성
if( (cmd_prcs = fork()) < 0 ) {
perror( "fork()" );
continue;
}
if( cmd_prcs == 0 ) {
dup2( cmd_pps[1], 1 );
dup2( cmd_pps[1], 2 );
close(cmd_pps[0]);
close(cmd_pps[1]);
execl( "/usr/bin/id", "-a", NULL );
// id 명령의 결과는 파이프를 통하여 전송됨
return 0;
}
else {
read( cmd_pps[0], cmd_buf, sizeof(cmd_buf) -1 );
// 파이프를 통하여 자식 프로세스의 id 명령 결과를 수신
snprintf( buf_snd, sizeof(buf_snd) -1, "PRIVMSG %s :%s\n", channel, cmd_buf );
write( sockfd, buf_snd, strlen(buf_snd) );
close(cmd_pps[0]);
close(cmd_pps[1]);
}
waitpid( cmd_prcs, &status, 0 );
}
// irc bot 종료 명령 체크
else if( strstr( buf, "!go_away" ) ) {
break;
}
memset( buf, 0x0, sizeof(buf) );
memset( cmd_buf, 0x0, sizeof(cmd_buf) );
memset( buf_snd, 0x0, sizeof(buf_snd) );
}
}
/******* 메시지 처리 끝 *******/
printf( "\n[-] EXIT\n" );
close(sockfd);
return 0;
}
void pong( int sockfd, char *ping, int sz )
{
int cnt;
char buffer[4096] = {0x00,};
strncpy( buffer, ping, sz );
memcpy( buffer, "PONG", 4 );
for( cnt = 1 ; cnt < sz ; cnt++ )
{
if( buffer[cnt] == '\n' )
break;
}
write( sockfd, buffer, cnt );
printf( "Request:\n" );
write( 1, buffer, cnt );
printf( "\n\n" );
}
int irc_req( int sockfd, char *req, ... )
{
va_list v_arg;
char buffer[4096] = {0x00,};
char *ptr;
strncpy( buffer, req, sizeof(buffer) -1 );
va_start( v_arg, req );
while( (ptr = va_arg( v_arg, char* )) != NULL )
{
strncat( buffer, " ", sizeof(buffer) -1 );
strncat( buffer, ptr, sizeof(buffer) -1 );
}
strncat( buffer, "\n", sizeof(buffer) -1 );
write( sockfd, buffer, strlen(buffer) );
printf( "Request:\n%s\n\n", buffer );
return 0;
}
hkpco님이 짜신겁니다...실제 컴파일하고 실행시켜보니 돌아가네요
어떻게 만져야 .. ;;