예제 #1
0
파일: eventlog.c 프로젝트: dreamsxin/zabbix
/* get Nth error from event log. 1 is the first. */
static int	zbx_get_eventlog_message(const wchar_t *wsource, HANDLE eventlog_handle, DWORD which, char **out_source,
		char **out_message, unsigned short *out_severity, unsigned long *out_timestamp,
		unsigned long *out_eventid)
{
	const char	*__function_name = "zbx_get_eventlog_message";
	int		buffer_size = 512;
	EVENTLOGRECORD	*pELR = NULL;
	DWORD		dwRead, dwNeeded, dwErr;
	wchar_t 	*pEventMessageFile = NULL, *pParamMessageFile = NULL, *pFile = NULL, *pNextFile = NULL, *pCh,
			*aInsertStrings[MAX_INSERT_STRS];
	HINSTANCE	hLib = NULL, hParamLib = NULL;
	long		i, err = 0;
	int		ret = FAIL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() lastlogsize:%lu", __function_name, which);

	*out_source = NULL;
	*out_message = NULL;
	*out_severity = 0;
	*out_timestamp = 0;
	*out_eventid = 0;
	memset(aInsertStrings, 0, sizeof(aInsertStrings));

	pELR = (EVENTLOGRECORD *)zbx_malloc((void *)pELR, buffer_size);

	while (0 == ReadEventLog(eventlog_handle, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ, which,
			pELR, buffer_size, &dwRead, &dwNeeded))
	{
		if (ERROR_INSUFFICIENT_BUFFER != (dwErr = GetLastError()))
		{
			zabbix_log(LOG_LEVEL_DEBUG, "%s(): %s", __function_name, strerror_from_system(dwErr));
			goto out;
		}

		buffer_size = dwNeeded;
		pELR = (EVENTLOGRECORD *)zbx_realloc((void *)pELR, buffer_size);
	}

	*out_severity = pELR->EventType;				/* return event type */
	*out_timestamp = pELR->TimeGenerated;				/* return timestamp */
	*out_eventid = pELR->EventID & 0xffff;
	*out_source = zbx_unicode_to_utf8((wchar_t *)(pELR + 1));	/* copy source name */

	/* get message file names */
	zbx_get_message_files(wsource, (wchar_t *)(pELR + 1), &pEventMessageFile, &pParamMessageFile);

	/* prepare insert string array */
	if (0 < pELR->NumStrings)
	{
		pCh = (wchar_t *)((unsigned char *)pELR + pELR->StringOffset);

		for (i = 0; i < pELR->NumStrings && i < MAX_INSERT_STRS; i++)
		{
			aInsertStrings[i] = pCh;
			pCh += wcslen(pCh) + 1;
		}
	}

	err = FAIL;

	for (pFile = pEventMessageFile; NULL != pFile && err != SUCCEED; pFile = pNextFile)
	{
		if (NULL != (pNextFile = wcschr(pFile, TEXT(';'))))
		{
			*pNextFile = '\0';
			pNextFile++;
		}

		if (NULL != (hLib = zbx_load_message_file(pFile)))
		{
			if (NULL != (*out_message = zbx_format_message(hLib, pELR->EventID, aInsertStrings)))
			{
				err = SUCCEED;

				if (NULL != (hParamLib = zbx_load_message_file(pParamMessageFile)))
				{
					zbx_translate_message_params(out_message, hParamLib);
					FreeLibrary(hParamLib);
				}
			}

			FreeLibrary(hLib);
		}
	}

	zbx_free(pEventMessageFile);
	zbx_free(pParamMessageFile);

	if (SUCCEED != err)
	{
		*out_message = zbx_strdcatf(*out_message, "The description for Event ID:%lu in Source:'%s'"
				" cannot be found. The local computer may not have the necessary registry"
				" information or message DLL files to display messages from a remote computer.",
				*out_eventid, NULL == *out_source ? "" : *out_source);

		if (0 < pELR->NumStrings)
		{
			char	*buf;

			*out_message = zbx_strdcat(*out_message, " The following information is part of the event: ");

			for (i = 0, pCh = (wchar_t *)((unsigned char *)pELR + pELR->StringOffset);
					i < pELR->NumStrings;
					i++, pCh += wcslen(pCh) + 1)
			{
				if (0 < i)
					*out_message = zbx_strdcat(*out_message, "; ");

				buf = zbx_unicode_to_utf8(pCh);
				*out_message = zbx_strdcat(*out_message, buf);
				zbx_free(buf);
			}
		}
	}

	ret = SUCCEED;
out:
	zbx_free(pELR);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
예제 #2
0
파일: eventlog.c 프로젝트: dreamsxin/zabbix
/* obtain a particular message from a desired eventlog */
static int	zbx_get_eventlog_message6(const wchar_t *wsource, zbx_uint64_t *which, unsigned short *out_severity,
		unsigned long *out_timestamp, char **out_provider, char **out_source, char **out_message,
		unsigned long *out_eventid, EVT_HANDLE *render_context, EVT_HANDLE *query, zbx_uint64_t *keywords)
{
	const char		*__function_name = "zbx_get_eventlog_message6";
	EVT_HANDLE		event_bookmark = NULL;
	EVT_VARIANT*		renderedContent = NULL;
	const wchar_t		*pprovider = NULL;
	char			*tmp_str = NULL;
	DWORD			size = DEFAULT_EVENT_CONTENT_SIZE;
	DWORD			bookmarkedCount = 0;
	DWORD			require = 0;
	const zbx_uint64_t	sec_1970 = 116444736000000000;
	const zbx_uint64_t	success_audit = 0x20000000000000;
	const zbx_uint64_t	failure_audit = 0x10000000000000;
	int			ret = FAIL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() EventRecordID:" ZBX_FS_UI64, __function_name, *which);

	if (NULL == *query)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s() no EvtQuery handle", __function_name);
		goto out;
	}

	/* get the entries */
	if (TRUE != EvtNext(*query, 1, &event_bookmark, INFINITE, 0, &require))
	{
		/* The event reading query had less items than we calculated before. */
		/* Either the eventlog was cleaned or our calculations were wrong.   */
		/* Either way we can safely abort the query by setting NULL value    */
		/* and returning success, which is interpreted as empty eventlog.    */
		if (ERROR_NO_MORE_ITEMS == GetLastError())
		{
			ret = SUCCEED;
		}
		else
		{
			zabbix_log(LOG_LEVEL_WARNING, "EvtNext failed: %s, EventRecordID:" ZBX_FS_UI64,
				strerror_from_system(GetLastError()), *which);
		}
		goto out;
	}

	/* obtain the information from the selected events */

	renderedContent = (EVT_VARIANT *)zbx_malloc((void *)renderedContent, size);

	if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent,
			&require, &bookmarkedCount))
	{
		/* information exceeds the space allocated */
		if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
		{
			zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed: %s", strerror_from_system(GetLastError()));
			goto out;
		}

		renderedContent = (EVT_VARIANT *)zbx_realloc((void *)renderedContent, require);
		size = require;

		if (TRUE != EvtRender(*render_context, event_bookmark, EvtRenderEventValues, size, renderedContent,
				&require, &bookmarkedCount))
		{
			zabbix_log(LOG_LEVEL_WARNING, "EvtRender failed: %s", strerror_from_system(GetLastError()));
			goto out;
		}
	}

	pprovider = VAR_PROVIDER_NAME(renderedContent);
	*out_provider = zbx_unicode_to_utf8(pprovider);

	if (NULL != VAR_SOURCE_NAME(renderedContent))
	{
		*out_source = zbx_unicode_to_utf8(VAR_SOURCE_NAME(renderedContent));
	}

	*keywords = VAR_KEYWORDS(renderedContent) & (success_audit | failure_audit);
	*out_severity = VAR_LEVEL(renderedContent);
	*out_timestamp = (unsigned long)((VAR_TIME_CREATED(renderedContent) - sec_1970) / 10000000);
	*out_eventid = VAR_EVENT_ID(renderedContent);
	*out_message = expand_message6(pprovider, event_bookmark);

	tmp_str = zbx_unicode_to_utf8(wsource);

	if (VAR_RECORD_NUMBER(renderedContent) != *which)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s() Overwriting expected EventRecordID:" ZBX_FS_UI64 " with the real"
				" EventRecordID:" ZBX_FS_UI64 " in eventlog '%s'", __function_name, *which,
				VAR_RECORD_NUMBER(renderedContent), tmp_str);
		*which = VAR_RECORD_NUMBER(renderedContent);
	}

	/* some events don't have enough information for making event message */
	if (NULL == *out_message)
	{
		*out_message = zbx_strdcatf(*out_message, "The description for Event ID:%lu in Source:'%s'"
				" cannot be found. Either the component that raises this event is not installed"
				" on your local computer or the installation is corrupted. You can install or repair"
				" the component on the local computer. If the event originated on another computer,"
				" the display information had to be saved with the event.", *out_eventid,
				NULL == *out_provider ? "" : *out_provider);

		if (EvtVarTypeString == (VAR_EVENT_DATA_TYPE(renderedContent) & EVT_VARIANT_TYPE_MASK))
		{
			unsigned int	i;
			char		*data = NULL;

			if (0 != (VAR_EVENT_DATA_TYPE(renderedContent) & EVT_VARIANT_TYPE_ARRAY) &&
				0 < VAR_EVENT_DATA_COUNT(renderedContent))
			{
				*out_message = zbx_strdcatf(*out_message, " The following information was included"
						" with the event: ");

				for (i = 0; i < VAR_EVENT_DATA_COUNT(renderedContent); i++)
				{
					if (NULL != VAR_EVENT_DATA_STRING_ARRAY(renderedContent, i))
					{
						if (0 < i)
							*out_message = zbx_strdcat(*out_message, "; ");

						data = zbx_unicode_to_utf8(VAR_EVENT_DATA_STRING_ARRAY(renderedContent, i));
						*out_message = zbx_strdcatf(*out_message, "%s", data);
						zbx_free(data);
					}
				}
			}
			else if (NULL != VAR_EVENT_DATA_STRING(renderedContent))
			{
				data = zbx_unicode_to_utf8(VAR_EVENT_DATA_STRING(renderedContent));
				*out_message = zbx_strdcatf(*out_message, "The following information was included"
						" with the event: %s", data);
				zbx_free(data);
			}
		}
	}

	ret = SUCCEED;
out:
	if (NULL != event_bookmark)
		EvtClose(event_bookmark);
	zbx_free(tmp_str);
	zbx_free(renderedContent);
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
예제 #3
0
파일: modules.c 프로젝트: Metalaria/Zabbix_
/******************************************************************************
 *                                                                            *
 * Function: load_modules                                                     *
 *                                                                            *
 * Purpose: load loadable modules (dynamic libraries)                         *
 *          It skips a module in case of any errors                           *
 *                                                                            *
 * Parameters: path - directory where modules are located                     *
 *             file_names - list of module names                              *
 *             timeout - timeout in seconds for processing of items by module *
 *             verbose - output list of loaded modules                        *
 *                                                                            *
 * Return value: SUCCEED - all modules is successfully loaded                 *
 *               FAIL - loading of modules failed                             *
 *                                                                            *
 ******************************************************************************/
int	load_modules(const char *path, char **file_names, int timeout, int verbose)
{
	const char	*__function_name = "load_modules";

	char		**file_name, *buffer = NULL;
	void		*lib;
	char		full_name[MAX_STRING_LEN], error[MAX_STRING_LEN];
	int		(*func_init)(), (*func_version)();
	ZBX_METRIC	*(*func_list)();
	void		(*func_timeout)();
	int		i, ret = FAIL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	for (file_name = file_names; NULL != *file_name; file_name++)
	{
		zbx_snprintf(full_name, sizeof(full_name), "%s/%s", path, *file_name);

		zabbix_log(LOG_LEVEL_DEBUG, "loading module \"%s\"", full_name);

		if (NULL == (lib = dlopen(full_name, RTLD_NOW)))
		{
			zabbix_log(LOG_LEVEL_CRIT, "cannot load module \"%s\": %s", *file_name, dlerror());
			goto fail;
		}

		*(void **)(&func_version) = dlsym(lib, ZBX_MODULE_FUNC_API_VERSION);
		if (NULL == func_version)
		{
			zabbix_log(LOG_LEVEL_CRIT, "cannot find \"" ZBX_MODULE_FUNC_API_VERSION "()\""
					" function in module \"%s\": %s", *file_name, dlerror());
			dlclose(lib);
			goto fail;
		}

		if (ZBX_MODULE_API_VERSION_ONE != (i = func_version()))
		{
			zabbix_log(LOG_LEVEL_CRIT, "unsupported module \"%s\" version: %d", *file_name, i);
			dlclose(lib);
			goto fail;
		}

		*(void **)(&func_init) = dlsym(lib, ZBX_MODULE_FUNC_INIT);
		if (NULL == func_init)
		{
			zabbix_log(LOG_LEVEL_CRIT, "cannot find \"" ZBX_MODULE_FUNC_INIT "()\""
					" function in module \"%s\": %s", *file_name, dlerror());
			dlclose(lib);
			goto fail;
		}

		if (ZBX_MODULE_OK != func_init())
		{
			zabbix_log(LOG_LEVEL_CRIT, "cannot initialize module \"%s\"", *file_name);
			dlclose(lib);
			goto fail;
		}

		/* the function is optional, zabbix will load the module ieven if it is missing */
		*(void **)(&func_timeout) = dlsym(lib, ZBX_MODULE_FUNC_ITEM_TIMEOUT);
		if (NULL == func_timeout)
		{
			zabbix_log(LOG_LEVEL_DEBUG, "cannot find \"" ZBX_MODULE_FUNC_ITEM_TIMEOUT "()\""
					" function in module \"%s\": %s", *file_name, dlerror());
		}
		else
			func_timeout(timeout);

		*(void **)(&func_list) = dlsym(lib, ZBX_MODULE_FUNC_ITEM_LIST);
		if (NULL == func_list)
		{
			zabbix_log(LOG_LEVEL_WARNING, "cannot find \"" ZBX_MODULE_FUNC_ITEM_LIST "()\""
					" function in module \"%s\": %s", *file_name, dlerror());
			dlclose(lib);
			continue;
		}

		if (SUCCEED == register_module(lib))
		{
			ZBX_METRIC	*metrics;

			metrics = func_list();

			for (i = 0; NULL != metrics[i].key; i++)
			{
				/* accept only CF_HAVEPARAMS flag from module items */
				metrics[i].flags &= CF_HAVEPARAMS;
				/* the flag means that the items comes from a loadable module */
				metrics[i].flags |= CF_MODULE;
				if (SUCCEED != add_metric(&metrics[i], error, sizeof(error)))
				{
					zabbix_log(LOG_LEVEL_CRIT, "cannot load module \"%s\": %s", *file_name, error);
					exit(EXIT_FAILURE);
				}
			}

			if (1 == verbose)
			{
				if (NULL != buffer)
					buffer = zbx_strdcat(buffer, ", ");
				buffer = zbx_strdcat(buffer, *file_name);
			}
		}
	}

	if (NULL != buffer)
		zabbix_log(LOG_LEVEL_WARNING, "loaded modules: %s", buffer);

	ret = SUCCEED;
fail:
	zbx_free(buffer);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
예제 #4
0
파일: common.c 프로젝트: phedders/zabbix
int	EXECUTE_STR(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{

#if defined(_WINDOWS)

	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi = {0};
	SECURITY_ATTRIBUTES sa;
	HANDLE hWrite=NULL, hRead=NULL;

#else /* not _WINDOWS */

	FILE	*hRead = NULL;

#endif /* _WINDOWS */

	int	ret = SYSINFO_RET_FAIL;

	char	stat_buf[128];
	char	*cmd_result=NULL;
	char	*command=NULL;
	int	len;

	assert(result);

	init_result(result);

	cmd_result = zbx_dsprintf(cmd_result,"");
	memset(stat_buf, 0, sizeof(stat_buf));

#if defined(_WINDOWS)

	/* Set the bInheritHandle flag so pipe handles are inherited */
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;

	/* Create a pipe for the child process's STDOUT */
	if (! CreatePipe(&hRead, &hWrite, &sa, sizeof(cmd_result)))
	{
		zabbix_log(LOG_LEVEL_DEBUG, "Unable to create pipe [%s]", strerror_from_system(GetLastError()));
		ret = SYSINFO_RET_FAIL;
		goto lbl_exit;
	}

	/* Fill in process startup info structure */
	memset(&si,0,sizeof(STARTUPINFO));
	si.cb		= sizeof(STARTUPINFO);
	si.dwFlags	= STARTF_USESTDHANDLES;
	si.hStdInput	= GetStdHandle(STD_INPUT_HANDLE);
	si.hStdOutput	= hWrite;
	si.hStdError	= hWrite;

	command = zbx_dsprintf(command, "cmd /C \"%s\"", param);

	/* Create new process */
	if (!CreateProcess(NULL,command,NULL,NULL,TRUE,0,NULL,NULL,&si,&pi))
	{
		zabbix_log(LOG_LEVEL_DEBUG, "Unable to create process: '%s' [%s]", command, strerror_from_system(GetLastError()));

		ret = SYSINFO_RET_FAIL;
		goto lbl_exit;
	}
	CloseHandle(hWrite);	hWrite = NULL;

	/* Read process output */
	while( ReadFile(hRead, stat_buf, sizeof(stat_buf)-1, &len, NULL) && len > 0 )
	{
		cmd_result = zbx_strdcat(cmd_result, stat_buf);
		memset(stat_buf, 0, sizeof(stat_buf));
	}

	/* Don't wait child process exiting. */
	/* WaitForSingleObject( pi.hProcess, INFINITE ); */

	/* Terminate child process */
	/* TerminateProcess(pi.hProcess, 0); */

	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	CloseHandle(hRead);	hRead = NULL;


#else /* not _WINDOWS */
	command = zbx_dsprintf(command, "%s", param);

	if(0 == (hRead = popen(command,"r")))
	{
		switch (errno)
		{
			case	EINTR:
				ret = SYSINFO_RET_TIMEOUT;
				break;
			default:
				ret = SYSINFO_RET_FAIL;
				break;
		}
		goto lbl_exit;
	}

	;
	/* Read process output */
	while( (len = fread(stat_buf, 1, sizeof(stat_buf)-1, hRead)) > 0 )
	{
		cmd_result = zbx_strdcat(cmd_result, stat_buf);
		memset(stat_buf, 0, sizeof(stat_buf));
	}

	if(0 != ferror(hRead))
	{
		switch (errno)
		{
			case	EINTR:
				ret = SYSINFO_RET_TIMEOUT;
				break;
			default:
				ret = SYSINFO_RET_FAIL;
				break;
		}
		goto lbl_exit;
	}

	if(pclose(hRead) == -1)
	{
		switch (errno)
		{
			case	EINTR:
				ret = SYSINFO_RET_TIMEOUT;
				break;
			default:
				ret = SYSINFO_RET_FAIL;
				break;
		}
		goto lbl_exit;
	}

	hRead = NULL;

#endif /* _WINDOWS */

	zabbix_log(LOG_LEVEL_DEBUG, "Before");

	zbx_rtrim(cmd_result,"\n\r\0");

	/* We got EOL only */
	if(cmd_result[0] == '\0')
	{
		ret = SYSINFO_RET_FAIL;
		goto lbl_exit;
	}

	zabbix_log(LOG_LEVEL_DEBUG, "Run remote command [%s] Result [%d] [%.20s]...", command, strlen(cmd_result), cmd_result);

	SET_TEXT_RESULT(result, strdup(cmd_result));

	ret = SYSINFO_RET_OK;

lbl_exit:

#if defined(_WINDOWS)
	if ( hWrite )	{ CloseHandle(hWrite);	hWrite = NULL; }
	if ( hRead)	{ CloseHandle(hRead);	hRead = NULL; }
#else /* not _WINDOWS */
	if ( hRead )	{ pclose(hRead);	hRead = NULL; }
#endif /* _WINDOWS */

	zbx_free(command)
	zbx_free(cmd_result);

	return ret;
}
예제 #5
0
파일: comms.c 프로젝트: Shmuma/z
/******************************************************************************
 *                                                                            *
 * Function: comms_create_request                                             *
 *                                                                            *
 * Purpose: dinamical xml request generation                                  *
 *                                                                            *
 * Return value: XML request                                                  *
 *                                                                            *
 * Author: Eugene Grigorjev                                                   *
 *                                                                            *
 * Comments:  required free allocated string with function 'zbx_free'         *
 *                                                                            *
 ******************************************************************************/
char*	comms_create_request(
	const char		*host,
	const char		*key,
	const char		*data,
	const char		*error,
	long			*lastlogsize,
	unsigned long	*timestamp,
	const char		*source,
	unsigned short	*severity
	)
{
#define ADD_XML_DATA(tag_name, var) \
	data_b64[0] = '\0'; \
	str_base64_encode(var, data_b64, (int)strlen(var)); \
	request = zbx_strdcatf(request, "<" tag_name ">%s</" tag_name ">",	data_b64)

	char data_b64[ZBX_MAX_B64_LEN];
	char *tmp_str = NULL;
	char *request = NULL;
	
	assert(host);
	assert(key);
	assert(data);

	/* zabbix_log(LOG_LEVEL_DEBUG, "comms_create_request host [%s] key [%s] data [%s]",host,key,data); */

	memset(data_b64,0,sizeof(data_b64));

	request = zbx_dsprintf(NULL,"%s", "<req>");
	
	ADD_XML_DATA("host",	host);
	ADD_XML_DATA("key",		key);
	ADD_XML_DATA("data",	data);

	if (error) {
		ADD_XML_DATA ("error", error);
	}

	if(lastlogsize)
	{
		tmp_str = zbx_dsprintf(NULL, "%li", *lastlogsize);
		ADD_XML_DATA("lastlogsize",	tmp_str);
		zbx_free(tmp_str);
	}

	if(timestamp)
	{
		assert(source);
		assert(severity);
		
		tmp_str = zbx_dsprintf(NULL, "%lu", *timestamp);
		ADD_XML_DATA("timestamp",	tmp_str);
		zbx_free(tmp_str);

		ADD_XML_DATA("source",		source);

		tmp_str = zbx_dsprintf(NULL, "%u", *severity);
		ADD_XML_DATA("severity",	tmp_str);
		zbx_free(tmp_str);
	}

	return zbx_strdcat(request, "</req>");
}
예제 #6
0
파일: comms.c 프로젝트: Shmuma/z
char*	comms_finish_multi_request (char* request)
{
	return zbx_strdcat (request, "</values><reqs>");
}
예제 #7
0
파일: activebuf.c 프로젝트: Shmuma/z
static int read_initial_buffer ()
{
    unsigned long sig;
    unsigned int i, j, len;
    int index;
    char c;
    char buf[1024];

    zabbix_log (LOG_LEVEL_DEBUG, "read_initial_buffer");

    /* check signature */
    if (!fread (&sig, sizeof (sig), 1, buffer.file))
        return 0;

    if (sig != buffer_signature)
        return 0;

    if (fread (&buffer.size, sizeof (unsigned int), 1, buffer.file) != 1)
        return 0;

    if (!buffer.size)           /* read finished, there are no items in buffer */
        return 1;

    zabbix_log (LOG_LEVEL_DEBUG, "Reading %d items of history from buffer", buffer.size);

    buffer.entries = (buffer_check_entry_t*)calloc (buffer.size, sizeof (buffer_check_entry_t));

    if (!buffer.entries) {
	    buffer.size = 0;
	    return 1;
    }

    for (i = 0; i < buffer.size; i++) {
        buffer.entries[i].key = NULL;
        len = 0;
        while ((c = fgetc (buffer.file))) {
            buf[len++] = c;
            if (len == 1023) {
                buf[len] = 0;
                buffer.entries[i].key = zbx_strdcat (buffer.entries[i].key, buf);
                len = 0;
            }
        }

        if (len) {
            buf[len] = 0;
            buffer.entries[i].key = zbx_strdcat (buffer.entries[i].key, buf);
        }

        fread (&buffer.entries[i].refresh, sizeof (int), 1, buffer.file);
        fread (&buffer.entries[i].beg_offset, sizeof (size_t), 1, buffer.file);
        fread (&buffer.entries[i].max_offset, sizeof (size_t), 1, buffer.file);
        fread (&buffer.entries[i].max_items,  sizeof (int), 1, buffer.file);

        buffer.entries[i].sizes = (unsigned short*)malloc (buffer.entries[i].max_items * sizeof (unsigned short));
        fread (buffer.entries[i].sizes, sizeof (unsigned short), buffer.entries[i].max_items, buffer.file);

        /* find index (hm-hm) and item's count */
        index = -1;
        buffer.entries[i].count = 0;
        buffer.entries[i].index = 0;

        for (j = 0; j < buffer.entries[i].max_items; j++) {
            if (!buffer.entries[i].sizes[j]) {
                if (index < 0)
                    index = j;
            }
            else
                buffer.entries[i].count++;
        }

        if (index >= 0)
            buffer.entries[i].index = index;

        zabbix_log (LOG_LEVEL_DEBUG, "Read item history. Key %s, refresh %d, len: %lu, items: %d, index: %d, count: %d", buffer.entries[i].key, 
                    buffer.entries[i].refresh, buffer.entries[i].max_offset - buffer.entries[i].beg_offset, buffer.entries[i].max_items,
                    buffer.entries[i].index, buffer.entries[i].count);
    }

    return 1;
}