diff --git a/exec/binkit.js b/exec/binkit.js
index fa13cb330694032955ba2fc37051615eb894a7e6..e716b1f7e1cefc97ee4450e77447ae9a71cdd093 100644
--- a/exec/binkit.js
+++ b/exec/binkit.js
@@ -12,12 +12,28 @@
  *    is "/path/to/outbound", it will not correctly handle the case
  *    where there is a "/path/to/outbound.001" directory.
  * 3) The domain is always 'fidonet'
+ * 4) Flow files are processed in alphabetical order, not the reccomended
+ *    order from FTS-5005.
  * 
  * See FTS-5005 for details.
  */
 
 load("binkp.js");
 load("fidocfg.js");
+load("freqit_common.js");
+
+FREQIT.add_file = function(filename, bp, cfg)
+{
+	if (filename === undefined)
+		return;
+	if (FREQIT.files >= cfg.maxfiles)
+		return;
+	if (FREQIT.added[filename] !== undefined)
+		return;
+	bp.addFile(filename);
+	FREQIT.files++;
+	FREQIT.added[filename]='';
+};
 
 function lock_flow(file, csy)
 {
@@ -124,11 +140,11 @@ function add_outbound_files(addrs, bp)
 			var fname;
 
 			switch(file_getext(file).toLowerCase()) {
-				case '.flo':
-				case '.ilo':
-				case '.hlo':
 				case '.clo':
 				case '.dlo':
+				case '.flo':
+				case '.hlo':
+				case '.ilo':
 					flo = new File(file);
 					if (!flo.open("r")) {
 						log(LOG_ERROR, "Unable to open FLO file '"+flo.name+"'.");
@@ -165,11 +181,11 @@ function add_outbound_files(addrs, bp)
 					}
 					flo.close();
 					break;
-				case '.out':
-				case '.iut':
-				case '.hut':
 				case '.cut':
 				case '.dut':
+				case '.hut':
+				case '.iut':
+				case '.out':
 					fname = '';
 					for (i=0; i<8; i++)
 						fname += fnchars[random(fnchars.length)];
@@ -177,11 +193,11 @@ function add_outbound_files(addrs, bp)
 					if (bp.addFile(file, fname))
 						bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
 					break;
-				case '.rep':
+				case '.req':
 					fname = '';
 					for (i=0; i<8; i++)
 						fname += fnchars[random(fnchars.length)];
-					fname += '.rep';
+					fname += '.req';
 					if (bp.addFile(file, fname))
 						bp.cb_data.binkit_file_actions[flo.name] = 'DELETE';
 					break;
@@ -207,7 +223,7 @@ function callout_auth_cb(mode, bp)
 	else {
 		bp.remote_addrs.forEach(function(addr) {
 			if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
-				if (bp.cb_data.binkitcfg.node[addr].pw === bp.cb_data.binkitpw)
+				if (bp.cb_data.binkitcfg.node[addr].pass === bp.cb_data.binkitpw)
 					addrs.push(addr);
 			}
 			else
@@ -215,13 +231,13 @@ function callout_auth_cb(mode, bp)
 		});
 	}
 
-	add_outbound_files(addrs);
+	add_outbound_files(addrs, bp);
 }
 
 /*
  * Delete completed flo files.
  */
-function callout_tx_callback(fname, bp)
+function tx_callback(fname, bp)
 {
 	var j;
 
@@ -236,9 +252,67 @@ function callout_tx_callback(fname, bp)
 	});
 }
 
-function callout_rx_callback(fname, bp)
+function handle_freq(reqfname, bp)
+{
+	var req=new File(reqfname);
+	var m;
+	var fname;
+	var pw;
+	var cfg = new FREQITCfg();
+
+	if (!req.open("r"))
+		return;
+	FREQIT.reset();
+
+	next_file:
+	while((fname=req.readln())) {
+		if ((m=fname.match(/^(.*) !(.*?)$/))!==null) {
+			pw=m[2];
+			fname=m[1];
+		}
+		// First, check for magic!
+		for (m in cfg.magic) {
+			if (m == fname.toLowerCase()) {
+				FREQIT.handle_magic(cfg.magic[m], bp, bp.authenticated === 'secure', pw, cfg);
+				continue next_file;
+			}
+		}
+
+		// Now, check for the file...
+		FREQIT.handle_regular(fname, bp, bp.authenticated === 'secure', pw, cfg);
+	}
+}
+
+function rx_callback(fname, bp)
 {
-	// TODO: Handle received files.
+	var semname;
+
+	if (fname.search(/\.(?:pkt|su.|mo.|tu.|we.|th.|fr.|sa.)$/i) !== -1) {
+		semname = system.data_dir + 'fidoin.now';
+		if (bp.binkit_create_semaphores.indexOf(semname) == -1)
+			bp.binkit_create_semaphores.push(semname);
+	}
+	else if (fname.search(/\.tic$/i) !== -1) {
+		semname = system.data_dir + 'tickit.now';
+		if (bp.binkit_create_semaphores.indexOf(semname) == -1)
+			bp.binkit_create_semaphores.push(semname);
+	}
+
+	if (fname.search(/\.req$/i) !== -1) {
+		handle_freq(fname, bp);
+		file_remove(fname);
+	}
+	else {
+		if (bp.authenticated === 'secure') {
+			if (!file_rename(fname, bp.binkit_scfg.secure_inbound+file_getname(fname)))
+				return false;
+		}
+		else {
+			if (!file_rename(fname, bp.binkit_scfg.inbound+file_getname(fname)))
+				return false;
+		}
+	}
+	return true;
 }
 
 function callout_want_callback(fobj, fsize, fdate, offset, bp)
@@ -275,10 +349,11 @@ function callout_want_callback(fobj, fsize, fdate, offset, bp)
 	return this.file.ACCEPT;
 }
 
-function callout_done(bp)
+function callout_done(bp, semaphores)
 {
 	var f;
 	var lines;
+	var semname;
 
 	bp.sent_files.forEach(function(file) {
 		if (bp.cb_data.binkit_file_actions[file] !== undefined) {
@@ -337,10 +412,10 @@ function callout_done(bp)
 	});
 }
 
-function callout(addr, scfg)
+function callout(addr, scfg, semaphores)
 {
 	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
-	var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, callout_rx_callback, callout_tx_callback);
+	var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, rx_callback, tx_callback);
 	var port;
 	var f;
 	var success = false;
@@ -352,6 +427,7 @@ function callout(addr, scfg)
 		binkit_scfg:scfg,
 		binkit_file_actions:{},
 		binkit_flow_contents:{},
+		binkit_create_semaphores:semaphores
 	};
 	if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
 		bp.cb_data.binkitpw = bp.cb_data.binkitcfg.node[addr].pass;
@@ -371,7 +447,7 @@ function callout(addr, scfg)
 	// We won't add files until the auth finishes...
 	success = bp.connect(addr, bp.cb_data.binkitpw, callout_auth_cb, port);
 
-	callout_done(bp);
+	callout_done(bp, semaphores);
 
 	f = new File(outbound_root(bp.cb_data.binkit_scfg.outbound)+addr.flo_outbound(bp.default_zone, bp.default_domain)+'try');
 	if (f.open("w")) {
@@ -384,7 +460,7 @@ function callout(addr, scfg)
 	}
 }
 
-function run_one_outbound_dir(dir, scfg)
+function run_one_outbound_dir(dir, scfg, semaphores)
 {
 	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
 	var ran = {};
@@ -481,7 +557,7 @@ function run_one_outbound_dir(dir, scfg)
 			if (i<flow_files.length) {
 				log(LOG_DEBUG, "Attempting callout for file "+flow_files[i]);
 				// Use a try/catch to ensure we clean up the lock files.
-				callout(addr, scfg);
+				callout(addr, scfg, semaphores);
 				ran[addr] = true;
 				unlock_flow(lock_files);
 			}
@@ -507,6 +583,7 @@ function run_outbound()
 	var outbound_base;
 	var outbound_dirs=[];
 	var tmp;
+	var semaphores = [];
 
 	log(LOG_INFO, "Running outbound");
 	scfg = new SBBSEchoCfg();
@@ -542,6 +619,93 @@ function run_outbound()
 	outbound_dirs.forEach(function(dir) {
 		run_one_outbound_dir(dir, scfg);
 	});
+
+	semaphores.forEach(function(semname) {
+		file_touch(semname);
+	});
+}
+
+function inbound_auth_cb(pwd, bp)
+{
+	/*
+	 * Loop through remote addresses, building a list of the ones with
+	 * the same password that we can send mail for.
+	 */
+	var addrs = [];
+
+	bp.remote_addrs.forEach(function(addr) {
+		var cpw;
+		if (bp.cb_data.binkitcfg.node[addr] !== undefined) {
+			cpw = bp.cb_data.binkitcfg.node[addr].pass;
+			if (cpw === undefined)
+				cpw = '-';
+			if (pwd[0].substr(0, 9) === 'CRAM-MD5-') {
+				if (bp.getCRAM('MD5', cpw) === pwd[0])
+					addrs.push(addr);
+			}
+			else {
+				// TODO: Deal with arrays of passwords?
+				if (bp.cb_data.binkitcfg.node[addr].nomd5 === false && bp.cb_data.binkitcfg.node[addr].pass === pwd[0])
+					addrs.push(addr);
+			}
+		}
+		else
+			log(LOG_DEBUG, "Unconfigured address "+addr);
+	});
+	bp.remote_addrs = addrs;
+
+	add_outbound_files(addrs, bp);
+	return addrs.length > 0;
+}
+
+function run_inbound(sock)
+{
+	var myaddr = FIDO.parse_addr(system.fido_addr_list[0], 1, 'fidonet');
+	var bp = new BinkP('BinkIT/'+("$Revision$".split(' ')[1]), undefined, rx_callback, tx_callback);
+	var port;
+	var f;
+	var success = false;
+	var semaphores = [];
+
+	log(LOG_INFO, "Got inbound call from "+sock.remote_ip_addr+":"+sock.remote_port);
+	bp.cb_data = {
+		binkitcfg:new BinkITCfg(),
+		binkit_scfg:new SBBSEchoCfg(),
+		binkit_file_actions:{},
+		binkit_flow_contents:{},
+		binkit_create_semaphores:semaphores
+	};
+
+	// TODO Global setting?
+	//bp.require_md5 = !(bp.cb_data.binkitcfg.node[addr].nomd5);
+	// TODO: Force debug mode for now...
+	bp.debug = true;
+	bp.default_zone = myaddr.zone;
+	bp.default_domain = myaddr.domain;
+	bp.want_callback = callout_want_callback;
+
+	// We can't use the defaults since the defaults are only 4D addresses.
+	bp.addr_list = [];
+	system.fido_addr_list.forEach(function(faddr){bp.addr_list.push(FIDO.parse_addr(faddr, this.default_zone, 'fidonet'));}, this);
+
+	// We won't add files until the auth finishes...
+	success = bp.accept(sock, inbound_auth_cb);
+
+	callout_done(bp, semaphores);
+
+	semaphores.forEach(function(semname) {
+		file_touch(semname);
+	});
+}
+
+var sock;
+try {
+	sock = client.socket;
 }
+catch(e) {}
 
-run_outbound();
+// If we're running as a service, call run_inbound().
+if (sock !== undefined)
+	run_inbound(sock);
+else
+	run_outbound();