/****************************************************************************** * TinTin++ * * Copyright (C) 2004 (See CREDITS file) * * * * This program is protected under the GNU GPL (See COPYING) * * * * 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 2 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, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ******************************************************************************/ /****************************************************************************** * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t * * * * coded by Peter Unold 1992 * ******************************************************************************/ #include "tintin.h" #include <errno.h> /************************/ /* the #session command */ /************************/ DO_COMMAND(do_session) { char temp[BUFFER_SIZE], left[BUFFER_SIZE]; struct session *sesptr; int cnt; substitute(ses, arg, temp, SUB_VAR|SUB_FUN); arg = temp; arg = get_arg_in_braces(arg, left, FALSE); if (*left == 0) { tintin_puts(ses, "#THESE SESSIONS HAVE BEEN DEFINED:"); for (sesptr = gts->next ; sesptr ; sesptr = sesptr->next) { show_session(ses, sesptr); } } else if (*left && *arg == 0) { if (*left == '+') { return activate_session(ses->next ? ses->next : gts->next ? gts->next : ses); } if (*left == '-') { return activate_session(ses->prev ? ses->prev : gts->prev ? gts->prev : ses); } if (is_number(left)) { for (cnt = 0, sesptr = gts ; sesptr ; cnt++, sesptr = sesptr->next) { if (cnt == atoi(left)) { return activate_session(sesptr); } } } tintin_puts(ses, "#THAT SESSION IS NOT DEFINED."); } else { ses = new_session(ses, left, arg, 0); } return gtd->ses; } /******************/ /* show a session */ /******************/ void show_session(struct session *ses, struct session *ptr) { char temp[BUFFER_SIZE]; sprintf(temp, "%-12s%20s:%-5s", ptr->name, ptr->host, ptr->port); if (ptr == gtd->ses) { strcat(temp, " (active)"); } else { strcat(temp, " "); } if (ptr->mccp) { strcat(temp, " (mccp) "); } if (HAS_BIT(ptr->flags, SES_FLAG_SNOOP)) { strcat(temp, " (snooped)"); } if (ptr->logfile) { strcat(temp, " (logging)"); } tintin_puts2(ses, temp); } /**********************************/ /* find a new session to activate */ /**********************************/ struct session *newactive_session(void) { push_call("newactive_session(void)"); if (gts->next) { activate_session(gts->next); } else { activate_session(gts); } pop_call(); return gtd->ses; } struct session *activate_session(struct session *ses) { check_all_events(gtd->ses, 0, 1, "SESSION DEACTIVATED", gtd->ses->name); gtd->ses = ses; dirty_screen(ses); tintin_printf(ses, "#SESSION '%s' ACTIVATED.", ses->name); check_all_events(ses, 0, 1, "SESSION ACTIVATED", ses->name); return ses; } /**********************/ /* open a new session */ /**********************/ struct session *new_session(struct session *ses, char *name, char *address, int desc) { int cnt = 0; char host[BUFFER_SIZE], port[BUFFER_SIZE]; struct session *newsession; push_call("new_session(%p,%p,%p,%d)",ses,name,address,desc); if (HAS_BIT(gtd->flags, TINTIN_FLAG_TERMINATE)) { pop_call(); return ses; } address = get_arg_in_braces(address, host, FALSE); address = get_arg_in_braces(address, port, FALSE); if (desc == 0) { if (*host == 0) { tintin_puts(ses, "#HEY! SPECIFY AN ADDRESS WILL YOU?"); pop_call(); return ses; } if (*port == 0) { tintin_puts(ses, "#HEY! SPECIFY A PORT NUMBER WILL YOU?"); pop_call(); return ses; } } for (newsession = gts ; newsession ; newsession = newsession->next) { if (!strcmp(newsession->name, name)) { tintin_puts(ses, "THERE'S A SESSION WITH THAT NAME ALREADY."); pop_call(); return ses; } } newsession = (struct session *) calloc(1, sizeof(struct session)); newsession->name = strdup(name); newsession->host = strdup(host); newsession->ip = strdup(""); newsession->port = strdup(port); newsession->group = strdup(gts->group); newsession->flags = gts->flags; newsession->telopts = gts->telopts; newsession->auto_tab = gts->auto_tab; newsession->cmd_color = strdup(gts->cmd_color); newsession->read_max = gts->read_max; newsession->read_buf = (unsigned char *) calloc(1, gts->read_max); LINK(newsession, gts->next, gts->prev); for (cnt = 0 ; cnt < LIST_MAX ; cnt++) { newsession->list[cnt] = copy_list(newsession, gts->list[cnt], cnt); } newsession->rows = gts->rows; newsession->cols = gts->cols; newsession->top_row = gts->top_row; newsession->bot_row = gts->bot_row; init_buffer(newsession, gts->scroll_max); if (desc) { tintin_printf2(ses, "#TRYING TO LAUNCH '%s' RUNNING '%s'.", newsession->name, newsession->host); } else { tintin_printf2(ses, "#TRYING TO CONNECT '%s' TO '%s' PORT '%s'.", newsession->name, newsession->host, newsession->port); } gtd->ses = newsession; dirty_screen(newsession); if (desc == 0) { connect_session(newsession); } else { SET_BIT(newsession->flags, SES_FLAG_CONNECTED|SES_FLAG_RUN); SET_BIT(newsession->telopts, TELOPT_FLAG_SGA); DEL_BIT(newsession->telopts, TELOPT_FLAG_ECHO); gtd->ses = newsession; gtd->ses->socket = desc; } pop_call(); return gtd->ses; } void connect_session(struct session *ses) { int sock; ses->connect_retry = utime() + gts->connect_retry; reconnect: sock = connect_mud(ses, ses->host, ses->port); if (sock == -1) { cleanup_session(ses); return; } if (sock) { gtd->ses = ses; ses->socket = sock; ses->connect_retry = 0; SET_BIT(ses->flags, SES_FLAG_CONNECTED); tintin_printf2(ses, ""); tintin_printf(ses, "#SESSION '%s' CONNECTED TO '%s' PORT '%s'", ses->name, ses->host, ses->port); if (atoi(ses->port) == TELNET_PORT) { init_telnet_session(ses); } check_all_events(ses, 0, 4, "SESSION CONNECTED", ses->name, ses->host, ses->ip, ses->port); return; } if (ses->connect_retry > utime()) { goto reconnect; } switch (ses->connect_error) { case EINTR: tintin_puts(ses, "#COULD NOT CONNECT - CALL INTERUPTED."); break; case ECONNREFUSED: tintin_puts(ses, "#COULD NOT CONNECT - REMOTE SERVER IS NOT REACHABLE."); break; case ENETUNREACH: tintin_puts(ses, "#COULD NOT CONNECT - THE NETWORK IS NOT REACHABLE FROM THIS HOST."); break; case ETIMEDOUT: tintin_puts(ses, "#COULD NOT CONNECT - CONNECTION TIMED OUT."); break; case EINPROGRESS: tintin_puts(ses, "#COULD NOT CONNECT - CONNECTION TIMED OUT."); break; default: tintin_puts(ses, "#COULD NOT CONNECT."); break; } cleanup_session(ses); } /*****************************************************************************/ /* cleanup after session died. if session=gtd->ses, try find new active */ /*****************************************************************************/ void cleanup_session(struct session *ses) { push_call("cleanup_session(%p)",ses); if (ses == gtd->update) { gtd->update = ses->next; } UNLINK(ses, gts->next, gts->prev); if (ses->socket) { if (close(ses->socket) == -1) { syserr("close in cleanup"); } } check_all_events(ses, 0, 4, "SESSION DISCONNECTED", ses->name, ses->host, ses->ip, ses->port); tintin_printf(gtd->ses, ""); tintin_printf(gtd->ses, "#SESSION '%s' DIED.", ses->name); if (ses == gtd->ses) { gtd->ses = newactive_session(); } if (ses->logfile) { fclose(ses->logfile); } if (ses->logline) { fclose(ses->logline); } LINK(ses, gtd->dispose_next, gtd->dispose_prev); pop_call(); return; } void dispose_session(struct session *ses) { int index; push_call("dispose_session(%p)", ses); UNLINK(ses, gtd->dispose_next, gtd->dispose_prev); for (index = 0 ; index < LIST_MAX ; index++) { free_list(ses->list[index]); } if (ses->map) { delete_map(ses); } if (ses->mccp) { inflateEnd(ses->mccp); free(ses->mccp); } init_buffer(ses, 0); free(ses->name); free(ses->host); free(ses->ip); free(ses->port); free(ses->group); free(ses->read_buf); free(ses->cmd_color); free(ses); pop_call(); return; }