Beispiel #1
0
static void read_one(ddns_alias_t *alias, int nonslookup)
{
	FILE *fp;
        char path[256];

        alias->last_update = 0;
        memset(alias->address, 0, sizeof(alias->address));

	cache_file(alias->name, path, sizeof(path));
	fp = fopen(path, "r");
	if (!fp) {
                if (nonslookup)
                        return;

		/* Try a DNS lookup of our last known IP#. */
                nslookup(alias);
	} else {
		struct stat st;
		char address[MAX_ADDRESS_LEN];

		if (fgets(address, sizeof(address), fp)) {
			logit(LOG_INFO, "Cached IP# %s from previous invocation.", address);
                        strncpy(alias->address, address, sizeof(alias->address));
		}

		/* Initialize time since last update from modification time of cache file. */
		if (!fstat(fileno(fp), &st)) {
			alias->last_update = st.st_mtime;
			logit(LOG_INFO, "Last update of %s on %s", alias->name, ctime(&st.st_mtime));
		}

		fclose(fp);
	}
}
Beispiel #2
0
void network_peer_cache::flush()
{
	std::ofstream cache_file("peer_cache");

	for (std::vector<ip::tcp::endpoint>::iterator it = peers_.begin(); it != peers_.end(); ++it)
		cache_file << it->address().to_string() << ':' << it->port();
}
Beispiel #3
0
FIMULTIBITMAP * DLL_CALLCONV
FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) {
	try {
		BOOL read_only = FALSE;	// modifications (if any) will be stored into the memory cache

		if (io && handle) {

			// retrieve the plugin list to find the node belonging to this plugin
			PluginList *list = FreeImage_GetPluginList();

			if (list) {
				PluginNode *node = list->FindNodeFromFIF(fif);

				if (node) {
					std::auto_ptr<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP);
					std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER);
					std::auto_ptr<FreeImageIO> tmp_io (new FreeImageIO (*io));
					header->io = tmp_io.get();
					header->m_filename = NULL;
					header->node = node;
					header->fif = fif;
					header->handle = handle;
					header->changed = FALSE;
					header->read_only = read_only;	
					header->m_cachefile = NULL;
					header->cache_fif = fif;
					header->load_flags = flags;

					// store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure

					bitmap->data = header.get();

					// cache the page count

					header->page_count = FreeImage_InternalGetPageCount(bitmap.get());

					// allocate a continueus block to describe the bitmap

					header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1));

					if (!read_only) {
						// set up the cache
						std::auto_ptr<CacheFile> cache_file (new CacheFile("", TRUE));
						
						if (cache_file->open()) {
							header->m_cachefile = cache_file.release();
						}
					}
					tmp_io.release();
					header.release();
					return bitmap.release();
				}
			}
		}
	} catch (std::bad_alloc &) {
		/** @todo report error */
	}
	return NULL;
}
Beispiel #4
0
CPLErr GDALWMSCache::Write(const char *key, const CPLString &file_name) {
    CPLString cache_file(KeyToCacheFile(key));
    //	printf("GDALWMSCache::Write(%s, %s) -> %s\n", key, file_name.c_str());
    if (CPLCopyFile(cache_file.c_str(), file_name.c_str()) != CE_None) {
        MakeDirs(cache_file.c_str());
        CPLCopyFile(cache_file.c_str(), file_name.c_str());
    }

    return CE_None;
}
Beispiel #5
0
CPLString GDALWMSCache::KeyToCacheFile(const char *key) {
    CPLString hash(MD5String(key));
    CPLString cache_file(m_cache_path);

    if (cache_file.size() && (cache_file[cache_file.size() - 1] != '/')) cache_file.append(1, '/');
    for (int i = 0; i < m_cache_depth; ++i) {
        cache_file.append(1, hash[i]);
        cache_file.append(1, '/');
    }
    cache_file.append(hash);
    cache_file.append(m_postfix);
    return cache_file;
}
Beispiel #6
0
CPLErr GDALWMSCache::Read(const char *key, CPLString *file_name) {
    CPLErr ret = CE_Failure;
    CPLString cache_file(KeyToCacheFile(key));
    VSILFILE* fp = VSIFOpenL(cache_file.c_str(), "rb");
    if (fp != NULL)
    {
        VSIFCloseL(fp);
        *file_name = cache_file;
        ret = CE_None;
    }
    //    printf("GDALWMSCache::Read(...) -> %s\n", cache_file.c_str());

    return ret;
}
Beispiel #7
0
/* Update cache with new IP 
 *  /var/run/inadyn/my.server.name.cache { LAST-IPADDR } MTIME */
int write_cache_file(ddns_alias_t *alias)
{
	FILE *fp;
        char path[256];

	cache_file(alias->name, path, sizeof(path));
	fp = fopen(path, "w");
	if (fp) {
		fprintf(fp, "%s", alias->address);
		fclose(fp);

		return 0;
	}

	return 1;
}
Beispiel #8
0
static void
io_loop(void)
{
	time_t delay;

	while (ServerRunning)

	{
		/* Run pending events, then get the number of seconds to the next
		 * event
		 */

		delay = eventNextTime();
		if(delay <= CurrentTime)
			eventRun();


		comm_select(250);

		/*
		 * Check to see whether we have to rehash the configuration ..
		 */
		if(dorehash)
		{
			rehash(1);
			dorehash = 0;
		}
		if(dorehashbans)
		{
			rehash_bans(1);
			dorehashbans = 0;
		}
		if(doremotd)
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Got signal SIGUSR1, reloading ircd motd file");
			free_cachefile(user_motd);
			user_motd = cache_file(MPATH, "ircd.motd", 0);
			doremotd = 0;
		}
	}
}
Beispiel #9
0
/* Create pid and cache file repository, make sure we can write to it.  If
 * we are restarted we cannot otherwise make sure we've not already updated
 * the IP -- and the user will be locked-out of their DDNS server provider
 * for excessive updates. */
int os_check_perms(void *UNUSED(arg))
{
	char path[256];

	/* Create files with permissions 0644 */
	umask(S_IWGRP | S_IWOTH);

	cache_file("example.com", path, sizeof(path));
	if (mkparentdir(path)) {
		logit(LOG_ERR, "No write permission to %s, aborting.", path);
		logit(LOG_ERR, "Cannot guarantee DDNS server won't lock you out for excessive updates.");

		return RC_FILE_IO_ACCESS_ERROR;
	}

	/* Not creating a pidfile is OK, the cache file is the critical point. */
	pidfile(pidfile_path);

	return 0;
}
Beispiel #10
0
network_peer_cache::network_peer_cache()
	: getp_(0)
{
	std::ifstream cache_file("peer_cache");

	while (cache_file && !cache_file.eof()) {
		std::string ip;
		cache_file >> ip;
		std::string::size_type separator = ip.find(':');

		if (separator == std::string::npos)
			continue;

		boost::asio::ip::address_v4 address = boost::asio::ip::address_v4::from_string(ip.substr(0, separator));

		DLOG(INFO) << "Loading cached peer: " << address.to_string() << ':' << ip.substr(separator + 1);

		peers_.push_back( ip::tcp::endpoint( address, boost::lexical_cast<unsigned short>( ip.substr(separator + 1) ) ) );
	}

}
Beispiel #11
0
int main(int argc, char *argv[])
{
   int i;
   int key;
   char *name;
   time_t start;
   size_t total=0;
   pid_t pid;

   start=time(NULL);
   if (getenv("DEBUG_CACHER")!=NULL)
     debug=1;
   if (argc==1){
     status();
     return 0;
   }
   if (argv[1][0]=='-'){
     cleanup();
     return 0;
   }
   signal(2,cleanup);
   signal(15,cleanup);
   for (key=SHM_KEY,i=1;i<argc;i++,key++){
      total+=cache_file(argv[i],key); 
   }
   if (debug)
     fprintf(stderr,"Total: %ld bytes in %ld seconds (%7.2f MB/s)\n",total,time(NULL)-start,(double)total/(double)(1024.0*1024.0*(time(NULL)-start)));
   if (pid=fork()){ //parent
     if (debug)
       fprintf(stderr,"Forking\n");
     return 0;
   }
   else{
     while(1){ sleep(60); }
   }
}
Beispiel #12
0
FIMULTIBITMAP * DLL_CALLCONV
FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) {

	FILE *handle = NULL;
	try {
		// sanity check on the parameters

		if (create_new) {
			read_only = FALSE;
		}

		// retrieve the plugin list to find the node belonging to this plugin

		PluginList *list = FreeImage_GetPluginList();

		if (list) {
			PluginNode *node = list->FindNodeFromFIF(fif);

			if (node) {
				std::auto_ptr<FreeImageIO> io (new FreeImageIO);

				SetDefaultIO(io.get());

				if (!create_new) {
					handle = fopen(filename, "rb");
					if (handle == NULL) {
						return NULL;
					}
				}

				std::auto_ptr<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP);
				std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER);
				header->m_filename = new char[strlen(filename) + 1];
				strcpy(header->m_filename, filename);
				header->node = node;
				header->fif = fif;
				header->io = io.get ();
				header->handle = handle;
				header->changed = FALSE;
				header->read_only = read_only;
				header->m_cachefile = NULL;
				header->cache_fif = fif;
				header->load_flags = flags;

				// store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure

				bitmap->data = header.get();

				// cache the page count

				header->page_count = FreeImage_InternalGetPageCount(bitmap.get());

				// allocate a continueus block to describe the bitmap

				if (!create_new) {
					header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1));
				}

				// set up the cache

				if (!read_only) {
					std::string cache_name;
					ReplaceExtension(cache_name, filename, "ficache");

					std::auto_ptr<CacheFile> cache_file (new CacheFile(cache_name, keep_cache_in_memory));

					if (cache_file->open()) {
						// we can use release() as std::bad_alloc won't be thrown from here on
						header->m_cachefile = cache_file.release();
					} else {
						// an error occured ...
						fclose(handle);
						return NULL;
					}
				}
				// return the multibitmap
				// std::bad_alloc won't be thrown from here on
				header.release(); // now owned by bitmap
				io.release();	  // now owned by bitmap
				return bitmap.release(); // now owned by caller
			}
		}
	} catch (std::bad_alloc &) {
		/** @todo report error */
	}
	if (handle)
		fclose(handle);
	return NULL;
}
Beispiel #13
0
int _rfs_open(struct rfs_instance *instance, const char *path, int flags, uint64_t *desc)
{
	if (instance->sendrecv.socket == -1)
	{
		return -ECONNABORTED;
	}

	unsigned path_len = strlen(path) + 1;
	uint16_t fi_flags = rfs_file_flags(flags);
	
	unsigned overall_size = sizeof(fi_flags) + path_len;

	struct rfs_command cmd = { cmd_open, overall_size };

	char *buffer = malloc(cmd.data_len);

	pack(path, path_len, 
	pack_16(&fi_flags, buffer
	));

	send_token_t token = { 0 };
	if (do_send(&instance->sendrecv, 
		queue_data(buffer, overall_size, 
		queue_cmd(&cmd, &token))) < 0)
	{
		free(buffer);
		return -ECONNABORTED;
	}

	free(buffer);

	struct rfs_answer ans = { 0 };

	if (rfs_receive_answer(&instance->sendrecv, &ans) == -1)
	{
		return -ECONNABORTED;
	}

	if (ans.command != cmd_open)
	{
		return cleanup_badmsg(instance, &ans);
	}

	if (ans.ret == -1)
	{
		if (ans.ret_errno == -ENOENT)
		{
			delete_from_cache(&instance->attr_cache, path);
		}

		return -ans.ret_errno;
	}

	uint32_t stat_failed = 0;
	uint32_t user_len = 0;
	uint32_t group_len = 0;

#define ans_buffer_size sizeof(*desc) \
+ sizeof(stat_failed) + STAT_BLOCK_SIZE + sizeof(user_len) + sizeof(group_len) \
+ (MAX_SUPPORTED_NAME_LEN + 1) + (MAX_SUPPORTED_NAME_LEN + 1)

	char ans_buffer[ans_buffer_size]  = { 0 };
	
	if (ans.data_len > sizeof(ans_buffer))
	{
		return cleanup_badmsg(instance, &ans);
	}
#undef ans_buffer_size
	
	if (rfs_receive_data(&instance->sendrecv, ans_buffer, ans.data_len) == -1)
	{
		return -ECONNABORTED;
	}

	struct stat stbuf = { 0 };

	const char *user = 
	unpack_32(&group_len, 
	unpack_32(&user_len, 
	unpack_stat(&stbuf, 
	unpack_32(&stat_failed, 
	unpack_64(desc, ans_buffer
	)))));
	const char *group = user + user_len;

	DEBUG("handle: %llu\n", (long long unsigned)(*desc));

	stbuf.st_uid = resolve_username(instance, user);
	stbuf.st_gid = resolve_groupname(instance, group, user);

	if (ans.ret_errno == 0)
	{
		if (stat_failed == 0)
		{
			cache_file(&instance->attr_cache, path, &stbuf);
		}
		
		resume_add_file_to_open_list(&instance->resume.open_files, path, flags, *desc);
	}
	else
	{
		delete_from_cache(&instance->attr_cache, path);
	}
	
	return ans.ret == -1 ? -ans.ret_errno : ans.ret;
}
bool http_cache::is_in_cache (const std::string& url) const
{
    return fs::exists(cache_file(url));
}
Beispiel #15
0
void QMakeSourceFileInfo::loadCache(const QString &cf)
{
    if(cf.isEmpty())
        return;

#ifdef QMAKE_USE_CACHE
    QMakeLocalFileName cache_file(cf);
    int fd = open(QMakeLocalFileName(cf).local().toLatin1(), O_RDONLY);
    if(fd == -1)
        return;
    QFileInfo cache_fi = findFileInfo(cache_file);
    if(!cache_fi.exists() || cache_fi.isDir())
        return;

    QFile file;
    if(!file.open(QIODevice::ReadOnly, fd))
        return;
    QTextStream stream(&file);

    if(stream.readLine() == qmake_version()) { //version check
        stream.skipWhiteSpace();

        bool verified = true;
        { //cache verification
            QMap<QString, QStringList> verify;
            int len = stream.readLine().toInt();
            for(int i = 0; i < len; ++i) {
                QString var = stream.readLine();
                QString val = stream.readLine();
                verify.insert(var, val.split(';', QString::SkipEmptyParts));
            }
            verified = verifyCache(verify);
        }
        if(verified) {
            stream.skipWhiteSpace();
            if(!files)
                files = new SourceFiles;
            while(!stream.atEnd()) {
                QString source = stream.readLine();
                QString type = stream.readLine();
                QString depends = stream.readLine();
                QString mocable = stream.readLine();
                stream.skipWhiteSpace();

                QMakeLocalFileName fn(source);
                QFileInfo fi = findFileInfo(fn);

                SourceFile *file = files->lookupFile(fn);
                if(!file) {
                    file = new SourceFile;
                    file->file = fn;
                    files->addFile(file);
                    file->type = (SourceFileType)type.toInt();
                    file->exists = fi.exists();
                }
                if(fi.exists() && fi.lastModified() < cache_fi.lastModified()) {
                    if(!file->dep_checked) { //get depends
                        if(!file->deps)
                            file->deps = new SourceDependChildren;
                        file->dep_checked = true;
                        QStringList depend_list = depends.split(";", QString::SkipEmptyParts);
                        for(int depend = 0; depend < depend_list.size(); ++depend) {
                            QMakeLocalFileName dep_fn(depend_list.at(depend));
                            QFileInfo dep_fi(findFileInfo(dep_fn));
                            SourceFile *dep = files->lookupFile(dep_fn);
                            if(!dep) {
                                dep = new SourceFile;
                                dep->file = dep_fn;
                                dep->exists = dep_fi.exists();
                                dep->type = QMakeSourceFileInfo::TYPE_UNKNOWN;
                                files->addFile(dep);
                            }
                            dep->included_count++;
                            file->deps->addChild(dep);
                        }
                    }
                    if(!file->moc_checked) { //get mocs
                        file->moc_checked = true;
                        file->mocable = mocable.toInt();
                    }
                }
            }
        }
    }
#endif
}
/*
 *	Store logins in the RADIUS utmp file.
 */
static rlm_rcode_t radutmp_accounting(void *instance, REQUEST *request)
{
	rlm_radutmp_t	*inst = instance;
	struct radutmp	utmp, u;
	VALUE_PAIR	*vp;
	int		status = -1;
	uint32_t	nas_address = 0;
	uint32_t	framed_address = 0;
	int		protocol = -1;
	int		fd;
	int		port_seen = 0;
	char		buffer[256];
	char		filename[1024];
	char		ip_name[32]; /* 255.255.255.255 */
	const char	*nas;
	NAS_PORT	*nas_port, myPort;
	radutmp_cache_t *cache;
	int		read_size;
	rbnode_t	*node;

	/*
	 *	Which type is this.
	 */
	if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0, TAG_ANY)) == NULL) {
		radlog(L_ERR, "rlm_radutmp: No Accounting-Status-Type record.");
		return RLM_MODULE_NOOP;
	}
	status = vp->vp_integer;

	/*
	 *	Look for weird reboot packets.
	 *
	 *	ComOS (up to and including 3.5.1b20) does not send
	 *	standard PW_STATUS_ACCOUNTING_* messages.
	 *
	 *	Check for:  o no Acct-Session-Time, or time of 0
	 *		    o Acct-Session-Id of "00000000".
	 *
	 *	We could also check for NAS-Port, that attribute
	 *	should NOT be present (but we don't right now).
	 */
	if ((status != PW_STATUS_ACCOUNTING_ON) &&
	    (status != PW_STATUS_ACCOUNTING_OFF)) do {
		int check1 = 0;
		int check2 = 0;

		if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0, TAG_ANY))
		     == NULL || vp->vp_date == 0)
			check1 = 1;
		if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID, 0, TAG_ANY))
		     != NULL && vp->length == 8 &&
		     memcmp(vp->vp_strvalue, "00000000", 8) == 0)
			check2 = 1;
		if (check1 == 0 || check2 == 0) {
#if 0 /* Cisco sometimes sends START records without username. */
			radlog(L_ERR, "rlm_radutmp: no username in record");
			return RLM_MODULE_FAIL;
#else
			break;
#endif
		}
		radlog(L_INFO, "rlm_radutmp: converting reboot records.");
		if (status == PW_STATUS_STOP)
			status = PW_STATUS_ACCOUNTING_OFF;
		if (status == PW_STATUS_START)
			status = PW_STATUS_ACCOUNTING_ON;
	} while(0);

	memset(&utmp, 0, sizeof(utmp));
	utmp.porttype = 'A';

	/*
	 *	First, find the interesting attributes.
	 */
	for (vp = request->packet->vps; vp; vp = vp->next) {
		switch (vp->da->attribute) {
			case PW_LOGIN_IP_HOST:
			case PW_FRAMED_IP_ADDRESS:
				framed_address = vp->vp_ipaddr;
				utmp.framed_address = vp->vp_ipaddr;
				break;
			case PW_FRAMED_PROTOCOL:
				protocol = vp->vp_integer;
				break;
			case PW_NAS_IP_ADDRESS:
				nas_address = vp->vp_ipaddr;
				utmp.nas_address = vp->vp_ipaddr;
				break;
			case PW_NAS_PORT:
				utmp.nas_port = vp->vp_integer;
				port_seen = 1;
				break;
			case PW_ACCT_DELAY_TIME:
				utmp.delay = vp->vp_integer;
				break;
			case PW_ACCT_SESSION_ID:
				/*
				 *	If it's too big, only use the
				 *	last bit.
				 */
				if (vp->length > sizeof(utmp.session_id)) {
					int length = vp->length - sizeof(utmp.session_id);

					/*
					 * 	Ascend is br0ken - it
					 * 	adds a \0 to the end
					 * 	of any string.
					 * 	Compensate.
					 */
					if (vp->vp_strvalue[vp->length - 1] == 0) {
						length--;
					}

					memcpy(utmp.session_id,
					      vp->vp_strvalue + length,
					      sizeof(utmp.session_id));
				} else {
					memset(utmp.session_id, 0,
					       sizeof(utmp.session_id));
					memcpy(utmp.session_id,
					       vp->vp_strvalue,
					       vp->length);
				}
				break;
			case PW_NAS_PORT_TYPE:
				if (vp->vp_integer <= 4)
					utmp.porttype = porttypes[vp->vp_integer];
				break;
			case PW_CALLING_STATION_ID:
				if(inst->callerid_ok)
					strlcpy(utmp.caller_id,
						(char *)vp->vp_strvalue,
						sizeof(utmp.caller_id));
				break;
		}
	}

	/*
	 *	If we didn't find out the NAS address, use the
	 *	originator's IP address.
	 */
	if (nas_address == 0) {
		nas_address = request->packet->src_ipaddr;
		utmp.nas_address = nas_address;
		nas = request->client->shortname;

	} else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == nas_address) {		/* might be a client, might not be. */
		nas = request->client->shortname;

	} else {
		/*
		 *	The NAS isn't a client, it's behind
		 *	a proxy server.  In that case, just
		 *	get the IP address.
		 */
		nas = ip_ntoa(ip_name, nas_address);
	}


	/*
	 *	Set the protocol field.
	 */
	if (protocol == PW_PPP)
		utmp.proto = 'P';
	else if (protocol == PW_SLIP)
		utmp.proto = 'S';
	else
		utmp.proto = 'T';

	utmp.time = request->timestamp - utmp.delay;

	/*
	 *	Get the utmp filename, via xlat.
	 */
	radius_xlat(filename, sizeof(filename), inst->filename, request, NULL);

	/*
	 *	Future: look up filename in filename tree, to get
	 *	radutmp_cache_t pointer
	 */
	cache = &inst->cache;

	/*
	 *	For now, double-check the filename, to be sure it isn't
	 *	changing.
	 */
	if (!cache->filename) {
		cache->filename = strdup(filename);
		rad_assert(cache->filename != NULL);

	} else if (strcmp(cache->filename, filename) != 0) {
		radlog(L_ERR, "rlm_radutmp: We do not support dynamically named files.");
		return RLM_MODULE_FAIL;
	}

	/*
	 *	If the lookup failed, create a new one, and add it
	 *	to the filename tree, and cache the file, as below.
	 */

	/*
	 *	For aging, in the future.
	 */
	cache->last_used = request->timestamp;

	/*
	 *	If we haven't already read the file, then read the
	 *	entire file, in order to cache its entries.
	 */
	if (!cache->cached_file) {
		cache_file(inst, cache);
	}

	/*
	 *	See if this was a reboot.
	 *
	 *	Hmm... we may not want to zap all of the users when
	 *	the NAS comes up, because of issues with receiving
	 *	UDP packets out of order.
	 */
	if (status == PW_STATUS_ACCOUNTING_ON && nas_address) {
		radlog(L_INFO, "rlm_radutmp: NAS %s restarted (Accounting-On packet seen)",
		       nas);
		if (!radutmp_zap(inst, cache, nas_address, utmp.time)) {
			rad_assert(0 == 1);
		}
		return RLM_MODULE_OK;
	}

	if (status == PW_STATUS_ACCOUNTING_OFF && nas_address) {
		radlog(L_INFO, "rlm_radutmp: NAS %s rebooted (Accounting-Off packet seen)",
		       nas);
		if (!radutmp_zap(inst, cache, nas_address, utmp.time)) {
			rad_assert(0 == 1);
		}
		return RLM_MODULE_OK;
	}

	/*
	 *	If we don't know this type of entry, then pretend we
	 *	succeeded.
	 */
	if (status != PW_STATUS_START &&
	    status != PW_STATUS_STOP &&
	    status != PW_STATUS_ALIVE) {
		radlog(L_ERR, "rlm_radutmp: NAS %s port %u unknown packet type %d, ignoring it.",
		       nas, utmp.nas_port, status);
		return RLM_MODULE_NOOP;
	}

	/*
	 *	Perhaps we don't want to store this record into
	 *	radutmp. We skip records:
	 *
	 *	- without a NAS-Port (telnet / tcp access)
	 *	- with the username "!root" (console admin login)
	 */
	if (!port_seen) {
		DEBUG2("  rlm_radutmp: No NAS-Port in the packet.  Cannot do anything.");
		DEBUG2("  rlm_radumtp: WARNING: checkrad will probably not work!");
		return RLM_MODULE_NOOP;
	}

	/*
	 *	Translate the User-Name attribute, or whatever else
	 *	they told us to use.
	 */
	*buffer = '\0';
	radius_xlat(buffer, sizeof(buffer), inst->username, request, NULL);

	/*
	 *	Don't log certain things...
	 */
	if (strcmp(buffer, "!root") == 0) {
		DEBUG2("  rlm_radutmp: Not recording administrative user");

		return RLM_MODULE_NOOP;
	}
	strlcpy(utmp.login, buffer, RUT_NAMESIZE);

	/*
	 *	First, try to open the file.  If it doesn't exist,
	 *	nuke the existing caches, and try to create it.
	 *
	 *	FIXME: Create any intermediate directories, as
	 *	appropriate.  See rlm_detail.
	 */
	fd = open(cache->filename, O_RDWR, inst->permission);
	if (fd < 0) {
		if (errno == ENOENT) {
			DEBUG2("  rlm_radutmp: File %s doesn't exist, creating it.", cache->filename);
			if (!cache_reset(inst, cache)) return RLM_MODULE_FAIL;

			/*
			 *	Try to create the file.
			 */
			fd = open(cache->filename, O_RDWR | O_CREAT,
				  inst->permission);
		}
	} else {		/* exists, but may be empty */
		struct stat buf;

		/*
		 *	If the file is empty, reset the cache.
		 */
		if ((stat(cache->filename, &buf) == 0) &&
		    (buf.st_size == 0) &&
		    (!cache_reset(inst, cache))) {
			return RLM_MODULE_FAIL;
		}
		DEBUG2("  rlm_radutmp: File %s was truncated.  Resetting cache.",
		       cache->filename);
	}

	/*
	 *	Error from creation, or error other than ENOENT: die.
	 */
	if (fd < 0) {
		radlog(L_ERR, "rlm_radutmp: Error accessing file %s: %s",
		       cache->filename, strerror(errno));
		return RLM_MODULE_FAIL;
	}

	/*
	 *	OK.  Now that we've prepared everything we want to do,
	 *	let's see if we've cached the entry.
	 */
	myPort.nas_address = utmp.nas_address;
	myPort.nas_port = utmp.nas_port;

	pthread_mutex_lock(&cache->mutex);
	node = rbtree_find(cache->nas_ports, &myPort);
	pthread_mutex_unlock(&cache->mutex);

	if (node) {
		nas_port = rbtree_node2data(cache->nas_ports, node);
#if 0

		/*
		 *	stat the file, and get excited if it's been
		 *	truncated.
		 *
		 *	i.e wipe out the cache, and re-read the file.
		 */

		/*
		 *	Now find the new entry.
		 */
		pthread_mutex_lock(&cache->mutex);
		node = rbtree_find(cache->nas_ports, &myPort);
		pthread_mutex_unlock(&cache->mutex);
#endif
	}

	if (!node) {
		radutmp_simul_t *user;

		/*
		 *	Not found in the cache, and we're trying to
		 *	delete an existing record: ignore it.
		 */
		if (status == PW_STATUS_STOP) {
			DEBUG2("  rlm_radumtp: Logout entry for NAS %s port %u with no Login: ignoring it.",
			       nas, utmp.nas_port);
			return RLM_MODULE_NOOP;
		}

		pthread_mutex_lock(&cache->mutex);

		/*
		 *	It's a START or ALIVE.  Try to find a free
		 *	offset where we can store the new entry, or
		 *	create one, if one doesn't already exist.
		 */
		if (!cache->free_offsets) {
			cache->free_offsets = rad_malloc(sizeof(NAS_PORT));
			memset(cache->free_offsets, 0,
			       sizeof(*(cache->free_offsets)));
			cache->free_offsets->offset = cache->max_offset;
			cache->max_offset += sizeof(u);
		}

		/*
		 *	Grab the offset, and put it into the various
		 *	caches.
		 */
		nas_port = cache->free_offsets;
		cache->free_offsets = nas_port->next;

		nas_port->nas_address = nas_address;
		nas_port->nas_port = utmp.nas_port;

		if (!rbtree_insert(cache->nas_ports, nas_port)) {
			rad_assert(0 == 1);
		}

		/*
		 *	Allocate new entry, and add it
		 *	to the tree.
		 */
		user = rad_malloc(sizeof(user));
		strlcpy(user->login, utmp.login,
			sizeof(user->login));
		user->simul_count = 1;

		if (!rbtree_insert(inst->user_tree, user)) {
			rad_assert(0 == 1);
		}

		pthread_mutex_unlock(&cache->mutex);

	}

	/*
	 *	Entry was found, or newly created in the cache.
	 *	Seek to the place in the file.
	 */
	lseek(fd, nas_port->offset, SEEK_SET);

	/*
	 *	Lock the utmp file, prefer lockf() over flock().
	 */
	rad_lockfd(fd, LOCK_LEN);

	/*
	 *	If it WAS found in the cache, double-check it against
	 *	what is in the file.
	 */
	if (node) {
		/*
		 *	If we didn't read anything, then this entry
		 *	doesn't exist.
		 *
		 *	Similarly, if the entry in the file doesn't
		 *	match what we recall, then nuke the cache
		 *	entry.
		 */
		read_size = read(fd, &u, sizeof(u));
		if ((read_size < 0) ||
		    ((read_size > 0) && (read_size  != sizeof(u)))) {
			/*
			 *	Bad read, or bad record.
			 */
			radlog(L_ERR, "rlm_radutmp: Badly formed file %s",
			       cache->filename);
			close(fd);
			return RLM_MODULE_FAIL;
		}

		rad_assert(read_size != 0);

		/*
		 *	We've read a record, go poke at it.
		 */
		if (read_size > 0) {
			/*
			 *	If these aren't true, then
			 *
			 *	a) we have cached a "logout" entry,
			 *	   which we don't do.
			 *
			 *	b) we have cached the wrong NAS address
			 *
			 *	c) we have cached the wrong NAS port.
			 */
			rad_assert(u.type == P_LOGIN);
			rad_assert(u.nas_address == utmp.nas_address);
			rad_assert(u.nas_port == utmp.nas_port);

			/*
			 *	An update for the same session.
			 */
			if (strncmp(utmp.session_id, u.session_id,
				    sizeof(u.session_id)) == 0) {

				/*
				 *	It's a duplicate start, so we
				 *	don't bother writing it.
				 */
				if (status == PW_STATUS_START) {
					DEBUG2("  rlm_radutmp: Login entry for NAS %s port %u duplicate, ignoring it.",
					       nas, u.nas_port);
					close(fd);
					return RLM_MODULE_OK;


				/*
				 *	ALIVE for this session, keep the
				 *	original login time.
				 */
				} else if (status == PW_STATUS_ALIVE) {
					utmp.time = u.time;

				/*
				 *	Stop: delete it from our cache.
				 */
				} else if (status == PW_STATUS_STOP) {
					radutmp_simul_t *user, myUser;

					pthread_mutex_lock(&cache->mutex);
					rbtree_deletebydata(cache->nas_ports,
							    nas_port);

					strlcpy(myUser.login,
						u.login, sizeof(myUser.login));
					user = rbtree_finddata(inst->user_tree,
							       &myUser);
					rad_assert(user != NULL);
					rad_assert(user->simul_count > 0);

					user->simul_count--;
					if (user->simul_count == 0) {
						rbtree_deletebydata(inst->user_tree, user);
					}

					pthread_mutex_unlock(&cache->mutex);

 				} else {
					/*
					 *	We don't know how to
					 *	handle this.
					 */
					rad_assert(0 == 1);
				}

			} else { /* session ID doesn't match */
				/*
				 *	STOP for the right NAS & port,
				 *	but the Acct-Session-Id is
				 *	different.  This means that
				 *	we missed the original "stop",
				 *	and a new "start".
				 */
				if (status == PW_STATUS_STOP) {
					radlog(L_ERR, "rlm_radutmp: Logout entry for NAS %s port %u has old Acct-Session-ID, ignoring it.",
					       nas, u.nas_port);
					close(fd);
					return RLM_MODULE_OK;
				}
			} /* checked session ID's */
		}  /* else we haven't read anything from the file. */
	} /* else the entry wasn't cached, but could have been inserted */

	/*
	 *	Hmm... we may have received a start or alive packet
	 *	AFTER a stop or nas-down, in that case, we want to
	 *	discard the new packet.  However, the original code
	 *	could over-write an idle record with a new login
	 *	record for another NAS && port, so we won't worry
	 *	about this case too much.
	 */

	/*
	 *	Seek to where the entry is, and write it blindly.
	 */
	lseek(fd, nas_port->offset, SEEK_SET); /* FIXME: err */

	if (status != PW_STATUS_STOP) {
		utmp.type = P_LOGIN;
		rad_assert(nas_port != NULL); /* it WAS cached */
	} else {
		/* FIXME: maybe assert that the entry was deleted... */
		memcpy(&utmp, &u, sizeof(utmp));
		utmp.type = P_IDLE;
	}

	write(fd, &utmp, sizeof(utmp)); /* FIXME: err */

	close(fd);	/* and implicitly release the locks */

	return RLM_MODULE_OK;
}