/* Acidblood network routines */ /* Acidblood IRC Bot Copyright (C) 1997-2000 Bryan Schwab bryan@darkice.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "acidblood.h" #include #include #include #include #include #include #include #include #include #include #include #include #include int getline_from_server( struct botstruct *botinfo, char *c, int s) { int x=0,len; struct timeval tv; fd_set infd; extern int errno; tv.tv_sec=(60 * (botinfo->timeout)); tv.tv_usec=0; /* Setup the input descriptor for watch */ FD_ZERO(&infd); FD_SET(s,&infd); if (globalint) { /* we were interrupted, keep going */ #ifdef DEBUG fprintf(stderr, "Resuming interruption. x=%d\n",globalx); #endif x=globalx; } else { /* reset pointer */ c[0]='\0'; } /* #ifdef DEBUG printf("Selecting...\n"); #endif */ while(1) { len=select(s+1,&infd,NULL,NULL,&tv); if(len > 0) { if(recv(s, &c[x], 1, 0) < 0) { perror("recv"); return(-1); } /* if(c[x]=='\r' || c[x]=='\n') { */ /* all strings end in \r\n, so look for the \n */ if(c[x]=='\n') { c[x]='\0'; #ifdef DEBUG fprintf(stderr,"Final value of x=%d\n", x); #endif break; } if (x > 1024) { /* hmm, looks like buffer got away somewhere, return an error */ return(-1); } x++; } else if (len == 0) { /* timeout */ fprintf(stderr,"select error\n"); perror("select"); return(-2); } else if (len == -1){ /* error */ if (errno == EINTR) { /* setup the variables to return */ #ifdef DEBUG fprintf(stderr, "Interrupted! Setting globalx=%d\n",x); #endif globalx = x; globalint++; } else { fprintf(stderr,"select error\n"); perror("select"); } return(-1); } } totalbytes+=x; /* #ifdef DEBUG printf("\n"); printf("Bytes=%d\n",x); printf("Total Bytes=%d\n",totalbytes); #endif */ globalint=0; return (x); } /* connect to the server */ /* at this point, everything is put into log files */ int connect_to_server( struct botstruct *botinfo, FILE **fp_socket, FILE **fp_log, int *s) { struct sockaddr_in sin; struct hostent *hp; /* defined globally now */ /* char *input; */ char output[80]; char temp[50]; char key[50]; char *tmpptr; char *codeptr; int code; char done=0; if ((input=malloc(1000))==NULL) { fprintf(stderr, "connect_to_server: Malloc error!\n"); return(-1); } if ((hp=gethostbyname(botinfo->server)) == NULL) { fprintf(*fp_log, "Network Error: Unknown host %s\n",botinfo->server); return(-1); } if ((*s=socket(AF_INET,SOCK_STREAM,0)) < 0) { fprintf(*fp_log, "Network Error: Cannot create socket!\n"); return(-1); } sin.sin_family=AF_INET; sin.sin_port=htons(botinfo->port); bcopy(hp->h_addr, &sin.sin_addr, hp->h_length); /* timeout in 30 seconds */ alarm(30); if (connect(*s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { fprintf(*fp_log, "Network Error: Cannot connect to port.\n"); return(-1); } /* reset alarm */ alarm(0); /* this could be removed */ if ((*fp_socket=fdopen(*s,"r"))==NULL) { return(-1); } printf("Registering...\n"); snprintf(output,80,"USER %s %s +iw :%s\n",botinfo->user,botinfo->server,botinfo->fname); if ((send(*s,output,strlen(output),0))==-1) { return(-1); } snprintf(output,80,"NICK %s\n",botinfo->nick); if ((send(*s,output,strlen(output),0))==-1) { return(-1); } /* Now we have told the server all we should have to */ done=0; while(1) { getline_from_server(botinfo, input, *s); #ifdef DEBUG printf("connect> %s\n",input); #endif /* if line is null, crashes, FIX */ /* Set codeptr to point to the first character after the first space */ codeptr=strchr(input, ' ')+1; if(isdigit(codeptr[0])) { /* if(codeptr[0] >= '0' && codeptr[0] <= '9') { */ sscanf(codeptr,"%d",&code); } else { code=-1; } if(input[0]==':') { /* Message from server or user */ if(code > 0) { /* Numeric code from server */ switch(code) { case 1: /* Welcome */ /* We could pull the irc server name from this.. just so we have it */ break; case 433: /* Nick already in use */ if(strncmp(botinfo->nick, botinfo->altnick, strlen(botinfo->altnick)+1)==0) { fprintf(stderr,"Regular and alternate nick names are in use. Exiting.\n"); fprintf(*fp_log,"Regular and alternate nick names are in use. Exiting.\n"); /* This exit is a bit dangerous... nothin is free()ed */ exit(0); } fprintf(*fp_log,"Nickname is already in use, using alternate.\n"); snprintf(output,80,"NICK %s\n",botinfo->altnick); if ((send(*s,output,strlen(output),0))==-1) return(-1); /* set new bot nick pointer */ if (botinfo->nick!=NULL) { free(botinfo->nick); } botinfo->nick=malloc(strlen(botinfo->altnick)+1); strncpy(botinfo->nick, botinfo->altnick, strlen(botinfo->altnick)+1); break; case 372: /* Motd body */ break; case 376: /* Motd end, this is where we stop trying to conenct to a server */ done=1; break; case 422: /* Motd missing */ done=1; break; } } else { /* PRIVMSG, etc, etc */ /* We aren't concerned about anything like that in here */ ; } } else if(memcmp(input,"PING",4)==0) { tmpptr=strtok(input,":"); tmpptr=strtok(NULL,"\n"); snprintf(output,80,"PONG :%s\n",tmpptr); if ((send(*s,output,strlen(output),0))==-1) { fprintf(*fp_log,"Error sending to server.\n"); exit(-1); } /* hmmmm, not good if we get an error! */ /* done=1; */ } else if(memcmp(input,"NOTICE",6)==0) { /* Ident, and other stuff in here. on efnet servers, this is an excellent place to put USER and NICK */ } else if (memcmp(input,"ERROR",5)==0) { fprintf(*fp_log,"%s",input); fflush(*fp_log); printf("%s",input); if ((strstr(input,"No Authorization"))!=NULL) { return(-2); } if ((strstr(input,"No more connections"))!=NULL) { return(-3); } if ((strstr(input, "Identd Required"))!=NULL) { return(-4); } if ((strstr(input, "Closing Link"))!=NULL) { return(-5); } } if(done) break; } curr3=top3; prev3=top3; if (botinfo->ns==1) {} else { while (get_channel(channeldata,temp,key) > 0) { snprintf(output,80,"JOIN %s %s\n",temp,key); if ((send(*s,output,strlen(output),0))==-1) { fprintf(*fp_log,"Error sending to server.\n"); return(-1); } } } /* if an away message exists, set away */ if (botinfo->awaymsg != NULL) { snprintf(output,80,"AWAY :%s\n",botinfo->awaymsg); if ((send(*s,output,strlen(output),0))==-1) { fprintf(*fp_log,"Error sending to server.\n"); return(-1); } } return(0); }