#include #include #include #include #include #include #include #include #include #include static const char *p_ent = "|"; static const char *a_ent = "&"; static const char *d_ent = "$"; #define check_error(cond, error) if (cond) { fputs(error "\n",stderr); exit(1); } #define check_alloc(ptr) check_error((ptr == NULL),"Couldn't allocate enough memory") static size_t escape_size (const char *c) { size_t ret = 0; while (*c != '\0') { switch(*c) { case '|': ret+=strlen(p_ent); break; case '&': ret+=strlen(a_ent); break; case '$': ret+=strlen(d_ent); break; default: ret++; break; } c++; } return ret+1; /*The string delimiter*/ } static char * do_escapes (const char *c) { char *res = malloc(escape_size(c)*sizeof(char)); char *ret = res; check_alloc(res); while (*c != '\0') { switch(*c) { case '|': memcpy(res,p_ent,strlen(p_ent)); res+=strlen(p_ent); break; case '&': /*&*/ memcpy(res,a_ent,strlen(a_ent)); res+=strlen(a_ent); break; case '$': /*$*/ memcpy(res,d_ent,strlen(d_ent)); res+=strlen(d_ent); break; default: *res = *c; res++; break; } c++; } *res='\0'; return ret; } static char *cmd1 = "$ForceMove %s|"; static char *cmd2 = "<%s> %s|$ForceMove %s|"; static char *gen_cmd1 (const char *urda) { char *rda, *send_buf; size_t blen; rda = do_escapes(urda); blen = strlen(cmd1)-2+strlen(rda)+1; send_buf = malloc(blen); check_alloc(send_buf); check_error((sprintf(send_buf, cmd1, rda) != blen-1),"Error generating commands"); free(rda); return send_buf; } static char *gen_cmd2 (const char *urda,const char *unick,const char *umes) { char *rda, *nick, *mes, *send_buf; size_t blen; rda = do_escapes(urda); nick = do_escapes(unick); mes = do_escapes(umes); blen = strlen(cmd2)-6+strlen(rda)+strlen(nick)+strlen(mes)+1; send_buf = malloc(blen); check_alloc(send_buf); check_error((sprintf(send_buf, cmd2, nick, mes, rda) != blen-1),"Error generating commands"); free(nick); free(mes); free(rda); return send_buf; } static int gen_sock (const char*port) { int ss; struct sockaddr_in sa; check_error(((ss = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0),"Couldn't create the socket"); memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(atoi(port)); check_error((bind(ss, (struct sockaddr *) &sa, sizeof(sa)) < 0),"Error during bind"); check_error((listen(ss,INT_MAX)<0),"Error during listen"); return ss; } char *send_buf; size_t send_size; static void *handle_req (void *arg) { int cs = *(int *)arg; free(arg); write(cs,send_buf,send_size); close(cs); return NULL; } /* Parameter 1: listen port Parameter 2: redirection address Parameter 3: Hub name Parameter 4: Redirect message */ int main (int argc, char** argv) { int ss; int *cs; pthread_t tid; pthread_attr_t attr; switch (argc) { case 3: send_buf=gen_cmd1(argv[2]); break; case 5: send_buf=gen_cmd2(argv[2],argv[3],argv[4]); break; default: fprintf(stderr,"Usage: %s port redirection_address [hub_name redirect_message]\n",argv[0]); fputs("Where:\n" " * Port: port to listen for connections\n" " * Redirection_address: Adress to redirect clients to (i.e. adcs://localhost:4111/)\n" " * Hub_name: Name of the hub used to send the message\n" " * Redirect_message: Message to send when redirectign the client\n",stderr); exit(1); } send_size=strlen(send_buf); /*Now generate the socket*/ ss=gen_sock(argv[1]); check_error((pthread_attr_init(&attr)!=0),"Can't initialize thread atributes"); check_error((pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED)!= 0),"Can't set detach state on thread atributes"); while (1) { cs = malloc(sizeof(int)); *cs = accept(ss,NULL,NULL); pthread_create(&tid,&attr,handle_req,cs); } return 0; }