/*   This has nothing to do with cryptography. */
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_PWD
#include <pwd.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "util.h"
#include "diffie/compat.h"
#include "mad.h"


/* Canonicalize path, and return a new path. Do everything in situ.
   The new path differs from path in:
	Multiple `/'s are collapsed to a single `/'.
	Leading `./'s and trailing `/.'s are removed.
	Trailing `/'s are removed.
	Non-leading `../'s and trailing `..'s are handled by removing
	portions of the path. */
char *canonicalize_pathname (char *path)
{
    int i, start;
    char stub_char;

    stub_char = (*path == PATH_SEP) ? PATH_SEP : '.';

    /* Walk along path looking for things to compact. */
    i = 0;
    for (;;) {
        if (!path[i])
	    break;

      	while (path[i] && path[i] != PATH_SEP)
	    i++;

      	start = i++;

      	/* If we didn't find any slashes, then there is nothing left to do. */
      	if (!path[start])
	    break;

#if defined(__QNX__)
		/*
		** QNX accesses the directories of nodes on its peer-to-peer
		** network by prefixing their directories with "//[nid]".
		** We don't want to collapse two '/'s if they're at the start
		** of the path, followed by digits, and ending with a '/'.
		*/
		if (start == 0 && i == 1)
		{
			char *p = path + 2;
			char *q = strchr(p, PATH_SEP);

			if (q > p)
			{
				*q = 0;
				if (!strcspn(p, "0123456789"))
				{
					start = q - path;
					i = start + 1;
				}
				*q = PATH_SEP;
			}
		}
#endif

        /* Handle multiple `/'s in a row. */
        while (path[i] == PATH_SEP)
	    i++;

        if ((start + 1) != i) {
	    strcpy (path + start + 1, path + i);
	    i = start + 1;
	}

        /* Handle backquoted `/'. */
        if (start > 0 && path[start - 1] == '\\')
	    continue;

        /* Check for trailing `/'. */
        if (start && !path[i]) {
	zero_last:
	    path[--i] = '\0';
	    break;
	}

        /* Check for `../', `./' or trailing `.' by itself. */
        if (path[i] == '.') {
	    /* Handle trailing `.' by itself. */
	    if (!path[i + 1])
	        goto zero_last;

	    /* Handle `./'. */
	    if (path[i + 1] == PATH_SEP) {
	        strcpy (path + i, path + i + 1);
	        i = start;
	        continue;
	    }

	    /* Handle `../' or trailing `..' by itself. 
	       Remove the previous ?/ part with the exception of
	       ../, which we should leave intact. */
	    if (path[i + 1] == '.' && (path[i + 2] == PATH_SEP || !path[i + 2])) {
	        while (--start > -1 && path[start] != PATH_SEP);
	        if (!strncmp (path + start + 1, ".." PATH_SEP_STR, 3))
	            continue;
	        strcpy (path + start + 1, path + i + 2);
	        i = start;
	        continue;
	    }
	}
    }

    if (!*path) {
        *path = stub_char;
        path[1] = '\0';
    }
    return path;
}


#ifdef HAVE_MAD
char *mad_copy_strings (char *file, int line, const char *first, ...)
#else
char *copy_strings (const char *first,...)
#endif
{
    va_list ap;
    int len;
    char *data, *result;

    if (!first)
	return 0;
    
    len = strlen (first);
    va_start (ap, first);

    while ((data = va_arg (ap, char *))!=0)
	len += strlen (data);

    len++;

#ifdef HAVE_MAD
    result = mad_alloc (len, file, line);
#else
    result = malloc (len);
#endif
    va_end (ap);
    va_start (ap, first);
    strcpy (result, first);
    while ((data = va_arg (ap, char *)) != 0)
	strcat (result, data);
    va_end (ap);

    return result;
}

#ifdef HAVE_MAD
void mad_wipe_password (char *passwd, char *file, int line)
#else
void wipe_password (char *passwd)
#endif
{
    char *p = passwd;
    for (; *p; p++)
	*p = 0;
#ifdef HAVE_MAD
    mad_free (passwd, file, line);
#else
    free (passwd);
#endif
}

char *unix_error_string (int error_num)
{
    static char buffer [256];
    char *error_msg;
	
#ifdef HAVE_STRERROR
    error_msg = strerror (error_num);
#else
    extern int sys_nerr;
    extern char *sys_errlist [];
    if ((0 <= error_num) && (error_num < sys_nerr))
	error_msg = sys_errlist[error_num];
    else
	error_msg = "strange errno";
#endif
    sprintf (buffer, "%.200s (%d)", error_msg, error_num);
    return buffer;
}

int exist_file (char *name)
{
    return access (name, R_OK) == 0;
}

void vfs_default_message_callback (char *p,...)
{
    va_list ap;
    va_start (ap, p);
    vprintf (p, ap);
    printf ("\n");
    va_end (ap);
}

char *vfs_default_getpasswd_callback (char *a, char *b, char *c, char *host, char *user) /*EK*/
{
    return (char *) strdup ((char *) getpass (b));
}

extern char *ftpfs_anonymous_passwd;

char *vfs_default_getanonpasswd_callback (char *s)
{
    return 0;
}

int vfs_default_gotinterrupt_callback (void)
{
    return 0;
}

void vfs_set_message_callback (void (*callback) (char *,...))
{
    vfs_message_callback = callback;
}

/*EK* added to extra arguments, host and user name. they may be NULL */
void vfs_set_getpasswd_callback (char *(*callback) (char *, char *, char *, char *, char*)) /*EK*/
{
    vfs_getpasswd_callback = callback;
}

void vfs_set_getanonpasswd_callback (char *(*callback) (char *)) /*EK*/
{
    vfs_getanonpasswd_callback = callback;
}

void vfs_set_gotinterrupt_callback (int (*callback) (void))
{
    vfs_gotinterrupt_callback = callback;
}






