/*
   axgetmail
   (c) 1999 by Radek Burget OK2JBG

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version
   2 of the license, or (at your option) any later version.

   conbbs: connect the BBS
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <sys/time.h>
#include <linux/ax25.h>
#include "calls.h"
#include "common.h"
#include "conbbs.h"

#ifndef VERSION
#define VERSION "0.07"
#endif

#define AXPORTS "/etc/ax25/axports"
#define CONTIME 300                  //connect timeout [seconds]
#define BUFSIZE 1024

char mycall[20];            /* my callsign */
char bbscall[20];           /* BBS callsign */
char bcall[20];             /* Base callsign of port */
char bbspath[256];          /* path to BBS */

int sock;                   /* the socket for connecting BBS */
int connected = 0;          /* is the BBS connected ? */

FILE *bbs_stream;           /* stream for communication with BBS */

/*----------------------------------------------------------------------*/

/* read axports file and translate the port name to a base callsign*/
int find_port(char *name, char *call)
{
  char buf[256];
  FILE *f;
  int found = 0;
  int speed, paclen, win;
  char descript[256];
  char pname[256];
  char pcall[256];

  f = fopen(AXPORTS, "r");
  if (f == NULL) return 0;
  while (!feof(f))
  {
    strcpy(buf, "");
    fgets(buf, 255, f);
    if (strlen(buf) != 0 && buf[0] != '#')
    {
      int n;
      n = sscanf(buf, "%s %s %i %i %i %s", pname, pcall, &speed,
                                      &paclen, &win, descript);
      if (n == 6 && strcmp(pname, name) == 0)
      {
        strcpy(call, pcall);
        found = 1;
        break;
      }
    }
  }
  fclose(f);
  return found;
}

/*----------------------------------------------------------------------*/

/* wait until the socket is connected */
int wait_connect(int sock)
{
  fd_set rfds;
  struct timeval tv;
  int rc;
  
  FD_ZERO(&rfds);
  FD_SET(sock, &rfds);
  tv.tv_sec = CONTIME;
  tv.tv_usec = 0;
  rc = select(sock+1, &rfds, NULL, NULL, &tv);
  if (rc > 0 && FD_ISSET(sock, &rfds))
  {
    return 1;
  }
  return 0;
}

/* Connect the BBS. Return 0 when unsuccesful. */
int connect_bbs()
{
   int len, lenp;
   char path[256];
   struct full_sockaddr_ax25 addr, addrp;
   int rc;

   sock = socket(AF_AX25, SOCK_SEQPACKET, PF_AX25);
   if (sock == -1)
   {
     message(MSG_ERROR, "Cannot create socket : %s\n", strerror(errno));
     return 0;
   }
   fcntl(sock, F_SETFL, O_NONBLOCK);
   sprintf(path, "%s %s", mycall, bcall);
   len = convert_path(path, &addr);
   if (len == -1)
   {
     message(MSG_ERROR, "Invalid path %s\n", path);
     return 0;
   }
   if (bind(sock, (struct sockaddr *)&addr, len) == -1)
   {
     message(MSG_ERROR, "Cannot bind() : %s\n", strerror(errno));
     return 0;
   }
   //connect new socket
   lenp = convert_path(bbspath, &addrp);
   if (connect(sock, (struct sockaddr *)&addrp, lenp) == -1)
     if (errno != EINPROGRESS)
     {
       message(MSG_ERROR, "Cannot connect() : %s\n", strerror(errno));
       return 0;
     }

   /* wait for connection */
   rc = wait_connect(sock);

   if (rc)
   {
     connected = 1;
   }

   return rc;
}

/*----------------------------------------------------------------------*/

FILE *conbbs(char *_mycall, char *_port, char *_dest)
{
  strcpy(mycall, _mycall); normalize_call(mycall);
  strcpy(bbspath, _dest);
  
  if (!find_port(_port, bcall))
  {
    message(MSG_ERROR, "Unknown port '%s'\n", _port);
    return NULL;
  }
  normalize_call(bcall);

  message(MSG_DEBUG, "conbbs params:\n"
                     "BBS : `%s'\n"
                     "Mycall : `%s'\n"
                     "Port : `%s'\n"
                     "Base call : `%s'\n",
                     bbspath, mycall, _port, bcall);

  if (!connect_bbs()) return NULL;

  bbs_stream = fdopen(sock, "r+");

  return bbs_stream;
}

/* disconnect BBS */
void disc_bbs(FILE *bbs_stream)
{
  if (connected)
  {
    message(MSG_INFO, "Disconnecting BBS\n");
    fclose(bbs_stream);
    close(sock);
    connected = 0;
  }
}

