/* * Code from: Philipp Meinen * Copyright (C): 2003-2004 Philipp Meinen * * Email: lancelot@lancelot2k.dyndns.org * Homepage: http://lancelot2k.dyndns.org * License: GPL * */ #define _FUNCTIONS_CC_ #include #include #include #include #include #include #include #include #include #include "functions.h" static char * readoneline(int filedesc); static void parse_config_params(struct from_config_file * settings, char * oneline); static char * get_config_file_name(void); void usage(char * name) { printf("Usage:\n"); printf("%s [options]\n\n", name); printf("Valid options are:\n"); printf("-i\t\tignore that user root starts the ircclient\n"); printf("-c\t\twrite a new default configfile\n"); printf("-t\t\ttest a configfile\n"); printf("-h or --help\tWhat you are reading now\n"); printf("-v\t\tprint a version info\n"); } struct from_config_file * get_config_file_settings(void) { char * directory = get_config_file_name(); if(directory == NULL) return NULL; struct from_config_file * settings; settings = new struct from_config_file; memset(settings, '\0', sizeof(struct from_config_file)); set_default_config(settings); /* now open the configfile */ int configfile; configfile = open(directory, O_RDONLY|O_CREAT, S_IRUSR|S_IWUSR); delete[] directory; if(configfile == -1) return settings;; char * oneline; /* read one line from the config file and parse it */ do { oneline = readoneline(configfile); if(oneline == NULL) { break; } parse_config_params(settings, oneline); delete[] oneline; oneline = NULL; } while(1); close(configfile); return settings; } void create_default_config(void) { char * directory = get_config_file_name(); printf("Writing a new config-file to %s\n", directory); int configfile; configfile = open(directory, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); delete[] directory; if(configfile == -1) { printf("error while opening the config-file\n"); return; } write(configfile, "nickname=\n", 10); write(configfile, "realname=", 9); write(configfile, DEFAULT_REALNAME, (sizeof DEFAULT_REALNAME)-1); write(configfile, "\nserver=", 8); write(configfile, DEFAULT_SERVERNAME, (sizeof DEFAULT_SERVERNAME)-1); write(configfile, "\nport=", 6); write(configfile, DEFAULT_PORT_STR, (sizeof DEFAULT_PORT_STR)-1); write(configfile, "\nmodes=", 7); write(configfile, DEFAULT_MODES, (sizeof DEFAULT_MODES)-1); write(configfile, "\nautoconnect=", 13); write(configfile, DEFAULT_AUTOCONNECT_STR, (sizeof DEFAULT_AUTOCONNECT_STR)-1); write(configfile, "\nautoreconnect=", 15); write(configfile, DEFAULT_AUTORECONNECT_STR, (sizeof DEFAULT_AUTORECONNECT_STR)-1); write(configfile, "\ncommand=/join #netwalker", 25); close(configfile); return; } char * readoneline(int filedesc) { int num = 0; char * buf = new char[READ_BUFLEN]; buf[0] = '\0'; char onechar[2]; onechar[1] = '\0'; do { num = read(filedesc, onechar, 1); if(num < 1) { /* end of file or error */ if(strlen(buf) > 0) { return buf; } else { /* when the end of the file was found and there is no buffer * to return we will return NULL */ delete[] buf; return NULL; } } else { /* not end of file */ if(onechar[0] == '\n') { /* we have found the end of the line */ return buf; } int len = strlen(buf); if(len < READ_BUFLEN-1) { /* there is enough space in the buffer */ strncat(buf, onechar, (READ_BUFLEN-len-1)); } /* if one line has more then READ_BUFLEN characters: * they simply wont be added to this buffer */ } } while(1); return NULL; } void parse_config_params(struct from_config_file * settings, char * oneline) { int len = strlen(oneline); if(len >= 6) { if(strncmp(oneline, "port=", 5) == 0) { settings->port = atoi(oneline+5); if((settings->port < 1) || (settings->port > 65535)) settings->port = 6667; else settings->port = DEFAULT_PORT_NUM; return; } } if(len >= 7) { if(strncmp(oneline, "modes=", 6) == 0) { strncpy(settings->modes, oneline+6, MODE_TO_SET_LEN-1); return; } } if(len >= 8) { if(strncmp(oneline, "server=", 7) == 0) { strncpy(settings->servername, oneline+7, SERVER_NAME_LEN-1); return; } } if(len >= 9) { if(strncmp(oneline, "command=", 8) == 0) { if(settings->command_on_startup_num < COMMAND_MAX) { strncpy(settings->command_on_startup[settings->command_on_startup_num], oneline+8, COMMAND_LEN-1); settings->command_on_startup_num++; } return; } } if(len >= 10) { if(strncmp(oneline, "nickname=", 9) == 0) { strncpy(settings->nickname, oneline+9, NICKNAME_LEN-1); return; } else if(strncmp(oneline, "realname=", 9) == 0) { oneline += 9; strncpy(settings->realname, oneline, REALNAME_LEN-1); oneline -= 9; return; } } if(len >= 13) { if(strncmp(oneline, "autoconnect=", 12) == 0) { string_toupper(oneline+12); if(strncmp(oneline+12, "YES", 3) == 0 || strncmp(oneline+12, "1", 1) == 0) { settings->autoconnect = 1; } else settings->autoconnect = 0; } } if(len >= 15) { if(strncmp(oneline, "leave_message=", 14) == 0) { strncpy(settings->part_quit_msg, oneline+14, PART_QUIT_MSG_LEN-1); } else if(strncmp(oneline, "autoreconnect=", 14) == 0) { string_toupper(oneline+14); if(strncmp(oneline+14, "YES", 3) == 0 || strncmp(oneline+14, "1", 1) == 0) { settings->autoreconnect = 1; } else settings->autoreconnect = 0; } } return; } char * get_config_file_name() { /* find the config-file */ char * homedir = getenv("HOME"); if(homedir == NULL){ printf("error while reading your home-directory"); return NULL; } int dirlen = strlen(homedir) + strlen(FILES_CONFIG_FILE) + 1; char * directory = new char[dirlen]; snprintf(directory, dirlen, "%s%s", homedir, FILES_CONFIG_FILE); return directory; } //int write_config_file(struct from_config_file * settings) //{ // char * directory = get_config_file_name(); // int configfile, i; // configfile = open(directory, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); // delete[] directory; // if(configfile == -1) { // return 0; // } // char writebuf[READ_BUFLEN]; // // snprintf(writebuf, READ_BUFLEN-1, "nickname=%s\n", settings->nickname); // if(write(configfile, writebuf, strlen(writebuf)) == -1) { // close(configfile); // return 0; // } // /* do i have to check the write() function every time? :/ */ // snprintf(writebuf, READ_BUFLEN-1, "realname=%s\n", settings->realname); // write(configfile, writebuf, strlen(writebuf)); // // snprintf(writebuf, READ_BUFLEN-1, "server=%s\n", settings->servername); // write(configfile, writebuf, strlen(writebuf)); // // snprintf(writebuf, READ_BUFLEN-1, "port=%d\n", settings->port); // write(configfile, writebuf, strlen(writebuf)); // // for(i = 0; i < settings->command_on_startup_num; i++) // { // snprintf(writebuf, READ_BUFLEN-1, "command=%s\n", settings->command_on_startup[i]); // write(configfile, writebuf, strlen(writebuf)); // } // // close(configfile); // return 1; //} void set_default_config(struct from_config_file * settings) { /* set some default parameter */ char * username = getenv("USER"); if(username != NULL) { if(username[0] != '\0') { strncpy(settings->nickname, username, NICKNAME_LEN-1); } } if(settings->nickname[0] == '\0') { strncpy(settings->nickname, DEFAULT_NICKNAME, NICKNAME_LEN-1); } strncpy(settings->realname, DEFAULT_REALNAME, REALNAME_LEN-1); strncpy(settings->servername, DEFAULT_SERVERNAME, SERVER_NAME_LEN-1); strncpy(settings->part_quit_msg, DEFAULT_PART_QUIT_MSG, PART_QUIT_MSG_LEN-1); strncpy(settings->modes, DEFAULT_MODES, MODE_TO_SET_LEN-1); settings->command_on_startup_num = 0; settings->port = DEFAULT_PORT_NUM; settings->autoconnect = DEFAULT_AUTOCONNECT; settings->autoreconnect = DEFAULT_AUTORECONNECT; return; } int num_lines(int text_len, int screen_len) { if(text_len > screen_len) { /* text is longer than only 1 line */ int len = 1; do { text_len -= screen_len; len++; } while(text_len > screen_len); return len; } else { /* text is only 1 line long */ return 1; } } int position_of_num_char(char * string, char search_char, int count) { int char_count = 0; if(count < 1) return -1; char *x = string; int position = 0; while(*x) { if(*x == search_char) { char_count++; if(count == char_count) return position; } x++; position++; } return -1; } void test_config_file(void) { char * directory = get_config_file_name(); printf("Reading settings from config-file %s\n\n", directory); int i; struct from_config_file * settings = NULL; settings = get_config_file_settings(); set_default_config(settings); if(settings == NULL) return; printf("The following options will be taken if netwalker irc-client is getting started:\n\n"); printf("Nickname:\t\t\t\t%s\n", settings->nickname); printf("Realname:\t\t\t\t%s\n", settings->realname); printf("Server:\t\t\t\t\t%s:%i\n", settings->servername, settings->port); printf("Modes:\t\t\t\t\t%s\n", settings->modes); printf("Leave Message:\t\t\t\t%s\n", settings->part_quit_msg); for(i = 0; i < settings->command_on_startup_num; i++) printf("%i. Command to send after connect:\t%s\n", (i+1), settings->command_on_startup[i]); return; } void print_version(void) { printf("This is the Netwalker irc-client version: %s\n", CLIENT_VERSION); return; } int search_next_num_char(char * string, char search_char, int count, int startposition) { int position = position_of_num_char(string+startposition, search_char, count); if(position == -1) return -1; return (position + startposition); } int count_chars_from_pos_to_pos(char * string, char search_char, int startposition, int endposition) { int len = (signed)strlen(string); if((endposition < 0) || (startposition < 0) || (startposition > len-2) || (endposition > len-2)) return -1; char *x = string+startposition; int count = 0; if(endposition == 0) { /* search the hole string */ while(*x) { if(*x == search_char) count++; x++; } } else { /* search only a part of the string */ int to_scan = (endposition - startposition) + 1; while(to_scan > 0) { if(*x == search_char) count++; to_scan--; x++; } } return count; } void string_tolower(char * string) { char * x = string; while(*x) { *x = tolower(*x); x++; } return; } void string_toupper(char * string) { char * x = string; while(*x) { *x = toupper(*x); x++; } return; } #include int CheckForInputData(void) { fd_set read_set; fd_set write_set; struct timeval timeout; FD_ZERO(&read_set); FD_ZERO(&write_set); FD_SET(0, &read_set); /* add stdin to the input sets */ if(IO_INPUT_WAITLEN < 1) { /* default timeout: 1/2 second */ timeout.tv_sec = (long)0; timeout.tv_usec = (long)500000; } else { timeout.tv_sec = (long)IO_INPUT_WAITLEN / 1000000; timeout.tv_usec = (long)IO_INPUT_WAITLEN % 1000000; } /* it is not very dangerous if we get an error in the select function * reaseon: every time when we get a SIGWINCH there is an "error" * and every time we switch our programm from back to foreground there is an error */ int fd_network = Classes.Connection->GetNetworkSocket(); if(fd_network == -1) { /* we only have to look for stdin data */ int ret = select(1, &read_set, (fd_set *)NULL, (fd_set *)NULL, &timeout); if(ret == -1) return -2; if(ret != 0) { if(FD_ISSET(0, &read_set)) { /* stdin data ready*/ return 1; } else return -1; /* error */ } } else { int status = Classes.Connection->GetConnectStatus(); int ret; if(status == STATUS_SYN_SENT) { /* only watch for stdin and write on the network */ FD_SET(fd_network, &write_set); /* add the fd for the network data to the input set to check for write */ ret = select((fd_network+1), &read_set, &write_set, (fd_set *)NULL, &timeout); } else { FD_SET(fd_network, &read_set); /* add the fd for the network data to the input sets */ ret = select((fd_network+1), &read_set, (fd_set *)NULL, (fd_set *)NULL, &timeout); } if(ret == -1) return -2; if(ret > 0) { if(status == STATUS_SYN_SENT) { if(FD_ISSET(fd_network, &write_set)) { Classes.Connection->SetConnectStatus(STATUS_CONNECTED); /* connection SEEMS to be established! * * it is also possible, that the connection is refused, aborted or reseted! * * but i check this in Server::WriteMessageToServer() ! */ } return 0; } else { if(FD_ISSET(fd_network, &read_set)) { /* network data ready */ return 2; } } if(FD_ISSET(0, &read_set)) { /* stdin data ready*/ return 1; } return -1; /* error */ } } return 0; /* no data */ } void make_first_char_away(char * string) { if(string[0] == '\0') return; char *x = string; x++; while(*x) { *(x-1) = *x; x++; } *(x-1) = '\0'; return; } void Bring_away_special_chars(char * string) { /* there are a lot of chars < 32 which have to be cut away * we dont bring away this chars because: * 0 ---> we cant make it disapper :p * 1 ---> action (/me or ctcp) * 2 ---> bold text * 3 ---> colored text * 15 ---> format reset control char * 31 ---> underlined text*/ #define num 25 if(string == NULL) return; if(string[0] == '\0') return; unsigned int chars_to_test_for[num] = { 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; char *x = string; for(int i = 0; i < num; i++) { while(*x) { if((unsigned int)*x == chars_to_test_for[i]) make_first_char_away(x); x++; } } #undef num } int does_match(char * string, char * pattern) { if(string == NULL || pattern == NULL) return 0; if(string[0] == '\0' || pattern[0] == '\0') return 0; int len = strlen(pattern); int match_to_char = 0; int startpos = 0; int pos = 0; while(*(string+pos)) { if(*(string+pos) == pattern[match_to_char]) { if(!match_to_char) startpos = pos; match_to_char++; } else { if(match_to_char) { pos = startpos; } match_to_char = 0; } if(match_to_char == len) return 1; pos++; } return 0; } int does_match_case_insensitive(char * string, char * pattern) { if(string == NULL || pattern == NULL) return 0; if(string[0] == '\0' || pattern[0] == '\0') return 0; int string_len = strlen(string); int pattern_len = strlen(pattern); char tmp_string[string_len+1]; char tmp_pattern[pattern_len+1]; memcpy(tmp_string, string, string_len+1); memcpy(tmp_pattern, pattern, pattern_len+1); string_tolower(tmp_string); string_tolower(tmp_pattern); return does_match(tmp_string, tmp_pattern); } int have_to_call_connect(void) { int status = Classes.Connection->GetConnectStatus(); if(Classes.Connection->GetDoConnect()) return 2; /* we were forced to connect */ if((status >= STATUS_RESOLV_IN_PROGRESS) && (status < STATUS_SYN_SENT)) { /* we are in the connect process but this is not finished, so call this function */ return 2; } int m_reconnect = Classes.Connection->GetMaybeReconnect(); if(Classes.IrcUser->GetAutoConnect() && status == STATUS_NOTHING && !m_reconnect) return 1; if(Classes.IrcUser->GetAutoReconnect() && status == STATUS_NOTHING && m_reconnect) return 1; /* we dont have to call the connect() function */ return 0; } void help_me(char * user_input) { /* each line of the help-index file has the followin format: * command:helpfile * */ int had_helpfile = 0; /* it is not allowed to add a doublepoint in the searchstring! */ int display_help_help = 0; char help_help[] = "help"; if(!user_input) { user_input = help_help; display_help_help = 1; } else if(user_input[0] == '\0') { user_input = help_help; display_help_help = 1; } int active_channel = Classes.IrcScreen->GetActiveChannel(); if(position_of_num_char(user_input, ':', 1) != -1) { Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, "your searchstring contains a doublepoint!"); return; } int help_index_file = open(FILES_HELP_DIRECTORY FILES_HELP_INDEX_FILE, O_RDONLY); if(help_index_file == -1) { Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, "Error while opening the index file for the help!"); return; } char * oneline = NULL; int dblp_pos = 0; int len = 0; char mr_helper[HELP_BUF_LEN]; if(display_help_help) Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_HELP, "Help is available for this commands:"); do { if(oneline) { delete[] oneline; oneline = NULL; } oneline = readoneline(help_index_file); if(!oneline) break; len = strlen(oneline); dblp_pos = position_of_num_char(oneline, ':', 1); if(len < 3 || dblp_pos == -1 || dblp_pos == 0 || dblp_pos == len-1) continue; oneline[dblp_pos] = '\0'; if(display_help_help) { snprintf(mr_helper, HELP_BUF_LEN, " %s", oneline); Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_HELP, mr_helper); continue; } if(!does_match_case_insensitive(oneline, user_input)) continue; /* the user input does match with this command * now we have to echo the output of the specified file */ had_helpfile = 1; char * help_file = oneline+dblp_pos+1; snprintf(mr_helper, HELP_BUF_LEN, "%s%s", FILES_HELP_DIRECTORY, help_file); int help_file_fd = open(mr_helper, O_RDONLY); if(help_file_fd == -1) { Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_ERROR, "Error while opening a help-file!"); return; } char * help_string = NULL; do { if(help_string) { delete[] help_string; help_string = NULL; } help_string = readoneline(help_file_fd); if(!help_string) break; /* end of file reached */ Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_HELP, help_string); } while(1); if(help_string) { delete[] help_string; help_string = NULL; } } while(1); if(oneline) delete[] oneline; if(!had_helpfile && !display_help_help) { Classes.MsgDB->SetIrcChatMessage(active_channel, DISPLAY_HELP, "No helpfile for your search found -> maybe you should use \"/help help\""); } close(help_index_file); return; } void * nameresolv_wrapper(void * function) { class Server * to_wrap = (class Server *)function; to_wrap->GetHostname(); return NULL; } int text_strlen(char * string) { if(string == NULL) return 0; char * x = string; int num = 0; while(*x) { switch(*x) { case FORMAT_BOLD_NUM: break; case FORMAT_COLOR_NUM: break; case FORMAT_UNDERLINE_NUM: break; case FORMAT_RESET_NUM: break; default: num++; break; } x++; } return num; } #undef _FUNCTIONS_CC_