Logo Search packages:      
Sourcecode: fbb version File versions  Download package

kernel.c

   /****************************************************************
    Copyright (C) 1986-2000 by

    F6FBB - Jean-Paul ROUBELAT
    6, rue George Sand
    31120 - Roquettes - France
      jpr@f6fbb.org

    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.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Parts of code have been taken from many other softwares.
    Thanks for the help.
    ****************************************************************/

/*

 * Routines de gestion des voies (Noyau).
 *
 */

#include <serv.h>

static void choix_suivant (int);
static void lit_port (int);
static void teste_console (void);
static void teste_voies (int);

/* Boucle principale du noyau */

void kernel (void)
{
      static int port = 1;
      static int loc_voie = 1;
      int i;

#ifdef __FBBDOS__
  kernel_boucle:
#endif

      if (!operationnel)
            return;

      aff_etat ('A');

      user_time_out ();

      is_idle = 1;

#ifdef __LINUX__
      pbsv ();
#endif

      watchdog ();
      teste_console ();
      deb_io ();
      fin_io ();

#ifdef __FBBDOS__

      if (backscroll)
      {
            if (t_scroll)
                  goto kernel_boucle;
            else
                  fin_backscroll ();
      }

#endif

#ifdef __LINUX__
      for (i = 1; i < NBPORT; i++)
      {
            if (++port == NBPORT)
                  port = 1;

            if ((p_port[port].pvalid) && (p_port[port].stop == 0))
            {
                  lit_port (port);
                  if (!operationnel)
                        return;

                  teste_voies (0);

                  for (i = 1; i < NBVOIES; i++)
                  {
                        if (p_port[no_port (i)].stop == 0)
                              teste_voies (i);
                  }

                  break;
            }
      }
#elif defined(__WIN32__)
      for (i = 1; i < NBPORT; i++)
      {
            if (++port == NBPORT)
                  port = 1;

            if ((p_port[port].pvalid) && (p_port[port].stop == 0))
            {
                  lit_port (port);
                  if (!operationnel)
                        return;

                  teste_voies (0);

                  if (++loc_voie == NBVOIES)
                        loc_voie = 1;

                  if (p_port[no_port (loc_voie)].stop == 0)
                        teste_voies (loc_voie);
            }
      }
#elif defined(__MSDOS__) || defined(__WINDOWS__)
      for (i = 1; i < NBPORT; i++)
      {
            if (++port == NBPORT)
                  port = 1;

            if ((p_port[port].pvalid) && (p_port[port].stop == 0))
            {
                  lit_port (port);
                  if (!operationnel)
                        return;

                  teste_voies (0);

                  if (++loc_voie == NBVOIES)
                        loc_voie = 1;

                  if (p_port[no_port (loc_voie)].stop == 0)
                        teste_voies (loc_voie);

                  break;
            }
      }
#endif

      if (loc_voie == 1)
      {
            k_tasks ();
      }

      if (!operationnel)
            return;

#ifdef __FBBDOS__
      goto kernel_boucle;
#endif
}

static void teste_console (void)
{
      df ("teste_console", 0);

      trait_time = 0;                     /* remet le compteur du watch-dog a 0 */

/***** A SUPPRIMER *****/
      selvoie (CONSOLE);

      switch (traite_console ())
      {
      case 0:
            break;
      case 1:
            if (pvoie->stop == 0)
            {
                  traite_voie (CONSOLE);
            }
            break;
      case 2:                             /* Demande de forward */
            break;
      }

      ff ();
}


static void tst_ddebcl (int port, uchar * mon, char *exped, char *indic)
{
      int i;
      int ok = 0;
      long ltemp;
      char stemp[80];
      char call[80];
      uchar checksum;
      unsigned ck;
      int ssid = 0;

      df ("tst_ddebcl", 7);

      if (*mon++ == '?')
      {

            if (*mon++ == ' ')
            {

                  checksum = 0;
                  for (i = 0; i < 10; i += 2)
                  {
                        if ((!ok) && ((mon[i] != '0') || (mon[i + 1] != '0')))
                              ok = 1;
                        if ((!isxdigit (mon[i])) && (!isxdigit (mon[i] + 1)))
                              break;
                        sscanf (mon + i, "%2x", &ck);
                        ck &= 0xff;
                        if (i < 8)
                              checksum += (uchar) ck;
                  }

                  if ((!ok) || (i != 10) || (checksum != ck))
                  {
                        ff ();
                        return;
                  }

                  sscanf (indic, "%[0-9A-Z]-%d", stemp, &ssid);
                  sscanf (exped, "%[0-9A-Z]", call);
                  stemp[6] = '\0';
                  call[6] = '\0';

                  if ((ssid != myssid) || (strcmp (stemp, mycall) != 0))
                  {
                        ff ();
                        return;
                  }

                  strn_cpy (8, stemp, mon);
                  sscanf (stemp, "%lX", &ltemp);

                  dde_synchro (call, ltemp, port);
            }
      }
      ff ();
}

static void choix_suivant (int voie)
{
      int choix;

      df ("choix_suivant", 1);

      if ((svoie[voie]->curfwd) && (voie == svoie[voie]->curfwd->forward))
      {
            choix = get_link (svoie[voie]->bbsfwd);
            if (choix < (int) svoie[voie]->nb_choix)
            {
                  ++choix;
                  set_link (svoie[voie]->bbsfwd, choix);
                  clr_bit_fwd (p_port[no_port (voie)].fwd, svoie[voie]->bbsfwd);
                  svoie[voie]->curfwd->fwdpos = svoie[voie]->curfwd->lastpos;
            }
            else
                  set_link (svoie[voie]->bbsfwd, 1);
      }
      ff ();
      return;
}


static int message (int voie, char *buffer)
{
      char *ptr;
      int val;

      df ("message", 3);

      buffer[2] = '*';
      if ((ptr = strtok (buffer, " ")) == NULL)
      {
            ff ();
            return (0);
      }

      ptr = strtok (NULL, " ");
      if (ptr == NULL)
            return (0);

      switch (*ptr)
      {
      case 'F':
      case 'D':
            if (strtok (NULL, " "))
            {
                  choix_suivant (voie);
                  val = dec_voie (voie);
                  ff ();
                  return (val);
            }
            break;
      case 'R':
            if (strlen (ptr) == 8)
            {
                  /* Readonly */
                  val = con_voie (voie, ptr);
                  svoie[voie]->read_only = 1;
                  ff ();
                  return (val);
            }
            else if (strlen (ptr) == 9)
            {
                  /* Reconnect */
                  dec_voie (voie);
                  val = con_voie (voie, ptr);
                  ff ();
                  return (val);
            }
            break;
      case 'C':
            if (strlen (ptr) == 9)
            {
                  /* Connected */
                  val = con_voie (voie, ptr);
                  ff ();
                  return (val);
            }
            break;
      case 'L':
            ptr = strtok (NULL, " ");     /* indicatif */
            if (strcmp (ptr, "FAILURE") == 0)
            {
                  if (svoie[voie]->conf)
                  {
                        svoie[voie]->conf = 0;
                        text_conf (T_CNF + 8);
                  }
                  choix_suivant (voie);
                  val = dec_voie (voie);
                  ff ();
                  return (val);
            }
            break;
      case 'B':
            if (svoie[voie]->conf)
            {
                  svoie[voie]->conf = 0;
                  text_conf (T_CNF + 9);
            }
            val = dec_voie (voie);
            ff ();
            return (val);
      default:
            if (svoie[voie]->conf)
            {
                  svoie[voie]->conf = 0;
            }
            break;
      }
      ff ();
      return (0);
}

void traite_commande (int voie, char *buffer, int len)
{
      if (svoie[voie]->kiss != -1)
      {
            if (!svoie[CONSOLE]->sta.connect)
                  aff_header (voie);
            init_timout (voie);
            if (svoie[voie]->kiss < 0)
            {
                  svoie[voie]->kiss = CONSOLE;
            }
            selvoie (svoie[voie]->kiss);
            out ("\n$O: ", 5);
            if (len >= 4)
            {
                  outsln (buffer + 4, len - 4);
                  selvoie (voie);
                  message (voie, buffer);
            }
      }
      else
      {
            nb_trait = 0;
            if (message (voie, buffer))
            {
                  traite_voie (voie);     /* Il y a des actions */
                  status (voie);
            }
      }
}

void traite_data (int voie, char *buffer, int len)
{
      aff_etat ('R');
      if (svoie[voie]->kiss >= 0)
      {
            if (!svoie[CONSOLE]->sta.connect)
                  aff_header (voie);
            init_timout (voie);
            selvoie (svoie[voie]->kiss);
            outs (buffer, len);
            write_capture (buffer, len);

            selvoie (voie);
      }
      else
      {
            in_buf (voie, buffer, len);
            status (voie);
      }
}

/*
 * Ressort un caractere du buffer d'entree
 * retourne le nb de caracteres (1 ou 0)
 */
int get_data (int voie)
{
      if (svoie[voie]->kiss >= 0)
      {
            /* Rien a faire, la data est deja partie */
            return (0);
      }
      else
      {
            return (get_inbuf (voie));
      }
}

static void lit_port (int port)
{
      char buffer[RCV_BUFFER_SIZE];
      int voie;
      int len = 0;
      int max;
      int cmd;
      ui_header ui;
      char header[200];
      char pid[20];
      char to[20];
      char ctl[20];
      char via[10];

      df ("lit_port", 1);

      memset (buffer, 0, sizeof (buffer));

#ifdef __WINDOWS__
      if (p_port[port].typort == TYP_TCP)
      {
            ff ();
            return;
      }
#endif

      if (p_port[port].typort == TYP_MOD)
      {
            lit_port_modem (port);
            aff_etat ('A');
            ff ();
            return;
      }

      max = 30;
      voie = 0xff;
      while (rcv_drv (&port, &voie, &cmd, buffer, &len, &ui))
      {
            switch (cmd)
            {

            case DISPLAY:
                  break;

            case NBCHR:
                  p_port[port].cur = *((long *) buffer);
                  break;

            case NBBUF:
                  p_port[port].mem = *((int *) buffer) << 5;
                  break;

            case STATS:
                  {
                        int ch_status = 0;
                        int mem = p_port[port].mem >> 5;

                        stat_ch *sta_new = (stat_ch *) buffer;
                        stat_ch *sta = &svoie[voie]->sta;

                        if ((sta_new->stat != -1) && (sta->stat != sta_new->stat))
                        {
                              sta->stat = sta_new->stat;
                              ch_status = 1;
                        }
                        if ((sta_new->connect != -1) && (sta->connect != sta_new->connect))
                        {
                              if (sta_new->connect == 1)
                              {
                                    sta->connect = 1;
                              }
                              ch_status = 1;
                        }
                        if ((sta_new->ret != -1) && (sta_new->ret != sta->ret))
                        {
                              sta->ret = sta_new->ret;
                              ch_status = 1;
                        }
                        if ((sta_new->ack != -1) && (sta_new->ack != sta->ack))
                        {
                              sta->ack = sta_new->ack;
                              ch_status = 1;
                        }
                        if ((sta_new->mem != -1) && (sta->mem != mem))
                        {
                              sta->mem = mem;
                              ch_status = 1;
                        }
                        svoie[voie]->ch_status = ch_status;
                  }
                  break;

            case DATA:
                  traite_data (voie, buffer, len);
                  break;

            case COMMAND:
                  traite_commande (voie, buffer, len);
                  break;

            case UNPROTO:
                  aff_etat ('M');
                  if (ui.pid)
                        sprintf (pid, " pid %02X", ui.pid);
                  else
                        *pid = '\0';

                  if (*ui.ctl)
                        sprintf (ctl, "ctl %s", ui.ctl);
                  else
                        *ctl = '\0';

                  if (*ui.to)
                        sprintf (to, " to %s ", ui.to);
                  else
                        *to = '\0';

                  if (*ui.via)
                        strcpy (via, "via ");
                  else
                        *via = '\0';

                  sprintf (header, "[%d] fm %s%s%s%s%s%s%s",
                               ui.port, ui.from, to, via, ui.via, ctl, pid, ui.txt);
                  add_heard (ui.port, get_indic (ui.from));
                  monitor (ui.port, header, strlen (header));
                  put_ui (header, W_MONH, strlen (header));

                  if (len == 0)
                        break;

                  switch (ui.pid)
                  {
                  case 0x01:
                        put_rose (buffer, W_MOND, len);
                        break;
                  case 0xcf:
                        put_nr (buffer, W_MOND, len);
                        break;
                  case 0xf0:
                        if (ui.ui)
                              tst_ddebcl (ui.port, buffer, ui.from, ui.to);
                        monitor (ui.port, buffer, len);
                        put_ui (buffer, W_MOND, len);
                        break;
                  case 0x0:
                        /* Pactor */
                        monitor (ui.port, buffer, len);
                        put_ui (buffer, W_MOND, len);
                        break;
                  }
                  break;

            }
            if (--max == 0)
                  break;
      }
      aff_etat ('A');
      ff ();
}

void teste_voies (int voie)
{
      int ch_stat = 0;
      long caltemps;
      static long lock_time = 0L;

      df ("teste_voies", 0);

      trait_time = 0;                     /* remet le compteur du watch-dog a 0 */

#ifdef __LINUX__
      if (is_cmd (voie))
      {
            /* A command is being processed */
            traite_voie (voie);
      }
      else
#endif
      if (voie == INEXPORT)
      {
            time (&caltemps);

            if ((inexport) && (!backscroll))
            {
                  struct stat statbuf;

                  if (stat (LOCK_IN, &statbuf) == -1)
                  {
                        lock_time = 0L;
                        aff_etat ('Y');
                        selvoie (INEXPORT);
                        traite_voie (INEXPORT);
                  }
                  else
                  {
                        if (lock_time == 0L)
                              lock_time = caltemps;
                        else if ((caltemps - lock_time) > 300L)
                        {
                              lock_time = 0L;
                              unlink (LOCK_IN);
                        }
                  }
            }
            return;
      }

      if (svoie[voie]->affport.port == 0xff)
      {
            ff ();
            return;
      }

      if (svoie[voie]->sta.connect)
      {
            ack_suiv (voie);
      }

      if ((!svoie[voie]->stop) && (svoie[voie]->seq))
      {                                         /* Recharge les bufs de sortie */
            if (tot_mem > 10000L)
            {
                  traite_voie (voie);
                  ch_stat = 1;
            }
            ff ();
            return;
      }

      if ((v_tell == 0) || (v_tell != voie) || ((v_tell) && (v_tell == voie)))
      {
            while ((!svoie[voie]->seq) && (inbuf_ok (voie)))
            {
                  ch_stat = 1;
                  traite_voie (voie);
            }
      }

      if (ch_stat)
            status (voie);

      ff ();
}


int min_ok (int voie)
{
      int port;
      int mini;

      df ("min_ok", 1);

      port = no_port (voie);
      mini = 300;

      switch (p_port[port].typort)
      {
      case TYP_BPQ:
            mini = (40 * 64);
            break;
      case TYP_DED:
            mini = (70 * 32);
      case TYP_FLX:
            p_port[port].mem = svoie[voie]->sta.mem * 250;
            mini = (250);
            break;
      }

      ff ();
      return (p_port[port].mem > mini);
}

Generated by  Doxygen 1.6.0   Back to index