First pass at experimental NIF
diff --git a/lib/bcrypt/c_src/bcrypt_erlang.c b/lib/bcrypt/c_src/bcrypt_erlang.c
deleted file mode 100644
index cfd1729..0000000
--- a/lib/bcrypt/c_src/bcrypt_erlang.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2008 Hunter Morris <huntermorris@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <erl_interface.h>
-#include <ei.h>
-#include <unistd.h>
-
-#include "erl_blf.h"
-
-#define dec_int16(s) ((((unsigned char*)(s))[0] << 8) | \
-                      (((unsigned char*)(s))[1]))
-
-#define enc_int16(i, s) {((unsigned char*)(s))[0] = ((i) >> 8) & 0xff;  \
-    ((unsigned char*)(s))[1] = (i) & 0xff;}
-
-#define BUFSIZE (1 << 16)
-#define CMD_SALT 0
-#define CMD_HASHPW 1
-
-typedef unsigned char byte;
-
-char *bcrypt(const char *, const char *);
-void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
-
-/* These methods came from the Erlang port command tutorial:
- * http://www.erlang.org/doc/tutorial/c_port.html#4.2
- */
-static int
-read_buf(int fd, byte *buf, int len)
-{
-  int i, got = 0;
-  do {
-    if ((i = read(fd, buf+got, len-got)) <= 0) {
-      if (i == 0) return got;
-      if (errno != EINTR)
-        return got;
-      i = 0;
-    }
-    got += i;
-  } while (got < len);
-  return (len);
-}
-
-static int
-read_cmd(byte *buf)
-{
-  int len;
-  if (read_buf(0, buf, 2) != 2)
-    return 0;
-  len = dec_int16(buf);
-  if (read_buf(0, buf, len) != len)
-    return 0;
-  return 1;
-}
-
-static int
-write_buf(int fd, byte *buf, int len)
-{
-  int i, done = 0; 
-  do {
-    if ((i = write(fd, buf+done, len-done)) < 0) {
-      if (errno != EINTR)
-        return (i);
-      i = 0;
-    }
-    done += i;
-  } while (done < len);
-  return (len);
-}
-
-static int
-write_cmd(byte *buf, int len)
-{
-  byte hd[2];
-  enc_int16(len, hd);
-  if (write_buf(1, hd, 2) != 2)
-    return 0;
-  if (write_buf(1, buf, len) != len)
-    return 0;
-  return 1;
-}
-
-static int
-process_reply(ETERM *pid, int cmd, const char *res)
-{
-  ETERM *result;
-  int len, retval;
-  byte *buf;
-  result = erl_format("{~i, ~w, ~s}", cmd, pid, res);
-  len = erl_term_len(result);
-  buf = erl_malloc(len);
-  erl_encode(result, buf);
-  retval = write_cmd(buf, len);
-  erl_free_term(result);
-  erl_free(buf);
-  return retval;
-}
-
-static int
-process_encode_salt(ETERM *pid, ETERM *data)
-{
-  int retval = 0;
-  ETERM *pattern, *cslt, *lr;
-  byte *csalt = NULL;
-  long log_rounds = -1;
-  int csaltlen = -1;
-  char ret[64];
-  pattern = erl_format("{Csalt, LogRounds}");
-  if (erl_match(pattern, data)) {
-    cslt = erl_var_content(pattern, "Csalt");
-    csaltlen = ERL_BIN_SIZE(cslt);
-    csalt = ERL_BIN_PTR(cslt);
-    lr = erl_var_content(pattern, "LogRounds");
-    log_rounds = ERL_INT_UVALUE(lr);
-    if (16 != csaltlen) {
-      retval = process_reply(pid, CMD_SALT, "Invalid salt length");
-    } else if (log_rounds < 4 || log_rounds > 31) {
-      retval = process_reply(pid, CMD_SALT, "Invalid number of rounds");
-    } else {
-      encode_salt(ret, (u_int8_t*)csalt, csaltlen, log_rounds);
-      retval = process_reply(pid, CMD_SALT, ret);
-    }
-    erl_free_term(cslt);
-    erl_free_term(lr);
-  };
-  erl_free_term(pattern);
-  return retval;
-}
-
-static int
-process_hashpw(ETERM *pid, ETERM *data)
-{
-  int retval = 0;
-  ETERM *pattern, *pwd, *slt;
-  char *password, *salt;
-  char *ret = NULL;
-  pattern = erl_format("{Pass, Salt}");
-  if (erl_match(pattern, data)) {
-    pwd = erl_var_content(pattern, "Pass");
-    password = erl_iolist_to_string(pwd);
-    slt = erl_var_content(pattern, "Salt");
-    salt = erl_iolist_to_string(slt);
-    if (NULL == (ret = bcrypt(password, salt)) ||
-        0 == strcmp(ret, ":")) {
-      retval = process_reply(pid, CMD_HASHPW, "Invalid salt");
-    } else {
-      retval = process_reply(pid, CMD_HASHPW, ret);
-    }
-    erl_free_term(pwd);
-    erl_free_term(slt);
-    erl_free(password);
-    erl_free(salt);
-  };
-  erl_free_term(pattern);
-  return retval;
-}
-
-static int
-process_command(unsigned char *buf)
-{
-  int retval = 0;
-  ETERM *pattern, *tuple, *cmd, *port, *data;
-  pattern = erl_format("{Cmd, Port, Data}");
-  tuple = erl_decode(buf);
-  if (erl_match(pattern, tuple)) {
-    cmd = erl_var_content(pattern, "Cmd");
-    port = erl_var_content(pattern, "Port");
-    data = erl_var_content(pattern, "Data");
-    switch (ERL_INT_VALUE(cmd)) {
-    case CMD_SALT:
-      retval = process_encode_salt(port, data);
-      break;
-    case CMD_HASHPW:
-      retval = process_hashpw(port, data);
-      break;
-    };
-    erl_free_term(cmd);
-    erl_free_term(port);
-    erl_free_term(data);
-  }
-  erl_free_term(pattern);
-  erl_free_term(tuple);
-  return retval;
-}
-
-static void
-loop(void)
-{
-  byte buf[BUFSIZE];
-  int retval = 0;
-  do {
-    if (read_cmd(buf) > 0)
-      retval = process_command(buf);
-    else
-      retval = 0;
-  } while (retval);
-}
-
-int
-main(int argc, char *argv[])
-{
-  erl_init(NULL, 0);
-  loop();
-  return 0;
-}
diff --git a/lib/bcrypt/c_src/bcrypt_nif.c b/lib/bcrypt/c_src/bcrypt_nif.c
new file mode 100644
index 0000000..7e41afc
--- /dev/null
+++ b/lib/bcrypt/c_src/bcrypt_nif.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009 Hunter Morris <huntermorris@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "erl_nif.h"
+#include "erl_blf.h"
+
+typedef unsigned char byte;
+
+char *bcrypt(const char *, const char *);
+void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
+
+static ERL_NIF_TERM
+encode_salt(ErlNifEnv* env, ERL_NIF_TERM csalt_term, ERL_NIF_TERM log_rounds_term)
+{
+    ErlNifBinary csalt, bin;
+    unsigned long log_rounds;
+
+    if (!enif_inspect_binary(env, csalt_term, &csalt) || 16 != csalt.size) {
+        return enif_make_badarg(env);
+    }
+
+    if (!enif_get_ulong(env, log_rounds_term, &log_rounds)) {
+        return enif_make_badarg(env);
+    }
+
+    if (!enif_alloc_binary(env, 64, &bin)) {
+        return enif_make_badarg(env);
+    }
+
+    if (!encode_salt(bin.data, (u_int8_t*)csalt.data, csalt.size, log_rounds)) {
+        return enif_make_badarg(env);
+    }
+
+    return enif_make_binary(env, bin);
+}
+
+static ERL_NIF_TERM
+hashpw(ErlNifEnv* env, ERL_NIF_TERM pass_term, ERL_NIF_TERM salt_term)
+{
+    ErlNifBinary pass, salt, bin;
+    char *ret = NULL;
+
+    if (!enif_inspect_binary(env, pass_term, &pass)) {
+        return enif_make_badarg(env);
+    }
+
+    if (!enif_inspect_binary(env, salt_term, &salt)) {
+        return enif_make_badarg(env);
+    }
+
+    if (!enif_alloc_binary(env, 60, &bin)) {
+        return enif_make_badarg(env);
+    }
+
+    if (NULL == (ret = bcrypt(pass.data, salt.data)) || 0 == strcmp(ret, ":")) {
+        return enif_make_badarg(env);
+    }
+
+    return enif_make_string(env, ret);
+}
+
+static ErlNifFunc bcrypt_nif_funcs[] =
+{
+    {"encode_salt", 2, encode_salt},
+    {"hashpw", 2, hashpw}
+};
+
+ERL_NIF_INIT(bcrypt_nif, bcrypt_nif_funcs, NULL, NULL, NULL, NULL)
diff --git a/lib/bcrypt/c_src/erl_blf.h b/lib/bcrypt/c_src/erl_blf.h
index 74e6fc3..d64535f 100644
--- a/lib/bcrypt/c_src/erl_blf.h
+++ b/lib/bcrypt/c_src/erl_blf.h
@@ -57,8 +57,8 @@
 
 /* Blowfish context */
 typedef struct BlowfishContext {
-	u_int32_t S[4][256];	/* S-Boxes */
-	u_int32_t P[BLF_N + 2];	/* Subkeys */
+    u_int32_t S[4][256];	/* S-Boxes */
+    u_int32_t P[BLF_N + 2];	/* Subkeys */
 } blf_ctx;
 
 /* Raw access to customized Blowfish