From 4fdc419424dd18df5807ed4218a84fa38e1dd6f6 Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 10 May 2012 00:04:26 +0200 Subject: [PATCH] added session manager and support for an external login system --- Makefile.am | 1 + login.php | 12 +++ src/IOEngine_select.c | 19 ++-- src/IOHandler.c | 38 ++++++-- src/IOHandler.h | 2 + src/UserClient.c | 98 ++++++++++++++++++- src/UserClient.h | 28 +++++- src/UserSession.c | 221 ++++++++++++++++++++++++++++++++++++++++++ src/UserSession.h | 42 ++++++++ src/main.c | 2 + src/overall.h | 2 + src/tools.c | 100 ++++++++++++++++++- src/tools.h | 8 ++ transirc.conf | 14 +++ 14 files changed, 565 insertions(+), 22 deletions(-) create mode 100644 login.php create mode 100644 src/UserSession.c create mode 100644 src/UserSession.h create mode 100644 transirc.conf diff --git a/Makefile.am b/Makefile.am index edd0e47..7d04a23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ transirc_SOURCES = src/version.c \ src/main.c \ src/ServerSocket.c \ src/tools.c \ + src/UserSession.c \ src/UserClient.c transirc_LDADD = $(MYSQL_LIBS) $(SYSTEM_LIBS) diff --git a/login.php b/login.php new file mode 100644 index 0000000..c6f95cc --- /dev/null +++ b/login.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/src/IOEngine_select.c b/src/IOEngine_select.c index dabe2e6..2f32bf0 100644 --- a/src/IOEngine_select.c +++ b/src/IOEngine_select.c @@ -56,15 +56,16 @@ static void engine_select_loop(struct timeval *timeout) { FD_SET(iofd->fd, &read_fds); if(iohandler_wants_writes(iofd)) FD_SET(iofd->fd, &write_fds); - } else if(iofd->type == IOTYPE_TIMER) { + } + if(iofd->type == IOTYPE_TIMER || iofd->timeout.tv_sec || iofd->timeout.tv_usec) { tdiff.tv_sec = iofd->timeout.tv_sec - now.tv_sec; tdiff.tv_usec = iofd->timeout.tv_usec - now.tv_usec; if(tdiff.tv_sec < 0 || (tdiff.tv_sec == 0 && tdiff.tv_usec <= 0)) { //exec timer - iofd->state = IO_CLOSED; - iohandler_events(iofd, 1, 0); - iohandler_close(iofd); + iohandler_events(iofd, 0, 0); + if(iofd->type == IOTYPE_TIMER) + iohandler_close(iofd); continue; } else if(tdiff.tv_usec < 0) { tdiff.tv_sec--; @@ -87,6 +88,8 @@ static void engine_select_loop(struct timeval *timeout) { } } + gettimeofday(&now, NULL); + //check all descriptors for(iofd = first_descriptor; iofd; iofd = tmp_iofd) { tmp_iofd = iofd->next; @@ -94,14 +97,16 @@ static void engine_select_loop(struct timeval *timeout) { if(FD_ISSET(iofd->fd, &read_fds) || FD_ISSET(iofd->fd, &write_fds)) { iohandler_events(iofd, FD_ISSET(iofd->fd, &read_fds), FD_ISSET(iofd->fd, &write_fds)); } - } else if(iofd->type == IOTYPE_TIMER) { + } + if(iofd->type == IOTYPE_TIMER || iofd->timeout.tv_sec || iofd->timeout.tv_usec) { tdiff.tv_sec = iofd->timeout.tv_sec - now.tv_sec; tdiff.tv_usec = iofd->timeout.tv_usec - now.tv_usec; if(tdiff.tv_sec < 0 || (tdiff.tv_sec == 0 && tdiff.tv_usec <= 0)) { //exec timer - iofd->state = IO_CLOSED; - iohandler_events(iofd, 1, 0); + iohandler_events(iofd, 0, 0); + if(iofd->type == IOTYPE_TIMER) + iohandler_close(iofd); continue; } } diff --git a/src/IOHandler.c b/src/IOHandler.c index b276272..375bcea 100644 --- a/src/IOHandler.c +++ b/src/IOHandler.c @@ -71,7 +71,7 @@ struct IODescriptor *iohandler_add(int sockfd, enum IOType type, iohandler_callb return descriptor; } -static void iohandler_remove(struct IODescriptor *descriptor) { +static void iohandler_remove(struct IODescriptor *descriptor, int engine_remove) { //remove IODescriptor from the list if(descriptor->prev) descriptor->prev->next = descriptor->next; @@ -79,7 +79,8 @@ static void iohandler_remove(struct IODescriptor *descriptor) { first_descriptor = descriptor->next; if(descriptor->next) descriptor->next->prev = descriptor->prev; - engine->remove(descriptor); + if(engine_remove) + engine->remove(descriptor); if(descriptor->readbuf.buffer) free(descriptor->readbuf.buffer); if(descriptor->writebuf.buffer) @@ -296,7 +297,7 @@ void iohandler_write(struct IODescriptor *iofd, const char *line) { } void iohandler_send(struct IODescriptor *iofd, const char *data, size_t datalen) { - if(iofd->type == IOTYPE_TIMER) return; //can not write to timer? :D + if(iofd->type == IOTYPE_TIMER || iofd->state == IO_CLOSED) return; //can not write to timer? :D if(iofd->writebuf.buflen < iofd->writebuf.bufpos + datalen) { iohandler_increase_iobuf(&iofd->writebuf, iofd->writebuf.bufpos + datalen); if(iofd->writebuf.buflen < iofd->writebuf.bufpos + datalen) @@ -335,10 +336,24 @@ void iohandler_try_write(struct IODescriptor *iofd) { } void iohandler_close(struct IODescriptor *iofd) { + int engine_remove = 1; + if(iofd->writebuf.bufpos) { + //try to send everything before closing +#if defined(F_GETFL) + flags = fcntl(sockfd, F_GETFL); + fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK); + flags = fcntl(sockfd, F_GETFD); + fcntl(sockfd, F_SETFD, flags|FD_CLOEXEC); +#else + engine_remove = 0; + engine->remove(iofd); +#endif + iohandler_try_write(iofd); + } //close IODescriptor if(iofd->type == IOTYPE_SERVER || iofd->type == IOTYPE_CLIENT || iofd->type == IOTYPE_STDIN) close(iofd->fd); - iohandler_remove(iofd); + iohandler_remove(iofd, engine_remove); } void iohandler_update(struct IODescriptor *iofd) { @@ -360,11 +375,13 @@ void iohandler_events(struct IODescriptor *iofd, int readable, int writeable) { callback_event.type = IOEVENT_TIMEOUT; break; case IO_LISTENING: - callback_event.data.accept_fd = accept(iofd->fd, NULL, 0); - if(callback_event.data.accept_fd < 0) { - //error: could not accept - } else - callback_event.type = IOEVENT_ACCEPT; + if(readable) { + callback_event.data.accept_fd = accept(iofd->fd, NULL, 0); + if(callback_event.data.accept_fd < 0) { + //error: could not accept + } else + callback_event.type = IOEVENT_ACCEPT; + } break; case IO_CONNECTING: if(readable) { //could not connect @@ -386,6 +403,7 @@ void iohandler_events(struct IODescriptor *iofd, int readable, int writeable) { int bytes = recv(iofd->fd, iofd->readbuf.buffer + iofd->readbuf.bufpos, iofd->readbuf.buflen - iofd->readbuf.bufpos, 0); if(bytes <= 0) { if (errno != EAGAIN) { + iofd->state = IO_CLOSED; callback_event.type = IOEVENT_CLOSED; callback_event.data.errid = errno; } @@ -429,6 +447,8 @@ void iohandler_events(struct IODescriptor *iofd, int readable, int writeable) { } break; } + if(callback_event.type == IOEVENT_IGNORE && !readable && !writeable) + callback_event.type = IOEVENT_TIMEOUT; if(callback_event.type != IOEVENT_IGNORE) iohandler_trigger_event(&callback_event); } diff --git a/src/IOHandler.h b/src/IOHandler.h index 7d33ce2..8bc2a37 100644 --- a/src/IOHandler.h +++ b/src/IOHandler.h @@ -57,6 +57,7 @@ struct IOBuffer { struct IODescriptor { int fd; + FILE *file; enum IOType type; enum IOStatus state; struct timeval timeout; @@ -80,6 +81,7 @@ struct IOEvent { }; struct IODescriptor *iohandler_add(int sockfd, enum IOType type, iohandler_callback *callback); +struct IODescriptor *iohandler_file(FILE *file, iohandler_callback *callback); struct IODescriptor *iohandler_timer(struct timeval timeout, iohandler_callback *callback); struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, const char *bind, iohandler_callback *callback); struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, iohandler_callback *callback); diff --git a/src/UserClient.c b/src/UserClient.c index fccf56b..e64b8a0 100644 --- a/src/UserClient.c +++ b/src/UserClient.c @@ -17,6 +17,8 @@ #include "UserClient.h" #include "IOHandler.h" #include "ServerSocket.h" +#include "UserSession.h" +#include "tools.h" static void userclient_callback(struct IOEvent *event); @@ -29,12 +31,17 @@ void userclient_accepted(struct ServerSocket *server, int sockfd) { iofd->state = IO_CONNECTED; iofd->read_lines = 1; iohandler_update(iofd); - client = malloc(sizeof(*client)); + client = calloc(1, sizeof(*client)); client->iofd = iofd; iofd->data = client; client->server = server; server->clientcount++; + struct UserLogin *login = calloc(1, sizeof(*login)); + client->user = login; + login->client = client; + + //add UserClient to the list client->prev = NULL; client->next = userclients; @@ -43,10 +50,29 @@ void userclient_accepted(struct ServerSocket *server, int sockfd) { userclients = client; //let's say hello to the client - iohandler_printf(iofd, "NOTICE AUTH :*** TransparentIRC " TRANSIRC_VERSION " (use /quote transirc for more information)"); + iohandler_printf(iofd, "NOTICE AUTH :*** [TransparentIRC] TransparentIRC v" TRANSIRC_VERSION " (use /quote transirc for more information)"); } void userclient_close(struct UserClient *client) { + if(client->flags & USERCLIENT_LOGGED_IN) { + usersession_client_close(client->user); + } else { + struct UserLogin *login = client->user; + if(client->flags & USERCLIENT_LOGIN_PROCESSING) { + usersession_login_abort(login); + } + if(login->username) + free(login->username); + if(login->password) + free(login->password); + if(login->nick) + free(login->nick); + if(login->reject_reason) + free(login->reject_reason); + if(login->session_class) + free(login->session_class); + free(login); + } iohandler_close(client->iofd); client->server->clientcount--; if(client->prev) @@ -55,6 +81,7 @@ void userclient_close(struct UserClient *client) { userclients = client->next; if(client->next) client->next->prev = client->prev; + free(client); } @@ -72,7 +99,72 @@ void userclient_close_server(struct ServerSocket *server, int keep_clients) { } static void userclient_recv(struct UserClient *client, char *line) { - iohandler_printf(client->iofd, "reply: %s", line); + if(!stricmplen(line, "TRANSIRC ", 9)) { + /* + char *argv[MAXNUMPARAMS]; + int argc = parse_line(line, argv, 1); + */ + + } else if(!(client->flags & USERCLIENT_LOGGED_IN)) { + struct UserLogin *login = client->user; + char *argv[MAXNUMPARAMS]; + int argc = parse_line(line, argv, 1); + if(argc < 3) return; + if(!stricmp(argv[1], "PASS")) { + char *delimiter = strchr(argv[2], ':'); + if(login->password) + free(login->password); + if(delimiter) { + *delimiter = '\0'; + delimiter++; + if(login->username) + free(login->username); + login->username = strdup(argv[2]); + login->password = strdup(delimiter); + } else + login->password = strdup(argv[2]); + } else if(!stricmp(argv[1], "USER")) { + if(!login->username) + login->username = strdup(argv[2]); + } else if(!stricmp(argv[1], "NICK")) { + if(login->nick) + free(login->nick); + login->nick = strdup(argv[2]); + if(!login->password) { + iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] You need to send your LOC data. Try /quote PASS :"); + } + } + if(login->username && login->password && login->nick && !(client->flags & USERCLIENT_LOGIN_PROCESSING)) { + //try to login + iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Checking login..."); + usersession_login(login); + } + } else { + + } +} + +void userclient_login_failed(struct UserLogin *login, char *reason) { + iohandler_printf(login->client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login rejected"); + userclient_close(login->client); +} + +void userclient_login_successful(struct UserLogin *login, struct UserSession *session, int recover) { + struct UserClient *client = login->client; + iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login accepted."); + if(login->username) + free(login->username); + if(login->password) + free(login->password); + if(login->nick) + free(login->nick); + free(login); + client->user = session; + if(recover) { + iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Recovering previous link (Nick: %s).", session->nick); + + + } } static void userclient_callback(struct IOEvent *event) { diff --git a/src/UserClient.h b/src/UserClient.h index 6b95ea1..bde6001 100644 --- a/src/UserClient.h +++ b/src/UserClient.h @@ -21,13 +21,35 @@ struct IODescriptor; struct ServerSocket; -//struct UserSession; +struct UserSession; + +#define USERCLIENT_LOGIN_PROCESSING 0x01 +#define USERCLIENT_LOGGED_IN 0x02 + +struct UserLogin { + struct UserClient *client; + char *username; + char *password; + char *nick; + + int login_accepted : 1; + char *reject_reason; + + char *session_class; + + struct IODescriptor *login_iofd; +}; struct UserClient { struct IODescriptor *iofd; struct ServerSocket *server; - //struct UserSession *user; + int flags; + void *user; /* struct UserSession / struct UserLogin */ + + char *username; + char *password; + char *nick; struct UserClient *next, *prev; }; @@ -35,5 +57,7 @@ struct UserClient { void userclient_accepted(struct ServerSocket *server, int sockfd); void userclient_close(struct UserClient *client); void userclient_close_server(struct ServerSocket *server, int keep_clients); +void userclient_login_failed(struct UserLogin *login, char *reason); +void userclient_login_successful(struct UserLogin *login, struct UserSession *session, int recover); #endif diff --git a/src/UserSession.c b/src/UserSession.c new file mode 100644 index 0000000..136b767 --- /dev/null +++ b/src/UserSession.c @@ -0,0 +1,221 @@ +/* UserSession.c - TransparentIRC 0.1 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 of the License, 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, see . + */ +#include "UserSession.h" +#include "IOHandler.h" +#include "UserClient.h" +#include "ConfigParser.h" +#include "tools.h" + +static struct UserSession *usersessions = NULL; + +static struct UserSession *usersession_add(char *username, char *password, char *nick) { + struct UserSession *session; + session = calloc(1, sizeof(*session)); + session->username = strdup(username); + session->password = strdup(password); + session->nick = strdup(nick); + + //add UserSession to the list + session->prev = NULL; + session->next = usersessions; + if(usersessions) + usersessions->prev = session; + usersessions = session; + + return session; +} + +/* +static void usersession_close(struct UserSession *session) { + if(session->client) + userclient_close(session->client); + + if(session->prev) + session->prev->next = session->next; + else + usersessions = session->next; + if(session->next) + session->next->prev = session->prev; + free(session->username); + free(session->password); + free(session->nick); + free(session); +} +*/ + +/* ****************** SESSION FUNCTIONS ****************** */ + +static void usersession_initialize_session(struct UserSession *session) { + +} + +/* ****************** EXTERNAL EVENTS ****************** */ + +void usersession_client_close(struct UserSession *session) { + session->client = NULL; + session->idle_since = time(0); + +} + +void usersession_client_notification(struct UserSession *session, char *notification) { + if(session->client) { + iohandler_printf(session->client->iofd, ":*TransparentIRC!TransIRC@TransparentIRC.system.notification NOTICE %s :[TransparentIRC] %s", session->nick, notification); + } +} + +/* ****************** LOGIN FUNCTIONS ****************** */ + +static void usersession_login_accept(struct UserLogin *login); +static void usersession_login_callback(struct IOEvent *event); + +void usersession_login(struct UserLogin *login) { + if(get_int_field("auth.external.enabled")) { + char *execute = get_string_field("auth.external.execute"); + char *parameters = get_string_field("auth.external.parameters"); + + struct variable_replace_map map[] = { + {'U', login->username}, + {'P', login->password}, + {'N', login->nick}, + {0, NULL} + }; + char paramstr[CMDLEN+1]; + build_var_string(paramstr, parameters, map); + char *argv[MAXNUMPARAMS]; + int argc = parse_line(paramstr, argv+1, 0); + argv[0] = execute; + argv[argc+1] = NULL; + int fp = run_external_process(execute, argv); + if(fp < 0) { + userclient_login_failed(login, "Login Script error."); + return; + } + struct IODescriptor *iofd = iohandler_add(fp, IOTYPE_CLIENT, usersession_login_callback); + if(iofd) { + iofd->read_lines = 1; + iofd->state = IO_CONNECTED; + int timeout = get_int_field("auth.external.timeout"); + if(timeout) { + gettimeofday(&iofd->timeout, NULL); + iofd->timeout.tv_sec += timeout; + } + iofd->data = login; + login->login_iofd = iofd; + login->client->flags |= USERCLIENT_LOGIN_PROCESSING; + } else + userclient_login_failed(login, "Internal error."); + } else + usersession_login_accept(login); +} + +static void usersession_login_accept(struct UserLogin *login) { + //search session for user (or create a new one) + struct UserSession *session, *active_session = NULL; + int sessioncount = 0; + for(session = usersessions; session; session = session->next) { + if(!stricmp(login->username, session->username)) { + sessioncount++; + if(!strcmp(login->password, session->password) && !stricmp(login->nick, session->nick)) { + active_session = session; + } + } + } + if(active_session) { + if(active_session->client) { + iohandler_printf(active_session->client->iofd, "ERROR :[TransparentIRC] Another client logged in."); + userclient_close(active_session->client); + } //active_session->client is now NULL + active_session->client = login->client; + userclient_login_successful(login, active_session, 1); + } else { + int sessionlimit = get_int_field("auth.session_limit"); + if(sessionlimit && sessioncount >= sessionlimit) { + userclient_login_failed(login, "Session limit reached."); + return; + } + active_session = usersession_add(login->username, login->password, login->nick); + if(!active_session) { + userclient_login_failed(login, "Could not create Session."); + return; + } + userclient_login_successful(login, active_session, 0); + usersession_initialize_session(active_session); + } +} + +void usersession_login_abort(struct UserLogin *login) { + struct IODescriptor *iofd = login->login_iofd; + iohandler_close(iofd); +} + +static void usersession_login_callback(struct IOEvent *event) { + struct UserLogin *login = event->iofd->data; + login->client->flags &= ~USERCLIENT_LOGIN_PROCESSING; + char *reply; + int login_finished = 0; + switch(event->type) { + case IOEVENT_RECV: + reply = event->data.recv_str; + if(!stricmplen(reply, "REJECT", 6)) { + if((reply = strchr(reply, ' '))) { + char reason[LINELEN]; + sprintf(reason, "Access denied: %s", reply + 7); + login->reject_reason = strdup(reason); + } else + login->reject_reason = strdup("Access denied."); + } else if(!stricmplen(reply, "ACCEPT", 6)) { + if((reply = strchr(reply, ' '))) { + char *passwd = strchr(reply, ' '); + if(passwd) { + *passwd = '\0'; + passwd++; + free(login->password); + login->password = strdup(passwd); + } + free(login->username); + login->username = strdup(reply); + } + login->login_accepted = 1; + } else { + char *argv[MAXNUMPARAMS]; + int argc = parse_line(reply, argv, 0); + if(argc < 2) return; + if(!stricmp(argv[0], "CLASS")) { + login->session_class = strdup(argv[1]); + } + + } + break; + case IOEVENT_TIMEOUT: + login->reject_reason = strdup("Login Script timeout."); + login_finished = 1; + break; + case IOEVENT_CLOSED: + login->reject_reason = strdup("Login Script error (no reply)."); + login_finished = 1; + break; + default: + return; + } + if(login_finished) { + iohandler_close(event->iofd); + if(login->login_accepted) + usersession_login_accept(login); + else + userclient_login_failed(login, login->reject_reason); + } +} diff --git a/src/UserSession.h b/src/UserSession.h new file mode 100644 index 0000000..deb9f59 --- /dev/null +++ b/src/UserSession.h @@ -0,0 +1,42 @@ +/* UserSession.h - TransparentIRC 0.1 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * 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 3 of the License, 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, see . + */ + +#ifndef _UserSession_h +#define _UserSession_h +#include "overall.h" + +struct UserClient; +struct UserLogin; + +struct UserSession { + char *username; + char *password; + char *nick; + + struct UserClient *client; + time_t idle_since; + time_t connected_since; + + struct UserSession *next, *prev; +}; + +void usersession_client_notification(struct UserSession *session, char *notification); +void usersession_login(struct UserLogin *login); +void usersession_login_abort(struct UserLogin *login); +void usersession_client_close(struct UserSession *session); + +#endif diff --git a/src/main.c b/src/main.c index 19e5307..ddf5568 100644 --- a/src/main.c +++ b/src/main.c @@ -17,6 +17,7 @@ #include "IOHandler.h" #include "ServerSocket.h" +#include "ConfigParser.h" char *configFile = "transirc.conf"; @@ -43,6 +44,7 @@ int main(int argc, char *argv[]) { } #endif parseParameters(argc, argv); + loadConfig(configFile); serversocket_listen("0.0.0.0", 9001); diff --git a/src/overall.h b/src/overall.h index 7345c79..edf7157 100644 --- a/src/overall.h +++ b/src/overall.h @@ -25,6 +25,8 @@ #define IO_READ_BUFLEN 1024 #define IO_MAX_TIMEOUT 10 #define LINELEN 512 +#define CMDLEN 512 +#define MAXNUMPARAMS 200 #include #include diff --git a/src/tools.c b/src/tools.c index 6478279..5a26b19 100644 --- a/src/tools.c +++ b/src/tools.c @@ -39,4 +39,102 @@ int stricmplen(const char *s1, const char *s2, int len) { if(i == len) break; } return c1 - c2; -} \ No newline at end of file +} + +int parse_line(char *line, char **argv, int irc_raw) { + int argc = 0; + if(irc_raw) { + if(line[0] == ':') + line++; + else + argv[argc++] = NULL; + } + while(*line) { + //skip leading spaces + while (*line == ' ') + *line++ = 0; + if (*line == ':' && irc_raw) { + //the rest is a single parameter + argv[argc++] = line + 1; + break; + } + argv[argc++] = line; + if (argc >= MAXNUMPARAMS) + break; + while (*line != ' ' && *line) + line++; + } + return argc; +} + +void build_var_string(char *buffer, char *format, struct variable_replace_map *map) { + int bufferpos = 0; + int i, escape = 0; + char *p = format; + char *tmp; + while(*p) { + if(escape) { + escape = 0; + goto build_var_string_addchar; + } + if(*p == '\\') { + escape = 1; + p++; + continue; + } + if(*p == '%') { + p++; + for(i = 0; ; i++) { + if(!map[i].character) { + tmp = NULL; + break; + } + if(map[i].character == *p) { + tmp = map[i].value; + break; + } + } + if(!tmp) { + p--; + goto build_var_string_addchar; + } + for(i = 0; tmp[i] && bufferpos < CMDLEN; i++) { + buffer[bufferpos++] = tmp[i]; + } + } else { + build_var_string_addchar: + buffer[bufferpos++] = *p; + if(bufferpos == CMDLEN) + break; + } + p++; + } + buffer[bufferpos++] = '\0'; +} + +int run_external_process(char *command, char **parameters) { //win32 incompatible + int sockets[2], child; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) + return -1; + if ((child = fork()) == -1) { + close(sockets[0]); + close(sockets[1]); + return -1; + } + else if (child) { // This is the parent. + close(sockets[0]); + wait(NULL); + return sockets[1]; + } else { // This is the child. + close(sockets[1]); + child = fork(); //double fork to prevent zombies + if(child < 0) exit(EXIT_FAILURE); + if(child != 0) exit(EXIT_SUCCESS); + if(dup2(sockets[0], 1) != -1) { + execvp(command, parameters); + } + close(sockets[0]); + exit(EXIT_FAILURE); + } +} + diff --git a/src/tools.h b/src/tools.h index 4f4d11e..33f4f02 100644 --- a/src/tools.h +++ b/src/tools.h @@ -19,7 +19,15 @@ #define _tools_h #include "overall.h" +struct variable_replace_map { + char character; + char *value; +}; + int stricmp(const char *s1, const char *s2); int stricmplen(const char *s1, const char *s2, int len); +int parse_line(char *line, char **argv, int irc_raw); +void build_var_string(char *buffer, char *format, struct variable_replace_map *map); +int run_external_process(char *command, char **parameters); #endif diff --git a/transirc.conf b/transirc.conf new file mode 100644 index 0000000..9729f84 --- /dev/null +++ b/transirc.conf @@ -0,0 +1,14 @@ + +"auth" { + "session_limit" = 2; + + "external" { + "enabled" = 1; + "execute" = "./login.php"; + // %U = Username + // %P = Password + // %N = Nick + "parameters" = "%U %P %N"; + "timeout" = 5; + }; +}; \ No newline at end of file -- 2.20.1