/* pfs-sftp-version.c:
 *
 ****************************************************************
 * Copyright (C) 2004 Johannes Berg
 * Copyright (C) 2006 Ludovic Courtès
 *
 * See the file "COPYING" for further information about
 * the copyright and warranty status of this work.
 */

#include "config-options.h"
#include "hackerlab/os/stdlib.h"
#include "hackerlab/machine/types.h"
#include "hackerlab/bugs/panic.h"
#include "hackerlab/os/stdarg.h"
#include "hackerlab/os/sys/types.h"
#include "hackerlab/os/unistd.h"
#include "hackerlab/os/sys/wait.h"
#include "hackerlab/os/signal.h"
#include "hackerlab/char/str.h"
#include "hackerlab/vu/safe-printfmt.h"
#include "tla/libarch/pfs-sftp-version.h"



/* SSH implementation descriptor.  */
struct arch_ssh_type_desc
{
  enum arch_ssh_type  type;
  const t_uchar      *binary_name;
};

static const struct arch_ssh_type_desc ssh_type_descriptors[] =
  {
    { ssh_type_lsh,      "lshc" },    /* GNU lsh */
    { ssh_type_openssh,  "ssh" },     /* OpenSSH */
    { ssh_type_psftp,    "psftp" },   /* Putty */
    { ssh_type_fsecure3, "ssh" },     /* F-Secure SSH (non-free) */
    { ssh_type_unknown,  0 }
  };


static enum arch_ssh_type
identify_ssh_type (const t_uchar *ssh_name)
{
  enum arch_ssh_type ssh_type = ssh_type_unknown;

  if (str_casecmp (ssh_name, "openssh") == 0)
    ssh_type = ssh_type_openssh;
  else if (str_casecmp (ssh_name, "lsh") == 0)
    ssh_type = ssh_type_lsh;
  else if (str_casecmp (ssh_name, "fsecure") == 0)
    ssh_type = ssh_type_fsecure3;
  else if (str_casecmp (ssh_name, "psftp") == 0)
    ssh_type = ssh_type_psftp;

  return ssh_type;
}

static const t_uchar *
ssh_binary_name (enum arch_ssh_type ssh_type)
{
  const struct arch_ssh_type_desc *td;

  for (td = &ssh_type_descriptors[0];
       td->type != ssh_type_unknown;
       td++)
    {
      if (td->type == ssh_type)
	break;
    }

  if (td->type == ssh_type_unknown)
    return NULL;

  return td->binary_name;
}


/* Default SSH type and binary, both determined at configure-time with
   `--with-ssh-type' and `--with-ssh-binary'.  */

static enum arch_ssh_type
default_ssh_type (void)
{
  static enum arch_ssh_type default_type = ssh_type_unknown;

  if (default_type == ssh_type_unknown)
    {
#ifdef cfg__ssh_type
      if (str_length (cfg__ssh_type) == 0)
        default_type = ssh_type_openssh;
      else
	/* We're hoping that `cfg__ssh_type' contains a valid SSH type name,
	   otherwise `ssh_type_unknown' will be yielded.  */
	default_type = identify_ssh_type (cfg__ssh_type);
#else
      /* Assume openssh by default.  */
      default_type = ssh_type_openssh;
#endif
    }

  return default_type;
}

static const t_uchar *
default_ssh_binary (void)
{
  static t_uchar openssh_binary[] = "ssh";

#ifdef cfg__ssh_binary
  static t_uchar default_binary[] = cfg__ssh_binary;

  if (str_length (default_binary) > 0)
    return default_binary;
#endif

  return openssh_binary;
}


enum arch_ssh_type
arch_pfs_sftp_ssh_type (void)
{
  enum arch_ssh_type ssh_type = ssh_type_unknown;
  t_uchar * env_type = (t_uchar *)getenv ("ARCH_SSH_TYPE");

  if (env_type)
    {
      ssh_type = identify_ssh_type (env_type);
      if (ssh_type == ssh_type_unknown)
	{
	  safe_printfmt (2, "ARCH_SSH_TYPE: %s: unknown SSH implementation type\n",
			 env_type);
	  safe_printfmt (2, "supported values: \"openssh\", \"lsh\", \"fsecure\", \"psftp\"\n");
	  exit (2);
	}
    }
  else
    ssh_type = default_ssh_type ();

  return ssh_type;
}

const t_uchar *
arch_pfs_sftp_ssh_binary (enum arch_ssh_type ssh_type)
{
  t_uchar *env_binary = (t_uchar *)getenv ("ARCH_SSH_BINARY");

  if (env_binary)
    return env_binary;

  if (ssh_type == default_ssh_type ())
    /* The result here can be different from the standard binary name
       corresponding to SSH_TYPE.  */
    return default_ssh_binary ();

  return ssh_binary_name (ssh_type);
}


/* tag: pfs-sftp-version.c by Johannes Berg  (23:40 Feb 15 2004)
*/
