/*
  sshappcommon.c

  Authors: Sami Lehtinen <sjl@ssh.com>

  Copyright (C) 1999-2000 SSH Communications Security Corp, Helsinki, Finland
  All rights reserved.

  Common functions for all ssh-applications.
*/

#include "sshincludes.h"
#include "ssh2includes.h"
#include "sshappcommon.h"
#include "ssheprintf.h"
#include "sshglob.h"

#define SSH_DEBUG_MODULE "SshAppCommon"

static const char *registered_program_name = NULL;

void ssh_register_program_name(const char *name)
{
  registered_program_name = name;
}

const char *ssh_get_program_name(void)
{
  return registered_program_name;
}

/* Prints version string to stderr. */
void ssh2_version(const char *name)
{
  if (name == NULL)
    {
      if (registered_program_name)
        name = registered_program_name;
      else
        return;
    }
  
  fprintf(stderr, "%s: %s on %s\n", name, SSH2_VERSION_STRING, HOSTTYPE);
}

#ifdef KERNEL
#define SSH_DEBUG_BUFFER_SIZE 512
#else /* KERNEL */
#define SSH_DEBUG_BUFFER_SIZE 4096
#endif /* KERNEL */

void (*ssh_informational_callback)(const char *message, void *context);
void *callback_context;

void ssh_informational_callback_register(void (*callback)
                                         (const char *message, void *context),
                                         void *context)
{
  ssh_informational_callback = callback;
  callback_context = context;
}

/* Function for conveying informational messages to user. The output
   is _not_ followed by a newline (by this function, that is; caller
   can add own newlines). */
void ssh_informational(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  if (ssh_informational_callback)
    {
      char buf[SSH_DEBUG_BUFFER_SIZE];
      ssh_evsnprintf(buf, sizeof(buf), format, args);
      (*ssh_informational_callback)(buf, callback_context);
    }
  else
    {
      vfprintf(stderr, format, args);
    }
  va_end(args);
}

/* Helper function, that destroys a list, and frees it's contents,
   too. If delete_proc is non-NULL, it is used to delete the list
   item. Otherwise, the item is just ssh_xfree()d. */
void ssh_app_free_list(SshDlList list, SshAppListNodeDeleteProc delete_proc)
{
  char *to_be_deleted;

  if (list == NULL)
    return;
  
  ssh_dllist_rewind(list);
  while (!ssh_dllist_is_empty(list))
    {
      to_be_deleted = ssh_dllist_delete_current(list);
      if (delete_proc)
        {
          delete_proc(to_be_deleted);
        }
      else
        {
          ssh_xfree(to_be_deleted);
        }  
    }
    
  ssh_dllist_free(list);
}

/* Helper function, that combines two lists. dst will receive nodes
   from src, and src will be freed. (so the pointer isn't valid after
   this call.) If one or both arguments are NULL, does nothing. */
void ssh_app_combine_lists(SshDlList dst, SshDlList src)
{
  SshDlListNode node;
  
  if (!dst || !src)
    return;
  
  ssh_dllist_rewind(src);
  while ((node = ssh_dllist_remove_current_node(src)) != NULL)
    {
      SSH_VERIFY(ssh_dllist_add_node(dst, node, SSH_DLLIST_END) ==      \
                 SSH_DLLIST_OK);      
    }

  ssh_dllist_free(src);
}

char *ssh_app_param_list_get_next(const char *string)
{
  char *rest, *temp;
  
  if ((rest = ssh_glob_next_unescaped_char(string, ',')) == NULL)
    return ssh_xstrdup(string);
  
  temp = ssh_xcalloc(rest - string + 2, sizeof(char));

  strncpy(temp, string, rest - string);

  return temp;
}
