/* * server.c: Things dealing with server connections, etc. * * Written By Michael Sandrof * * Copyright(c) 1990 * * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT */ #ifndef lint static char rcsid[] = "@(#)$Id: server.c,v 1.27 1994/10/17 11:52:55 mrg Exp $"; #endif #include "irc.h" #ifdef ESIX # include #endif /* ESIX */ #ifdef HAVE_SYS_UN_H # include int connect_to_unix(); #endif /* HAVE_SYS_UN_H */ #include "server.h" #include "ircaux.h" #include "whois.h" #include "lastlog.h" #include "exec.h" #include "window.h" #include "output.h" #include "names.h" #include "parse.h" #include "screen.h" static void add_to_server_buffer __P((int, char *)); /* * Don't want to start ircserv by default... */ int using_server_process = 0; /* server_list: the list of servers that the user can connect to,etc */ Server *server_list = (Server *) 0; /* number_of_servers: in the server list */ int number_of_servers = 0; extern WhoisQueue *WQ_head; extern WhoisQueue *WQ_tail; int primary_server = -1; int from_server = -1; int attempting_to_connect= 0; int never_connected = 1; /* true until first connection * is made */ int connected_to_server = 0; /* true when connection is * confirmed */ char *connect_next_nick; int parsing_server_index = -1; extern int dgets_errno; /* * Why this as well as MyHostAddr? Well, if your host is a gateway, this * will be set to the address for your host which is nearest to everybody * else on IRC in most circumstances. Thus it is most useful for DCC * connections telling other clients where you are. MyHostAddr holds the * first address returned by the name server, which may or may not be best, * but is used in things like talk where the behaviour should mimic the * standard programs. * * None of this applies if you are using ircserv. In this case, local_ip_address * is the same as MyHostAddr. */ /* extern struct in_addr local_ip_address; */ /* moved to irc.h */ /* * close_server: Given an index into the server list, this closes the * connection to the corresponding server. It does no checking on the * validity of the index. It also first sends a "QUIT" to the server being * closed */ void close_server(index, message) int index; char *message; { int i, min, max; if (index == -1) { min = 0; max = number_of_servers; } else { min = index; max = index + 1; } for (i = min; i < max; i++) { if (i == primary_server) { /* make sure no leftover whois's are out there */ clean_whois_queue(); if (waiting) irc_io_loop = 0; set_waiting_channel(i); } else clear_channel_list(i); server_list[i].operator = 0; server_list[i].connected = 0; server_list[i].buffer = (char *) 0; if (-1 != server_list[i].write) { if (message && *message) { sprintf(buffer, "QUIT :%s\n", message); send(server_list[i].write, buffer, strlen(buffer), 0); } new_close(server_list[i].write); if (server_list[i].write == server_list[i].read) server_list[i].read = -1; server_list[i].write = -1; } if (-1 != server_list[i].read) { new_close(server_list[i].read); server_list[i].read = -1; } #ifndef _Windows if (-1 != server_list[i].pid) { kill(server_list[i].pid, SIGKILL); server_list[i].pid = (pid_t) -1; } #endif } } /* * set_server_bits: Sets the proper bits in the fd_set structure according to * which servers in the server list have currently active read descriptors. */ void set_server_bits(rd) fd_set *rd; { int i; for (i = 0; i < number_of_servers; i++) if (server_list[i].read != -1) FD_SET(server_list[i].read, rd); } /* * do_server: check the given fd_set against the currently open servers in * the server list. If one have information available to be read, it is read * and and parsed appropriately. If an EOF is detected from an open server, * one of two things occurs. 1) If the server was the primary server, * get_connected() is called to maintain the connection status of the user. * 2) If the server wasn't a primary server, connect_to_server() is called to * try to keep that connection alive. */ void do_server(rd) fd_set *rd; { define_big_buffer(buffer); int des, i; static int times = 0; int old_timeout; for (i = 0; i < number_of_servers && !break_io_processing; i++) { if ((des = server_list[i].read) != -1 && FD_ISSET(des, rd)) { int junk; char *bufptr; char *s; from_server = i; old_timeout = dgets_timeout(2); s = server_list[from_server].buffer; bufptr = buffer; if (s && *s) { int len = strlen(s); strncpy(buffer, s, len); bufptr += len; } do { junk = dgets(bufptr, BIG_BUFFER_SIZE, des, (char *) 0); switch (junk) { case -1: #ifdef PHONE say("server %s: dgets timed out. continuing...(%s)", server_list[i].name, bufptr); #endif add_to_server_buffer(from_server, buffer); continue; break; case 0: close_server(i, empty_string); say("Connection closed from %s: %s", server_list[i].name, dgets_errno ? strerror(dgets_errno) : "connection timed out"); if (i == primary_server) { if (server_list[i].eof) { say("Unable to connect to server %s", server_list[i].name); if (++i == number_of_servers) { clean_whois_queue(); say("Use /SERVER to connect to a server"); times = 0; } else get_connected(i); } else { if (times++ > 1) { clean_whois_queue(); say("Use /SERVER to connect to a server"); times = 0; } else get_connected(i); } } else if (server_list[i].eof) { say("Connection to server %s lost.", server_list[i].name); close_server(i, empty_string); clean_whois_queue(); window_check_servers(); } else if (connect_to_server(server_list[i].name, server_list[i].port, -1)) { say("Connection to server %s lost.", server_list[i].name); close_server(i, empty_string); clean_whois_queue(); window_check_servers(); } server_list[i].eof = 1; break; default: parsing_server_index = i; parse_server(buffer); new_free(&server_list[i].buffer); parsing_server_index = -1; message_from((char *) 0, LOG_CRAP); break; } (void) dgets_timeout(0); } while (junk > 0); (void) dgets_timeout(old_timeout); from_server = primary_server; } } free_big_buffer(buffer); } /* * find_in_server_list: given a server name, this tries to match it against * names in the server list, returning the index into the list if found, or * -1 if not found */ extern int find_in_server_list(server, port) char *server; int port; { int i, len, len2; len = strlen(server); for (i = 0; i < number_of_servers; i++) { if (port && server_list[i].port && port != server_list[i].port) continue; len2 = strlen(server_list[i].name); if (len2 > len) { if (!my_strnicmp(server, server_list[i].name, len)) return (i); } else { if (!my_strnicmp(server, server_list[i].name, len2)) return (i); } } return (-1); } /* * parse_server_index: given a string, this checks if it's a number, and if * so checks it validity as a server index. Otherwise -1 is returned */ int parse_server_index(str) char *str; { int i; if (is_number(str)) { i = atoi(str); if ((i >= 0) && (i < number_of_servers)) return (i); } return (-1); } /* * get_server_index: Given a string, this checks first to see if that string * represents an integer. If so, it is checked for validity as a server * index and returned. If the string is not an integer, * find_in_server_list() is called and it's value returned. -1 is returned * if an invalid interger is used */ int get_server_index(name) char *name; { int i; if ((i = parse_server_index(name)) == -1) return (find_in_server_list(name, 0)); else return (i); } /* * add_to_server_list: adds the given server to the server_list. If the * server is already in the server list it is not re-added... however, if the * overwrite flag is true, the port and passwords are updated to the values * passes. If the server is not on the list, it is added to the end. In * either case, the server is made the current server. */ void add_to_server_list(server, port, password, nick, overwrite) char *server; int port; char *password; char *nick; int overwrite; { if ((from_server = find_in_server_list(server, port)) == -1) { from_server = number_of_servers++; if (server_list) server_list = (Server *) new_realloc(server_list, number_of_servers * sizeof(Server)); else server_list = (Server *) new_malloc(number_of_servers * sizeof(Server)); server_list[from_server].name = (char *) 0; server_list[from_server].itsname = (char *) 0; server_list[from_server].password = (char *) 0; server_list[from_server].away = (char *) 0; server_list[from_server].version_string = (char *) 0; server_list[from_server].operator = 0; server_list[from_server].read = -1; server_list[from_server].write = -1; server_list[from_server].pid = -1; server_list[from_server].version = 0; server_list[from_server].whois = 0; server_list[from_server].flags = SERVER_2_6_2; server_list[from_server].nickname = (char *) 0; server_list[from_server].connected = 0; server_list[from_server].eof = 0; server_list[from_server].motd = 1; malloc_strcpy(&(server_list[from_server].name), server); if (password && *password) malloc_strcpy(&(server_list[from_server].password), password); if (nick && *nick) malloc_strcpy(&(server_list[from_server].nickname), nick); server_list[from_server].port = port; server_list[from_server].WQ_head = (WhoisQueue *) 0; server_list[from_server].WQ_tail = (WhoisQueue *) 0; server_list[from_server].whois_stuff.nick = (char *) 0; server_list[from_server].whois_stuff.user = (char *) 0; server_list[from_server].whois_stuff.host = (char *) 0; server_list[from_server].whois_stuff.channel = (char *) 0; server_list[from_server].whois_stuff.channels = (char *) 0; server_list[from_server].whois_stuff.name = (char *) 0; server_list[from_server].whois_stuff.server = (char *) 0; server_list[from_server].whois_stuff.server_stuff = (char *) 0; server_list[from_server].whois_stuff.away = (char *) 0; server_list[from_server].whois_stuff.oper = 0; server_list[from_server].whois_stuff.chop = 0; server_list[from_server].whois_stuff.not_on = 0; server_list[from_server].buffer = (char *) 0; } else { if (overwrite) { server_list[from_server].port = port; if (password || !server_list[from_server].password) { if (password && *password) malloc_strcpy(&(server_list[from_server].password), password); else new_free(&(server_list[from_server].password)); } } if (strlen(server) > strlen(server_list[from_server].name)) malloc_strcpy(&(server_list[from_server].name), server); } } static void remove_from_server_list(i) int i; { int old_server = from_server, flag = 1; Window *tmp; TravInfo ti; from_server = i; clean_whois_queue(); from_server = old_server; if (server_list[i].name) new_free(&server_list[i].name); if (server_list[i].itsname) new_free(&server_list[i].itsname); if (server_list[i].password) new_free(&server_list[i].password); if (server_list[i].away) new_free(&server_list[i].away); if (server_list[i].version_string) new_free(&server_list[i].version_string); if (server_list[i].nickname) new_free(&server_list[i].nickname); if (server_list[i].whois_stuff.nick) new_free(&server_list[i].whois_stuff.nick); if (server_list[i].whois_stuff.user) new_free(&server_list[i].whois_stuff.user); if (server_list[i].whois_stuff.host) new_free(&server_list[i].whois_stuff.host); if (server_list[i].whois_stuff.channel) new_free(&server_list[i].whois_stuff.channel); if (server_list[i].whois_stuff.channels) new_free(&server_list[i].whois_stuff.channels); if (server_list[i].whois_stuff.name) new_free(&server_list[i].whois_stuff.name); if (server_list[i].whois_stuff.server) new_free(&server_list[i].whois_stuff.server); if (server_list[i].whois_stuff.server_stuff) new_free(&server_list[i].whois_stuff.server_stuff); bcopy((char *) &server_list[i + 1], (char *) &server_list[i], (number_of_servers - i) * sizeof(Server)); server_list = (Server *) new_realloc(server_list, --number_of_servers * sizeof(Server)); /* update all he structs with server in them */ channel_server_delete(i); #ifndef _Windows exec_server_delete(i); #endif while ((tmp = traverse_all_windows(&flag, &ti)) != NULL) if (tmp->server > i) tmp->server--; } /* * parse_server_info: This parses a single string of the form * "server:portnum:password:nickname". It the points port to the portnum * portion and password to the password portion. This chews up the original * string, so * upon return, name will only point the the name. If portnum * or password are missing or empty, their respective returned value will * point to null. */ void parse_server_info(name, port, password, nick) char *name, **port, **password, **nick; { char *ptr; *port = *password = *nick = NULL; if ((ptr = (char *) index(name, ':')) != NULL) { *(ptr++) = (char) 0; if (strlen(ptr) == 0) *port = (char *) 0; else { *port = ptr; if ((ptr = (char *) index(ptr, ':')) != NULL) { *(ptr++) = (char) 0; if (strlen(ptr) == 0) *password = '\0'; else { *password = ptr; if ((ptr = (char *) index(ptr, ':')) != NULL) { *(ptr++) = '\0'; if (!strlen(ptr)) *nick = NULL; else *nick = ptr; } } } } } } /* * build_server_list: given a whitespace separated list of server names this * builds a list of those servers using add_to_server_list(). Since * add_to_server_list() is used to added each server specification, this can * be called many many times to add more servers to the server list. Each * element in the server list case have one of the following forms: * * servername * * servername:port * * servername:port:password * * servername::password * * Note also that this routine mucks around with the server string passed to it, * so make sure this is ok */ void build_server_list(servers) char *servers; { char *host, *rest, *password = (char *) 0, *port = (char *) 0, *nick = (char *) 0; int port_num; if (servers == (char *) 0) return; /* port_num = irc_port; */ while (servers) { if ((rest = (char *) index(servers, '\n')) != NULL) *rest++ = '\0'; while ((host = next_arg(servers, &servers)) != NULL) { parse_server_info(host, &port, &password, &nick); if (port && *port) port_num = atoi(port); else port_num = irc_port; add_to_server_list(host, port_num, password, nick, 0); } servers = rest; } } /* * connect_to_server_direct: handles the tcp connection to a server. If * successful, the user is disconnected from any previously connected server, * the new server is added to the server list, and the user is registered on * the new server. If connection to the server is not successful, the * reason for failure is displayed and the previous server connection is * resumed uniterrupted. * * This version of connect_to_server() connects directly to a server * */ static int connect_to_server_direct(server_name, port) char *server_name; int port; { int new_des; struct sockaddr_in localaddr; int address_len; using_server_process = 0; oper_command = 0; errno = 0; #ifdef HAVE_SYS_UN_H if (*server_name == '/') new_des = connect_to_unix(port, server_name); else #endif /* HAVE_SYS_UN_H */ new_des = connect_by_number(port, server_name); if (new_des < 0) { say("Unable to connect to port %d of server %s: %s", port, server_name, errno ? strerror(errno) : "unknown host"); if ((from_server != -1)&& (server_list[from_server].read != -1)) say("Connection to server %s resumed...", server_list[from_server].name); return (-1); } if (never_connected #ifdef HAVE_SYS_UN_H && *server_name != '/' #endif /* HAVE_SYS_UN_H */ ) { address_len = sizeof(struct sockaddr_in); getsockname(new_des, (struct sockaddr *) &localaddr, &address_len); local_ip_address.s_addr = ntohl(localaddr.sin_addr.s_addr); } update_all_status(); add_to_server_list(server_name, port, (char *) 0, (char *) 0, 1); if (port) { server_list[from_server].read = new_des; server_list[from_server].write = new_des; } else /* port= */ server_list[from_server].read = new_des; server_list[from_server].operator = 0; return (0); } /* * connect_to_server_process: handles the tcp connection to a server. If * successful, the user is disconnected from any previously connected server, * the new server is added to the server list, and the user is registered on * the new server. If connection to the server is not successful, the * reason for failure is displayed and the previous server connection is * resumed uniterrupted. * * This version of connect_to_server() uses the ircserv process to talk to a * server */ static int connect_to_server_process(server_name, port) char *server_name; int port; { #ifdef _Windows return -1; #else int write_des[2], read_des[2], pid, c; char *path, *name = (char *) 0, *s; int old_timeout; path = IRCSERV_PATH; if ((s = rindex(path, '/')) != NULL) malloc_strcpy(&name, s + 1); if (!name) name = path; if (*path == '\0') return (connect_to_server_direct(server_name, port)); using_server_process = 1; oper_command = 0; write_des[0] = -1; write_des[1] = -1; if (pipe(write_des) || pipe(read_des)) { if (write_des[0] != -1) { close(write_des[0]); close(write_des[1]); } say("Couldn't start new process: %s", strerror(errno)); return (connect_to_server_direct(server_name, port)); } switch (pid = fork()) { case -1: say("Couldn't start new process: %s\n", strerror(errno)); return (-1); case 0: (void) MY_SIGNAL(SIGINT, SIG_IGN, 0); dup2(read_des[1], 1); dup2(write_des[0], 0); close(read_des[0]); close(write_des[1]); sprintf(buffer, "%u", port); setuid(getuid()); execl(path, name, server_name, buffer, (char *) 0); printf("-5 0\n"); /* -1 - -4 returned by connect_by_number() */ fflush(stdout); _exit(1); default: close(read_des[1]); close(write_des[0]); break; } old_timeout = dgets_timeout(3); c = dgets(buffer, BIG_BUFFER_SIZE, read_des[0], (char *) 0); (void) dgets_timeout(old_timeout); if ((c == 0) || ((c = atoi(buffer)) != 0)) { if (c == -5) return (connect_to_server_direct(server_name, port)); else { char *ptr; if ((ptr = (char *) index(buffer, ' ')) != NULL) { ptr++; if (atoi(ptr) > 0) say("Unable to connect to port %d of server %s: %s", port, server_name, strerror(atoi(ptr))); else say("Unable to connect to port %d of server %s: Unknown host", port, server_name); } else say("Unable to connect to port %d of server %s: Unknown host", port, server_name); if ((from_server != -1) && (server_list[from_server].read != -1)) say("Connection to server %s resumed...", server_list[from_server].name); close(read_des[0]); close(write_des[1]); return (-1); } } update_all_status(); add_to_server_list(server_name, port, (char *) 0, (char *) 0, 1); server_list[from_server].read = read_des[0]; server_list[from_server].write = write_des[1]; server_list[from_server].pid = pid; server_list[from_server].operator = 0; return (0); #endif } /* * connect_to_server: Given a name and portnumber, this will attempt to * connect to that server using either a direct connection or process * connection, depending on the value of using_server_process. If connection * is successful, the proper NICK, USER, and PASS commands are sent to the * server. If the c_server parameter is not -1, then the server with that * index will be closed upon successful connection here. Also, if connection * is successful, the attempting_to_connect variable is incremented. This is * checked in the notice.c routines to make sure that connection was truely * successful (and not closed immediately by the server). */ int connect_to_server(server_name, port, c_server) char *server_name; int port; int c_server; { int index; message_from((char *) 0, LOG_CURRENT); index = find_in_server_list(server_name, port); attempting_to_connect++; if (index == -1 || server_list[index].read == -1) { if (port == -1) { if (index != -1) port = server_list[index].port; else port = irc_port; } say("Connecting to port %d of server %s", port, server_name); if (using_server_process) index = connect_to_server_process(server_name, port); else index = connect_to_server_direct(server_name, port); if (index) { attempting_to_connect--; return -1; } if ((c_server != -1) && (c_server != from_server)) close_server(c_server, "changing servers"); if (connect_next_nick && *connect_next_nick) { malloc_strcpy(&(server_list[from_server].nickname), connect_next_nick); new_free(&connect_next_nick); } if (server_list[from_server].nickname == (char *) 0) malloc_strcpy(&(server_list[from_server].nickname), nickname); send_to_server("NICK %s", server_list[from_server].nickname); if (server_list[from_server].password) send_to_server("PASS %s", server_list[from_server].password); send_to_server("USER %s %s %s :%s", username, (send_umode && *send_umode) ? send_umode : hostname, server_list[from_server].name, realname); } else { say("Connected to port %d of server %s", port, server_name); from_server = index; } message_from((char *) 0, LOG_CRAP); update_all_status(); return 0; } /* * get_connected: This function connects the primary server for IRCII. It * attempts to connect to the given server. If this isn't possible, it * traverses the server list trying to keep the user connected at all cost. */ void get_connected(server) int server; { int s, ret = -1; if (server_list) { if (server == number_of_servers) server = 0; else if (server < 0) server = number_of_servers - 1; s = server; if (connect_to_server(server_list[server].name, server_list[server].port, primary_server)) { while (server_list[server].read == -1) { server++; if (server == number_of_servers) server = 0; if (server == s) { clean_whois_queue(); say("Use /SERVER to connect to a server"); break; } from_server = server; ret = connect_to_server(server_list[server].name, server_list[server].port, primary_server); } if (!ret) from_server = server; else from_server = -1; } change_server_channels(primary_server, from_server); set_window_server(-1, from_server, 1); } else { clean_whois_queue(); say("Use /SERVER to connect to a server"); } } #ifdef SERVERS_FILE /* * read_server_file: reads hostname:portnum:password server information from * a file and adds this stuff to the server list. See build_server_list()/ */ int read_server_file() { FILE *fp; char format[11]; char *file_path = (char *) 0; malloc_strcpy(&file_path, irc_lib); malloc_strcat(&file_path, SERVERS_FILE); sprintf(format, "%%%ds", BIG_BUFFER_SIZE); fp = fopen(file_path, "r"); new_free(&file_path); if ((FILE *) 0 != fp) { while (fscanf(fp, format, buffer) != EOF) build_server_list(buffer); fclose(fp); return (0); } return (1); } #endif /* display_server_list: just guess what this does */ void display_server_list() { int i; if (server_list) { if (from_server != -1) say("Current server: %s %d", server_list[from_server].name, server_list[from_server].port); else say("Current server: "); if (primary_server != -1) say("Primary server: %s %d", server_list[primary_server].name, server_list[primary_server].port); else say("Primary server: "); say("Server list:"); for (i = 0; i < number_of_servers; i++) { if (!server_list[i].nickname) { if (server_list[i].read == -1) say("\t%d) %s %d", i, server_list[i].name, server_list[i].port); else say("\t%d) %s %d", i, server_list[i].name, server_list[i].port); } else { if (server_list[i].read == -1) say("\t%d) %s %d (was %s)", i, server_list[i].name, server_list[i].port, server_list[i].nickname); else say("\t%d) %s %d (%s)", i, server_list[i].name, server_list[i].port, server_list[i].nickname); } } } else say("The server list is empty"); } void MarkAllAway(command, message) char *command; char *message; { int old_server; old_server = from_server; for (from_server=0; from_serverh_addr, (char *) &MyHostAddr, sizeof(MyHostAddr)); local_ip_address.s_addr = ntohl(MyHostAddr.s_addr); } #endif if (*server == '-') { if (!my_strnicmp(server + 1, "DELETE", strlen(server + 1))) { if ((server = next_arg(args, &args)) != NULL) { if ((i = parse_server_index(server)) == -1) { if (-1 == (i = find_in_server_list(server, 0))) { say("No such server in list"); return; } } if (server_list[i].connected) { say("Can not delete server that is already open"); return; } remove_from_server_list(i); return; } say("Need server number for -DELETE"); return; } } if ((port = next_arg(args, &args)) != NULL) port_num = atoi(port); else port_num = irc_port; if (*server == '+') { if (*(++server)) { if ((i = parse_server_index(server)) != -1) { server = server_list[i].name; port_num = server_list[i].port; } if (!connect_to_server(server, port_num, -1)) { set_window_server(0, from_server, 0); #ifndef PHONE set_level_by_refnum(0, LOG_ALL); #else set_level_by_refnum(0, LOG_NONE); #endif } return; } get_connected(primary_server + 1); return; } else if (*server == '-') { if (*(++server)) { int i; if ((i = parse_server_index(server)) == -1) { if ((i = find_in_server_list(server, port_num)) == -1) { say("No such server in server list: %s", server); return; } } if (i == primary_server) { say("You can't close your primary server!"); return; } close_server(i, "closing server"); window_check_servers(); return; } get_connected(primary_server - 1); return; } if ((i = parse_server_index(server)) != -1) { server = server_list[i].name; port_num = server_list[i].port; } if (connect_to_server(server, port_num, primary_server) != -1) { change_server_channels(primary_server, from_server); if (primary_server > -1 && from_server != primary_server && !server_list[from_server].away && server_list[primary_server].away) malloc_strcpy(&server_list[from_server].away, server_list[primary_server].away); set_window_server(-1, from_server, 1); } } else display_server_list(); } /* * flush_server: eats all output from server, until there is at least a * second delay between bits of servers crap... useful to abort a /links. */ void flush_server() { fd_set rd; struct timeval timeout; int flushing = 1; int des; int old_timeout; if ((des = server_list[from_server].read) == -1) return; timeout.tv_usec = 0; timeout.tv_sec = 1; old_timeout = dgets_timeout(1); while (flushing) { FD_ZERO(&rd); FD_SET(des, &rd); switch (new_select(&rd, (fd_set *) 0, &timeout)) { case -1: case 0: flushing = 0; break; default: if (FD_ISSET(des, &rd)) { if (0 == dgets(buffer, BIG_BUFFER_SIZE, des, (char *) 0)) flushing = 0; } break; } } /* make sure we've read a full line from server */ FD_ZERO(&rd); FD_SET(des, &rd); if (new_select(&rd, (fd_set *) 0, &timeout) > 0) dgets(buffer, BIG_BUFFER_SIZE, des, (char *) 0); (void) dgets_timeout(old_timeout); } /* * set_server_whois: sets the whois value for the given server index. If the * whois value is 0, it assumes the server doesn't send End of WHOIS commands * and the whois.c routines use the old fashion way of getting whois info. If * the whois value is non-zero, then the server sends End of WHOIS and things * can be done more effienciently */ void set_server_whois(index, value) int index, value; { server_list[index].whois = value; } /* get_server_whois: Returns the whois value for the given server index */ int get_server_whois(index) int index; { if (index == -1) index = primary_server; return (server_list[index].whois); } void set_server_2_6_2(index, value) int index, value; { set_server_flag(index, SERVER_2_6_2, value); } int get_server_2_6_2(index) int index; { if (index == -1) index = primary_server; return (get_server_flag(index, SERVER_2_6_2)); } void set_server_flag(index, flag, value) int index; int flag; int value; { if (index == -1) index = primary_server; if (value) server_list[index].flags |= flag; else server_list[index].flags &= ~flag; } int get_server_flag(index, value) int index; int value; { if (index == -1) index = primary_server; return server_list[index].flags & value; } /* * set_server_version: Sets the server version for the given server type. A * zero version means pre 2.6, a one version means 2.6 aso. (look server.h * for typedef) */ void set_server_version(index, version) int index; int version; { if (index == -1) index = primary_server; server_list[index].version = version; } /* * get_server_version: returns the server version value for the given server * index */ int get_server_version(index) int index; { if (index == -1) index = primary_server; return (server_list[index].version); } /* get_server_name: returns the name for the given server index */ char * get_server_name(index) int index; { if (index == -1) index = primary_server; return (server_list[index].name); } /* set_server_itsname: returns the server's idea of its name */ char * get_server_itsname(index) int index; { if (index==-1) index=primary_server; if (server_list[index].itsname) return server_list[index].itsname; else return server_list[index].name; } void set_server_itsname(index, name) int index; char *name; { if (index==-1) index=primary_server; malloc_strcpy(&server_list[index].itsname, name); } /* * is_server_open: Returns true if the given server index represents a server * with a live connection, returns false otherwise */ int is_server_open(index) int index; { if (index < 0) return (0); return (server_list[index].read != -1); } /* * is_server_connected: returns true if the given server is connected. This * means that both the tcp connection is open and the user is properly * registered */ int is_server_connected(index) int index; { return (server_list[index].connected); } /* get_server_port: Returns the connection port for the given server index */ int get_server_port(index) int index; { if (index == -1) index = primary_server; return (server_list[index].port); } /* * get_server_nickname: returns the current nickname for the given server * index */ char * get_server_nickname(index) int index; { if ((index != -1) && server_list[index].nickname) return (server_list[index].nickname); else return (nickname); } /* get_server_qhead - get the head of the whois queue */ WhoisQueue * get_server_qhead(index) int index; { if (index != -1) return server_list[index].WQ_head; else return WQ_head; } /* get_server_whois_stuff */ WhoisStuff * get_server_whois_stuff(index) int index; { if (index == -1) index=primary_server; return &server_list[index].whois_stuff; } /* get_server_qtail - get the tail of the whois queue */ WhoisQueue * get_server_qtail(index) int index; { if (index !=-1) return server_list[index].WQ_tail; else return WQ_tail; } /* set_server_qhead - set the head of the whois queue */ void set_server_qhead(index, value) int index; WhoisQueue *value; { if (index != -1) server_list[index].WQ_head=value; else WQ_head=value; } /* set_server_qtail - set the tail of the whois queue */ void set_server_qtail(index, value) int index; WhoisQueue *value; { if (index !=-1) server_list[index].WQ_tail=value; else WQ_tail=value; } /* * get_server_operator: returns true if the user has op privs on the server, * false otherwise */ int get_server_operator(index) int index; { return (server_list[index].operator); } /* * set_server_operator: If flag is non-zero, marks the user as having op * privs on the given server. */ void set_server_operator(index, flag) int index; int flag; { server_list[index].operator = flag; } /* * set_server_nickname: sets the nickname for the given server to nickname. * This nickname is then used for all future connections to that server * (unless changed with NICK while connected to the server */ void set_server_nickname(index, nick) int index; char *nick; { if (index != -1) { malloc_strcpy(&(server_list[index].nickname), nick); if (index == primary_server) strmcpy(nickname,nick,NICKNAME_LEN); } update_all_status(); } void set_server_motd(index,flag) int index; int flag; { if (index != -1) server_list[index].motd = flag; } int get_server_motd(index) int index; { if (index != -1) return(server_list[index].motd); return (0); } void server_is_connected(index, value) int index, value; { server_list[index].connected = value; if (value) server_list[index].eof = 0; } /* send_to_server: sends the given info the the server */ void #ifdef USE_STDARG_H send_to_server(char *format, ...) #else send_to_server(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) char *format; char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8, *arg9, *arg10; #endif { define_big_buffer(buffer); /* make this buffer *much* * bigger than needed */ char *buf = buffer; int len, des; int server; #ifdef USE_STDARG_H va_list vlist; va_start(vlist, format); #endif if ((server = from_server) == -1) server = primary_server; if (server != -1 && ((des = server_list[server].write) != -1)) { server_list[server].sent = 1; #ifdef USE_STDARG_H vsprintf(buf, format, vlist); va_end(vlist); #else sprintf(buf, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); #endif len = strlen(buffer); if (len > (IRCD_BUFFER_SIZE - 2)) buffer[IRCD_BUFFER_SIZE - 2] = (char) 0; strmcat(buffer, "\n", IRCD_BUFFER_SIZE); send(des, buffer, strlen(buffer), 0); } else say("You are not connected to a server, use /SERVER to connect."); free_big_buffer(buffer); } #ifdef HAVE_SYS_UN_H /* * Connect to a UNIX domain socket. Only works for servers. * submitted by Avalon for use with server 2.7.2 and beyond. */ int connect_to_unix(port, path) int port; char *path; { struct sockaddr_un un; int sock; sock = socket(AF_UNIX, SOCK_STREAM, 0); un.sun_family = AF_UNIX; sprintf(un.sun_path, "%-.100s/%-.6d", path, port); if (connect(sock, (struct sockaddr *)&un, strlen(path)+2) == -1) { close(sock); return -1; } return sock; } #endif /* HAVE_SYS_UN_H */ /* * close_all_server: Used whn creating new screens to close all the open * server connections in the child process... */ extern void close_all_server() { int i; for (i = 0; i < number_of_servers; i++) { if (server_list[i].read != -1) new_close(server_list[i].read); if (server_list[i].write != -1) new_close(server_list[i].write); } } extern char * create_server_list() { int i; char *value = (char *) 0; *buffer = '\0'; for (i = 0; i < number_of_servers; i++) if (server_list[i].read != -1) { strcat(buffer, server_list[i].itsname); strcat(buffer, " "); } malloc_strcpy(&value, buffer); return value; } static void add_to_server_buffer(server, buf) int server; char *buf; { if (buf && *buf) { if (server_list[server].buffer) malloc_strcat(&server_list[server].buffer, buf); else malloc_strcpy(&server_list[server].buffer, buf); } }