/*
		                  LCRZO
                             Network library
             Copyright(c) 1999,2000,2001,2002 Laurent Constantin
                                  -----

  Main server    : http://www.laurentconstantin.com/
  Backup servers : http://go.to/laurentconstantin/
                   http://laurentconstantin.est-la.com/
                   http://laurentconstantin.free.fr/
                   http://lauconstantin.multimania.com/
  [my current email address is on the web servers]

                                  -----
  This file is part of Lcrzo.

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

  Lcrzo 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
  Lesser General Public License for more details (http://www.gnu.org).

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

/* -- Note about comments and variable names --
   In versions 1.00 up to 2.08, lcrzo was only written in French (my
   mother tongue). Since version 3.00, lcrzo is written in English, but
   most of comments and variable names are still in French.
   In future versions, I'll try to translate everything into English,
   but as you may guess, that's a quite big work...
   So, for the moment, here are some word translation, if you want to
   be able to understand what's going on in the functions :
     afficher - print     ;  ajouter - add         ;  copie - copy
     dernier - last       ;  donnee - data         ;  ecrire - write
     entete - header      ;  envoye - sent         ;  ferme - close
     fichier - file       ;  lire - read           ;  masque - mask 
     nboct - byte number  ;  ouvre, ouvrir - open  ;  paq, paquet - packet
     plage - range        ;  premier - first       ;  recu - received
     reseau - network     ;  retour - return       ;  taille - size
     tunnel - pipe

*/

#include "lcrzo_incl.h"

/*-------------------------------------------------------------*/
int lcrzo_hs_init(lcrzo_conststring instring,
		  lcrzo_hs ouths)
{ lcrzo_er(lcrzo_string_init_coretext(instring, LCRZO_HS_MAXBYTES, ouths));
  return(LCRZO_ERR_OK);
}
int lcrzo_ips_init(lcrzo_conststring inips,
		   lcrzo_ips outips)
{ lcrzo_ips ips;
  char *pc;
    
  if (outips==NULL) pc=ips;
  else pc=outips;

  lcrzo_er(lcrzo_string_init_coretext(inips, LCRZO_IPS_MAXBYTES, pc));

  /*try to convert it to see if it's OK*/
  lcrzo_er(lcrzo_ipa_init_ips(pc, NULL));

  return(LCRZO_ERR_OK);
}
int lcrzo_ipa_init(lcrzo_uint8 a, lcrzo_uint8 b,
		   lcrzo_uint8 c, lcrzo_uint8 d, lcrzo_ipa ipa_dest)
{ if (ipa_dest!=NULL)
  { ipa_dest[0]=a;
    ipa_dest[1]=b;
    ipa_dest[2]=c;
    ipa_dest[3]=d;
  }
  return(LCRZO_ERR_OK);
}
int lcrzo_ipl_init(lcrzo_uint8 a, lcrzo_uint8 b,
		 lcrzo_uint8 c, lcrzo_uint8 d, lcrzo_ipl *pipl_dest)
{ if (pipl_dest!=NULL) *pipl_dest= (a<<24) | (b<<16) | (c<<8) | d;
  return(LCRZO_ERR_OK);
}
int lcrzo_eths_init(lcrzo_conststring ineths,
		    lcrzo_eths outeths)
{ lcrzo_eths eths;
  char *pc;
    
  if (outeths==NULL) pc=eths;
  else pc=outeths;

  lcrzo_er(lcrzo_string_init_coretext(ineths, LCRZO_ETHS_MAXBYTES, pc));

  /*try to convert it to see if it's OK*/
  lcrzo_er(lcrzo_etha_init_eths(pc, NULL));

  return(LCRZO_ERR_OK);
}
int lcrzo_etha_init(lcrzo_uint8 a, lcrzo_uint8 b, lcrzo_uint8 c, lcrzo_uint8 d,
		    lcrzo_uint8 e, lcrzo_uint8 f, lcrzo_etha etha_dest)
{ if (etha_dest!=NULL)
  { etha_dest[0]=a;
    etha_dest[1]=b;
    etha_dest[2]=c;
    etha_dest[3]=d;
    etha_dest[4]=e;
    etha_dest[5]=f;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hs_init_hs(lcrzo_consths inhs,
		     lcrzo_hs ouths)
{ lcrzo_er(lcrzo_string_init_coretext(inhs, LCRZO_HS_MAXBYTES, ouths));
  return(LCRZO_ERR_OK);
}
int lcrzo_ips_init_ips(lcrzo_constips inips,
		       lcrzo_ips outips)
{ lcrzo_ips ips;
  char *pc;
    
  if (outips==NULL) pc=ips;
  else pc=outips;

  lcrzo_er(lcrzo_string_init_coretext(inips, LCRZO_IPS_MAXBYTES, pc));

  /*try to convert it to see if it's OK*/
  lcrzo_er(lcrzo_ipa_init_ips(pc, NULL));

  return(LCRZO_ERR_OK);
}
int lcrzo_ipa_init_ipa(lcrzo_constipa inipa, 
		       lcrzo_ipa outipa)
{
  if (outipa!=NULL)
  { memcpy(outipa, inipa, LCRZO_IPA_MAXBYTES);
  }
  return(LCRZO_ERR_OK);
}
int lcrzo_ipl_init_ipl(lcrzo_ipl inipl, 
		       lcrzo_ipl *poutipl)
{
  if (poutipl!=NULL)
  { *poutipl=inipl;
  }
  return(LCRZO_ERR_OK);
}
int lcrzo_eths_init_eths(lcrzo_consteths ineths,
			 lcrzo_eths outeths)
{ lcrzo_eths eths;
  char *pc;
    
  if (outeths==NULL) pc=eths;
  else pc=outeths;

  lcrzo_er(lcrzo_string_init_coretext(ineths, LCRZO_ETHS_MAXBYTES, pc));

  /*try to convert it to see if it's OK*/
  lcrzo_er(lcrzo_etha_init_eths(pc, NULL));

  return(LCRZO_ERR_OK);

}
int lcrzo_etha_init_etha(lcrzo_constetha inetha,
			 lcrzo_etha outetha)
{
  if (outetha!=NULL)
  { memcpy(outetha, inetha, LCRZO_ETHA_MAXBYTES);
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
/*conversions ips-ipaipl et eths-etha*/

/*-------------------------------------------------------------*/
int lcrzo_priv_global_set_errmsglcrzo_address(lcrzo_conststring address);
int lcrzo_priv_global_set_errmsglcrzo_address(lcrzo_conststring address)
{ int ret;
  lcrzo_int16 language;
  lcrzo_string msg;

  lcrzo_er(lcrzo_global_get_language(&language));
  if ( language==LCRZO_GLOBAL_LANG_FR ) 
  { ret=lcrzo_string_initm_text("La mauvaise adresse est : ", &msg);
  }
  else
  { ret=lcrzo_string_initm_text("The bad address is : ", &msg);
  }
  if (ret==LCRZO_ERR_OK)
  { ret=lcrzo_string_appendm_text(address, &msg);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_priv_global_set_errmsglcrzo(msg);
    }
    lcrzo_string_free(msg);
  }

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_global_set_errmsglcrzo_range(lcrzo_conststring range);
int lcrzo_priv_global_set_errmsglcrzo_range(lcrzo_conststring range)
{ int ret;
  lcrzo_int16 language;
  lcrzo_string msg;

  lcrzo_er(lcrzo_global_get_language(&language));
  if ( language==LCRZO_GLOBAL_LANG_FR ) 
  { ret=lcrzo_string_initm_text("Le mauvais intervalle est : ", &msg);
  }
  else
  { ret=lcrzo_string_initm_text("The bad range is : ", &msg);
  }
  if (ret==LCRZO_ERR_OK)
  { ret=lcrzo_string_appendm_text(range, &msg);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_priv_global_set_errmsglcrzo(msg);
    }
    lcrzo_string_free(msg);
  }

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_ipa_init_ips(const lcrzo_ips ipsin, lcrzo_ipa ipa)
{ lcrzo_ips ips;
  int i, j, n, cn;
  char c;

  lcrzo_er(lcrzo_string_init_coretext(ipsin, LCRZO_IPS_MAXBYTES, ips));
  i=0;
  j=0;
  n=-1;
  while ( LCRZO_TRUE )
  { c=ips[i];
    /* it's a number */
    if ( c>='0' && c<='9' )
    { cn=c-'0';
      if ( n==-1 )
      { /* first digit */
        n=cn;
      }
      else
      { n = n*10 + cn;
        if ( n>255 ) goto lcrzo_ipa_init_ips_g;
      }
    }
    /* it's a separator */
    else if ( c=='.' || c=='\0' )
    { /* check we have a valid number */
      if ( n==-1 ) goto lcrzo_ipa_init_ips_g;
      if ( ipa!=NULL ) ipa[j]=(lcrzo_uint8)n;
      /* prepare for next */
      j++;
      n=-1;
      /* check for stop */
      if ( j==LCRZO_IPA_MAXBYTES && c!='\0' ) goto lcrzo_ipa_init_ips_g;
      if ( c=='\0' ) break;
    }
    /* it's a forbidden char */
    else
    { goto lcrzo_ipa_init_ips_g;
    }
    /* take next char */
    i++;
  }
  /* check we've set all entries */
  if ( j!=LCRZO_IPA_MAXBYTES ) goto lcrzo_ipa_init_ips_g;

  return(LCRZO_ERR_OK);

 lcrzo_ipa_init_ips_g:
  lcrzo_priv_global_set_errmsglcrzo_address(ips);
  return(LCRZO_ERR_FMIP); 
}

/*-------------------------------------------------------------*/
/* equivalent de inet_addr ou inet_aton*/
int lcrzo_ipl_init_ips(const lcrzo_ips ipsin, lcrzo_ipl *pipl)
{ lcrzo_ips ips;
  int i, j, n, cn;
  char c;

  lcrzo_er(lcrzo_string_init_coretext(ipsin, LCRZO_IPS_MAXBYTES, ips));
  i=0;
  j=0;
  n=-1;
  if (pipl!=NULL) *pipl=0;
  while ( LCRZO_TRUE )
  { c=ips[i];
    /* it's a number */
    if ( c>='0' && c<='9' )
    { cn=c-'0';
      if ( n==-1 )
      { /* first digit */
        n=cn;
      }
      else
      { n = n*10 + cn;
        if ( n>255 ) goto lcrzo_ipl_init_ips_g;
      }
    }
    /* it's a separator */
    else if ( c=='.' || c=='\0' )
    { /* check we have a valid number */
      if ( n==-1 ) goto lcrzo_ipl_init_ips_g;
      if (pipl!=NULL) *pipl= (lcrzo_uint32)((*pipl)<<8) | (lcrzo_uint32)n;
      /* prepare for next */
      j++;
      n=-1;
      /* check for stop */
      if ( j==LCRZO_IPA_MAXBYTES && c!='\0' ) goto lcrzo_ipl_init_ips_g;
      if ( c=='\0' ) break;
    }
    /* it's a forbidden char */
    else
    { goto lcrzo_ipl_init_ips_g;
    }
    /* take next char */
    i++;
  }
  /* check we've set all entries */
  if ( j!=LCRZO_IPA_MAXBYTES ) goto lcrzo_ipl_init_ips_g;

  return(LCRZO_ERR_OK);

 lcrzo_ipl_init_ips_g:
  lcrzo_priv_global_set_errmsglcrzo_address(ips);
  return(LCRZO_ERR_FMIP); 
}

/*-------------------------------------------------------------*/
int lcrzo_ips_init_ipa(const lcrzo_ipa ipa, lcrzo_ips ips)
{ int i;

  /*parameters verification*/
  if (ipa==NULL) return(LCRZO_ERR_PANULLPTR);

  /*this function is always OK*/
  if (ips==NULL) return(LCRZO_ERR_OK);

  lcrzo_string_init_text("", LCRZO_IPS_MAXBYTES, ips);
  for (i=0;i<LCRZO_IPA_MAXBYTES-1;i++)
  { lcrzo_string_append_int(ipa[i], "%d", LCRZO_IPS_MAXBYTES, ips);
    lcrzo_string_append_char((char)'.', 1, LCRZO_IPS_MAXBYTES, ips);
  }
  lcrzo_string_append_int(ipa[LCRZO_IPA_MAXBYTES-1], "%d",
			  LCRZO_IPS_MAXBYTES, ips);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipl_init_ipa(const lcrzo_ipa ipa, lcrzo_ipl *pipl)
{
  /*parameters verification*/
  if (ipa==NULL) return(LCRZO_ERR_PANULLPTR);

  if (pipl!=NULL) *pipl= (ipa[0]<<24) | (ipa[1]<<16) | (ipa[2]<<8) | ipa[3];
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ips_init_ipl(lcrzo_ipl ipl, lcrzo_ips ips)
{
  /*this function is always OK*/
  if (ips==NULL) return(LCRZO_ERR_OK);

  lcrzo_string_init_int((lcrzo_uint8)(ipl>>24), "%d", LCRZO_IPS_MAXBYTES, ips);
  lcrzo_string_append_char('.', 1, LCRZO_IPS_MAXBYTES, ips);
  lcrzo_string_append_int((lcrzo_uint8)((ipl>>16)&0xFF), "%d",
		       LCRZO_IPS_MAXBYTES,ips);
  lcrzo_string_append_char('.', 1, LCRZO_IPS_MAXBYTES, ips);
  lcrzo_string_append_int((lcrzo_uint8)((ipl>>8)&0xFF), "%d",
		       LCRZO_IPS_MAXBYTES, ips);
  lcrzo_string_append_char('.', 1, LCRZO_IPS_MAXBYTES, ips);
  lcrzo_string_append_int((lcrzo_uint8)(ipl&0xFF), "%d", LCRZO_IPS_MAXBYTES, ips);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipa_init_ipl(lcrzo_ipl ipl, lcrzo_ipa ipa)
{ 
  if (ipa!=NULL)
  { ipa[0]=(lcrzo_uint8)(ipl>>24);
    ipa[1]=(lcrzo_uint8)((ipl>>16)&0xFF);
    ipa[2]=(lcrzo_uint8)((ipl>>8)&0xFF);
    ipa[3]=(lcrzo_uint8)(ipl&0xFF);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_etha_init_eths(const lcrzo_eths ethsin, lcrzo_etha etha)
{ lcrzo_eths eths;
  int i, j, n, cn;
  char c;

  lcrzo_er(lcrzo_string_init_coretext(ethsin, LCRZO_ETHS_MAXBYTES, eths));
  i=0;
  j=0;
  n=-1;
  while ( LCRZO_TRUE )
  { c=eths[i];
    /* it's a number */
    if ( (c>='0' && c<='9') || (c>='A' && c<='F') || (c>='a' && c<='f') )
    { if (c>='0' && c<='9') cn=c-'0';
      else if (c>='A' && c<='F') cn=c-'A'+10;
      else if (c>='a' && c<='f') cn=c-'a'+10;
      else return(LCRZO_ERR_IEINTERNALERROR);
      if ( n==-1 )
      { /* first digit */
        n=cn;
      }
      else
      { n = n*16 + cn;
        if ( n>255 ) goto lcrzo_etha_init_eths_g;
      }
    }
    /* it's a separator */
    else if ( c==':' || c=='\0' )
    { /* check we have a valid number */
      if ( n==-1 ) goto lcrzo_etha_init_eths_g;
      if ( etha!=NULL ) etha[j]=(lcrzo_uint8)n;
      /* prepare for next */
      j++;
      n=-1;
      /* check for stop */
      if ( j==LCRZO_ETHA_MAXBYTES && c!='\0' ) goto lcrzo_etha_init_eths_g;
      if ( c=='\0' ) break;
    }
    /* it's a forbidden char */
    else
    { goto lcrzo_etha_init_eths_g;
    }
    /* take next char */
    i++;
  }
  /* check we've set all entries */
  if ( j!=LCRZO_ETHA_MAXBYTES ) goto lcrzo_etha_init_eths_g;

  return(LCRZO_ERR_OK);

 lcrzo_etha_init_eths_g:
  lcrzo_priv_global_set_errmsglcrzo_address(eths);
  return(LCRZO_ERR_FMETH); 
}

/*-------------------------------------------------------------*/
int lcrzo_eths_init_etha(const lcrzo_etha etha, lcrzo_eths eths)
{ int i;

  /*parameters verification*/
  if (etha==NULL) return(LCRZO_ERR_PANULLPTR);

  /*this function is always OK*/
  if (eths==NULL) return(LCRZO_ERR_OK);

  lcrzo_string_init_text("", LCRZO_ETHS_MAXBYTES, eths);
  for (i=0;i<LCRZO_ETHA_MAXBYTES-1;i++)
  { lcrzo_string_append_int(etha[i], "%02X", LCRZO_ETHS_MAXBYTES, eths);
    lcrzo_string_append_char(':', 1, LCRZO_ETHS_MAXBYTES, eths);
  }
  lcrzo_string_append_int(etha[LCRZO_ETHA_MAXBYTES-1], "%02X",
		       LCRZO_ETHS_MAXBYTES, eths);
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
/*conversions faisant appel a une fonction reseau*/

/*-------------------------------------------------------------*/
/*trouve la reponse en utilisant le resolver (local, dns, yp, etc.)*/
int lcrzo_priv_ipa_init_hs_resolver(const lcrzo_hs hs, lcrzo_ipa ipa);
int lcrzo_priv_ipa_init_hs_resolver(const lcrzo_hs hs, lcrzo_ipa ipa)
{ struct hostent *phe;
  int i;

  lcrzo_hs_verifbof(hs);
  phe=gethostbyname(hs);
  if ( phe!=NULL )
  { if (ipa!=NULL)
    { for (i=0;i<LCRZO_IPA_MAXBYTES;i++) ipa[i]=phe->h_addr_list[0][i];
    }
    lcrzo_err_purge();
    return(LCRZO_ERR_OK);
  }

  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
/*trouve la reponse en utilisant le resolver durant n secondes*/
typedef struct {
  lcrzo_ipc ipc;
  lcrzo_hs hs;
} lcrzo__priv_ipa_init_hs_resolvalarm_s;
void   MemTrace_Report    (FILE *);
int    MemTrace_Init      (const char *, int);
void   MemTrace_Flush     (void);

int lcrzo__priv_ipa_init_hs_resolvalarm(void *infos,
					lcrzo_int32 infossize,
					lcrzo_process *pparentprocess);
int lcrzo__priv_ipa_init_hs_resolvalarm(void *infos,
					lcrzo_int32 infossize,
					lcrzo_process *pparentprocess)
{ lcrzo__priv_ipa_init_hs_resolvalarm_s *ps=(lcrzo__priv_ipa_init_hs_resolvalarm_s *)infos;
  lcrzo_ipa ipa;
  int ret;

  lcrzo_er(lcrzo_ipc_currentprocessissideb(&ps->ipc));
  lcrzo_er(lcrzo_ipc_close_read(&ps->ipc));

  /* ask resolver */
  ret=lcrzo_priv_ipa_init_hs_resolver(ps->hs, ipa);
  lcrzo_er(lcrzo_ipc_write_uint32(&ps->ipc, ret));
  if ( ret==LCRZO_ERR_OK )
  { lcrzo_er(lcrzo_ipc_write_ipa(&ps->ipc, ipa));
  }

  return(LCRZO_ERR_OK);
  /* just for the compiler warning */
  infossize=infossize;
  pparentprocess=pparentprocess;
}
int lcrzo_priv_ipa_init_hs_resolvalarm(const lcrzo_hs hs, lcrzo_ipa ipa);
int lcrzo_priv_ipa_init_hs_resolvalarm(const lcrzo_hs hs, lcrzo_ipa ipa)
{ lcrzo__priv_ipa_init_hs_resolvalarm_s ihr;
  lcrzo_process child;
  lcrzo_time alarmtimeout;
  lcrzo_uint8 timeout;
  lcrzo_bool answerreceived;
  lcrzo_uint32 childret;
  int ret;

  /* initialize IPC communication */
  lcrzo_er(lcrzo_ipc_init(&ihr.ipc));

  /* set child infos */
  lcrzo_er(lcrzo_hs_init(hs, ihr.hs));

  /* create child */
  lcrzo_er(lcrzo_process_other_init(&lcrzo__priv_ipa_init_hs_resolvalarm, 
				    (lcrzo_data)&ihr, sizeof(ihr), &child));
  lcrzo_er(lcrzo_ipc_currentprocessissidea(&ihr.ipc));
  lcrzo_er(lcrzo_ipc_close_write(&ihr.ipc));

  /* check if child gave us data */
  lcrzo_er(lcrzo_global_get_resolver_timeout(&timeout));
  lcrzo_er(lcrzo_time_init_sec(timeout, &alarmtimeout));
  answerreceived=LCRZO_FALSE;
  ret=lcrzo_ipc_read_uint32(&ihr.ipc, &alarmtimeout, &childret);
  if (ret==LCRZO_ERR_OK)
  { if (childret==LCRZO_ERR_OK)
    { /* we have one second to read the ipa */ 
      ret=lcrzo_time_init_sec(1, &alarmtimeout);
      if (ret==LCRZO_ERR_OK)
      { ret=lcrzo_ipc_read_ipa(&ihr.ipc, &alarmtimeout, ipa);
        if (ret==LCRZO_ERR_OK) answerreceived=LCRZO_TRUE; 
      }
    }
  }
  lcrzo_er(lcrzo_ipc_close(&ihr.ipc));
  
  /* may need to kill the child */
  lcrzo_er(lcrzo_process_other_exit(&child));
  /* always wait for the child */
  lcrzo_er(lcrzo_process_other_wait_end(&child, LCRZO_WAIT_INFINITE,
					NULL, NULL));

  /* return */
  if (answerreceived)
  { return(LCRZO_ERR_OK);
  }
  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
/*trouve la reponse en utilisant le resolver (local, dns, yp, etc.)*/
int lcrzo_priv_hs_init_ipa_resolver(const lcrzo_ipa ipa, lcrzo_hs hs);
int lcrzo_priv_hs_init_ipa_resolver(const lcrzo_ipa ipa, lcrzo_hs hs)
{ struct hostent *phe;

  phe=gethostbyaddr((const char *)ipa, LCRZO_IPA_MAXBYTES, AF_INET);
  if ( phe!=NULL )
  { lcrzo_hs_verifbof(phe->h_name);
    lcrzo_string_init_text(phe->h_name, LCRZO_HS_MAXBYTES, hs);
    lcrzo_err_purge();
    return(LCRZO_ERR_OK);
  }

  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
/*trouve la reponse en utilisant le resolver durant n secondes*/
typedef struct {
  lcrzo_ipc ipc;
  lcrzo_ipa ipa;
} lcrzo__priv_hs_init_ipa_resolvalarm_s;
int lcrzo__priv_hs_init_ipa_resolvalarm(void *infos, lcrzo_int32 infossize, lcrzo_process *pparentprocess);
int lcrzo__priv_hs_init_ipa_resolvalarm(void *infos, lcrzo_int32 infossize, lcrzo_process *pparentprocess)
{ lcrzo__priv_hs_init_ipa_resolvalarm_s *ps=(lcrzo__priv_hs_init_ipa_resolvalarm_s *)infos;
  lcrzo_hs hs;
  int ret;

  lcrzo_er(lcrzo_ipc_currentprocessissideb(&ps->ipc));
  lcrzo_er(lcrzo_ipc_close_read(&ps->ipc));

  /* ask resolver */
  ret=lcrzo_priv_hs_init_ipa_resolver(ps->ipa, hs);
  lcrzo_er(lcrzo_ipc_write_uint32(&ps->ipc, ret));
  if ( ret==LCRZO_ERR_OK )
  { lcrzo_er(lcrzo_ipc_write_hs(&ps->ipc, hs));
  }
  
  lcrzo_er(lcrzo_ipc_close(&ps->ipc));
  return(LCRZO_ERR_OK);
  /* just for the compiler warning */
  infossize=infossize;
  pparentprocess=pparentprocess;
}
int lcrzo_priv_hs_init_ipa_resolvalarm(const lcrzo_ipa ipa, lcrzo_hs hs);
int lcrzo_priv_hs_init_ipa_resolvalarm(const lcrzo_ipa ipa, lcrzo_hs hs)
{ lcrzo__priv_hs_init_ipa_resolvalarm_s hir;
  lcrzo_process child;
  lcrzo_time alarmtimeout;
  lcrzo_uint8 timeout;
  lcrzo_bool answerreceived;
  lcrzo_uint32 childret;
  int ret;

  /* initialize IPC communication */
  lcrzo_er(lcrzo_ipc_init(&hir.ipc));

  /* set child infos */
  memcpy(hir.ipa, ipa, LCRZO_IPA_MAXBYTES);

  /* create child */
  lcrzo_er(lcrzo_process_other_init(&lcrzo__priv_hs_init_ipa_resolvalarm,
				    (lcrzo_data)&hir, sizeof(hir), &child));
  lcrzo_er(lcrzo_ipc_currentprocessissidea(&hir.ipc));
  lcrzo_er(lcrzo_ipc_close_write(&hir.ipc));

  /* check if child gave us data */
  lcrzo_er(lcrzo_global_get_resolver_timeout(&timeout));
  lcrzo_er(lcrzo_time_init_sec(timeout, &alarmtimeout));
  answerreceived=LCRZO_FALSE;
  ret=lcrzo_ipc_read_uint32(&hir.ipc, &alarmtimeout, &childret);
  if (ret==LCRZO_ERR_OK)
  { if (childret==LCRZO_ERR_OK)
    { /* we have one second to read the ipa */ 
      lcrzo_er(lcrzo_time_init_sec(1, &alarmtimeout));
      ret=lcrzo_ipc_read_hs(&hir.ipc, &alarmtimeout, hs);
      if (ret==LCRZO_ERR_OK) answerreceived=LCRZO_TRUE; 
    }
  }
  lcrzo_er(lcrzo_ipc_close(&hir.ipc));

  /* may need to kill the child */
  lcrzo_er(lcrzo_process_other_exit(&child));
  /* always wait for the child */
  lcrzo_er(lcrzo_process_other_wait_end(&child, LCRZO_WAIT_INFINITE,
					NULL, NULL));

  /* return */
  if (answerreceived)
  { return(LCRZO_ERR_OK);
  }
  return(LCRZO_ERR_OKUNRESOLVED);
}


/*-------------------------------------------------------------*/
/* cette fonction envoie une requete arp sur le reseau, et sniffe
   la reponse*/
int lcrzo_priv_etha_init_ipa__spoofsniff(const lcrzo_device device, 
					 const lcrzo_ipa ipa, lcrzo_etha etha);
int lcrzo_priv_etha_init_ipa__spoofsniff(const lcrzo_device device, 
					 const lcrzo_ipa ipa, lcrzo_etha etha)
{ lcrzo_sniff sniff;
  lcrzo_spoof spoof;
  lcrzo_uint32 mtu;
  lcrzo_hdrleth hdrleth;
  lcrzo_hdrlarp hdrlarp, hdrlarprecu;
  lcrzo_etha ethaforcomp;
  lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool foundanswer;
  lcrzo_time currenttime, endtime, waitingtime;
  int ret, i;

  /*initialisation de l'entete ETH*/
  lcrzo_er(lcrzo_hdrleth_initdefault(&hdrleth));
  for ( i=0 ; i<LCRZO_ETHA_MAXBYTES ; i++ )
  { lcrzo_er(lcrzo_uint8_init_rand(1, 0xFE, &(ethaforcomp[i])));
  }
  lcrzo_er(lcrzo_priv_global_get_intspoof_eth(device, 
					      ethaforcomp, hdrleth.src));
  lcrzo_er(lcrzo_etha_init(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, hdrleth.dst));
  hdrleth.type=LCRZO_HDRLETH_TYPE_ARP;

  /*initialisation de l'entete ARP*/
  lcrzo_er(lcrzo_hdrlarp_initdefault(&hdrlarp));
  hdrlarp.op = 1;
  memcpy(hdrlarp.hw_src, hdrleth.src, LCRZO_ETHA_MAXBYTES);
  lcrzo_er(lcrzo_priv_global_get_intspoof_ip(device, 
					     ipa, hdrlarp.prot_src));
  lcrzo_er(lcrzo_etha_init(0,0,0,0,0,0, hdrlarp.hw_dst));
  memcpy(hdrlarp.prot_dst, ipa, LCRZO_IPA_MAXBYTES);
  
  /*initialisation du sniff*/
  lcrzo_er(lcrzo_mtu_init_device(device, &mtu));
  lcrzo_er(lcrzo_sniff_init(device, mtu, LCRZO_SNIFF_TYPE_NORMAL, "arp or rarp", &sniff));
  
  /*envoi de la requete arp*/
  lcrzo_er(lcrzo_spoof_init(&spoof));
  ret=lcrzo_spoof_etharp(&spoof, device, hdrleth, hdrlarp);
  if (ret!=LCRZO_ERR_OK)
  { lcrzo_er(lcrzo_sniff_close(&sniff));
    lcrzo_er(lcrzo_spoof_close(&spoof));
    return(LCRZO_ERR_OKUNRESOLVED);
  }
  lcrzo_er(lcrzo_spoof_close(&spoof));

  /* set ending time : we have one second to find the answer*/
  lcrzo_er(lcrzo_time_init_currenttime(&currenttime));
  lcrzo_er(lcrzo_time_plus_sec(&currenttime, 1, &endtime));

  /* main loop */
  foundanswer=LCRZO_FALSE;
  do 
  { /* determine new max waiting time */
    lcrzo_er(lcrzo_time_init_currenttime(&currenttime));
    ret=lcrzo_time_minus_time(&endtime, &currenttime, &waitingtime);
    if (ret==LCRZO_ERR_SPTIMEDIFFNEG) break;
    
    /* sniff */
    ret=lcrzo_sniff_nextm(&sniff, &waitingtime, &data, &datasize);
    if (ret!=LCRZO_ERR_OK) break;
    /*lcrzo_packet_print_eth(data, datasize, LCRZO_PRINTPROFILE_ARRAYDUMP);*/

    /*on voit si c'est la reponse attendue*/
    ret=lcrzo_packet_decode_etharp(data, datasize, NULL, &hdrlarprecu);
    lcrzo_data_free(data);
    if ( ret==LCRZO_ERR_OK && hdrlarprecu.op==2 )
    { if (lcrzo_ipa_equal(hdrlarprecu.prot_src, ipa))
      { /*on a trouve*/
        memcpy(etha, hdrlarprecu.hw_src, LCRZO_ETHA_MAXBYTES);
        foundanswer=LCRZO_TRUE;
        break;
      }
    }
  }
  while (!foundanswer);

  /*fermeture des contextes */
  lcrzo_sniff_close(&sniff);

  /* answer was found */
  if (foundanswer) return(LCRZO_ERR_OK);
  /*pas de reponse*/
  return(LCRZO_ERR_OKUNRESOLVED);
}
int lcrzo_priv_etha_init_ipa_spoofsniff(const lcrzo_ipa ipa, lcrzo_etha etha);
int lcrzo_priv_etha_init_ipa_spoofsniff(const lcrzo_ipa ipa, lcrzo_etha etha)
{ lcrzo_device device;
  int retour;
  lcrzo_int32 count, i;
  lcrzo_etha localetha;
  lcrzo_ipl ipl;

  /*on spoofe et sniffe tous les devices*/
  lcrzo_er(lcrzo_device_count(LCRZO_DEVICE_TYPE_ONLYBOARDS, &count));
  for ( i=1 ; i<=count ; i++ )
  { lcrzo_er(lcrzo_device_value_pos(LCRZO_DEVICE_TYPE_ONLYBOARDS, i, device));
    /*printf("demande sur le device=%s\n", device);*/
    retour=lcrzo_priv_etha_init_ipa__spoofsniff(device, ipa, localetha);
    if (retour==LCRZO_ERR_OK)
    { lcrzo_er(lcrzo_ipl_init_ipa(ipa, &ipl));
      lcrzo_er(lcrzo_priv_conf_arp_add_system(device, localetha, ipl, LCRZO_FALSE));
      if (etha!=NULL) memcpy(etha, localetha, LCRZO_ETHA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }

  /*adresse non resolue*/
  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_etha_init_ipa_conf(const lcrzo_ipa ipa, lcrzo_etha etha);
int lcrzo_priv_etha_init_ipa_conf(const lcrzo_ipa ipa, lcrzo_etha etha)
{ lcrzo_int32 count, i;
  lcrzo_ipl wantedipl, ipl;

  lcrzo_er(lcrzo_ipl_init_ipa(ipa, &wantedipl));
  lcrzo_er(lcrzo_conf_arp_count(&count));
  for ( i=1 ; i<=count ; i++ )
  { lcrzo_er(lcrzo_conf_arp_value_pos(i, NULL, etha, &ipl, NULL, NULL));
    if ( wantedipl == ipl )
    { return(LCRZO_ERR_OK);
    }
  } 
  /*adresse non resolue*/
  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_ipa_init_etha__spoofsniff(const lcrzo_device device, 
				    const lcrzo_etha etha, lcrzo_ipa ipa);
int lcrzo_priv_ipa_init_etha__spoofsniff(const lcrzo_device device, 
				    const lcrzo_etha etha, lcrzo_ipa ipa)
{ lcrzo_sniff sniff;
  lcrzo_spoof spoof;
  lcrzo_uint32 mtu;
  lcrzo_hdrleth hdrleth;
  lcrzo_hdrlarp hdrlarp, hdrlarprecu;
  lcrzo_ipa ipaforcomp;
  lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool foundanswer;
  lcrzo_time currenttime, endtime, waitingtime;
  int ret, i;

  /*initialisation de l'entete ETH*/
  lcrzo_er(lcrzo_hdrleth_initdefault(&hdrleth));
  lcrzo_er(lcrzo_priv_global_get_intspoof_eth(device, 
					      etha, hdrleth.src));
  lcrzo_er(lcrzo_etha_init(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, hdrleth.dst));
  hdrleth.type=LCRZO_HDRLETH_TYPE_ARP;

  /*initialisation de l'entete RARP*/
  lcrzo_er(lcrzo_hdrlarp_initdefault(&hdrlarp));
  hdrlarp.op = 3;
  memcpy(hdrlarp.hw_src, hdrleth.src, LCRZO_ETHA_MAXBYTES);
  for ( i=0 ; i<LCRZO_IPA_MAXBYTES ; i++ )
  { lcrzo_er(lcrzo_uint8_init_rand(1, 0xFE, &(ipaforcomp[i])));
  }
  lcrzo_er(lcrzo_priv_global_get_intspoof_ip(device, 
					     ipaforcomp, hdrlarp.prot_src));
  lcrzo_er(lcrzo_ipa_init(0,0,0,0, hdrlarp.prot_dst));
  memcpy(hdrlarp.hw_dst, etha, LCRZO_ETHA_MAXBYTES);

  /*initialisation du sniff*/
  lcrzo_er(lcrzo_mtu_init_device(device, &mtu));
  lcrzo_er(lcrzo_sniff_init(device, mtu, LCRZO_SNIFF_TYPE_NORMAL, "arp or rarp", &sniff));

  /*envoi de la requete rarp*/
  lcrzo_er(lcrzo_spoof_init(&spoof));
  ret=lcrzo_spoof_etharp(&spoof, device, hdrleth, hdrlarp);
  if (ret!=LCRZO_ERR_OK)
  { lcrzo_er(lcrzo_sniff_close(&sniff));
    lcrzo_er(lcrzo_spoof_close(&spoof));
    return(LCRZO_ERR_OKUNRESOLVED);
  }
  lcrzo_er(lcrzo_spoof_close(&spoof));

  /* set ending time : we have one second to find the answer*/
  lcrzo_er(lcrzo_time_init_currenttime(&currenttime));
  lcrzo_er(lcrzo_time_plus_sec(&currenttime, 1, &endtime));

  /* main loop */
  foundanswer=LCRZO_FALSE;
  do 
  { /* determine new max waiting time */
    lcrzo_er(lcrzo_time_init_currenttime(&currenttime));
    ret=lcrzo_time_minus_time(&endtime, &currenttime, &waitingtime);
    if (ret==LCRZO_ERR_SPTIMEDIFFNEG) break;
    
    /* sniff */
    ret=lcrzo_sniff_nextm(&sniff, &waitingtime, &data, &datasize);
    if (ret!=LCRZO_ERR_OK) break;
    /*lcrzo_packet_print_eth(data, datasize, LCRZO_PRINTPROFILE_ARRAYDUMP);*/

    /*on voit si c'est la reponse attendue*/
    ret=lcrzo_packet_decode_etharp(data, datasize, NULL, &hdrlarprecu);
    lcrzo_data_free(data);
    if ( ret==LCRZO_ERR_OK && hdrlarprecu.op==4 )
    { if (lcrzo_ipa_equal(hdrlarprecu.hw_dst, etha))
      { /*on a trouve*/
        memcpy(ipa, hdrlarprecu.prot_src, LCRZO_IPA_MAXBYTES);
        foundanswer=LCRZO_TRUE;
        break;
      }
    }
  }
  while (!foundanswer);

  /*fermeture des contextes */
  lcrzo_sniff_close(&sniff);

  /* answer was found */
  if (foundanswer) return(LCRZO_ERR_OK);
  /*pas de reponse*/
  return(LCRZO_ERR_OKUNRESOLVED);
}
int lcrzo_priv_ipa_init_etha_spoofsniff(const lcrzo_etha etha, lcrzo_ipa ipa);
int lcrzo_priv_ipa_init_etha_spoofsniff(const lcrzo_etha etha, lcrzo_ipa ipa)
{ lcrzo_device device;
  int retour;
  lcrzo_int32 count, i;
  lcrzo_ipa localipa;
  lcrzo_ipl ipl;

  lcrzo_er(lcrzo_device_count(LCRZO_DEVICE_TYPE_ONLYBOARDS, &count));
  for ( i=1 ; i<=count ; i++ )
  { lcrzo_er(lcrzo_device_value_pos(LCRZO_DEVICE_TYPE_ONLYBOARDS, i, device));
    retour=lcrzo_priv_ipa_init_etha__spoofsniff(device, etha, localipa);
    if (retour==LCRZO_ERR_OK)
    { lcrzo_er(lcrzo_ipl_init_ipa(localipa, &ipl));
      lcrzo_er(lcrzo_priv_conf_arp_add_system(device, etha, ipl, LCRZO_FALSE));
      if (ipa!=NULL) memcpy(ipa, localipa, LCRZO_IPA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }

  /*adresse non resolue*/
  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_ipa_init_etha_conf(const lcrzo_etha etha, lcrzo_ipa ipa);
int lcrzo_priv_ipa_init_etha_conf(const lcrzo_etha etha, lcrzo_ipa ipa)
{ lcrzo_int32 count, i;
  lcrzo_etha wantedetha;
  lcrzo_ipl ipl;

  lcrzo_er(lcrzo_conf_arp_count(&count));
  for ( i=1 ; i<=count ; i++ )
  { lcrzo_er(lcrzo_conf_arp_value_pos(i, NULL, wantedetha, &ipl, NULL, NULL));
    if ( lcrzo_etha_equal(etha, wantedetha) )
    { lcrzo_er(lcrzo_ipa_init_ipl(ipl, ipa));
      return(LCRZO_ERR_OK);
    }
  } 
  /*adresse non resolue*/
  return(LCRZO_ERR_OKUNRESOLVED);
}

/*-------------------------------------------------------------*/
/*conversions faisant appel a des sous fonctions ci-dessus*/

/*-------------------------------------------------------------*/
/*les 4 fonctions ci-dessous vont tenter de resoudre la requete
  en utilisant successivement les differentes methodes.*/
int lcrzo_ipa_init_hs(const lcrzo_hs hs, lcrzo_ipa ipa)
{ int retour;
  lcrzo_hs hs_copie;
  lcrzo_uint8 resolver_timeout;

  /* first, remove leading and ending spaces */
  lcrzo_er(lcrzo_string_init_coretext(hs, LCRZO_HS_MAXBYTES, hs_copie));

  /* special case because of Windows's resolver */
  if (strlen(hs_copie)==0)
  { return(LCRZO_ERR_OKUNRESOLVED);
  }

  /*on essaie ipa_init_ips*/
  retour=lcrzo_ipa_init_ips(hs_copie, ipa);
  if ( retour==LCRZO_ERR_OK ) return(LCRZO_ERR_OK);

  /* it did'nt work, so now we try the resolver */
  lcrzo_global_get_resolver_timeout(&resolver_timeout);
  if ( resolver_timeout )
  { retour=lcrzo_priv_ipa_init_hs_resolvalarm(hs_copie, ipa);
  }
  else
  { retour=lcrzo_priv_ipa_init_hs_resolver(hs_copie, ipa);
  }
  lcrzo_err_purge();
  if (retour==LCRZO_ERR_OK) return(LCRZO_ERR_OK);
  /*on n'a pas pu resoudre*/
  return(LCRZO_ERR_OKUNRESOLVED);
}

int lcrzo_hs_init_ipa(const lcrzo_ipa ipa, lcrzo_hs hs)
{ int retour;
  lcrzo_uint8 resolver_timeout;

  /*parameters verification*/
  if (ipa==NULL) return(LCRZO_ERR_PANULLPTR);

  /*on interroge le resolver*/
  lcrzo_global_get_resolver_timeout(&resolver_timeout);
  if ( resolver_timeout )
  { retour=lcrzo_priv_hs_init_ipa_resolvalarm(ipa, hs);
  }
  else
  { retour=lcrzo_priv_hs_init_ipa_resolver(ipa, hs);
  }
  lcrzo_err_purge();
  if (retour==LCRZO_ERR_OK) return(LCRZO_ERR_OK);
  /*on n'a pas pu resoudre*/
  return(LCRZO_ERR_OKUNRESOLVED);
}

#include "sysdep/lcrzo_priv_etha_init_ipa_ioctlarp.c"
#include "sysdep/lcrzo_priv_etha_init_ipa_etcethers.c"
#include "sysdep/lcrzo_priv_etha_init_ipa_iphlpapi.c"
int lcrzo_etha_init_ipa(const lcrzo_ipa ipa, lcrzo_etha etha)
{ int ret;
  lcrzo_etha localetha;

  /*parameters verification*/
  if (ipa==NULL) return(LCRZO_ERR_PANULLPTR);

  /*on interroge la conf locale*/
  ret=lcrzo_priv_etha_init_ipa_conf(ipa, localetha);
  if ( ret==LCRZO_ERR_OK )
  { if ( localetha[0] || localetha[1] || localetha[2] ||
	 localetha[3] || localetha[4] || localetha[5] )
    { lcrzo_err_purge();
      if (etha!=NULL) memcpy(etha, localetha, LCRZO_ETHA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }

  /*we ask ioctl*/
  ret=lcrzo_priv_etha_init_ipa_ioctlarp(ipa, localetha);
  if ( ret==LCRZO_ERR_OK )
  { if ( localetha[0] || localetha[1] || localetha[2] ||
	 localetha[3] || localetha[4] || localetha[5] )
    { lcrzo_err_purge();
      if (etha!=NULL) memcpy(etha, localetha, LCRZO_ETHA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }
    
  /*we ask /etc/ethers*/
  ret=lcrzo_priv_etha_init_ipa_etcethers(ipa, localetha);
  if ( ret==LCRZO_ERR_OK )
  { if ( localetha[0] || localetha[1] || localetha[2] ||
	 localetha[3] || localetha[4] || localetha[5] )
    { lcrzo_err_purge();
      if (etha!=NULL) memcpy(etha, localetha, LCRZO_ETHA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }
      
  /* ask IPHLPAPI (Windows) */
  ret=lcrzo_priv_etha_init_ipa_iphlpapi(ipa, localetha);
  if ( ret==LCRZO_ERR_OK )
  { if ( localetha[0] || localetha[1] || localetha[2] ||
	 localetha[3] || localetha[4] || localetha[5] )
    { lcrzo_err_purge();
      if (etha!=NULL) memcpy(etha, localetha, LCRZO_ETHA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }
        
  /* send an ARP request on the net */
  ret=lcrzo_priv_etha_init_ipa_spoofsniff(ipa, localetha);
  if ( ret==LCRZO_ERR_OK )
  { if ( localetha[0] || localetha[1] || localetha[2] ||
	 localetha[3] || localetha[4] || localetha[5] )
    { lcrzo_err_purge();
      if (etha!=NULL) memcpy(etha, localetha, LCRZO_ETHA_MAXBYTES);
      return(LCRZO_ERR_OK);
    }
  }

  /* could not resolve */
  return(LCRZO_ERR_OKUNRESOLVED);
}

#include "sysdep/lcrzo_priv_ipa_init_etha_ioctlrarp.c"
#include "sysdep/lcrzo_priv_ipa_init_etha_etcethers.c"
int lcrzo_ipa_init_etha(const lcrzo_etha etha, lcrzo_ipa ipa)
{ int retour;

  /*parameters verification*/
  if (etha==NULL) return(LCRZO_ERR_PANULLPTR);

  /*on interroge la conf locale*/
  retour=lcrzo_priv_ipa_init_etha_conf(etha, ipa);
  if (retour==LCRZO_ERR_OK) return(LCRZO_ERR_OK);
  /*we ask ioctl*/
  retour=lcrzo_priv_ipa_init_etha_ioctlrarp(etha, ipa);
  lcrzo_err_purge();
  if (retour==LCRZO_ERR_OK) return(LCRZO_ERR_OK);
  /*we ask /etc/ethers*/
  retour=lcrzo_priv_ipa_init_etha_etcethers(etha, ipa);
  lcrzo_err_purge();
  if (retour==LCRZO_ERR_OK) return(LCRZO_ERR_OK);
  /*on envoie une requete sur le reseau*/
  retour=lcrzo_priv_ipa_init_etha_spoofsniff(etha, ipa);
  lcrzo_err_purge();
  if (retour==LCRZO_ERR_OK) return(LCRZO_ERR_OK);
  /*l'adresse n'a pas pu etre resolue*/
  return(LCRZO_ERR_OKUNRESOLVED);
}


/*-------------------------------------------------------------*/
/*conversions faisant appel a des intermediaires*/

/*-------------------------------------------------------------*/
int lcrzo_ips_init_hs(const lcrzo_hs hs, lcrzo_ips ips)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_hs(hs, ipa));
  lcrzo_er(lcrzo_ips_init_ipa(ipa, ips));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipl_init_hs(const lcrzo_hs hs, lcrzo_ipl *pipl)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_hs(hs, ipa));
  lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_eths_init_hs(const lcrzo_hs hs, lcrzo_eths eths)
{ lcrzo_etha etha;

  lcrzo_er(lcrzo_etha_init_hs(hs, etha));
  lcrzo_er(lcrzo_eths_init_etha(etha, eths));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_etha_init_hs(const lcrzo_hs hs, lcrzo_etha etha)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_hs(hs, ipa));
  lcrzo_er(lcrzo_etha_init_ipa(ipa, etha));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hs_init_ips(const lcrzo_ips ips, lcrzo_hs hs)
{ lcrzo_etha ipa;

  lcrzo_er(lcrzo_ipa_init_ips(ips, ipa));
  lcrzo_er(lcrzo_hs_init_ipa(ipa, hs));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_eths_init_ips(const lcrzo_ips ips, lcrzo_eths eths)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_ips(ips, ipa));
  lcrzo_er(lcrzo_eths_init_ipa(ipa, eths));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_etha_init_ips(const lcrzo_ips ips, lcrzo_etha etha)
{ lcrzo_etha ipa;

  lcrzo_er(lcrzo_ipa_init_ips(ips, ipa));
  lcrzo_er(lcrzo_etha_init_ipa(ipa, etha));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_eths_init_ipa(const lcrzo_ipa ipa, lcrzo_eths eths)
{ lcrzo_etha etha;

  lcrzo_er(lcrzo_etha_init_ipa(ipa, etha));
  lcrzo_er(lcrzo_eths_init_etha(etha, eths));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hs_init_ipl(lcrzo_ipl ipl, lcrzo_hs hs)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_ipl(ipl, ipa));
  lcrzo_er(lcrzo_hs_init_ipa(ipa, hs));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_eths_init_ipl(lcrzo_ipl ipl, lcrzo_eths eths)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_ipl(ipl, ipa));
  lcrzo_er(lcrzo_eths_init_ipa(ipa, eths));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_etha_init_ipl(lcrzo_ipl ipl, lcrzo_etha etha)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_ipl(ipl, ipa));
  lcrzo_er(lcrzo_etha_init_ipa(ipa, etha));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hs_init_eths(const lcrzo_eths eths, lcrzo_hs hs)
{ lcrzo_etha etha;

  lcrzo_er(lcrzo_etha_init_eths(eths, etha));
  lcrzo_er(lcrzo_hs_init_etha(etha, hs));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ips_init_eths(const lcrzo_eths eths, lcrzo_ips ips)
{ lcrzo_etha etha;

  lcrzo_er(lcrzo_etha_init_eths(eths, etha));
  lcrzo_er(lcrzo_ips_init_etha(etha, ips));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipa_init_eths(const lcrzo_eths eths, lcrzo_ipa ipa)
{ lcrzo_etha etha;

  lcrzo_er(lcrzo_etha_init_eths(eths, etha));
  lcrzo_er(lcrzo_ipa_init_etha(etha, ipa));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipl_init_eths(const lcrzo_eths eths, lcrzo_ipl *pipl)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_eths(eths, ipa));
  lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hs_init_etha(const lcrzo_etha etha, lcrzo_hs hs)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_etha(etha, ipa));
  lcrzo_er(lcrzo_hs_init_ipa(ipa, hs));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ips_init_etha(const lcrzo_etha etha, lcrzo_ips ips)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_etha(etha, ipa));
  lcrzo_er(lcrzo_ips_init_ipa(ipa, ips));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipl_init_etha(const lcrzo_etha etha, lcrzo_ipl *pipl)
{ lcrzo_ipa ipa;

  lcrzo_er(lcrzo_ipa_init_etha(etha, ipa));
  lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
lcrzo_bool lcrzo_hs_equal(const lcrzo_hs hs1, const lcrzo_hs hs2)
{ int ret;
  lcrzo_hs h1, h2;
  lcrzo_ipl ipl1, ipl2;

  /* for hostname comparison, if hs1/hs2 have the correct size and
     are equal, we suppose it's ok, and do not lost time comparing
     their IP addresses.
  */
  ret=lcrzo_string_init_coretext(hs1, LCRZO_HS_MAXBYTES, h1);
  if (ret!=LCRZO_ERR_OK) return(0);
  ret=lcrzo_string_init_coretext(hs2, LCRZO_HS_MAXBYTES, h2);
  if (ret!=LCRZO_ERR_OK) return(0);
  if (!strcmp(h1, h2)) return(1);

  /* strings are not equal, so we spend time comparing IP addresses */
  ret=lcrzo_ipl_init_hs(h1, &ipl1);
  if (ret!=LCRZO_ERR_OK) return(0);
  ret=lcrzo_ipl_init_hs(h2, &ipl2);
  if (ret!=LCRZO_ERR_OK) return(0);

  return(lcrzo_ipl_equal(ipl1, ipl2));
}

/*-------------------------------------------------------------*/
lcrzo_int8 lcrzo_hs_cmp(const lcrzo_hs hs1, const lcrzo_hs hs2)
{ int ret;
  lcrzo_hs h1, h2;
  lcrzo_ipl ipl1, ipl2;

  /* for hostname comparison, if hs1/hs2 have the correct size and
     are equal, we suppose it's ok, and do not lost time comparing
     their IP addresses.
  */
  ret=lcrzo_string_init_coretext(hs1, LCRZO_HS_MAXBYTES, h1);
  if (ret!=LCRZO_ERR_OK) return(2);
  ret=lcrzo_string_init_coretext(hs2, LCRZO_HS_MAXBYTES, h2);
  if (ret!=LCRZO_ERR_OK) return(2);
  if (!strcmp(h1, h2)) return(0);

  /* strings are not equal, so we spend time comparing IP addresses */
  ret=lcrzo_ipl_init_hs(h1, &ipl1);
  if (ret!=LCRZO_ERR_OK) return(2);
  ret=lcrzo_ipl_init_hs(h2, &ipl2);
  if (ret!=LCRZO_ERR_OK) return(2);

  return(lcrzo_ipl_cmp(ipl1, ipl2));
}

/*-------------------------------------------------------------*/
lcrzo_bool lcrzo_ips_equal(const lcrzo_ips ips1, const lcrzo_ips ips2)
{ int ret;
  lcrzo_ipl ipl1, ipl2;

  /* for ips comparison, ips must be valid */
  ret=lcrzo_ipl_init_ips(ips1, &ipl1);
  if (ret!=LCRZO_ERR_OK) return(0);
  ret=lcrzo_ipl_init_ips(ips2, &ipl2);
  if (ret!=LCRZO_ERR_OK) return(0);

  return(lcrzo_ipl_equal(ipl1, ipl2));
}

/*-------------------------------------------------------------*/
lcrzo_int8 lcrzo_ips_cmp(const lcrzo_ips ips1, const lcrzo_ips ips2)
{ int ret;
  lcrzo_ipl ipl1, ipl2;

  /* for ips comparison, ips must be valid */
  ret=lcrzo_ipl_init_ips(ips1, &ipl1);
  if (ret!=LCRZO_ERR_OK) return(2);
  ret=lcrzo_ipl_init_ips(ips2, &ipl2);
  if (ret!=LCRZO_ERR_OK) return(2);

  return(lcrzo_ipl_cmp(ipl1, ipl2));
}

/*-------------------------------------------------------------*/
lcrzo_bool lcrzo_ipa_equal(const lcrzo_ipa ipa1, const lcrzo_ipa ipa2)
{ lcrzo_bool ret;
  /*parameters verification*/
  if (ipa1==NULL) return(LCRZO_FALSE);
  if (ipa2==NULL) return(LCRZO_FALSE);
  if (memcmp((const void*)ipa1, (const void*)ipa2, LCRZO_IPA_MAXBYTES))
    ret=LCRZO_FALSE;
  else
    ret=LCRZO_TRUE;
  return(ret);
}

/*-------------------------------------------------------------*/
lcrzo_int8 lcrzo_ipa_cmp(const lcrzo_ipa ipa1, const lcrzo_ipa ipa2)
{ 
  /*parameters verification*/
  if (ipa1==NULL) return(2);
  if (ipa2==NULL) return(2);

  if ( ipa1[0]<ipa2[0] ) return(-1);
  else if ( ipa1[0]>ipa2[0] ) return(+1);
  else
  { if ( ipa1[1]<ipa2[1] ) return(-1);
    else if ( ipa1[1]>ipa2[1] ) return(+1);
    else
    { if ( ipa1[2]<ipa2[2] ) return(-1);
      else if ( ipa1[2]>ipa2[2] ) return(+1);
      else
      { if ( ipa1[3]<ipa2[3] ) return(-1);
        else if ( ipa1[3]>ipa2[3] ) return(+1);
        else return(0);
      }
    }
  }
}

/*-------------------------------------------------------------*/
lcrzo_bool lcrzo_ipl_equal(lcrzo_ipl ipl1, lcrzo_ipl ipl2)
{
  if (ipl1==ipl2) return(1);
  else return(0);
}

/*-------------------------------------------------------------*/
lcrzo_int8 lcrzo_ipl_cmp(lcrzo_ipl ipl1, lcrzo_ipl ipl2)
{ if (ipl1<ipl2) return(-1);
  else if (ipl1>ipl2) return(+1);
  else return(0);
}

/*-------------------------------------------------------------*/
lcrzo_bool lcrzo_eths_equal(const lcrzo_eths eths1, const lcrzo_eths eths2)
{ int ret;
  lcrzo_etha etha1, etha2;

  /* for eths comparison, eths must be valid */
  ret=lcrzo_etha_init_eths(eths1, etha1);
  if (ret!=LCRZO_ERR_OK) return(0);
  ret=lcrzo_etha_init_eths(eths2, etha2);
  if (ret!=LCRZO_ERR_OK) return(0);

  return(lcrzo_etha_equal(etha1, etha2));
}

/*-------------------------------------------------------------*/
lcrzo_int8 lcrzo_eths_cmp(const lcrzo_eths eths1, const lcrzo_eths eths2)
{ int ret;
  lcrzo_etha etha1, etha2;

  /* for eths comparison, eths must be valid */
  ret=lcrzo_etha_init_eths(eths1, etha1);
  if (ret!=LCRZO_ERR_OK) return(2);
  ret=lcrzo_etha_init_eths(eths2, etha2);
  if (ret!=LCRZO_ERR_OK) return(2);

  return(lcrzo_etha_cmp(etha1, etha2));
}

/*-------------------------------------------------------------*/
lcrzo_bool lcrzo_etha_equal(const lcrzo_etha etha1, const lcrzo_etha etha2)
{ lcrzo_bool ret;
  /*parameters verification*/
  if (etha1==NULL) return(0);
  if (etha2==NULL) return(0);
  if (memcmp((const void*)etha1, (const void*)etha2, LCRZO_ETHA_MAXBYTES))
    ret=LCRZO_FALSE;
  else
    ret=LCRZO_TRUE;
  return(ret);
}

/*-------------------------------------------------------------*/
lcrzo_int8 lcrzo_etha_cmp(const lcrzo_etha etha1, const lcrzo_etha etha2)
{
  /*parameters verification*/
  if (etha1==NULL) return(2);
  if (etha2==NULL) return(2);

  if ( etha1[0]<etha2[0] ) return(-1);
  else if ( etha1[0]>etha2[0] ) return(+1);
  else
  { if ( etha1[1]<etha2[1] ) return(-1);
    else if ( etha1[1]>etha2[1] ) return(+1);
    else
    { if ( etha1[2]<etha2[2] ) return(-1);
      else if ( etha1[2]>etha2[2] ) return(+1);
      else
      { if ( etha1[3]<etha2[3] ) return(-1);
        else if ( etha1[3]>etha2[3] ) return(+1);
        else
        { if ( etha1[4]<etha2[4] ) return(-1);
          else if ( etha1[4]>etha2[4] ) return(+1);
          else
          { if ( etha1[5]<etha2[5] ) return(-1);
            else if ( etha1[5]>etha2[5] ) return(+1);
            else return(0);
          }
        }
      }
    }
  }
}

/*-------------------------------------------------------------*/
int lcrzo_hs_initdefault(lcrzo_hs hs)
{ if (hs!=NULL) hs[0]='\0';
  return(LCRZO_ERR_OK);
}
int lcrzo_ips_initdefault(lcrzo_ips ips)
{ if (ips!=NULL) ips[0]='\0';
  return(LCRZO_ERR_OK);
}
int lcrzo_ipa_initdefault(lcrzo_ipa ipa)
{ int i;
  if (ipa!=NULL)
  { for (i=0;i<LCRZO_IPA_MAXBYTES;i++) ipa[i]=0;
  }
  return(LCRZO_ERR_OK);
}
int lcrzo_ipl_initdefault(lcrzo_ipl *pipl)
{ if (pipl!=NULL) *pipl=0;
  return(LCRZO_ERR_OK);
}
int lcrzo_eths_initdefault(lcrzo_eths eths)
{ if (eths!=NULL) eths[0]='\0';
  return(LCRZO_ERR_OK);
}
int lcrzo_etha_initdefault(lcrzo_etha etha)
{ int i;
  if (etha!=NULL) 
  { for (i=0;i<LCRZO_ETHA_MAXBYTES;i++) etha[i]=0;
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_hs_init_stdin(const char *message,
			lcrzo_consths hsdefaut, 
			lcrzo_hs hs)
{ char prompt;
  lcrzo_string usertext;
  lcrzo_bool hsdefautisvalid;
  int ret;

  /*parameters verification*/
  hsdefautisvalid=LCRZO_FALSE;
  if (hsdefaut!=NULL)
  { if (strlen(hsdefaut))
    { ret=lcrzo_ipa_init_hs(hsdefaut, NULL);
      if (ret==LCRZO_ERR_OK)
      { hsdefautisvalid=LCRZO_TRUE;
      }
    }
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0')
    { printf("%s ", message);
      if (hsdefautisvalid) printf("[%s]", hsdefaut);
      printf("%c ", prompt);
    }
    prompt='>';
    /*saisie de la chaine de l'utilisateur*/
    lcrzo_er(lcrzo_priv_stdin(&usertext, NULL));
    /*si rien n'a ete entre, on met le defaut*/
    if (strlen(usertext)==0 && hsdefautisvalid)
    { lcrzo_string_free(usertext);
      lcrzo_er(lcrzo_hs_init_hs(hsdefaut, hs));
      /*si les tentatives precedentes etaient en erreur
	on est oblige de mettre a zero ici car on ne
	passe plus dans lcrzo_ipa_init_hs()*/
      lcrzo_err_purge();
      break;
    }
    /*conversion de hs en ipa*/
    ret=lcrzo_ipa_init_hs(usertext, NULL);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_hs_init_hs(usertext, hs);
    }
    lcrzo_string_free(usertext);
    lcrzo_err_purge();
    if (ret==LCRZO_ERR_OK) break;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipa_init_stdin(const char *message,
			 lcrzo_consths hsdefaut, 
			 lcrzo_ipa ipa)
{ char prompt;
  lcrzo_ipa ipadefaut;
  lcrzo_string usertext;
  lcrzo_bool hsdefautisvalid;
  int ret;

  /*parameters verification*/
  hsdefautisvalid=LCRZO_FALSE;
  if (hsdefaut!=NULL)
  { if (strlen(hsdefaut))
    { ret=lcrzo_ipa_init_hs(hsdefaut, ipadefaut);
      if (ret==LCRZO_ERR_OK)
      { hsdefautisvalid=LCRZO_TRUE;
      }
    }
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0')
    { printf("%s ", message);
      if (hsdefautisvalid) printf("[%s]", hsdefaut);
      printf("%c ", prompt);
    }
    prompt='>';
    /*saisie de la chaine de l'utilisateur*/
    lcrzo_er(lcrzo_priv_stdin(&usertext, NULL));
    /*si rien n'a ete entre, on met le defaut*/
    if (strlen(usertext)==0 && hsdefautisvalid)
    { lcrzo_string_free(usertext);
      if (ipa!=NULL) memcpy(ipa, ipadefaut, LCRZO_IPA_MAXBYTES);
      /*si les tentatives precedentes etaient en erreur
	on est oblige de mettre a zero ici car on ne
	passe plus dans lcrzo_ipa_init_hs()*/
      lcrzo_err_purge();
      break;
    }
    /*conversion de hs en ipa*/
    ret=lcrzo_ipa_init_hs(usertext, ipa);
    lcrzo_string_free(usertext);
    lcrzo_err_purge();
    if (ret==LCRZO_ERR_OK) break;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ipl_init_stdin(const char *message,
			 lcrzo_consths hsdefaut, 
			 lcrzo_ipl *pipl)
{ lcrzo_ipa ipa;
  lcrzo_er(lcrzo_ipa_init_stdin(message, hsdefaut, ipa));
  lcrzo_er(lcrzo_ipl_init_ipa(ipa, pipl));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ips_init_stdin(const char *message,
			 lcrzo_consths hsdefaut, 
			 lcrzo_ips ips)
{ lcrzo_ipa ipa;
  lcrzo_er(lcrzo_ipa_init_stdin(message, hsdefaut, ipa));
  lcrzo_er(lcrzo_ips_init_ipa(ipa, ips));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_etha_init_stdin(const char *message,
			  lcrzo_consteths ethsdefaut, 
			  lcrzo_etha etha)
{ char prompt;
  lcrzo_etha ethadefaut;
  lcrzo_string usertext;
  lcrzo_bool ethsdefautisvalid;
  int ret;

  /*parameters verification*/
  ethsdefautisvalid=LCRZO_FALSE;
  if (ethsdefaut!=NULL)
  { if (strlen(ethsdefaut))
    { ret=lcrzo_etha_init_eths(ethsdefaut, ethadefaut);
      if (ret==LCRZO_ERR_OK)
      { ethsdefautisvalid=LCRZO_TRUE;
      }
    }
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0')
    { printf("%s ", message);
      if (ethsdefautisvalid) printf("[%s]", ethsdefaut);
      printf("%c ", prompt);
    }
    prompt='>';
    /*saisie de la chaine de l'utilisateur*/
    lcrzo_er(lcrzo_priv_stdin(&usertext, NULL));
    /*si rien n'a ete entre, on met le defaut*/
    if (strlen(usertext)==0 && ethsdefautisvalid)
    { lcrzo_string_free(usertext);
      if (etha!=NULL) memcpy(etha, ethadefaut, LCRZO_ETHA_MAXBYTES);
      /*si les tentatives precedentes etaient en erreur
        on est oblige de mettre a zero ici car on ne
        passe plus dans lcrzo_ipa_init_hs()*/
      lcrzo_err_purge();
      break;
    }
    /*conversion de eths en etha*/
    ret=lcrzo_etha_init_eths(usertext, etha);
    lcrzo_string_free(usertext);
    lcrzo_err_purge();
    if (ret==LCRZO_ERR_OK) break;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_eths_init_stdin(const char *message,
			  lcrzo_consteths ethsdefaut, 
			  lcrzo_eths eths)
{ lcrzo_etha etha;
  lcrzo_er(lcrzo_etha_init_stdin(message, ethsdefaut, etha));
  lcrzo_er(lcrzo_eths_init_etha(etha, eths));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_str2int(char *str, lcrzo_uint32 maxi,
			int chainevideautorisee, lcrzo_uint32 valeursivide,
			int coderr, lcrzo_uint32 *pint);
int lcrzo_priv_str2int(char *str, lcrzo_uint32 maxi,
			int chainevideautorisee, lcrzo_uint32 valeursivide,
			int coderr, lcrzo_uint32 *pint)
{ char *pc;
  lcrzo_uint32 nb;

  if ( strlen(str)==0 )
  { if (chainevideautorisee)
    { *pint=valeursivide;
      return(LCRZO_ERR_OK);
    }
    else return(coderr);
  }
  nb=strtoul(str, &pc, 10);
  if ( *pc != '\0' ) return(coderr);
  if ( nb > maxi ) return(coderr);
  *pint=nb;
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_etha_init_ethrange(const lcrzo_ethrange plage,
		       lcrzo_etha ethainf,
		       lcrzo_etha ethasup)
{ int poscarac, retour, type, i, doitplusavoirzero;
  lcrzo_uint32 nbbitsmasque;
  lcrzo_ethrange plagepurge, gauche, droite;
  char *pc;
  lcrzo_etha ethinf, ethsup, masque, ethinfandmasque;

  /*verifie la plage entree*/
  lcrzo_er(lcrzo_string_init_coretext(plage, LCRZO_ETHRANGE_MAXBYTES,
				   plagepurge));
  if (strlen(plagepurge)>LCRZO_ETHRANGE_MAXBYTES)
    return(LCRZO_ERR_PAOVERFLOW);

  /*cherche d'abord une adresse eth seule "a:b:c:d:e:f"*/
  retour=lcrzo_etha_init_eths(plagepurge, ethinf);
  if (retour==LCRZO_ERR_OK)
  { if (ethainf!=NULL) memcpy(ethainf, ethinf, LCRZO_ETHA_MAXBYTES);
    if (ethasup!=NULL) memcpy(ethasup, ethinf, LCRZO_ETHA_MAXBYTES);
    return(LCRZO_ERR_OK);
  }

  /*les autres plages doivent contenir -, / ou %*/
  type=0;
  poscarac=0; /*pour faire plaisir au compilateur*/
  pc=strchr(plagepurge, '-'); if (pc!=NULL) { type=1; poscarac=pc-plagepurge; }
  pc=strchr(plagepurge, '/'); if (pc!=NULL) { type=2; poscarac=pc-plagepurge; }
  pc=strchr(plagepurge, '%'); if (pc!=NULL) { type=3; poscarac=pc-plagepurge; }
  if (!type) goto lcrzo_etha_init_ethrange_g;

  /*on scinde la chaine en 2*/
  lcrzo_er(lcrzo_string_init_text(plagepurge, LCRZO_ETHRANGE_MAXBYTES, gauche));
  gauche[poscarac]='\0';
  lcrzo_er(lcrzo_string_init_text(plagepurge+poscarac+1,
			     LCRZO_ETHRANGE_MAXBYTES, droite));

  /*on cherche maintenant une adresse de la forme "1:2:3:4:5:6-a:b:c:d:e:f"*/
  if ( type==1 )
  { retour=lcrzo_etha_init_eths(gauche, ethinf);
    if (retour==LCRZO_ERR_OK)
    { retour=lcrzo_etha_init_eths(droite, ethsup);
      if (retour==LCRZO_ERR_OK)
      { if (lcrzo_etha_cmp(ethinf, ethsup)==1)
	  return(LCRZO_ERR_PAINFHIGHERSUP);
        if (ethainf!=NULL) memcpy(ethainf, ethinf, LCRZO_ETHA_MAXBYTES);
	if (ethasup!=NULL) memcpy(ethasup, ethsup, LCRZO_ETHA_MAXBYTES);
	return(LCRZO_ERR_OK);
      }
    } 
    goto lcrzo_etha_init_ethrange_g;
  }

  /*pour les autres types, gauche doit etre un eths, ou un fragment d'eths*/
  i=0;
  do
  { retour=lcrzo_etha_init_eths(gauche, ethinf);
    i++;
    lcrzo_er(lcrzo_string_append_char(':', 1,LCRZO_ETHRANGE_MAXBYTES, gauche));
    lcrzo_er(lcrzo_string_append_char('0', 1,LCRZO_ETHRANGE_MAXBYTES, gauche));
  } while ( retour!=LCRZO_ERR_OK && i<LCRZO_ETHA_MAXBYTES );
  if ( retour!=LCRZO_ERR_OK ) goto lcrzo_etha_init_ethrange_g;
  /*ethinf contient maintenant la partie de gauche*/

  /*a droite, il doit y avoir soit un entier, soit un masque*/ 
  retour=lcrzo_priv_str2int(droite, 48, 0, 0,
			     LCRZO_ERR_FMETHRANGE, &nbbitsmasque);
  if (retour!=LCRZO_ERR_OK)
  { /*il doit donc y avoir un "FF:FF:0:0:0:0"*/
    retour=lcrzo_etha_init_eths(droite, ethsup);
    if (retour!=LCRZO_ERR_OK) goto lcrzo_etha_init_ethrange_g;
    /*on verifie que ipsup est bien un masque*/
    nbbitsmasque=48;
    doitplusavoirzero=0;
    for ( i=0 ; i<48 ; i++ )
    { if ( !(ethsup[LCRZO_ETHA_MAXBYTES-1]&1) )
      { if (!doitplusavoirzero)
          nbbitsmasque--;
        else
	  goto lcrzo_etha_init_ethrange_g;
      }
      else
      { doitplusavoirzero=1;
      }
      lcrzo_priv_etha_shr(ethsup, ethsup);
    }
  }
  /*nbbitsmasque contient maintenant le nb de bits du masque*/

  /*calcul du masque a partir de nbbitsmasque*/
  lcrzo_etha_init(0,0,0,0,0,0, masque);
  for ( i=0 ; i<48-(int)nbbitsmasque ; i++ )
  { lcrzo_priv_etha_shl(masque, masque);
    masque[LCRZO_ETHA_MAXBYTES-1]=(lcrzo_uint8)(masque[LCRZO_ETHA_MAXBYTES-1]
						| 1);
  }
  /*masque doit maintenant contenir 0b0000000...00000111111111111*/

  /*on verifie la coherence entre ethinf et nbbitsmasque*/
  lcrzo_priv_etha_and(ethinf, masque, ethinfandmasque);
  if ( ethinfandmasque[0] | ethinfandmasque[1] | ethinfandmasque[2] |
       ethinfandmasque[3] | ethinfandmasque[4] | ethinfandmasque[5] )
  { goto lcrzo_etha_init_ethrange_g;
  }

  /*affecte le resultat*/
  lcrzo_priv_etha_or(ethinf, masque, ethsup);
  if (type==2)
  { if (ethainf!=NULL) memcpy(ethainf, ethinf, LCRZO_ETHA_MAXBYTES);
    if (ethasup!=NULL) memcpy(ethasup, ethsup, LCRZO_ETHA_MAXBYTES);
  }
  else 
  { /* xx%47 et xx%48 sont invalides*/
    if (nbbitsmasque>=47) goto lcrzo_etha_init_ethrange_g; 
    if (ethainf!=NULL) lcrzo_priv_etha_inc(ethinf, ethainf);
    if (ethasup!=NULL) lcrzo_priv_etha_dec(ethsup, ethasup);
  }
  return(LCRZO_ERR_OK);
 lcrzo_etha_init_ethrange_g:
  lcrzo_priv_global_set_errmsglcrzo_range(plage);
  return(LCRZO_ERR_FMETHRANGE);
}

/*-------------------------------------------------------------*/
int lcrzo_ethrange_init_etha(lcrzo_etha ethainf,
		       lcrzo_etha ethasup,
		       lcrzo_ethrange plage)
{ lcrzo_etha masque, tmp, zero, masqueandethainf, notmasqueorethainf;
  lcrzo_etha ethainfmoinsun, ethasupplusun;
  int i;

  /*parameters verification*/
  if (ethainf==NULL) return(LCRZO_ERR_PANULLPTR);
  if (ethasup==NULL) return(LCRZO_ERR_PANULLPTR);

  if (lcrzo_etha_cmp(ethainf, ethasup)==1)
  { return(LCRZO_ERR_PAINFHIGHERSUP);
  }
  else if (lcrzo_etha_equal(ethainf, ethasup)) 
  { lcrzo_er(lcrzo_eths_init_etha(ethainf, plage));
  }
  else
  { /*we should never encounter an error, so we can stop now, if we do not
    need to compute "plage".*/
    if (plage==NULL) return(LCRZO_ERR_OK);
    /*on tente d'abord un affichage du type "x:x:x:x:x:x/y" */
    lcrzo_priv_etha_xor(ethainf, ethasup, tmp);
    lcrzo_etha_init(0,0,0,0,0,0, zero);
    lcrzo_etha_init(0,0,0,0,0,0, masque);
    i=48;
    while(!lcrzo_etha_equal(tmp, zero))
    { lcrzo_priv_etha_shr(tmp, tmp);
      lcrzo_priv_etha_shl(masque, masque);
      masque[LCRZO_ETHA_MAXBYTES-1]=(lcrzo_uint8)(masque[LCRZO_ETHA_MAXBYTES
							-1] | 1 );
      i--;
    }
    lcrzo_priv_etha_not(masque, masque);
    /*masque doit maintenant contenir 0b111111111111...1111110000*/
    lcrzo_priv_etha_and(masque, ethainf, masqueandethainf);
    lcrzo_priv_etha_not(masque, tmp);
    lcrzo_priv_etha_or(tmp, ethainf, notmasqueorethainf);
    if ( lcrzo_etha_equal(masqueandethainf, ethainf) &&
	 lcrzo_etha_equal(notmasqueorethainf, ethasup) )
    { /*il s'agit d'un intervalle correct*/
      lcrzo_er(lcrzo_eths_init_etha(ethainf, plage));
      lcrzo_er(lcrzo_string_append_char('/', 1,LCRZO_ETHRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_string_append_int(i, "%d", LCRZO_ETHRANGE_MAXBYTES, plage));
      return(LCRZO_ERR_OK);
    }
    lcrzo_priv_etha_dec(ethainf, ethainfmoinsun);
    lcrzo_priv_etha_inc(ethasup, ethasupplusun);
    if ( lcrzo_etha_equal(masqueandethainf, ethainfmoinsun) &&
	 lcrzo_etha_equal(notmasqueorethainf, ethasupplusun) )
    { /*il s'agit d'un intervalle correct, sans les broadcast*/
      lcrzo_er(lcrzo_eths_init_etha(ethainfmoinsun, plage));
      lcrzo_er(lcrzo_string_append_char('%', 1, LCRZO_ETHRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_string_append_int(i, "%d", LCRZO_ETHRANGE_MAXBYTES, plage));
    }
    else
    { lcrzo_er(lcrzo_eths_init_etha(ethainf, plage));
      lcrzo_er(lcrzo_string_append_char('-', 1, LCRZO_ETHRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_eths_init_etha(ethasup, plage+strlen(plage)));
    }
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_ipl_init_iprange(const lcrzo_iprange plage,
				lcrzo_ipl *piplinf,
				lcrzo_ipl *piplsup);
int lcrzo_priv_ipl_init_iprange(const lcrzo_iprange plage,
				lcrzo_ipl *piplinf,
				lcrzo_ipl *piplsup)
{ int poscarac, retour, type, i, doitplusavoirzero;
  lcrzo_uint32 nbbitsmasque, masque;
  lcrzo_iprange plagepurge, gauche, droite;
  char *pc;
  lcrzo_ipl ipinf, ipsup;

  /* clean input */
  lcrzo_er(lcrzo_string_init_coretext(plage, LCRZO_IPRANGE_MAXBYTES, 
				      plagepurge));
  if (strlen(plagepurge)>LCRZO_IPRANGE_MAXBYTES)
    return(LCRZO_ERR_PAOVERFLOW);

  /*cherche d'abord une adresse IP seule "1.2.3.4"*/
  retour=lcrzo_ipl_init_ips(plagepurge, &ipinf);
  if (retour==LCRZO_ERR_OK)
  { if (piplinf!=NULL) *piplinf=ipinf;
    if (piplsup!=NULL) *piplsup=ipinf;
    return(LCRZO_ERR_OK);
  }

  /*les autres plages doivent contenir -, / ou %*/
  type=0;
  poscarac=0; /*pour faire plaisir au compilateur*/
  pc=strchr(plagepurge, '-'); if (pc!=NULL) { type=1; poscarac=pc-plagepurge; }
  pc=strchr(plagepurge, '/'); if (pc!=NULL) { type=2; poscarac=pc-plagepurge; }
  pc=strchr(plagepurge, '%'); if (pc!=NULL) { type=3; poscarac=pc-plagepurge; }
  if (!type) return(LCRZO_ERR_FMIPRANGE);

  /*on scinde la chaine en 2*/
  lcrzo_er(lcrzo_string_init_text(plagepurge, LCRZO_IPRANGE_MAXBYTES, gauche));
  gauche[poscarac]='\0';
  lcrzo_er(lcrzo_string_init_text(plagepurge+poscarac+1,
			     LCRZO_IPRANGE_MAXBYTES, droite));

  /*on cherche maintenant une adresse de la forme "1.2.3.4-5.6.7.8"*/
  if ( type==1 )
  { retour=lcrzo_ipl_init_ips(gauche, &ipinf);
    if (retour==LCRZO_ERR_OK)
    { retour=lcrzo_ipl_init_ips(droite, &ipsup);
      if (retour==LCRZO_ERR_OK)
      { if (ipsup<ipinf) return(LCRZO_ERR_PAINFHIGHERSUP);
        if (piplinf!=NULL) *piplinf=ipinf;
        if (piplsup!=NULL) *piplsup=ipsup;
	return(LCRZO_ERR_OK);
      }
    }
    return(LCRZO_ERR_FMIPRANGE);
  }

  /*pour les autres types, gauche doit etre un ips, ou un fragment d'ips*/
  i=0;
  do
  { retour=lcrzo_ipl_init_ips(gauche, &ipinf);
    i++;
    lcrzo_er(lcrzo_string_append_char('.', 1, LCRZO_IPRANGE_MAXBYTES, gauche));
    lcrzo_er(lcrzo_string_append_char('0', 1, LCRZO_IPRANGE_MAXBYTES, gauche));
  } while ( retour!=LCRZO_ERR_OK && i<=3 );
  if ( retour!=LCRZO_ERR_OK ) return(LCRZO_ERR_FMIPRANGE);
  /*ipinf contient maintenant la partie de gauche*/

  /*a droite, il doit y avoir soit un entier, soit un masque*/ 
  retour=lcrzo_priv_str2int(droite, 32, 0, 0,
			     LCRZO_ERR_FMIPRANGE, &nbbitsmasque);
  if (retour!=LCRZO_ERR_OK)
  { /*il doit donc y avoir un "255.255.0.0"*/
    retour=lcrzo_ipl_init_ips(droite, &ipsup);
    if (retour!=LCRZO_ERR_OK) return(LCRZO_ERR_FMIPRANGE);
    /*on verifie que ipsup est bien un masque*/
    nbbitsmasque=32;
    doitplusavoirzero=0;
    for ( i=0 ; i<32 ; i++ )
    { if ( !(ipsup&1) )
      { if (!doitplusavoirzero)
          nbbitsmasque--;
        else
	  return(LCRZO_ERR_FMIPRANGE);
      }
      else
      { doitplusavoirzero=1;
      }
      ipsup >>= 1;
    }
  }
  /*nbbitsmasque contient maintenant le nb de bits du masque*/

  /*calcul du masque a partir de nbbitsmasque*/
  masque=0;
  for ( i=0 ; i<32-(int)nbbitsmasque ; i++ )
  { masque=(masque<<1)|1;
  }
  /*masque doit maintenant contenir 0b0000000...00000111111111111*/

  /*on verifie la coherence entre ipinf et nbbitsmasque*/
  if (ipinf&masque) return(LCRZO_ERR_FMIPRANGE);

  /*affecte le resultat*/
  if (type==2)
  { if (piplinf!=NULL) *piplinf=ipinf;
    if (piplsup!=NULL) *piplsup=ipinf|masque;
  }
  else 
  { /* xx%31 et xx%32 sont invalides*/
    if (nbbitsmasque>=31) return(LCRZO_ERR_FMIPRANGE);
    if (piplinf!=NULL) *piplinf=ipinf+1;
    if (piplsup!=NULL) *piplsup=(ipinf|masque)-1;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_ipl_init_hsrange(lcrzo_conststring range,
				lcrzo_ipl *piplinf,
				lcrzo_ipl *piplsup);
int lcrzo_priv_ipl_init_hsrange(lcrzo_conststring range,
				lcrzo_ipl *piplinf,
				lcrzo_ipl *piplsup)
{ lcrzo_string left, right;
  lcrzo_ipl ipl, ipl2;
  int poschar, ret;
  char *pc;
  
  /* the separator is '=' */
  pc=strchr(range, '=');
  if (pc==NULL)
  { /* range should only contain one lcrzo_hs */
    lcrzo_er(lcrzo_ipl_init_hs(range, &ipl));
    lcrzo_er(lcrzo_ipl_init_ipl(ipl, piplinf));
    lcrzo_er(lcrzo_ipl_init_ipl(ipl, piplsup));
    return(LCRZO_ERR_OK);
  }
  poschar=pc-range;

  /* cut range in two parts */
  lcrzo_er(lcrzo_string_initm_text(range, &left));
  left[poschar]='\0';
  lcrzo_efr(lcrzo_string_initm_text(range+poschar+1, &right),
	    lcrzo_string_free(left));

  /* obtain value */
  ret=lcrzo_ipl_init_hs(left, &ipl);
  if (ret==LCRZO_ERR_OK)
  { ret=lcrzo_ipl_init_hs(right, &ipl2);
    if (ret==LCRZO_ERR_OK)
    { if (ipl2<ipl) return(LCRZO_ERR_PAINFHIGHERSUP);
      lcrzo_er(lcrzo_ipl_init_ipl(ipl, piplinf));
      lcrzo_er(lcrzo_ipl_init_ipl(ipl2, piplsup));
      return(LCRZO_ERR_OK);
    }
  }
  lcrzo_string_free(left);
  lcrzo_string_free(right);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_ipl_init_iprange(lcrzo_conststring range,
			   lcrzo_ipl *piplinf,
			   lcrzo_ipl *piplsup)
{ lcrzo_string cleannedrange;
  lcrzo_bool badchar;
  int i, ret;
  char c;

  /* search char to determine if it is ips or hs */
  badchar=LCRZO_FALSE;
  for ( i=0 ; i<(int)strlen(range) ; i++ )
  { c=range[i];
    if ( c>='0' && c<='9' ) {}
    else if ( c==' ' || c=='\t' ) {}
    else if ( c=='.' ) {}
    else if ( c=='-' || c=='/' || c=='%' ) {}
    else
    { badchar=LCRZO_TRUE;
      break;
    }
  }

  if (badchar)
  { lcrzo_er(lcrzo_string_initm_coretext(range, &cleannedrange));
    ret=lcrzo_priv_ipl_init_hsrange(cleannedrange, piplinf, piplsup);
    lcrzo_string_free(cleannedrange);
  }
  else
  { ret=lcrzo_priv_ipl_init_iprange(range, piplinf, piplsup);
  }

  if (ret!=LCRZO_ERR_OK)
  { lcrzo_priv_global_set_errmsglcrzo_range(range);
  }

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_iprange_init_ipl(lcrzo_ipl iplinf,
		     lcrzo_ipl iplsup,
		     lcrzo_iprange plage)
{ lcrzo_uint32 masque, tmp, i;

  if (iplinf>iplsup)
  { return(LCRZO_ERR_PAINFHIGHERSUP);
  }
  else if (iplinf==iplsup) 
  { lcrzo_er(lcrzo_ips_init_ipl(iplinf, plage));
  }
  else
  { /*we should never encounter an error, so we can stop now, if we do not
    need to compute "plage".*/
    if (plage==NULL) return(LCRZO_ERR_OK);
    /*on tente d'abord un affichage du type "x.x.x.x/y" */
    tmp = iplinf^iplsup;
    masque=0;
    i=32;
    while(tmp)
    { tmp>>=1;
      masque=(masque<<1)|1;
      i--;
    }
    masque = (~masque);
    /*masque doit maintenant contenir 0b111111111111...1111110000*/
    if ( (masque&iplinf)==iplinf &&
	 ((~masque)|iplinf)==iplsup )
    { /*il s'agit d'un intervalle correct*/
      lcrzo_er(lcrzo_ips_init_ipl(iplinf, plage));
      lcrzo_er(lcrzo_string_append_char('/', 1, LCRZO_IPRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_string_append_int(i, "%d", LCRZO_IPRANGE_MAXBYTES, plage));
    }
    else if ( (masque&iplinf)==(iplinf-1) &&
	      ((~masque)|iplinf)==(iplsup+1) )
    { /*il s'agit d'un intervalle correct, sans les broadcast*/
      lcrzo_er(lcrzo_ips_init_ipl(iplinf-1, plage));
      lcrzo_er(lcrzo_string_append_char('%', 1, LCRZO_IPRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_string_append_int(i, "%d", LCRZO_IPRANGE_MAXBYTES, plage));
    }
    else
    { lcrzo_er(lcrzo_ips_init_ipl(iplinf, plage));
      lcrzo_er(lcrzo_string_append_char('-', 1, LCRZO_IPRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_ips_init_ipl(iplsup, plage+strlen(plage)));
    }
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_port_init_portrange(const lcrzo_portrange plage,
			 lcrzo_uint16 *pportinf,
			 lcrzo_uint16 *pportsup)
{ int posmoins, ret;
  lcrzo_portrange plagepurge, inf, sup;
  char *pc;
  lcrzo_uint32 port;
  lcrzo_uint16 portinf, portsup;

  /*verifie la plage entree*/
  lcrzo_er(lcrzo_string_init_coretext(plage, LCRZO_PORTRANGE_MAXBYTES,
				   plagepurge));
  if (strlen(plagepurge)>LCRZO_PORTRANGE_MAXBYTES)
    return(LCRZO_ERR_PAOVERFLOW);

  /*trouve la position du '-'*/
  pc=strchr(plagepurge, '-');
  if (pc==NULL)
  { /*il ne doit y avoir qu'un port*/
    ret=lcrzo_priv_str2int(plagepurge, 0xFFFF, 0, 0,
			   LCRZO_ERR_FMPORTRANGE, &port);
    if (ret!=LCRZO_ERR_OK) goto lcrzo_port_init_portrange_g;
    portinf=(lcrzo_uint16)port;
    portsup=(lcrzo_uint16)port;
  }
  else
  { posmoins=pc-plagepurge;
    /*il y a un '-' dans la chaine*/
    /*on s'occupe du port inferieur*/  
    ret=lcrzo_string_init_text(plagepurge, LCRZO_PORTRANGE_MAXBYTES, inf);
    if (ret!=LCRZO_ERR_OK) goto lcrzo_port_init_portrange_g;
    inf[posmoins]='\0';
    ret=lcrzo_priv_str2int(inf, 0xFFFF, 1, 1,
				 LCRZO_ERR_FMPORTRANGE, &port);
    if (ret!=LCRZO_ERR_OK) goto lcrzo_port_init_portrange_g;
        
    portinf=(lcrzo_uint16)port;
    /*on s'occupe du port superieur*/
    ret=lcrzo_string_init_text(plagepurge+posmoins+1,
			       LCRZO_PORTRANGE_MAXBYTES, sup);
    if (ret!=LCRZO_ERR_OK) goto lcrzo_port_init_portrange_g;
    ret=lcrzo_priv_str2int(sup, 0xFFFF, 1, 0xFFFF,
			   LCRZO_ERR_FMPORTRANGE, &port);
    if (ret!=LCRZO_ERR_OK) goto lcrzo_port_init_portrange_g;
    portsup=(lcrzo_uint16)port;
    if (portinf>portsup)
    { ret=LCRZO_ERR_PAINFHIGHERSUP;
      goto lcrzo_port_init_portrange_g;
    }
  }
  if (pportinf!=NULL) *pportinf=portinf;
  if (pportsup!=NULL) *pportsup=portsup;
  return(LCRZO_ERR_OK);
 lcrzo_port_init_portrange_g:
  lcrzo_priv_global_set_errmsglcrzo_range(plage);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_portrange_init_port(lcrzo_uint16 portinf,
			      lcrzo_uint16 portsup,
			      lcrzo_portrange plage)
{
  if (portinf>portsup) return(LCRZO_ERR_PAINFHIGHERSUP);
  else if (portinf==portsup)
  { lcrzo_er(lcrzo_string_init_int(portinf, "%d",
			       LCRZO_PORTRANGE_MAXBYTES, plage));
  }
  else
  { if (plage!=NULL)
    { lcrzo_er(lcrzo_string_init_int(portinf, "%d",
				     LCRZO_PORTRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_string_append_char('-', 1, 
					LCRZO_PORTRANGE_MAXBYTES, plage));
      lcrzo_er(lcrzo_string_append_int(portsup, "%d",
				       LCRZO_PORTRANGE_MAXBYTES, plage));
    }
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_ethrange_init_stdin(lcrzo_conststring message,
			      lcrzo_conststring defaultrange,
			      lcrzo_ethrange ethrange)
{ char prompt;
  lcrzo_string usertext;
  lcrzo_bool defautisvalid;
  int ret;

  /*parameters verification*/
  defautisvalid=LCRZO_FALSE;
  if (defaultrange!=NULL)
  { if (strlen(defaultrange))
    { ret=lcrzo_etha_init_ethrange(defaultrange, NULL, NULL);
      if (ret==LCRZO_ERR_OK)
      { defautisvalid=LCRZO_TRUE;
      }
    }
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0')
    { printf("%s ", message);
      if (defautisvalid) printf("[%s]", defaultrange);
      printf("%c ", prompt);
    }
    prompt='>';
    /*saisie de la chaine de l'utilisateur*/
    lcrzo_er(lcrzo_priv_stdin(&usertext, NULL));
    /*si rien n'a ete entre, on met le defaut*/
    if (strlen(usertext)==0 && defautisvalid)
    { lcrzo_string_free(usertext);
      lcrzo_er(lcrzo_string_init_text(defaultrange, LCRZO_ETHRANGE_MAXBYTES,
				      ethrange));
      /*si les tentatives precedentes etaient en erreur
	on est oblige de mettre a zero ici car on ne
	passe plus dans lcrzo_ipa_init_hs()*/
      lcrzo_err_purge();
      break;
    }
    /*conversion*/
    ret=lcrzo_etha_init_ethrange(usertext, NULL, NULL);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_string_init_text(usertext, LCRZO_ETHRANGE_MAXBYTES,
				 ethrange);
    }
    lcrzo_string_free(usertext);
    lcrzo_err_purge();
    if (ret==LCRZO_ERR_OK) break;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_iprange_init_stdin(lcrzo_conststring message,
			     lcrzo_conststring defaultrange,
			     lcrzo_iprange iprange)
{ char prompt;
  lcrzo_string usertext;
  lcrzo_bool defautisvalid;
  int ret;

  /*parameters verification*/
  defautisvalid=LCRZO_FALSE;
  if (defaultrange!=NULL)
  { if (strlen(defaultrange))
    { ret=lcrzo_ipl_init_iprange(defaultrange, NULL, NULL);
      if (ret==LCRZO_ERR_OK)
      { defautisvalid=LCRZO_TRUE;
      }
    }
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0')
    { printf("%s ", message);
      if (defautisvalid) printf("[%s]", defaultrange);
      printf("%c ", prompt);
    }
    prompt='>';
    /*saisie de la chaine de l'utilisateur*/
    lcrzo_er(lcrzo_priv_stdin(&usertext, NULL));
    /*si rien n'a ete entre, on met le defaut*/
    if (strlen(usertext)==0 && defautisvalid)
    { lcrzo_string_free(usertext);
      lcrzo_er(lcrzo_string_init_text(defaultrange, LCRZO_IPRANGE_MAXBYTES,
				      iprange));
      /*si les tentatives precedentes etaient en erreur
	on est oblige de mettre a zero ici car on ne
	passe plus dans lcrzo_ipa_init_hs()*/
      lcrzo_err_purge();
      break;
    }
    /*conversion*/
    ret=lcrzo_ipl_init_iprange(usertext, NULL, NULL);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_string_init_text(usertext, LCRZO_IPRANGE_MAXBYTES,
				 iprange);
    }
    lcrzo_string_free(usertext);
    lcrzo_err_purge();
    if (ret==LCRZO_ERR_OK) break;
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_portrange_init_stdin(lcrzo_conststring message,
			       lcrzo_conststring defaultrange,
			       lcrzo_portrange portrange)
{ char prompt;
  lcrzo_string usertext;
  lcrzo_bool defautisvalid;
  int ret;

  /*parameters verification*/
  defautisvalid=LCRZO_FALSE;
  if (defaultrange!=NULL)
  { if (strlen(defaultrange))
    { ret=lcrzo_port_init_portrange(defaultrange, NULL, NULL);
      if (ret==LCRZO_ERR_OK)
      { defautisvalid=LCRZO_TRUE;
      }
    }
  }

  prompt=':';
  while(LCRZO_TRUE)
  { /*affichage du message*/
    if (message!=NULL) if (message[0]!='\0')
    { printf("%s ", message);
      if (defautisvalid) printf("[%s]", defaultrange);
      printf("%c ", prompt);
    }
    prompt='>';
    /*saisie de la chaine de l'utilisateur*/
    lcrzo_er(lcrzo_priv_stdin(&usertext, NULL));
    /*si rien n'a ete entre, on met le defaut*/
    if (strlen(usertext)==0 && defautisvalid)
    { lcrzo_string_free(usertext);
      lcrzo_er(lcrzo_string_init_text(defaultrange, LCRZO_PORTRANGE_MAXBYTES,
				      portrange));
      /*si les tentatives precedentes etaient en erreur
	on est oblige de mettre a zero ici car on ne
	passe plus dans lcrzo_ipa_init_hs()*/
      lcrzo_err_purge();
      break;
    }
    /*conversion*/
    ret=lcrzo_port_init_portrange(usertext, NULL, NULL);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_string_init_text(usertext, LCRZO_PORTRANGE_MAXBYTES,
				 portrange);
    }
    lcrzo_string_free(usertext);
    lcrzo_err_purge();
    if (ret==LCRZO_ERR_OK) break;
  }
  return(LCRZO_ERR_OK);
}









