/*
* 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 <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#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 <ctime>
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_
syntax highlighted by Code2HTML, v. 0.9.1