/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */

#include <jni.h>
#ifdef XP_WIN32
#include <conio.h>
#else
#include <unistd.h>
#include <termios.h>  
#endif
#ifdef Linux
#define getpassphrase getpass
#endif
#ifdef Darwin
#define getpassphrase getpass
#endif
#include "com_sun_enterprise_cli_framework_CliUtil.h"
#include "com_sun_enterprise_util_natives_NativeUtils.h"
//C++ include
#include <string>
#include <vector>

using namespace std;

#if defined(__APPLE__) && defined(__DYNAMIC__)
#include<crt_externs.h>
static char ** environ;
#else
extern char ** environ; // Standard environment definition
#endif 


/*
 * Class:     CliUtil
 * Method:    getStringEnv
 * Signature: ()Ljava/lang/String;
 */
vector<char*> getStringEnv(const char *prefix)
{
    int ii=0;
    vector<char*> vEnv;
        /* const char* chName = "AS_ADMIN_"; */
    const char* chName = prefix;

#if defined(__APPLE__) && defined(__DYNAMIC__)
    environ = *_NSGetEnviron();
#endif

    int len = strlen(chName);
    while (environ[ii] != NULL) {
      if (strncmp(chName, (char*)environ[ii], len ) == 0) {
         vEnv.push_back((char*)environ[ii]);
      }
      ii++;
   }
   return vEnv;
}


/*
 * Class:     CliUtil
 * Method:    getEnv
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_com_sun_enterprise_cli_framework_CliUtil_getEnv (JNIEnv *env, jobject obj, jstring prefix)
{
  const char *envPrefix = env->GetStringUTFChars(prefix, 0);
  vector<char*> vString = getStringEnv(envPrefix);
  
  /*avoid memory leak in JVM so need to call ReleaseStringUTFChars */
  env->ReleaseStringUTFChars(prefix, 0);
  
  jclass stringClass = env->FindClass("java/lang/String");
  jobjectArray retArr = env->NewObjectArray(vString.size(), stringClass, 0);
  char* str;
  jstring javaString;
  /* create object array */
  for (int ii=0; ii<vString.size(); ++ii) {
    str = vString[ii];
    //the length of AS_ADMIN_ is length 9
    //printf("str = %s\n", str+9);
    javaString = env->NewStringUTF(str);
    env->SetObjectArrayElement(retArr, ii, javaString);
  }
  return retArr;
}


/*
 * Class:     CliUtil
 * Method:    getPassword
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sun_enterprise_cli_framework_CliUtil_getPassword
  (JNIEnv *env, jobject obj)
{
#ifdef XP_UNIX
    char	*buf;
    buf = (char *)getpassphrase("");
    return(env->NewStringUTF(buf));
#else
    char passwd[80];
    int i = 0;
    int ch;

    while (1) {
        if (i >= sizeof(passwd) - 1)
            break;

        ch = _getch();

        if (ch == '\r')
            break;
    
        switch(ch) {
        case 0x08:
   
            if (i > 0)
                i--;
            break;
        default:
            passwd[i++] = ch;
            break;
        }
    }
    passwd[i] = '\0';
    _putch('\n');
    return (env->NewStringUTF(passwd));
#endif

}



/*
 * Class:     CliUtil
 * Method:    getAllEnv
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_com_sun_enterprise_cli_framework_CliUtil_getAllEnv (JNIEnv *env, jobject obj)
{
    int jj=0;
    vector<char*> vString;

#if defined(__APPLE__) && defined(__DYNAMIC__)
    environ = *_NSGetEnviron();
#endif
    
    while (environ[jj] != NULL) {
        vString.push_back((char*)environ[jj]);
        jj++;
    }
    
    jclass stringClass = env->FindClass("java/lang/String");
    jobjectArray retArr = env->NewObjectArray(vString.size(), stringClass, 0);
    char* str;
    
    jstring javaString;
    /* create object array */
    for (int ii=0; ii<vString.size(); ++ii) {
        str = vString[ii];
        //the length of AS_ADMIN_ is length 9
        //printf("str = %s\n", str+9);
        javaString = env->NewStringUTF(str);
        env->SetObjectArrayElement(retArr, ii, javaString);
    }
    return retArr;
}


/*
 * Class:     com_sun_enterprise_util_natives_NativeUtils
 * Method:    getPasswordNative
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sun_enterprise_util_natives_NativeUtils_getPasswordNative(JNIEnv *env, jobject obj)
{
    return Java_com_sun_enterprise_cli_framework_CliUtil_getPassword(env, obj);
}

#ifndef XP_WIN32

static struct termios stored_settings;

void set_keypress(void)
{
    struct termios new_settings;
    tcgetattr(0,&stored_settings);
    new_settings = stored_settings;

    /* Disable canonical mode, and set buffer size to 1 byte */

    new_settings.c_lflag &= (~ICANON);
    new_settings.c_cc[VTIME] = 0;
    new_settings.c_cc[VMIN] = 1;
    
        //disable echoing
    new_settings.c_lflag &= (~ECHO);
    tcsetattr(0,TCSANOW,&new_settings);
    return;
    
}


void reset_keypress(void)
{
    tcsetattr(0,TCSANOW,&stored_settings);
    return;
}
#endif


/*
 * Class:     CliUtil
 * Method:    getKeyboardInput
 * Signature: ()
 */
JNIEXPORT jchar JNICALL Java_com_sun_enterprise_cli_framework_CliUtil_getKeyboardInput
  (JNIEnv *env, jobject obj)
{
#ifdef XP_WIN32
    char ch = getch();
    return (jchar)ch;    
#else
    set_keypress();
    char ch = getchar();
    reset_keypress();
    return (jchar)ch;
#endif

}
