Esempio n. 1
0
File: dep_cpp.c Progetto: malind/bam
static void cachehit_callback(struct NODE *node, struct CACHENODE *cachenode, void *user)
{
	struct CACHERUNINFO *info = (struct CACHERUNINFO *)user;
	
	/* check if the file has been removed */
	struct NODE *existing_node = node_find_byhash(node->graph, cachenode->hashid);
	if(existing_node)
	{
		struct NODE *newnode = node_add_dependency (node, existing_node);
		dependency_cpp_run(info->context, newnode, info->callback, info->userdata);
	}
	else
	{
		time_t timestamp = file_timestamp(cachenode->filename);
		if(timestamp)
		{
			/* this shouldn't be able to fail */
			struct NODE *newnode;
			node_create(&newnode, info->context->graph, cachenode->filename, NULL, timestamp);
			node_add_dependency (node, newnode);

			/* recurse the dependency checking */
			dependency_cpp_run(info->context, newnode, info->callback, info->userdata);
		}
		else
		{
			node->dirty = NODEDIRTY_MISSING;
		}
	}
}
Esempio n. 2
0
timestamp_t Texture::filesTimestamp() {
  int i;
  timestamp_t res=0, t;
  switch(_target) {
    case GL_TEXTURE_CUBE_MAP:
      for(i=0;i<6;i++) if (_filename_cube[i]) {
        t=file_timestamp(_filename_cube[i]);
        if (t>res) res=t;
      }
      break;
    case GL_TEXTURE_2D:
      if (_filename)
        res=file_timestamp(_filename);
      break;
  }
  return res;
}
Esempio n. 3
0
File: dep_cpp.c Progetto: malind/bam
static int node_findfile(struct GRAPH *graph, const char *filename, struct NODE **node, time_t *timestamp)
{
	/* first check the graph */
	*node = node_find(graph, filename);
	if(*node)
		return 1;

	/* then check the file system */
	*timestamp = file_timestamp(filename);
	if(*timestamp && file_isregular(filename))
		return 1;

	return 0;
}
Esempio n. 4
0
struct variable *sys_fileattr(struct context *context)
{
    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *path = param_var(args, 1);

    const char *path2 = byte_array_to_string(path->str);
    long siz = file_size(path2);
    long mod = file_timestamp(path2);
    struct variable *siz2 = variable_new_int(context, (int32_t)siz);
    struct variable *mod2 = variable_new_int(context, (int32_t)mod);
    variable_push(context, siz2);
    variable_push(context, mod2 );
    struct variable *result = variable_new_src(context, 2);

    return result;
}
Esempio n. 5
0
File: luafuncs.c Progetto: MAP94/bam
/* update_globalstamp(string filename) */
int lf_update_globalstamp(lua_State *L)
{
	struct CONTEXT *context;
	time_t file_stamp;
	
	if(lua_gettop(L) < 1)
		luaL_error(L, "update_globalstamp: too few arguments");
	luaL_checktype(L, 1, LUA_TSTRING);

	context = context_get_pointer(L);
	file_stamp = file_timestamp(lua_tostring(L,1)); /* update global timestamp */
	
	if(file_stamp > context->globaltimestamp)
		context->globaltimestamp = file_stamp;
	
	return 0;
}
Esempio n. 6
0
File: main.c Progetto: malind/bam
static int bam_setup(struct CONTEXT *context, const char *scriptfile, const char **targets, int num_targets)
{
	/* */	
	if(session.verbose)
		printf("%s: setup started\n", session.name);
	
	/* set filename */
	context->filename = scriptfile;
	
	/* set global timestamp to the script file */
	context->globaltimestamp = file_timestamp(scriptfile);

	/* */
	context->forced = option_force;
	
	/* fetch script directory */
	{
		char cwd[MAX_PATH_LENGTH];
		char path[MAX_PATH_LENGTH];

		if(!getcwd(cwd, sizeof(cwd)))
		{
			printf("%s: error: couldn't get current working directory\n", session.name);
			return -1;
		}
		
		if(path_directory(context->filename, path, sizeof(path)))
		{
			printf("%s: error: path too long '%s'\n", session.name, path);
			return -1;
		}
		
		if(path_join(cwd, -1, path, -1, context->script_directory, sizeof(context->script_directory)))
		{
			printf("%s: error: path too long when joining '%s' and '%s'\n", session.name, cwd, path);
			return -1;
		}
	}
	
	/* register all functions */
	event_begin(0, "lua setup", NULL);
	if(register_lua_globals(context->lua, context->script_directory, context->filename) != 0)
	{
		printf("%s: error: registering of lua functions failed\n", session.name);
		return -1;
	}
	event_end(0, "lua setup", NULL);

	/* load script */	
	if(session.verbose)
		printf("%s: reading script from '%s'\n", session.name, scriptfile);

	event_begin(0, "script load", NULL);
	/* push error function to stack and load the script */
	lua_getglobal(context->lua, "errorfunc");
	switch(luaL_loadfile(context->lua, scriptfile))
	{
		case 0: break;
		case LUA_ERRSYNTAX:
			lf_errorfunc(context->lua);
			return -1;
		case LUA_ERRMEM:
			printf("%s: memory allocation error\n", session.name);
			return -1;
		case LUA_ERRFILE:
			printf("%s: error opening '%s'\n", session.name, scriptfile);
			return -1;
		default:
			printf("%s: unknown error\n", session.name);
			return -1;
	}
	event_end(0, "script load", NULL);

	/* start the background stat thread */
	node_graph_start_statthread(context->graph);

	/* call the code chunk */
	event_begin(0, "script run", NULL);
	if(lua_pcall(context->lua, 0, LUA_MULTRET, -2) != 0)
	{
		node_graph_end_statthread(context->graph);
		printf("%s: script error (-t for more detail)\n", session.name);
		return -1;
	}
	event_end(0, "script run", NULL);

	/* stop the background stat thread */
	event_begin(0, "stat", NULL);
	node_graph_end_statthread(context->graph);
	event_end(0, "stat", NULL);
	
	/* run deferred functions */
	event_begin(0, "deferred cpp dependencies", NULL);
	if(run_deferred_functions(context, context->firstdeferred_cpp) != 0)
		return -1;
	event_end(0, "deferred cpp dependencies", NULL);
		
	event_begin(0, "deferred search dependencies", NULL);
	if(run_deferred_functions(context, context->firstdeferred_search) != 0)
		return -1;
	event_end(0, "deferred search dependencies", NULL);

	/* */	
	if(session.verbose)
		printf("%s: making build target\n", session.name);
	
	/* make build target */
	{
		struct NODE *node;
		int all_target = 0;
		int i;

		if(node_create(&context->target, context->graph, "_bam_buildtarget", NULL, TIMESTAMP_PSEUDO))
			return -1;

		if(num_targets)
		{
			/* search for all target */
			for(i = 0; i < num_targets; i++)
			{
				if(strcmp(targets[i], "all") == 0)
				{
					all_target = 1;
					break;
				}
			}
		}
		
		/* default too all if we have no targets or default target */
		if(num_targets == 0 && !context->defaulttarget)
			all_target = 1;
		
		if(all_target)
		{
			/* build the all target */
			for(node = context->graph->first; node; node = node->next)
			{
				if(node->firstparent == NULL && node != context->target)
				{
					if(!node_add_dependency (context->target, node))
						return -1;
				}
			}
		}
		else
		{
			if(num_targets)
			{
				for(i = 0; i < num_targets; i++)
				{
					struct NODE *node = node_find(context->graph, targets[i]);
					if(!node)
					{
						printf("%s: target '%s' not found\n", session.name, targets[i]);
						return -1;
					}
					
					if(option_dependent)
					{
						/* TODO: this should perhaps do a reverse walk up in the tree to
							find all dependent node with commandline */
						struct NODELINK *parent;
						for(parent = node->firstparent; parent; parent = parent->next)
						{
							if(!node_add_dependency (context->target, parent->node))
								return -1;
						}
								
					}
					else
					{
						if(!node_add_dependency (context->target, node))
							return -1;
					}
				}
			}
			else
			{
				if(!node_add_dependency (context->target, context->defaulttarget))
					return -1;
			}

		}
	}

	/* zero out the global timestamp if we don't want to use it */
	if(option_no_scripttimestamp)
		context->globaltimestamp = 0;

	/* */	
	if(session.verbose)
		printf("%s: setup done\n", session.name);
	
	/* return success */
	return 0;
}
Esempio n. 7
0
int main(int argc, char *argv[])
{
	// Handle signals
	signal(SIGINT,shut_down);
	signal(SIGHUP,shut_down);
	signal(SIGTERM,shut_down);
	signal(SIGQUIT,shut_down);

	// HCI device number, MAC struct
	int device = 0;
	bdaddr_t bdaddr;
	bacpy(&bdaddr, BDADDR_ANY);

	// Time to scan. Scan time is roughly 1.28 seconds * scan_window
	// Originally this was always 8, now we adjust based on device:
	#ifdef OPENWRT
	int scan_window = 8;
	#elif PWNPLUG
	int scan_window = 5;
	#else
	int scan_window = 3;
	#endif

	// Maximum number of devices per scan
	int max_results = 255;
	int num_results;

	// Device cache and index
	int cache_index = 0;

	// HCI cache setting
	int flags = IREQ_CACHE_FLUSH;

	// Strings to hold MAC and name
	char addr[19] = {0};
	char addr_buff[19] = {0};

	// String for time
	char cur_time[20];

	// Process ID read from PID file
	int ext_pid;

	// Pointers to filenames
	char *infofilename = LIVE_INF;

	// Change default filename based on date
	char OUT_FILE[1000] = OUT_PATH;
	strncat(OUT_FILE, file_timestamp(),sizeof(OUT_FILE)-strlen(OUT_FILE)-1);
	char *outfilename = OUT_FILE;

	// Mode to open output file in
	char *filemode = "a+";

	// Output buffer
	char outbuffer[500];

	// Buffer for data from the second loop
	char exitbuffer[500];

	// Misc Variables
	int i, ri, opt;

	// Record numbner of BlueZ errors
	int error_count = 0;

	// Current epoch time
	long long int epoch;

	// Kernel version info
	struct utsname sysinfo;
	uname(&sysinfo);

	while ((opt=getopt_long(argc,argv,"+o:i:r:a:w:vxctghldbfenksmq", main_options, NULL)) != EOF)
	{
		switch (opt)
		{
		case 'i':
			if (!strncasecmp(optarg, "hci", 3))
				hci_devba(atoi(optarg + 3), &bdaddr);
			else
				str2ba(optarg, &bdaddr);
			break;
		case 'o':
			outfilename = strdup(optarg);
			break;
		case 'r':
			config.retry_count = atoi(optarg);
			break;
		case 'a':
			config.amnesia = atoi(optarg);
			break;
		case 'w':
			config.scan_window = round((atoi(optarg) / 1.28));
			break;
		case 'c':
			config.showclass = 1;
			break;
		case 'e':
			config.encode = 1;
			break;
		case 'f':
			config.friendlyclass = 1;
			break;
		case 'v':
			config.verbose = 1;
			break;
		case 'g':
			config.status = 1;
			break;
		case 't':
			config.showtime = 1;
			break;
		case 's':
			config.syslogonly = 1;
			break;
		case 'x':
			config.obfuscate = 1;
			break;
		case 'q':
			config.quiet = 1;
			break;
		case 'l':
			if(!LIVEMODE)
			{
				printf("Live mode has been disabled in this build. See documentation.\n");
				exit(0);
			}
			else
				config.bluelive = 1;
			break;
		case 'b':
			config.bluepropro = 1;
			break;
		case 'd':
			config.daemon = 1;
			break;
		case 'n':
			config.getname = 1;
			break;
		case 'm':
			if(!OUILOOKUP)
			{
				printf("Manufacturer lookups have been disabled in this build. See documentation.\n");
				exit(0);
			}
			else
				config.getmanufacturer = 1;
			break;
		case 'h':
			help();
			exit(0);
		case 'k':
			// Read PID from file into variable
			ext_pid = read_pid();
			if (ext_pid != 0)
			{
				printf("Killing Bluelog process with PID %i...",ext_pid);
				if(kill(ext_pid,15) != 0)
				{
					printf("ERROR!\n");
					printf("Unable to kill Bluelog process. Check permissions.\n");
					exit(1);
				}
				else
					printf("OK.\n");

				// Delete PID file
				unlink(PID_FILE);
			}
			else
				printf("No running Bluelog process found.\n");

			exit(0);
		default:
			printf("Unknown option. Use -h for help, or see README.\n");
			exit(1);
		}
	}

	// See if there is already a process running
	if (read_pid() != 0)
	{
		printf("Another instance of Bluelog is already running!\n");
		printf("Use the -k option to kill a running Bluelog process.\n");
		exit(1);
	}

	// Load config from file if no options given on command line
	if(cfg_exists() && argc == 1)
	{
		if (cfg_read() != 0)
		{
			printf("Error opening config file!\n");
			exit(1);
		}
		// Put interface into BT struct
		hci_devba(config.hci_device, &bdaddr);
	}

	// Perform sanity checks on varibles
	cfg_check();

	// Setup libmackerel
	mac_init();

	// Boilerplate
	if (!config.quiet)
	{
		printf("%s (v%s%s) by MS3FGX\n", APPNAME, VERSION, VER_MOD);
		#if defined OPENWRT || PWNPLUG
			printf("----");
		#endif
		printf("---------------------------\n");
	}

	// Show notification we loaded config from file
	if(cfg_exists() && argc == 1 && !config.quiet)
		printf("Config loaded from: %s\n", CFG_FILE);

	// Init Hardware
	ba2str(&bdaddr, config.addr);
	if (!strcmp(config.addr, "00:00:00:00:00:00"))
	{
		if (!config.quiet)
			printf("Autodetecting device...");
		device = hci_get_route(NULL);
		// Put autodetected device MAC into addr
		hci_devba(device, &bdaddr);
		ba2str(&bdaddr, config.addr);
	}
	else
	{
		if (!config.quiet)
			printf("Initializing device...");
		device = hci_devid(config.addr);
	}

	// Open device and catch errors
	config.bt_socket = hci_open_dev(device);
	if (device < 0 || config.bt_socket < 0)
	{
		// Failed to open device, that can't be good
		printf("\n");
		printf("Error initializing Bluetooth device!\n");
		exit(1);
	}

	// If we get here the device should be online.
	if (!config.quiet)
		printf("OK\n");

	// Status message for BPP
	if (!config.quiet)
		if (config.bluepropro)
			printf("Output formatted for BlueProPro.\n"
				   "More Info: www.hackfromacave.com\n");

	// Open socket
	if (config.udponly)
		open_udp_socket();

	// Open output file, unless in networking mode
	if (!config.syslogonly && !config.udponly)
	{
		if (config.bluelive)
		{
			// Change location of output file
			outfilename = LIVE_OUT;
			filemode = "w";
			if (!config.quiet)
				printf("Starting Bluelog Live...\n");
		}
		if (!config.quiet)
			printf("Opening output file: %s...", outfilename);
		if ((outfile = fopen(outfilename, filemode)) == NULL)
		{
			printf("\n");
			printf("Error opening output file!\n");
			exit(1);
		}
		if (!config.quiet)
			printf("OK\n");
	}
	else
		if (!config.quiet)
			printf("Network mode enabled, not creating log file.\n");

	// Open status file
	if (config.bluelive)
	{
		if (!config.quiet)
			printf("Opening info file: %s...", infofilename);
		if ((infofile = fopen(infofilename,"w")) == NULL)
		{
			printf("\n");
			printf("Error opening info file!\n");
			exit(1);
		}
		if (!config.quiet)
			printf("OK\n");
	}

	// Write PID file
	if (!config.daemon)
		write_pid(getpid());

	// Get and print time to console and file
	strcpy(cur_time, get_localtime());

	if (!config.daemon)
		printf("Scan started at [%s] on %s\n", cur_time, config.addr);

	if (config.showtime && (outfile != NULL))
	{
		fprintf(outfile,"[%s] Scan started on %s\n", cur_time, config.addr);
		// Make sure this gets written out
		fflush(outfile);
	}

	// Write info file for Bluelog Live
	if (config.bluelive)
	{
		fprintf(infofile,"<div class=\"sideitem\">%s Version: %s%s</div>\n", APPNAME, VERSION, VER_MOD);
		fprintf(infofile,"<div class=\"sideitem\">Device: %s</div>\n", config.addr);
		fprintf(infofile,"<div class=\"sideitem\">Started: %s</div>\n", cur_time);

		// Think we are done with you now
		fclose(infofile);
	}

	// Log success to this point
	syslog(LOG_INFO,"Init OK!");

	// Daemon switch
	if (config.daemon)
		daemonize();
	else
		if (!config.quiet)
			#if defined PWNPAD
			printf("Close this window to end scan.\n");
			#else
			printf("Hit Ctrl+C to end scan.\n");
			#endif

	// Init result struct
	results = (inquiry_info*)malloc(max_results * sizeof(inquiry_info));

	// Start scan, be careful with this infinite loop...
	for(;;)
	{
		// Flush results buffer
		memset(results, '\0', max_results * sizeof(inquiry_info));

		// Scan and return number of results
		num_results = hci_inquiry(device, scan_window, max_results, NULL, &results, flags);

		// A negative number here means an error during scan
		if(num_results < 0)
		{
			// Increment error count
			error_count++;

			// Ignore occasional errors on Pwn Plug and OpenWRT
			#if !defined PWNPLUG || OPENWRT
			// All other platforms, print error and bail out
			syslog(LOG_ERR,"Received error from BlueZ!");
			printf("Scan failed!\n");
			// Check for kernel 3.0.x
			if (!strncmp("3.0.",sysinfo.release,4))
			{
				printf("\n");
				printf("-----------------------------------------------------\n");
				printf("Device scanning failed, and you are running a 3.0.x\n");
				printf("Linux kernel. This failure is probably due to the\n");
				printf("following kernel bug:\n");
				printf("\n");
				printf("http://marc.info/?l=linux-kernel&m=131629118406044\n");
				printf("\n");
				printf("You will need to upgrade your kernel to at least the\n");
				printf("the 3.1 series to continue.\n");
				printf("-----------------------------------------------------\n");

			}
			shut_down(1);
			#else
			// Exit on back to back errors
			if (error_count > 5)
			{
				printf("Scan failed!\n");
				syslog(LOG_ERR,"BlueZ not responding, unrecoverable!");
				shut_down(1);
			}

			// Otherwise, throttle back a bit, might help
			sleep(1);
			#endif
		}
		else
		{
			// Clear error counter
			error_count = 0;
		}

		// Check if we need to reset device cache
		if ((cache_index + num_results) >= MAX_DEV)
		{
			syslog(LOG_INFO,"Resetting device cache...");
			memset(dev_cache, 0, sizeof(dev_cache));
			cache_index = 0;
		}



		// Loop through results
		for (i = 0; i < num_results; i++)
		{
			// Return current MAC from struct
			ba2str(&(results+i)->bdaddr, addr);

			// Compare to device cache
			for (ri = 0; ri <= cache_index; ri++)
			{
				// Determine if device is already logged
				if (strcmp (addr, dev_cache[ri].priv_addr) == 0)
				{
					// This device has been seen before

					// Increment seen count, update printed time
					dev_cache[ri].seen++;
					strcpy(dev_cache[ri].time, get_localtime());
					dev_cache[ri].missing_count = 0;

					// If we don't have a name, query again
					if ((dev_cache[ri].print == 3) && (dev_cache[ri].seen > config.retry_count))
					{
						syslog(LOG_INFO,"Unable to find name for %s!", addr);
						dev_cache[ri].print = 1;
					}
					else if ((dev_cache[ri].print == 3) && (dev_cache[ri].seen < config.retry_count))
					{
						// Query name
						strcpy(dev_cache[ri].name, namequery(&(results+i)->bdaddr));

						// Did we get one?
						if (strcmp (dev_cache[ri].name, "VOID") != 0)
						{
							syslog(LOG_INFO,"Name retry for %s successful!", addr);
							// Force print
							dev_cache[ri].print = 1;
						}
						else
							syslog(LOG_INFO,"Name retry %i for %s failed!",dev_cache[ri].seen, addr);
					}

					// Amnesia mode
					if (config.amnesia >= 0)
					{
						// Find current epoch time
						epoch = time(NULL);
						if ((epoch - dev_cache[ri].epoch) >= (config.amnesia * 60))
						{
							// Update epoch time
							dev_cache[ri].epoch = epoch;
							// Set device to print
							dev_cache[ri].print = 1;
						}
					}

					// This device is seen before, but has been away
					if (strcmp (dev_cache[ri].status, "gone") == 0)
					{
						dev_cache[ri].print = 1;
						strcpy(dev_cache[ri].status, "returned");
					}

					// Unless we need to get printed, move to next result
					if (dev_cache[ri].print != 1)
						break;
				}
				else if (strcmp (dev_cache[ri].addr, "") == 0)
				{
					// Write new device MAC (visible and internal use)
					strcpy(dev_cache[ri].addr, addr);
					strcpy(dev_cache[ri].priv_addr, addr);

					// Query for name
					if (config.getname)
						strcpy(dev_cache[ri].name, namequery(&(results+i)->bdaddr));
					else
						strcpy(dev_cache[ri].name, "IGNORED");

					// Get time found
					strcpy(dev_cache[ri].time, get_localtime());
					dev_cache[ri].epoch = time(NULL);

					// Class info
					dev_cache[ri].flags = (results+i)->dev_class[2];
					dev_cache[ri].major_class = (results+i)->dev_class[1];
					dev_cache[ri].minor_class = (results+i)->dev_class[0];

					// Init misc variables
					dev_cache[ri].seen = 1;
					dev_cache[ri].missing_count = 0;
					strcpy(dev_cache[ri].status, "new");

					// Increment index
					cache_index++;

					// If we have a device name, get printed
					if (strcmp (dev_cache[ri].name, "VOID") != 0)
						dev_cache[ri].print = 1;
					else
					{
						// Found with no name.
						// Print message to syslog, prevent printing, and move on
						syslog(LOG_INFO,"Device %s discovered with no name, will retry", dev_cache[ri].addr);
						dev_cache[ri].print = 3;
						break;
					}
				}

				// Ready to print?
				if (dev_cache[ri].print == 1)
				{
					// Encode MAC
					if (config.encode || config.obfuscate)
					{
						// Clear buffer
						memset(addr_buff, '\0', sizeof(addr_buff));

						if (config.obfuscate)
							strcpy(addr_buff, mac_obfuscate(dev_cache[ri].priv_addr));

						if (config.encode)
							strcpy(addr_buff, mac_encode(dev_cache[ri].priv_addr));

						// Copy to cache
						strcpy(dev_cache[ri].addr, addr_buff);
					}

					// Print everything to console if verbose is on, optionally friendly class info
					if (config.verbose)
					{
						if (config.friendlyclass)
						{
							printf("[%s] %s,%s,%s,(%s) - %s\n",\
								dev_cache[ri].time, dev_cache[ri].addr,\
								dev_cache[ri].name, device_class(dev_cache[ri].major_class,\
								dev_cache[ri].minor_class), device_capability(dev_cache[ri].flags), dev_cache[ri].status);
						}
						else
						{
							printf("[%s] %s,%s,0x%02x%02x%02x - %s\n",\
								dev_cache[ri].time, dev_cache[ri].addr,\
								dev_cache[ri].name, dev_cache[ri].flags,\
								dev_cache[ri].major_class, dev_cache[ri].minor_class, dev_cache[ri].status);
						}
					}

					if (config.bluelive)
					{
						// Write result with live function
						live_entry(ri);
					}
					else if (config.bluepropro)
					{
						// Set output format for BlueProPro
						fprintf(outfile,"%s", dev_cache[ri].addr);
						fprintf(outfile,",0x%02x%02x%02x", dev_cache[ri].flags,\
						dev_cache[ri].major_class, dev_cache[ri].minor_class);
						fprintf(outfile,",%s\n", dev_cache[ri].name);
					}
					else
					{
						// Flush buffer
						memset(outbuffer, 0, sizeof(outbuffer));

						// Print time first if enabled
						if (config.showtime)
							sprintf(outbuffer,"[%s],", dev_cache[ri].time);

						// Always output MAC
						sprintf(outbuffer+strlen(outbuffer),"%s", dev_cache[ri].addr);

						// Optionally output class
						if (config.showclass)
							sprintf(outbuffer+strlen(outbuffer),",0x%02x%02x%02x", dev_cache[ri].flags,\
							dev_cache[ri].major_class, dev_cache[ri].minor_class);

						// "Friendly" version of class info
						if (config.friendlyclass)
							sprintf(outbuffer+strlen(outbuffer),",%s,(%s)",\
							device_class(dev_cache[ri].major_class, dev_cache[ri].minor_class),\
							device_capability(dev_cache[ri].flags));

						// Get manufacturer
						if (config.getmanufacturer)
							sprintf(outbuffer+strlen(outbuffer),",%s", mac_get_vendor(dev_cache[ri].priv_addr));

						// Append the name
						if (config.getname)
							sprintf(outbuffer+strlen(outbuffer),",%s", dev_cache[ri].name);

						// Append the status
						if (config.status)
							sprintf(outbuffer+strlen(outbuffer)," - %s", dev_cache[ri].status);

						// Send buffer, else file. File needs newline
						if (config.syslogonly)
							syslog(LOG_INFO,"%s", outbuffer);
						else if (config.udponly)
						{
							// Append newline to socket, kind of hacky
							sprintf(outbuffer+strlen(outbuffer),"\n");
							send_udp_msg(outbuffer);
						}
						else
							fprintf(outfile,"%s\n",outbuffer);
					}
					dev_cache[ri].print = 0;
					break;
				}
				// If we make it this far, it means we will check next stored device
			}

			// If there's a file open, write changes
			if (outfile != NULL)
				fflush(outfile);
		}

		// Now check if any devices are missing

		// Loop through the cache
		for (ri = 0; ri < cache_index; ri++)
		{

			for (i = 0; i <= num_results; i++)
			{
				// Return current MAC from struct
				ba2str(&(results+i)->bdaddr, addr);

				// Determine if device still present
				if (strcmp (addr, dev_cache[ri].priv_addr) == 0)
				{

					break;
				}

				// Device not found.
				if (i == num_results)
				{
					// The device is missing but not marked as gone -> it has just disappeared
					if (strcmp(dev_cache[ri].status, "gone") != 0)
					{
						// Devices aren't present every time. Wait a while before marking it gone
						if (dev_cache[ri].missing_count < 10)
						{
							dev_cache[ri].missing_count++;
						}
						else
						// It's really gone :(
						{
							strcpy(dev_cache[ri].status,"gone");

							// Print to console
							if (config.verbose) {
								printf("[%s] %s,%s - %s\n",\
										dev_cache[ri].time, dev_cache[ri].addr,\
										dev_cache[ri].name, dev_cache[ri].status);

							}

							// Flush buffer
							memset(exitbuffer, 0, sizeof(exitbuffer));

							// Print time first if enabled
							if (config.showtime)
								sprintf(exitbuffer,"[%s],", dev_cache[ri].time);

							// Always output MAC
							sprintf(exitbuffer+strlen(exitbuffer),"%s", dev_cache[ri].addr);

							// Append the name
							if (config.getname)
								sprintf(exitbuffer+strlen(exitbuffer),",%s", dev_cache[ri].name);

							// Append the status
							if (config.status)
								sprintf(exitbuffer+strlen(exitbuffer)," - %s", dev_cache[ri].status);

							// Send buffer, else file. File needs newline
							if (config.syslogonly)
								syslog(LOG_INFO,"%s", exitbuffer);
							else if (config.udponly)
							{
								// Append newline to socket, kind of hacky
								sprintf(exitbuffer+strlen(exitbuffer),"\n");
								send_udp_msg(exitbuffer);
							}
							else
								fprintf(outfile,"%s\n",exitbuffer);

							// If there's a file open, write changes
							if (outfile != NULL)
								fflush(outfile);

						}
					}

				}

			}

		}



	}
	// If we get here, shut down
	shut_down(0);
	// STFU
	return (1);
}