#include <stdio.h>
#include <iodef.h>
#include <brkdef.h>
#include <descrip.h>
#include <ssdef.h>
#include <string.h>
#include <stdlib.h>
#include <lib$routines.h>
#include <stdarg.h>
#include "base_includes.h"
#include "window_i.h"
#include "notify.h"
#include "server_i.h"
#include "qio.h"
#include "chan.h"
#include "binding.h"
#include "on.h"
#include "sock.h"
#include "split.h"
#include "inp.h"
#include "system.h"
#include "handle.h"
#include "exec.h"
#include "load.h"
#ifdef USE_DEFINES_H
#include "defines.h"
#endif

void set_server_away(server_ptr srv, int on)
  { if (on) set_away(srv);
    else clear_away(srv); }

server_ptr get_server_next(server_ptr srv)
  { return srv?srv->next:NULL; }

char *get_server_name(server_ptr srv)
  { return srv?srv->server_name:NULL; }

char *get_server_nick(server_ptr srv)
  { return srv?srv->nick:NULL; }

chan_ptr get_server_chanlist(server_ptr srv)
  { return srv?srv->chan_list:NULL; }


#define lf '\012'                    /* Terminator for a line in irc */

static unsigned short port = DEF_PORT;      /* The standard IRC port. */

extern long myaddress;

int quit = FALSE;
static char ast_wait[] = "0000 00:00:00.30";
static $DESCRIPTOR(ast_wait_d, ast_wait);
static unsigned ast_time[2];
static void irc_receive(server_ptr srv);
char def_nick[MAXLEN];

server_ptr server_list = NULL;
extern server_ptr gsrv;
int process_receive(server_ptr srv);
extern int flushing, old_display;

/* ------------------------------------------------------------------------ */
void set_redirect(char *str, server_ptr srv)
{
  if (!srv) return;
  if (srv->redirect) myfree(srv->redirect);
  if (str) srv->redirect = m_strcpy(str);
  else srv->redirect = NULL;
}

/* ------------------------------------------------------------------------ */
server_ptr lookup_server(char *server, char *nick, int connected, int port)
{
  server_ptr walk;
  for (walk=server_list;walk;walk=walk->next) {
    if ((strcasecmp(server, walk->server_name)==0) &&
        (!nick || !walk->nick || (strcasecmp(nick, walk->nick) == 0)) &&
        (!port || (walk->port == port)))
      if (connected == walk->connected) return walk;
  }
  return NULL;
}

/* ------------------------------------------------------------------------ */
static void server_disconnected(server_ptr serv)
{
  win_ptr walk;
  if (flushing)
  {
    setivar(VAR_DISPLAY, old_display);
    flushing = FALSE;
    say("*** Flushing completed.");
  }
  if (serv->connected) {
    if (serv->to_join) myfree(serv->to_join);
    serv->chan_list = kill_server_channels(serv->chan_list, &serv->to_join);
  }
  tcp_shutdown(serv->iochan);
  reset_notify(serv->notify_list);
  serv->iochan = 0;
  myfree(serv->redirect);
  serv->redirect = NULL;
  if (serv->connected) {
    set_win_lvl_srv(serv, CRAP);
    say("The connection has been closed by the server.");
    (void)handle_on(o_disconnect, serv->server_name, 0);
    unset_win_lvl_srv();
  }
  set_server_away(serv, FALSE);
  serv->connected = FALSE;
}

/* ------------------------------------------------------------------------ */
static int server_newdata(server_ptr temp)
{
  int tosave;
  tosave = temp->iosb.length;
  if ((tosave > 0) && ODD(temp->iosb.status))
  {
    if (temp->processing) temp->modified_in_processing = TRUE;
    if (tosave >= temp->incoming_free) {
      yell("### Too much incoming data queued. Some will be lost [%d bytes].",
           tosave - (temp->incoming_free-1));
      tosave = temp->incoming_free-1;
    }
    memcpy(&(temp->incoming[temp->incoming_start_free]), temp->buffer, tosave);
    temp->incoming_free -= tosave;
    temp->incoming_start_free += tosave;
    temp->incoming[temp->incoming_start_free] = 0;
    if (temp->incoming_free<=sizeof(temp->buffer))
      temp->need_requeue = TRUE;
    temp->modified = TRUE;
/*#define DEBUG_OVERFLOW*/
#ifdef DEBUG_OVERFLOW
    yell("used %d free %d need %d [requeue %s]", temp->incoming_start_free,
         temp->incoming_free, sizeof(temp->buffer)-1,
         temp->need_requeue?"TRUE":"FALSE");
#endif
    return TRUE;
  }
/* Get any remaining queued messages */
  process_receive(temp);
  server_disconnected(temp);
  return FALSE;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
static int scan_server_list(short chan)
{
  server_ptr temp;
  unsigned status;
  int old;

  log_enter;
  temp = server_list;

  while (temp) {
    if (sys$clref(temp->event_flag) == SS$_WASSET)
      if (temp->connected) {
        if (!quit)
          if (server_newdata(temp)) {
            sys$setef(SERVER_EF);
#ifdef OLD_AST
            process_receive(temp);
#endif
            if (!temp->need_requeue) irc_receive(temp);
          }
      } else {
        server_disconnected(temp);
      }
    temp = temp->next;
  }
  log_exit;
  return 1;
}

/* ------------------------------------------------------------------------ */
void remove_server(server_ptr srv, int reason)
{
  if (!srv) return;
  if (!srv->connected) return;
  if (reason==1) new_send(srv, "QUIT :No more windows left!\n");
  else if (reason==2) new_send(srv, "QUIT :Switching servers!\n");
  else if (reason==3) ;
  srv->connected = FALSE;
  if (srv->to_join) myfree(srv->to_join);
  srv->chan_list = kill_server_channels(srv->chan_list, &srv->to_join);
}
/* ------------------------------------------------------------------------ */
static int my_nslookup(char *host, char *add)
{
  extern int nslookup(char *, char *, char *);
  char *local;
  if (good_host((unsigned char *)add, host)) return 1;
  local = getvar(VAR_NAMESERVER);
  if (local && nslookup(local, host, add)) return 1;
  if (nslookup("128.205.1.2", host, add)) return 1;
  if (nslookup("128.205.7.1", host, add)) return 1;
  say("*** Fatal error in nslookup of %s", host);
  return 0;
}

/* ------------------------------------------------------------------------ */
short open_connection(server, port)
  char *server;
  unsigned short port;
{
  char msg[80], *ns_local;
  short serv_chan;
  struct sockaddr_in_type sin;         /* The sin for our connection */

  sin.sin_family = AF_INET;
  sin.sin_port = tcp_htons(port);
  sin.sin_zero[0] = 0;
  sin.sin_zero[1] = 0;
  say("*** Connecting to port %d of %s", port, server);
  if (!my_nslookup(server, (char *)&sin.sin_address)) return -1;
  if ((serv_chan = tcp_socket (AF_INET, SOCK_STREAM, PF_INET)) == -1) {
    get_socket_error(msg);
    say("socket: %s", msg);
    return -1;
  }
  if (tcp_connect(serv_chan, &sin, sizeof(sin)) == -1) {
    get_socket_error(msg);
    say("connect: %s", msg);
    return -1;
  }
  return serv_chan;
}

/* ------------------------------------------------------------------------ */
static server_ptr insert_server(server_ptr top, server_ptr new)
{
  server_ptr walk;
  for (walk = top; walk && walk->next; walk = walk->next) ;
  new->next = NULL;
  if (walk) walk->next = new;
  else top = new;
  return top;
}
/* ------------------------------------------------------------------------ */
static void init_server(server_ptr temp)
{
/* Fields not set: server_name port nick chan_list notify_list last_notify
                   next
*/
  temp->iochan = 0;
  temp->event_flag = 0;
  if (temp->redirect) myfree(temp->redirect);
  memset(&(temp->iosb), 0, sizeof(temp->iosb));
  temp->redirect;
  temp->last = temp->incoming;
  temp->buffer[0] = temp->incoming[0] = 0;
  temp->incoming_free = sizeof(temp->incoming)-1;
  temp->incoming_start_free = 0;
  temp->need_requeue = temp->connected = FALSE;
  set_server_away(temp, FALSE);
}
/* ------------------------------------------------------------------------ */
static server_ptr new_server_node(char *serv, char *nick, char *pass, int port)
{
  server_ptr temp;
  temp = (server_ptr)mymalloc(sizeof(struct server));
  if (!temp) return NULL;
  memset(temp, 0, sizeof(struct server));
  strcpy(temp->server_name, serv);
  if (nick) temp->nick = m_strcpy(nick);
  else temp->nick = NULL;
  temp->port = port?port:DEF_PORT;
  if (pass) temp->pass = m_strcpy(pass);
  else temp->pass = NULL;
  init_server(temp);
  server_list = insert_server(server_list, temp);
  return temp;
}
/* ------------------------------------------------------------------------ */
static void fillin_server_values(server_ptr ptr, server_ptr old)
{
  if (!ptr) return;
  if (!ptr->nick || !*ptr->nick)
    if (old && old->nick) ptr->nick = m_strcpy(old->nick);
    else if (gsrv && gsrv->nick) ptr->nick = m_strcpy(gsrv->nick);
    else ptr->nick = m_strcpy(def_nick);
  if (!ptr->port) ptr->port = DEF_PORT;
}

/* ------------------------------------------------------------------------ */
/* If old is NULL, then we are changing the server associated with 1 window
/* If old is !NULL, then we are changing all of instances of the old
/*   server */
static int connect_server_by_ptr(server_ptr ptr, server_ptr old)
{
  int iochan, status;
  win_ptr walk;

  fillin_server_values(ptr, old);
  iochan = open_connection(ptr->server_name, ptr->port);
  if (iochan == -1) return FALSE;
  ptr->iochan = iochan;
  if (!ptr->event_flag)
    if (!(status = lib$get_ef(&(ptr->event_flag)))) {
      say("*** Could not allocated event flag for server.");
      return FALSE;
    }
  sys$clref(ptr->event_flag);
  if (!ptr->notify_list)
    if (old) ptr->notify_list = copy_notify_list(old->notify_list);
    else if (gsrv) ptr->notify_list = copy_notify_list(gsrv->notify_list);
    else ptr->notify_list = copy_notify_list(NULL);
  if (old) { /* had a check to see if it was connected.. why? */
    remove_server(old, 2);
    if (old != ptr) {
      for (walk=NULL; (walk = next_window(walk)); )
        if (get_window_server(walk) == old) set_window_server(walk, ptr);
      if (old->to_join) {
        if (ptr->to_join) myfree(ptr->to_join);
        ptr->to_join = m_strcpy(old->to_join);
      }
    }
  }
/* This chunk of code will set any window that doesn't already have a server */
  for (walk=NULL; (walk = next_window(walk)); )
    if (get_window_server(walk) == NULL) set_window_server(walk, ptr);
  ptr->connected = TRUE;
  ptr->welcomed = FALSE;
  ptr->processing = FALSE;
  ptr->modified_in_processing = FALSE;
  set_ever_connected(ptr);
  win_serverset(ptr);
  reset_notify(ptr->notify_list);
  startup(ptr, ptr->pass);
  if (!handle_on(o_connect, ptr->server_name, 0))
    say("*** New server set.");
  irc_receive(ptr);
  return TRUE;
}
/* ------------------------------------------------------------------------ */
void connect_server_by_number(int num)
{
  server_ptr list = server_list;
  while (num-->0) list = list->next;
  if (list)
    if (!list->connected) connect_server_by_ptr(list, gsrv);
    else say("*** Already connected to that server");
  else say("*** There aren't that many servers!");
}
/* ------------------------------------------------------------------------ */
server_ptr add_server(char *server, char *nick, unsigned short port, 
                      char *pass, server_ptr oldserv, server_ptr match)
{
  server_ptr temp;

  if (!match) {
    if (!(temp = new_server_node(server, nick, pass, port))) {
      say("*** Could not malloc space for server.");
      return NULL;
    }
  } else {
    temp = match;
    temp->port = port;
    myfree(temp->nick);
    temp->nick = m_strcpy(nick);
    init_server(temp);
  }
  temp->chan_list = NULL;

  connect_server_by_ptr(temp, oldserv);
  return temp;
}

/* ------------------------------------------------------------------------ */
extern int waiting;
static char *parse_buffer(char *str, server_ptr srv)
{
  char *dummy, good = TRUE;
  dummy = str;
  do {
    while (*str && (*str != lf)) str++;
    if (*str==lf) {
      *str = 0;
      if (str[-1] == 13) str[-1] = 0;
      handle_line(dummy, srv);
      dummy = ++str;
    } else good = FALSE;
  } while (good&&waiting);
  return dummy;
}

/* ------------------------------------------------------------------------ */
void process_wait(server_ptr gsrv)
{
  char tmp[MAXLEN], save[MAXLEN*2], *ret = save;
  struct iosb_type iosb;
  int num, good;
  save[0] = 0;
  yell("[%s] still stuck in buffer", gsrv->last);
  strcpy(save, gsrv->last);
  do {
    num = tcp_receive(gsrv->iochan, tmp, sizeof(tmp)-1, &iosb, 0, NULL);
    good = 1;
    if (iosb.length>0) {
      ret = save;
      tmp[iosb.length] = 0;
      memcpy(&save[strlen(save)], tmp, iosb.length+1);
      ret = parse_buffer(save, gsrv);
      if (save!=ret) strcpy(save, ret);
    }
    say("waiting = %d", waiting);
  } while (waiting && (iosb.length > 0));
  strcpy(gsrv->last+1, ret);
/*  yell("leaving [%s] in buffer", ret); */
}

int process_receive(server_ptr temp)
{
  int good, change, linec=0, old;
  char *dummy, *walk, *last_char;

#if 0
  if (temp->processing) return 0;
#endif
#if 0
  if (temp->processing)
  {
     yell("recursive call");
     if (temp->need_requeue) yell("need requeue for new data");
  }
#endif
  temp->modified = FALSE;
  temp->processing = TRUE;

  walk = dummy = temp->last;
  last_char = &(temp->incoming[temp->incoming_start_free]);
  good = TRUE;
  do {
    while ((walk<last_char) && (*walk != lf)) walk++;
    if (*walk==lf) {
      *walk = 0;
      if (walk[-1] == 13) walk[-1] = 0;
      temp->last = walk+1;
      handle_line(dummy, temp);
      if (temp->last != (walk+1))
      {
/*        yell("modified in a recursive call"); */
        last_char = &(temp->incoming[temp->incoming_start_free]);
        dummy = walk = temp->last;
      } else dummy = ++walk;
      linec++;
      if (linec >= 5) good = FALSE;
    } else good = FALSE;
  } while (good);
  old = sys$setast(0);

/* if we processed some data this run.. */
  change = dummy - temp->incoming;
  if (change) {
    temp->last = temp->incoming;
    strcpy(temp->incoming, dummy);
    temp->incoming_free += change;
    temp->incoming_start_free -= change;
  }
  temp->processing = FALSE;
/*
  yell("lala %d - free, %d - start of free", temp->incoming_free,
       temp->incoming_start_free);
*/
  if (old==SS$_WASSET) sys$setast(1);
/* If we didn't get to the last character for some reason, return FALSE
   to indicate taht we are not done. */
  if (walk < last_char)
    return FALSE;
  return TRUE;
/*  return (linec?0:1); */
}
/* ------------------------------------------------------------------------ */
/* assumes process_receive and irc_receive do not modify the server list    */
static void lamer(void)
{
  server_ptr temp = server_list;
  int old, did_all = TRUE;
  while (temp) {
    if (temp->connected && !quit) {
      if (!process_receive(temp)) did_all = FALSE;
      if (temp->need_requeue) {
        temp->need_requeue = FALSE;
        irc_receive(temp);
      }
    }
    temp = temp->next;
  }
  old = sys$setast(0);
  if (did_all) sys$clref(SERVER_EF);
  for (temp = server_list; temp; temp = temp->next)
    if (temp->modified) sys$setef(SERVER_EF);
  if (old==SS$_WASSET) sys$setast(1);
}

/* ------------------------------------------------------------------------ */
void wait_routine(int ef)
{
  unsigned long mask;
  log_enter;
  mask = (1<<SERVER_EF) + (1<<ef);
  log_enter;
  do {
    log_enter;
    sys$wflor(SERVER_EF, mask);
    lamer();
    log_exit;
  } while ((sys$clref(ef) != SS$_WASSET));
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* The order of things:
 *   1. add_connect_to_list() to insert a connection into the queue
 *   2. start_read() to let the master_read function know to start
 *      monitoring the connection (and tell it what to do with the data)
/* ------------------------------------------------------------------------ */
static connect_node *master_connect_list = NULL;
/* ------------------------------------------------------------------------ */
void master_list(char *str)
{
  int old;
  connect_node *w;
  old = sys$setast(0);
  say("*** T chan acce host_id   port [%s]", str);
  for (w = master_connect_list; w; w = w->next)
  {
    say("*** %1.1d %4.4d %4.4d %9.9u %5.5d", w->type, w->iochan,
        w->accept_chan, w->sin?tcp_htonl(w->sin->sin_address):-1,
        w->sin?tcp_htons(w->sin->sin_port):-1);
  }
  say("*** End of connect list");
  if (old==SS$_WASSET) sys$setast(1);
}

/* ------------------------------------------------------------------------ */
static int master_read(short chan)
{              
  int old, kill_it;
  connect_node *walk, *save, *p = NULL;
  old = sys$setast(0);
  walk = master_connect_list;
  while (walk)
    if ((sys$clref(walk->event_flag) == SS$_WASSET) &&
        (walk->iosb.status != 0))
    {
      kill_it = FALSE;
      if ((walk->iosb.status != 1) || (walk->iosb.length <= 0))
      {
        if (walk->on_exit) walk->on_exit(walk);
        else say("death %d %d", walk->iosb.status, walk->iosb.length);
        kill_it = TRUE;
      } else {
        if (walk->on_read)
          if (walk->on_read(walk))
            tcp_receive(walk->iochan, walk->buffer, sizeof(walk->buffer),
                        &walk->iosb, walk->event_flag, master_read);
          else
            kill_it = TRUE;
        else say("%s", walk->buffer);
      }
      if (kill_it) {
        tcp_shutdown(walk->iochan);
        lib$free_ef(&walk->event_flag);
        if (walk->sin) myfree(walk->sin);
        if (walk->specific) myfree(walk->specific);
        if (p) p->next = walk->next;
        else master_connect_list = walk->next;
        save = walk;
        walk = walk->next;
        myfree(save);
      } else { p = walk; walk = walk->next; }
    } else { p = walk; walk = walk->next; }
  if (old==SS$_WASSET) sys$setast(1);
  return 1;
}

/* ------------------------------------------------------------------------ */
char *start_read(short chan, short nchan, READ_ROUT on_read, READ_ROUT on_exit)
{
  int old;
  connect_node *walk;
  old = sys$setast(0);
  for (walk = master_connect_list; walk; walk = walk->next)
    if (walk->iochan == chan)
    {
      if (walk->iochan != nchan) {
        tcp_shutdown(walk->iochan);
        walk->iochan = nchan;
      }
      walk->on_read = on_read;
      walk->on_exit = on_exit;
      tcp_receive(walk->iochan, walk->buffer, sizeof(walk->buffer),
                  &walk->iosb, walk->event_flag, master_read);
      if (old==SS$_WASSET) sys$setast(1);
      return walk->specific;
    }
  if (old==SS$_WASSET) sys$setast(1);
  return NULL;
}

/* ------------------------------------------------------------------------ */
void add_connect_to_list(short chan, SIN *mysin, char *specific, int type)
{
  int status;
  connect_node *temp;
  temp = (connect_node *)mymalloc(sizeof(connect_node));
  if (!temp) return;
  temp->type = type;
  temp->iochan = chan;
  temp->sin = mysin;
  temp->buffer[0] = 0;
  status = lib$get_ef(&(temp->event_flag));
  if (!(status & 1)) temp->event_flag = 0;
  temp->on_read = temp->on_exit = NULL;
  temp->specific = specific;
  temp->next = master_connect_list;
  master_connect_list = temp;
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
int new_send(server_ptr node, char *format, ...)
{
  int ss;
  char string[MAXLEN*2];
  va_list args;

  if (!node || !node->connected) {
    say("*** You are not connect to a server - try /server %s",
        node?node->server_name:"us.undernet.org");
    return 0;
  }
  va_start(args, format);
  vsprintf(string, format, args);
  va_end(args);
  if (getivar(VAR_DEBUG) & DEBUG$SEND)
    yell("%s", string);

  if ((ss = tcp_send(node->iochan, string, strlen(string))) == -1) {
    get_socket_error(string);
    say("send: %s", string);
    server_disconnected(node);
  }
  return ss;
}

/* ------------------------------------------------------------------------ */
void print_server_list(void)
{
  server_ptr s;
  int count = 0;
  say("*** Server list:");
  for (s = server_list; s; s = s->next, count++)
    if (s->nick)
      say("***   %2d) %s %d (%s%s) [%d]", count, s->server_name, s->port,
          s->connected?"":"was ", s->nick, s->iochan);
    else
      say("***   %2d) %s %d [%d]", count, s->server_name, s->port, s->iochan);
}

/* ------------------------------------------------------------------------ */
static void irc_receive(server_ptr temp)
{
  int ss;
  if (!temp) return;
  if (sizeof(temp->buffer) >= temp->incoming_free)
  {
    temp->need_requeue = TRUE;
    return;
  }
  temp->need_requeue = FALSE;
  ss = tcp_receive(temp->iochan, temp->buffer, sizeof(temp->buffer)-1,
                   &(temp->iosb), temp->event_flag, scan_server_list);
  if (ss==-1) {
    char msg[80];
    get_socket_error(msg);
    say("irc_receive: %s", msg);
  }
}

/* ------------------------------------------------------------------------ */
int good_host(unsigned char int_addr[4], char *host)
{
  int ack;
  ack = sscanf(host, "%d.%d.%d.%d", &int_addr[0], &int_addr[1], &int_addr[2],
               &int_addr[3]);
  if (ack==4) return TRUE;
  return FALSE;
}

/* ------------------------------------------------------------------------ */
static void getmy_host(void)
{
  char hostname[80], *host;
  host = getvar(VAR_HOSTNAME);
  if (!host || !*host) {
    tcp_gethostname(hostname);
    host = hostname;
  }
  if (host && *host)
    if (!my_nslookup(host, (char *)&myaddress))
    {
      say("*** Fatal error in nslookup of %s. Aborting", host);
      say("*** You will not be able to dcc send");
    }
   else say("*** %s translated.", host);
}

/* ------------------------------------------------------------------------ */
static void interactive(void)
{
  char input[MAXLEN], *walk, line[MAXLEN];

  while (1) {
    walk = input;
    (void)read_input(input, 560, NULL);
    if (*input) {
      if (getbvar(VAR_INPUT_ALIASES)) 
        parse_line(input, "", FALSE, TRUE);
      else
        parse_line(input, NULL, FALSE, TRUE);
      add_input_list(input);
    }
    free_hold();
    updatestatwin();
    find_input_prompt(FALSE);
  }
}

/* ------------------------------------------------------------------------ */
static void error_handler(void)
{
  (void)printf("This is really lame1\n");
  quit = TRUE;
  delete_windows();
  cleanup_input();
  exec_close_all();
  (void)printf("This is really lame2\n");
}

/* ------------------------------------------------------------------------ */
extern int DUMB;
extern char global_ircrc[MAXLEN];

/* ------------------------------------------------------------------------ */
static void read_servers_file(char *file)
{
  FILE *fp;
  char *word, str[MAXLEN], *walk;
  if (!(fp = fopen(file, "r"))) return;
  while (fgets(str, sizeof(str)-1, fp))
  {
    walk = str;
    word = next_arg(&walk);
    new_server_node(word, NULL, NULL, atoi(walk));
  }
  fclose(fp);
}

/* ------------------------------------------------------------------------ */
void master_init(char *gfile, char *pfile)
{
  init_binds();
  init_input_list(getivar(VAR_HISTORY));
/* The order must be: init_keybdio, init_window, start_keybdio */
/* init_window does things which depend on init_keybdio and start_keybdio
   can not be called until init_window is done or the program hangs */
  init_keybdio();
  init_window();    /* dependant on INPUT_DEFINED and DUMB */
  start_keybdio();
  load_file(gfile, 0, NULL); /* Load the global file */
  getmy_host();
  load_file(pfile, 0, NULL); /* Load the personal file */
}

/* ------------------------------------------------------------------------ */
void start_first_server(void)
{
  int status;
  server_ptr temp;
  char start_line[255];

  status = sys$bintim(&ast_wait_d, ast_time);
  if (!ODD(status)) my_sig(status, "ast bintime");
  for (temp = server_list; !gsrv && temp; temp = temp->next)
  {
    sprintf(start_line, "%s:%d:%s:%s", temp->server_name, temp->port,
            temp->pass?temp->pass:"", temp->nick?temp->nick:def_nick);
    user_server(start_line, 0, NULL);
  }
}

/* ------------------------------------------------------------------------ */
static int old_main(argc, argv)
  int argc;
  char **argv;
{
  unsigned status, dummy;
  char server[MAXLEN], loadfile[80], *ods = NULL, *ds = NULL, base_path[80];
  int curr = 0, port = DEF_PORT, set_server = 0, loop;

  strcpy(base_path, argv[0]);
  ds = base_path;
/* will not work with >'s for directory specifications.
   What if it's a logical: irclib:irc.exe ?? */
  while ((ds = (char *)strstr(ds, "]"))) ods = ++ds;
  if (ods) *ods = 0;
  sprintf(global_ircrc, "%sglobal.ircrc", base_path);

  if (!get_logical("IRCNICK", def_nick, FALSE))
    (void)get_username(def_nick, FALSE);
  if (!get_logical("IRCRC", loadfile, FALSE))
    strcpy(loadfile, "sys$login:.ircrc");
  if (get_logical("IRCSERVER", server, FALSE))
    set_server = 1;

  for (loop=1;loop<argc;loop++) {
    if (argv[loop][0] == '-') {
      if (argv[loop][1] == 'd') DUMB = 1;
      else if (argv[loop][1] == 'b') DUMB = 2;
      else if (argv[loop][1] == 'p') {
         if (++loop<argc) port = atoi(argv[loop]);
      }
      else if (argv[loop][1] == 'l') {
         if (++loop<argc) strcpy(loadfile, argv[loop]);
      }
    } else {
      if (curr==0) (void)strcpy(def_nick, argv[loop]);
      if (curr==1) {
        (void)strcpy(server, argv[loop]);
        set_server = 1;
      }
      curr++;
    }
  }
  master_init((char *)global_ircrc, loadfile);
#ifdef ENABLE_SERVER
  if (set_server)
    new_server_node(server, NULL, NULL, port);
  else
#else
  say("*** The SERVER command has been disabled.");
#endif
  {
    sprintf(global_ircrc, "%sircii.servers", base_path);
    read_servers_file(global_ircrc);
  }

  start_first_server();
  (void)launch_timer(); /* 15 second timer - async operations */
  interactive();        /* Handle user input - never exits */
  return 1;
}

int main(int argc, char *argv[])
{
/*  lib$establish(error_handler); /* use this so we can read the traceback */
  return old_main(argc, argv);
}
