Exemple #1
0
static int	get_sensor(const char *name, unsigned flags, AGENT_RESULT *result)
{
	DIR	*dir;
	struct	dirent *entries;
	struct	stat buf;
	char	filename[MAX_STRING_LEN];
	char	line[MAX_STRING_LEN];
	double	d1,d2,d3;

	FILE	*f;

        assert(result);

        init_result(result);	
	
	dir=opendir("/proc/sys/dev/sensors");
	if(NULL == dir)
	{
		return SYSINFO_RET_FAIL;
	}

	while((entries=readdir(dir))!=NULL)
	{
		strscpy(filename,"/proc/sys/dev/sensors/");	
		zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN);
		zbx_strlcat(filename,name,MAX_STRING_LEN);

		if(stat(filename,&buf)==0)
		{
			if( NULL == (f = fopen(filename,"r") ))
			{
				continue;
			}
			fgets(line,MAX_STRING_LEN,f);
			zbx_fclose(f);

			if(sscanf(line,"%lf\t%lf\t%lf\n",&d1, &d2, &d3) == 3)
			{
				closedir(dir);
				SET_DBL_RESULT(result, d3);
				return  SYSINFO_RET_OK;
			}
			else
			{
				closedir(dir);
				return  SYSINFO_RET_FAIL;
			}
		}
	}
	closedir(dir);
	return	SYSINFO_RET_FAIL;
}
/******************************************************************************
 *                                                                            *
 * Function: zbx_module_docker_up                                             *
 *                                                                            *
 * Purpose: check if container is running                                     *
 *                                                                            *
 * Return value: 1 - is running, 0 - is not running                           *
 *                                                                            *
 ******************************************************************************/
int     zbx_module_docker_up(AGENT_REQUEST *request, AGENT_RESULT *result)
{
        zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_up()");
        char    *container, *metric;
        int     ret = SYSINFO_RET_FAIL;

        if (1 != request->nparam)
        {
                zabbix_log(LOG_LEVEL_ERR, "Invalid number of parameters: %d",  request->nparam);
                SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
                return SYSINFO_RET_FAIL;
        }
        
        if (stat_dir == NULL) {
                zabbix_log(LOG_LEVEL_DEBUG, "docker.up check is not available at the moment - no stat directory.");
                SET_MSG_RESULT(result, zbx_strdup(NULL, "docker.up check is not available at the moment - no stat directory."));
                return SYSINFO_RET_OK;
        }        

        container = get_rparam(request, 0);
        char    *stat_file = "/cpuacct.stat";
        char    *cgroup = "cpuacct/";
        size_t  filename_size = strlen(base_dir) + strlen(cgroup) + strlen(container) + strlen(stat_dir) + strlen(stat_file) + 2;
        char    *filename = malloc(filename_size);
        zbx_strlcpy(filename, base_dir, filename_size);
        zbx_strlcat(filename, cgroup, filename_size);
        zbx_strlcat(filename, stat_dir, filename_size);
        zbx_strlcat(filename, container, filename_size);
        zbx_strlcat(filename, stat_file, filename_size);
        zabbix_log(LOG_LEVEL_DEBUG, "Metric source file: %s", filename);
        FILE    *file;
        if (NULL == (file = fopen(filename, "r")))
        {
                zabbix_log(LOG_LEVEL_DEBUG, "Can't open docker container metric file: '%s', container doesn't run", filename);
                SET_DBL_RESULT(result, 0);
                return SYSINFO_RET_OK;
        }
        zbx_fclose(file);
        zabbix_log(LOG_LEVEL_DEBUG, "Can open docker container metric file: '%s', container is running", filename);
        SET_DBL_RESULT(result, 1);
        return SYSINFO_RET_OK;
}
Exemple #3
0
int	TCP_LISTEN(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
#ifdef HAVE_PROC
	FILE	*f = NULL;
	char	c[MAX_STRING_LEN];
	char	porthex[MAX_STRING_LEN];
	char	pattern[MAX_STRING_LEN];
	int	ret = SYSINFO_RET_FAIL;

	assert(result);

	init_result(result);

	if(num_param(param) > 1)
	{
		return SYSINFO_RET_FAIL;
	}

	if(get_param(param, 1, porthex, MAX_STRING_LEN) != 0)
	{
		return SYSINFO_RET_FAIL;
	}

	strscpy(pattern,porthex);
	zbx_strlcat(pattern," 00000000:0000 0A", MAX_STRING_LEN);

	if(NULL == (f = fopen("/proc/net/tcp","r")))
	{
		return	SYSINFO_RET_FAIL;
	}

	while (NULL != fgets(c,MAX_STRING_LEN,f))
	{
		if(NULL != strstr(c,pattern))
		{
			SET_UI64_RESULT(result, 1);
			ret = SYSINFO_RET_OK;
			break;
		}
	}
	zbx_fclose(f);

	SET_UI64_RESULT(result, 0);

	return ret;
#else
	return	SYSINFO_RET_FAIL;
#endif
}
int	zbx_module_redis_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
{
	char		*CONFIG_SOURCE_IP = NULL;	
	zbx_sock_t	s;
	char		*rs_host, *str_rs_port;
	unsigned int    rs_port;
	const char      *buf;
	char		rv[MAX_STRING_LEN];
	int		rs_status = 0;
	time_t		now;
	char		str_time[MAX_STRING_LEN];
	char		cmd[MAX_STRING_LEN];
	char		hv[MAX_STRING_LEN];
	struct tm	*tm = NULL;


	if (request->nparam == 2)
	{
		rs_host = get_rparam(request, 0);
		str_rs_port = get_rparam(request, 1);
		rs_port = atoi(str_rs_port);
	}
	else if (request->nparam == 1)
	{
		rs_host = REDIS_DEFAULT_INSTANCE_HOST;
		str_rs_port = get_rparam(request, 0);
		rs_port = atoi(str_rs_port);
	}
	else
	{
		/* set optional error message */
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters"));
		return SYSINFO_RET_FAIL;
	}

	/* for dev
	zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], args:[%s,%d]", rs_host, rs_port);
	*/

	time(&now);
	tm = localtime(&now);
	strftime(str_time, MAX_STRING_LEN, "%Y%m%d%H%M%S", tm);
	/* for dev
	zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], str_time:[%s]", str_time);
	*/

	zbx_snprintf(cmd, MAX_STRING_LEN, "set ZBX_PING %s\r\nget ZBX_PING\r\nquit\r\n",str_time);
	zbx_snprintf(hv, MAX_STRING_LEN, "+OK$%d%s+OK", strlen(str_time), str_time);


	if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, rs_host, rs_port, 0))
	{
		/* for dev
		zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], connect to [%s:%d] successful", rs_host, rs_port);
		*/

		if (SUCCEED == zbx_tcp_send_raw(&s, cmd))
		{
			/* for dev
			zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], send request successful");
			*/

			strscpy(rv, "");

			while (NULL != (buf = zbx_tcp_recv_line(&s)))
			{
				/* for dev
				zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], get [%s]", buf);
				*/
				zbx_strlcat(rv, buf, MAX_STRING_LEN);
			}
			/* for dev
			zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], all get [%s]", rv);
			*/
			if (0 == strcmp(rv, hv))
			{
				/* for dev
				zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], redis instance:[%s:%d] is up", rs_host, rs_port);
				*/
				rs_status = 1;
			}
		}

		zbx_tcp_close(&s);
	}

	if (rs_status == 1)
	{
		SET_UI64_RESULT(result, 1);
	}
	else
	{
		SET_UI64_RESULT(result, 0);
	}

	return SYSINFO_RET_OK;
}
Exemple #5
0
/******************************************************************************
 *                                                                            *
 * Function: execute_action                                                   *
 *                                                                            *
 * Purpose: execute an action depending on mediatype                          *
 *                                                                            *
 * Parameters: alert - alert details                                          *
 *             mediatype - media details                                      *
 *                                                                            *
 * Return value: SUCCESS - action executed sucessfully                        *
 *               FAIL - otherwise, error will contain error message           *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
int execute_action(DB_ALERT *alert,DB_MEDIATYPE *mediatype, char *error, int max_error_len)
{
	int 	res=FAIL;
	int	pid;

	char	full_path[MAX_STRING_LEN];

	char    env_alertid[128],env_actionid[128],env_clock[128],env_mediatypeid[128],
		env_status[128];
	char    *zbxenv[] = { (char *)&env_alertid, (char *)&env_actionid, (char *)&env_clock,
		(char *)&env_mediatypeid, (char *)&env_status,
		(char *)0 };

	zabbix_log( LOG_LEVEL_DEBUG, "In execute_action(%s)",
		mediatype->smtp_server);

	if(mediatype->type==MEDIA_TYPE_EMAIL)
	{
		alarm(40);
		res = send_email(mediatype->smtp_server,mediatype->smtp_helo,mediatype->smtp_email,alert->sendto,alert->subject,
			alert->message, error, max_error_len);
		alarm(0);
	}
#if defined (HAVE_JABBER)
	else if(mediatype->type==MEDIA_TYPE_JABBER)
	{
		/* Jabber uses its own timeouts */
		res = send_jabber(mediatype->username, mediatype->passwd, alert->sendto, alert->subject,
				alert->message, error, max_error_len);
	}
#endif /* HAVE_JABBER */
	else if(mediatype->type==MEDIA_TYPE_SMS)
	{
		/* SMS uses its own timeouts */
		res = send_sms(mediatype->gsm_modem,alert->sendto,alert->message, error, max_error_len);
	}
	else if(mediatype->type==MEDIA_TYPE_EXEC)
	{
/*		if(-1 == execl(CONFIG_ALERT_SCRIPTS_PATH,mediatype->exec_path,alert->sendto,alert->subject,alert->message))*/
		zabbix_log( LOG_LEVEL_DEBUG, "Before execl([%s],[%s])",
			CONFIG_ALERT_SCRIPTS_PATH,
			mediatype->exec_path);

/*		if(-1 == execl("/home/zabbix/bin/lmt.sh","lmt.sh",alert->sendto,alert->subject,alert->message,(char *)0))*/

		pid = zbx_fork();
		if(0 != pid)
		{
			waitpid(pid,NULL,0);
		}
		else
		{
			strscpy(full_path,CONFIG_ALERT_SCRIPTS_PATH);
			zbx_strlcat(full_path,"/",MAX_STRING_LEN);
			zbx_strlcat(full_path,mediatype->exec_path,MAX_STRING_LEN);
			ltrim_spaces(full_path);
			zabbix_log( LOG_LEVEL_DEBUG, "Before executing [%s]",
				full_path);

			zbx_snprintf(env_alertid,127,"ZABBIX_ALERT_ID=%d",
				alert->alertid);
			zbx_snprintf(env_actionid,127,"ZABBIX_ACTION_ID=%d",
				alert->actionid);
			zbx_snprintf(env_clock,127,"ZABBIX_ALERT_TIME=%d",
				alert->clock);
			zbx_snprintf(env_mediatypeid,127,"ZABBIX_ALERT_MEDIATYPEID=%d",
				alert->mediatypeid);
			zbx_snprintf(env_status,127,"ZABBIX_ALERT_STATUS=%d",
				alert->status);

/*			if(-1 == execl(full_path,mediatype->exec_path,alert->sendto,alert->subject,alert->message,(char *)0))*/
			if(-1 == execle(full_path,mediatype->exec_path,alert->sendto,alert->subject,alert->message,(char *)0, zbxenv))

			{
				zabbix_log( LOG_LEVEL_ERR, "Error executing [%s] [%s]",
					full_path,
					strerror(errno));
				zabbix_syslog("Error executing [%s] [%s]",
					full_path,
					strerror(errno));
				zbx_snprintf(error,max_error_len,"Error executing [%s] [%s]",
					full_path,
					strerror(errno));
				res = FAIL;
			}
			else
			{
				res = SUCCEED;
			}
			/* In normal case the program will never reach this point */
			zabbix_log( LOG_LEVEL_DEBUG, "After execl()");
			exit(0);
		}
		res = SUCCEED;
	}
	else
	{
		zabbix_log( LOG_LEVEL_ERR, "Unsupported media type [%d] for alert ID [%d]",
			mediatype->type,
			alert->alertid);
		zabbix_syslog("Unsupported media type [%d] for alert ID [%d]",
			mediatype->type,
			alert->alertid);
		zbx_snprintf(error,max_error_len,"Unsupported media type [%d]",
			mediatype->type);
		res=FAIL;
	}

	zabbix_log( LOG_LEVEL_DEBUG, "End execute_action()");

	return res;
}
Exemple #6
0
Fichier : proc.c Projet : Shmuma/z
int	    PROC_NUM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
#if defined(HAVE_PROC_1_STATUS)

    DIR     *dir;
    struct  dirent *entries;
    struct  stat buf;
    char    filename[MAX_STRING_LEN];
    char    line[MAX_STRING_LEN];

    char    name1[MAX_STRING_LEN];
    char    name2[MAX_STRING_LEN];

    char    procname[MAX_STRING_LEN];
    char    usrname[MAX_STRING_LEN];
    char    procstat[MAX_STRING_LEN];

    int     proc_ok = 0;
    int     usr_ok = 0;
    int     stat_ok = 0;

    struct  passwd *usrinfo = NULL;
    long int	lvalue = 0;

    FILE    *f;
	int	proccount = 0;

        assert(result);

        init_result(result);
	
    
        if(num_param(param) > 3)
        {
                return SYSINFO_RET_FAIL;
        }
    
        if(get_param(param, 1, procname, MAX_STRING_LEN) != 0)
        {
                return SYSINFO_RET_FAIL;
        }
    
        if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0)
        {
                usrname[0] = 0;
        }
        else
        {
            if(usrname[0] != 0)
            {
                usrinfo = getpwnam(usrname);
                if(usrinfo == NULL)
                {
                    /* incorrect user name */
                    return SYSINFO_RET_FAIL;
                }			        
            }
        }
    
	if(get_param(param, 3, procstat, MAX_STRING_LEN) != 0)
	{
		procstat[0] = '\0';
	}

	if(procstat[0] == '\0')
	{
		strscpy(procstat, "all");
	}
    
        if(strcmp(procstat,"run") == 0)
        {
            strscpy(procstat,"R");	
        }
        else if(strcmp(procstat,"sleep") == 0)
        {
            strscpy(procstat,"S");	
        }
        else if(strcmp(procstat,"zomb") == 0)
        {
            strscpy(procstat,"Z");	
        }
        else if(strcmp(procstat,"all") == 0)
        {
            procstat[0] = 0;
        }
        else
        {
            return SYSINFO_RET_FAIL;
        }
		
        dir=opendir("/proc");
        if(NULL == dir)
        {
            return SYSINFO_RET_FAIL;
        }

        while((entries=readdir(dir))!=NULL)
        {
            proc_ok = 0;
            stat_ok = 0;
            usr_ok = 0;
    
/* Self is a symbolic link. It leads to incorrect results for proc_cnt[zabbix_agentd] */
/* Better approach: check if /proc/x/ is symbolic link */
            if(strncmp(entries->d_name,"self",MAX_STRING_LEN) == 0)
            {
                continue;
            }

            strscpy(filename,"/proc/");	
            zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN);
            zbx_strlcat(filename,"/status",MAX_STRING_LEN);

            if(stat(filename,&buf)==0)
            {
                if(NULL == (f = fopen(filename,"r") ))
                {
                    continue;
                }
    
                if(procname[0] != 0)
                {
                    fgets(line,MAX_STRING_LEN,f);
                    if(sscanf(line,"%s\t%s\n",name1,name2)==2)
                    {
                        if(strcmp(name1,"Name:") == 0)
                        {
                            if(strcmp(procname,name2)==0)
                            {
                                proc_ok = 1;
                            }
                        }
                    }
                
                    if(proc_ok == 0) 
                    {
                        zbx_fclose(f);
                        continue;
                    }
                }
                else
                {
                    proc_ok = 1;
                }

                if(procstat[0] != 0)
                {
                    while(fgets(line, MAX_STRING_LEN, f) != NULL)
                    {	
                    
                        if(sscanf(line, "%s\t%s\n", name1, name2) != 2)
                        {
                            continue;
                        }
                        
                        if(strcmp(name1,"State:") != 0)
                        {
                            continue;
                        }
                        
                        if(strcmp(name2, procstat))
                        {
                            stat_ok = 1;
                            break;
                        }
                    }
                }
                else
                {
                    stat_ok = 1;
                }
                
                if(usrinfo != NULL)
                {
                    while(fgets(line, MAX_STRING_LEN, f) != NULL)
                    {	
                    
                        if(sscanf(line, "%s\t%li\n", name1, &lvalue) != 2)
                        {
                            continue;
                        }
                        
                        if(strcmp(name1,"Uid:") != 0)
                        {
                            continue;
                        }
                        
                        if(usrinfo->pw_uid == (uid_t)(lvalue))
                        {
                            usr_ok = 1;
                            break;
                        }
                    }
                }
                else
                {
                    usr_ok = 1;
                }
                
                if(proc_ok && stat_ok && usr_ok)
                {
                    proccount++;
                }
                
                zbx_fclose(f);
            }
    }
    closedir(dir);

	SET_UI64_RESULT(result, proccount);
    return SYSINFO_RET_OK;
#else
    return	SYSINFO_RET_FAIL;
#endif
}
Exemple #7
0
Fichier : proc.c Projet : Shmuma/z
int     PROC_MEMORY(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
#if defined(HAVE_PROC_1_STATUS)

    DIR     *dir;
    struct  dirent *entries;
    struct  stat buf;
    char    filename[MAX_STRING_LEN];
    char    line[MAX_STRING_LEN];

    char    name1[MAX_STRING_LEN];
    char    name2[MAX_STRING_LEN];

    char    procname[MAX_STRING_LEN];
    char    usrname[MAX_STRING_LEN];
    char    mode[MAX_STRING_LEN];

    int     proc_ok = 0;
    int     usr_ok = 0;
    int	    do_task = DO_SUM;


    struct  passwd *usrinfo = NULL;
    long long int	llvalue = 0;

    FILE    *f;

    double	memsize = -1;
    int	proccount = 0;

        assert(result);

        init_result(result);
	
        if(num_param(param) > 3)
        {
                return SYSINFO_RET_FAIL;
        }

        if(get_param(param, 1, procname, MAX_STRING_LEN) != 0)
        {
                return SYSINFO_RET_FAIL;
        }
    
        if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0)
        {
                usrname[0] = 0;
        }
        else
        {
        if(usrname[0] != 0)
        {
                    usrinfo = getpwnam(usrname);
                    if(usrinfo == NULL)
                    {
	                /* incorrect user name */
                            return SYSINFO_RET_FAIL;
	            }			        
        }
    }

    if(get_param(param, 3, mode, MAX_STRING_LEN) != 0)
    {
       mode[0] = '\0';
    }

    if(mode[0] == '\0')
    {
        strscpy(mode, "sum");
    }
    
    if(strcmp(mode,"avg") == 0)
    {
        do_task = DO_AVG;
    }
    else if(strcmp(mode,"max") == 0)
    {
        do_task = DO_MAX;
    }
    else if(strcmp(mode,"min") == 0)
    {
        do_task = DO_MIN;
    }
    else if(strcmp(mode,"sum") == 0)
    {
        do_task = DO_SUM;
    }
    else
    {
        return SYSINFO_RET_FAIL;
    }
    
    dir=opendir("/proc");
    if(NULL == dir)
    {
            return SYSINFO_RET_FAIL;
    }

    while((entries=readdir(dir))!=NULL)
    {
        proc_ok = 0;
        usr_ok = 0;
    
        strscpy(filename,"/proc/");	
        zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN);
        zbx_strlcat(filename,"/status",MAX_STRING_LEN);
    
    /* Self is a symbolic link. It leads to incorrect results for proc_cnt[zabbix_agentd] */
    /* Better approach: check if /proc/x/ is symbolic link */
        if(strncmp(entries->d_name,"self",MAX_STRING_LEN) == 0)
        {
            continue;
        }
    
        if(stat(filename,&buf)==0)
        {
            if(NULL == (f = fopen(filename,"r") ))
            {
                continue;
            }
    
            if(procname[0] != 0)
            {
                fgets(line,MAX_STRING_LEN,f);
                if(sscanf(line,"%s\t%s\n",name1,name2)==2)
                            {
                                    if(strcmp(name1,"Name:") == 0)
                                    {
                                            if(strcmp(procname,name2)==0)
                                            {
                                                    proc_ok = 1;
                                            }
                                    }
                            }
            
                if(proc_ok == 0) 
                {
                    zbx_fclose(f);
                    continue;
                }
            }
            else
            {
                proc_ok = 1;
            }
            
            if(usrinfo != NULL)
            {
                while(fgets(line, MAX_STRING_LEN, f) != NULL)
                {	
                
                    if(sscanf(line, "%s\t%lli\n", name1, &llvalue) != 2)
                    {
                        continue;
                    }
                    
                    if(strcmp(name1,"Uid:") != 0)
                    {
                        continue;
                    }
                    
                    if(usrinfo->pw_uid == (uid_t)(llvalue))
                    {
                        usr_ok = 1;
                        break;
                    }
                }
            }
            else
            {
                usr_ok = 1;
            }
            
            if(proc_ok && usr_ok)
            {
                while(fgets(line, MAX_STRING_LEN, f) != NULL)
                {	
                
                    if(sscanf(line, "%s\t%lli %s\n", name1, &llvalue, name2) != 3)
                    {
                        continue;
                    }
                    
                    if(strcmp(name1,"VmSize:") != 0)
                    {
                        continue;
                    }
                    
                    proccount++;
                    
                    if(strcasecmp(name2, "kB") == 0)
                    {
                        llvalue <<= 10;
                    }
                    else if(strcasecmp(name2, "mB") == 0)
                    {
                        llvalue <<= 20;
                    }
                    else if(strcasecmp(name2, "GB") == 0)
                    {
                        llvalue <<= 30;
                    }
                    else if(strcasecmp(name2, "TB") == 0)
                    {
                        llvalue <<= 40;
                    }
                    
                    if(memsize < 0)
                    {
                        memsize = (double) llvalue;
                    }
                    else
                    {
                        if(do_task == DO_MAX)
                        {
                            memsize = MAX(memsize, (double) llvalue);
                        }
                        else if(do_task == DO_MIN)
                        {
                            memsize = MIN(memsize, (double) llvalue);
                        }
                        else
                        {
                            memsize +=  (double) llvalue;
                        }
                    }
                    
                    break;
                }
            }
            
                    
            zbx_fclose(f);
        }
    }
    closedir(dir);
    
    if(memsize < 0)
    {
        /* incorrect process name */
        memsize = 0;
    }
    
    if(do_task == DO_AVG)
    {
	SET_DBL_RESULT(result, proccount == 0 ? 0 : ((double)memsize/(double)proccount));
    }
    else
    {
	SET_UI64_RESULT(result, memsize);
    }
    return SYSINFO_RET_OK;
#else
	return	SYSINFO_RET_FAIL;
#endif
}
Exemple #8
0
int	PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result)
{
	DIR	*dir;
	int	proc;

	struct dirent	*entries;
	zbx_stat_t	buf;
	struct passwd	*usrinfo;
	struct prpsinfo	psinfo;

	char	filename[MAX_STRING_LEN];

	char	*procname, *proccomm, *param;

	double	memsize = -1;
	int	pgsize = getpagesize();
	int	proccount = 0, do_task;
	pid_t	curr_pid = getpid();

	if (4 < request->nparam)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
		return SYSINFO_RET_FAIL;
	}

	procname = get_rparam(request, 0);
	param = get_rparam(request, 1);

	if (NULL != param && '\0' != *param)
	{
		if (NULL == (usrinfo = getpwnam(param)))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information."));
			return SYSINFO_RET_FAIL;
		}
	}
	else
		usrinfo = NULL;

	param = get_rparam(request, 2);

	if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum"))	/* default parameter */
		do_task = ZBX_DO_SUM;
	else if (0 == strcmp(param, "avg"))
		do_task = ZBX_DO_AVG;
	else if (0 == strcmp(param, "max"))
		do_task = ZBX_DO_MAX;
	else if (0 == strcmp(param, "min"))
		do_task = ZBX_DO_MIN;
	else
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
		return SYSINFO_RET_FAIL;
	}

	proccomm = get_rparam(request, 3);

	if (NULL == (dir = opendir("/proc")))
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno)));
		return SYSINFO_RET_FAIL;
	}

	while (NULL != (entries = readdir(dir)))
	{
		strscpy(filename, "/proc/");
		zbx_strlcat(filename, entries->d_name, MAX_STRING_LEN);

		if (0 == zbx_stat(filename, &buf))
		{
			proc = open(filename, O_RDONLY);
			if (-1 == proc)
				goto lbl_skip_procces;

			if (-1 == ioctl(proc, PIOCPSINFO, &psinfo))
				goto lbl_skip_procces;

			/* Self process information. It leads to incorrect results for proc.mem[zabbix_agentd]. */
			if (psinfo.pr_pid == curr_pid)
				goto lbl_skip_procces;

			if (NULL != procname && '\0' != *procname)
				if (0 == strcmp(procname, psinfo.pr_fname))
					goto lbl_skip_procces;

			if (NULL != usrinfo)
				if (usrinfo->pw_uid != psinfo.pr_uid)
					goto lbl_skip_procces;

			if (NULL != proccomm && '\0' != *proccomm)
				if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL))
					goto lbl_skip_procces;

			proccount++;

			if (0 > memsize) /* first initialization */
			{
				memsize = (double)(psinfo.pr_rssize * pgsize);
			}
			else
			{
				if (ZBX_DO_MAX == do_task)
					memsize = MAX(memsize, (double)(psinfo.pr_rssize * pgsize));
				else if (ZBX_DO_MIN == do_task)
					memsize = MIN(memsize, (double)(psinfo.pr_rssize * pgsize));
				else	/* SUM */
					memsize += (double)(psinfo.pr_rssize * pgsize);
			}
lbl_skip_procces:
			if (-1 != proc)
				close(proc);
		}
	}

	closedir(dir);

	if (0 > memsize)
	{
		/* incorrect process name */
		memsize = 0;
	}

	if (ZBX_DO_AVG == do_task)
		SET_DBL_RESULT(result, 0 == proccount ? 0 : memsize / (double)proccount);
	else
		SET_UI64_RESULT(result, memsize);

	return SYSINFO_RET_OK;
}
Exemple #9
0
int	PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result)
{
	DIR	*dir;
	int	proc;

	struct  dirent	*entries;
	zbx_stat_t	buf;
	struct passwd	*usrinfo;
	struct prpsinfo	psinfo;

	char	filename[MAX_STRING_LEN];

	char	*procname, *proccomm, *param;

	int	proccount = 0, zbx_proc_stat;
	pid_t	curr_pid = getpid();

	if (4 < request->nparam)
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
		return SYSINFO_RET_FAIL;
	}

	procname = get_rparam(request, 0);
	param = get_rparam(request, 1);

	if (NULL != param && '\0' != *param)
	{
		if (NULL == (usrinfo = getpwnam(param)))
		{
			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information."));
			return SYSINFO_RET_FAIL;
		}
	}
	else
		usrinfo = NULL;

	param = get_rparam(request, 2);

	if (NULL == param || '\0' == *param || 0 == strcmp(param, "all"))
		zbx_proc_stat = -1;
	else if (0 == strcmp(param, "run"))
		zbx_proc_stat = PR_SRUN;
	else if (0 == strcmp(param, "sleep"))
		zbx_proc_stat = PR_SSLEEP;
	else if (0 == strcmp(param, "zomb"))
		zbx_proc_stat = PR_SZOMB;
	else
	{
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
		return SYSINFO_RET_FAIL;
	}

	proccomm = get_rparam(request, 3);

	if (NULL == (dir = opendir("/proc")))
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno)));
		return SYSINFO_RET_FAIL;
	}

	while (NULL != (entries = readdir(dir)))
	{
		strscpy(filename, "/proc/");
		zbx_strlcat(filename, entries->d_name,MAX_STRING_LEN);

		if (0 == zbx_stat(filename, &buf))
		{
			proc = open(filename, O_RDONLY);
			if (-1 == proc)
				goto lbl_skip_procces;

			if (-1 == ioctl(proc, PIOCPSINFO, &psinfo))
				goto lbl_skip_procces;

			/* Self process information. It leads to incorrect results for proc.num[zabbix_agentd]. */
			if (psinfo.pr_pid == curr_pid)
				goto lbl_skip_procces;

			if (NULL != procname && '\0' != *procname)
				if (0 != strcmp(procname, psinfo.pr_fname))
					goto lbl_skip_procces;

			if (NULL != usrinfo)
				if (usrinfo->pw_uid != psinfo.pr_uid)
					goto lbl_skip_procces;

			if (-1 != zbx_proc_stat)
				if (psinfo.pr_sname != zbx_proc_stat)
					goto lbl_skip_procces;

			if (NULL != proccomm && '\0' != *proccomm)
				if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL))
					goto lbl_skip_procces;

			proccount++;
lbl_skip_procces:
			if (-1 != proc)
				close(proc);
		}
	}

	closedir(dir);

	SET_UI64_RESULT(result, proccount);

	return SYSINFO_RET_OK;
}
Exemple #10
0
int	PROC_MEM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
	DIR	*dir;
	int	proc;

	struct dirent	*entries;
	struct stat		buf;
	struct passwd	*usrinfo = NULL;
	struct prpsinfo	psinfo;

	char	filename[MAX_STRING_LEN];

	char	procname[MAX_STRING_LEN];
	char	usrname[MAX_STRING_LEN];
	char	mode[MAX_STRING_LEN];
	char	proccomm[MAX_STRING_LEN];

	int	do_task = DO_SUM;

	double	memsize = -1;
	int	pgsize = getpagesize();
	int	proccount = 0;
	pid_t	curr_pid = getpid();

	if(num_param(param) > 4)
	{
		return SYSINFO_RET_FAIL;
	}

	if(get_param(param, 1, procname, MAX_STRING_LEN) != 0)
	{
		return SYSINFO_RET_FAIL;
	}

	if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0)
	{
		usrname[0] = 0;
	}
	else
        {
		if(usrname[0] != 0)
		{
			usrinfo = getpwnam(usrname);
			if(usrinfo == NULL)
			{ /* incorrect user name */
				return SYSINFO_RET_FAIL;
			}
		}
	}

	if(get_param(param, 3, mode, MAX_STRING_LEN) != 0)
	{
		mode[0] = '\0';
	}

	if(mode[0] == '\0')
	{
		strscpy(mode, "sum");
	}

	if(strcmp(mode,"avg") == 0)
	{
		do_task = DO_AVG;
	}
	else if(strcmp(mode,"max") == 0)
	{
		do_task = DO_MAX;
	}
	else if(strcmp(mode,"min") == 0)
	{
		do_task = DO_MIN;
	}
	else if(strcmp(mode,"sum") == 0)
	{
		do_task = DO_SUM;
	}
	else
	{
		return SYSINFO_RET_FAIL;
	}

	if(get_param(param, 4, proccomm, MAX_STRING_LEN) != 0)
	{
		proccomm[0] = '\0';
	}

	dir=opendir("/proc");
	if(NULL == dir)
	{
	    return SYSINFO_RET_FAIL;
	}

	while((entries=readdir(dir))!=NULL)
	{
		strscpy(filename,"/proc/");
		zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN);

		if(stat(filename,&buf)==0)
		{
			proc = open(filename,O_RDONLY);
			if(proc == -1)
				goto lbl_skip_procces;

			if(ioctl(proc,PIOCPSINFO,&psinfo) == -1)
				goto lbl_skip_procces;

			/* Self process information. It leads to incorrect results for proc_cnt[zabbix_agentd] */
			if(psinfo.pr_pid == curr_pid)
				goto lbl_skip_procces;

			if(procname[0] != 0)
				if(strcmp(procname,psinfo.pr_fname) != 0)
					goto lbl_skip_procces;


			if(usrinfo != NULL)
				if(usrinfo->pw_uid != psinfo.pr_uid)
					goto lbl_skip_procces;

			if(proccomm[0] != '\0')
				if(zbx_regexp_match(psinfo.pr_psargs,proccomm,NULL) == NULL)
					goto lbl_skip_procces;

			proccount++;

			if(memsize < 0) /* First inicialization */
			{
				memsize = (double) (psinfo.pr_rssize * pgsize);
			}
			else
			{
				if(do_task == DO_MAX)
				{
					memsize = MAX(memsize, (double) (psinfo.pr_rssize * pgsize));
				}
				else if(do_task == DO_MIN)
				{
					memsize = MIN(memsize, (double) (psinfo.pr_rssize * pgsize));
				}
				else /* SUM */
				{
					memsize +=  (double) (psinfo.pr_rssize * pgsize);
				}
			}
lbl_skip_procces:
			if(proc) close(proc);
		}
	}

	closedir(dir);

	if(memsize < 0)
	{
		/* incorrect process name */
		memsize = 0;
	}

	if(do_task == DO_AVG)
	{
		SET_DBL_RESULT(result, proccount == 0 ? 0 : ((double)memsize/(double)proccount));
	}
	else
	{
		SET_UI64_RESULT(result, memsize);
	}

	return SYSINFO_RET_OK;
}
Exemple #11
0
int	PROC_NUM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result)
{
	DIR	*dir;
	int	proc;

	struct  dirent	*entries;
	struct  stat	buf;
	struct passwd	*usrinfo = NULL;
	struct prpsinfo	psinfo;

	char	filename[MAX_STRING_LEN];

	char	procname[MAX_STRING_LEN];
	char	usrname[MAX_STRING_LEN];
	char	procstat[MAX_STRING_LEN];
	char	proccomm[MAX_STRING_LEN];

	int	do_task = DO_SUM;

	int	proccount = 0;
	pid_t	curr_pid = getpid();

	if(num_param(param) > 4)
	{
		return SYSINFO_RET_FAIL;
	}

	if(get_param(param, 1, procname, MAX_STRING_LEN) != 0)
	{
		return SYSINFO_RET_FAIL;
	}

	if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0)
	{
		usrname[0] = 0;
	}
	else
        {
		if(usrname[0] != 0)
		{
			usrinfo = getpwnam(usrname);
			if(usrinfo == NULL)
			{ /* incorrect user name */
				return SYSINFO_RET_FAIL;
			}
		}
	}

	if(get_param(param, 3, procstat, MAX_STRING_LEN) != 0)
	{
		procstat[0] = '\0';
	}

	if(procstat[0] == '\0')
	{
		strscpy(procstat, "all");
	}

        if(strcmp(procstat,"run") == 0)
        {
		procstat[0] = PR_SRUN;		procstat[1] = '\0';
        }
        else if(strcmp(procstat,"sleep") == 0)
        {
		procstat[0] = PR_SSLEEP;	procstat[1] = '\0';
        }
        else if(strcmp(procstat,"zomb") == 0)
        {
		procstat[0] = PR_SZOMB;		procstat[1] = '\0';
        }
        else if(strcmp(procstat,"all") == 0)
        {
		procstat[0] = '\0';
        }
        else
        {
		return SYSINFO_RET_FAIL;
        }

	if(get_param(param, 4, proccomm, MAX_STRING_LEN) != 0)
	{
		proccomm[0] = '\0';
	}

	dir=opendir("/proc");
	if(NULL == dir)
	{
	    return SYSINFO_RET_FAIL;
	}

	while((entries=readdir(dir))!=NULL)
	{
		strscpy(filename,"/proc/");
		zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN);

		if(stat(filename,&buf)==0)
		{
			proc = open(filename,O_RDONLY);
			if(proc == -1)
				goto lbl_skip_procces;

			if(ioctl(proc,PIOCPSINFO,&psinfo) == -1)
				goto lbl_skip_procces;

			/* Self process information. It leads to incorrect results for proc_cnt[zabbix_agentd] */
			if(psinfo.pr_pid == curr_pid)
				goto lbl_skip_procces;

			if(procname[0] != 0)
				if(strcmp(procname,psinfo.pr_fname) != 0)
					goto lbl_skip_procces;

			if(usrinfo != NULL)
				if(usrinfo->pw_uid != psinfo.pr_uid)
					goto lbl_skip_procces;

			if(procstat[0] != '\0')
				if(psinfo.pr_sname != procstat[0])
					goto lbl_skip_procces;

			if(proccomm[0] != '\0')
				if(zbx_regexp_match(psinfo.pr_psargs,proccomm,NULL) == NULL)
					goto lbl_skip_procces;

			proccount++;

lbl_skip_procces:
			if(proc) close(proc);
		}
	}

	closedir(dir);

	SET_UI64_RESULT(result, proccount);

	return SYSINFO_RET_OK;
}
Exemple #12
0
/*
 * Connect to the database.
 * If fails, program terminates.
 */
int	zbx_db_connect(char *host, char *user, char *password, char *dbname, char *dbsocket, int port)
{
	int	ret = ZBX_DB_OK;
#ifdef	HAVE_SQLITE3
	char	*p, *path;
#endif /* HAVE_SQLITE3 */

#ifdef	HAVE_MYSQL
	/* For MySQL >3.22.00 */
	/*	if( ! mysql_connect( conn, NULL, dbuser, dbpassword ) )*/

	conn = mysql_init(NULL);

	if (!mysql_real_connect(conn, host, user, password, dbname, port, dbsocket, CLIENT_MULTI_STATEMENTS))
	{
		zabbix_errlog(ERR_Z3001, dbname, mysql_errno(conn), mysql_error(conn));
		ret = ZBX_DB_FAIL;
	}

	if (ZBX_DB_OK == ret)
	{
		if (0 != mysql_select_db(conn, dbname))
		{
			zabbix_errlog(ERR_Z3001, dbname, mysql_errno(conn), mysql_error(conn));
			ret = ZBX_DB_FAIL;
		}
	}

	if (ZBX_DB_OK == ret)
		DBexecute("SET CHARACTER SET utf8");

	if (ZBX_DB_FAIL == ret)
	{
		switch (mysql_errno(conn)) {
		case CR_CONN_HOST_ERROR:
		case CR_SERVER_GONE_ERROR:
		case CR_CONNECTION_ERROR:
		case CR_SERVER_LOST:
		case ER_SERVER_SHUTDOWN:
		case ER_UNKNOWN_ERROR:
			ret = ZBX_DB_DOWN;
			break;
		default:
			break;
		}
	}

	return ret;
#endif
#ifdef	HAVE_POSTGRESQL
	char		*cport = NULL;
	DB_RESULT	result;
	DB_ROW		row;
	int		sversion;

	if( port )	cport = zbx_dsprintf(cport, "%i", port);

	conn = PQsetdbLogin(host, cport, NULL, NULL, dbname, user, password );

	zbx_free(cport);

	/* check to see that the backend connection was successfully made */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		zabbix_errlog(ERR_Z3001, dbname, 0, PQerrorMessage(conn));
		ret = ZBX_DB_FAIL;
	}

	result = DBselect("select oid from pg_type where typname = 'bytea'");
	row = DBfetch(result);
	if(row)
	{
		ZBX_PG_BYTEAOID = atoi(row[0]);
	}
	DBfree_result(result);

#ifdef	HAVE_FUNCTION_PQSERVERVERSION
	sversion = PQserverVersion(conn);
	zabbix_log(LOG_LEVEL_DEBUG, "PostgreSQL Server version: %d", sversion);
#else
	sversion = 0;
#endif	/* HAVE_FUNCTION_PQSERVERVERSION */

	if (sversion >= 80100)
	{
		/* disable "nonstandard use of \' in a string literal" warning */
		DBexecute("set escape_string_warning to off");
	}

	return ret;
#endif
#ifdef	HAVE_ORACLE
	char	connect[MAX_STRING_LEN];

	zbx_strlcpy(connect, user, sizeof(connect));

	if (password && *password) {
		zbx_strlcat(connect, "/", sizeof(connect));
		zbx_strlcat(connect, password, sizeof(connect));

		if (dbname && *dbname) {
			zbx_strlcat(connect, "@", sizeof(connect));
			zbx_strlcat(connect, dbname, sizeof(connect));
		}
	}

	if (SQLO_SUCCESS != sqlo_init(SQLO_OFF, 1, 100)) {
		zabbix_errlog(ERR_Z3001, connect, 0, "Failed to init libsqlora8");
		ret = ZBX_DB_FAIL;
	}

	if (ZBX_DB_OK == ret) {
		/* login */ /* TODO: how to use port??? */
		if (SQLO_SUCCESS != sqlo_connect(&oracle, connect)) {
			zabbix_errlog(ERR_Z3001, connect, 0, "sqlo_connect");
			ret = ZBX_DB_FAIL;
		}
	}

	if (ZBX_DB_OK == ret)
		sqlo_autocommit_off(oracle);

	return ret;
#endif
#ifdef	HAVE_SQLITE3
	/* check to see that the backend connection was successfully made */
	if (SQLITE_OK != (ret = sqlite3_open(dbname, &conn))) {
		zabbix_errlog(ERR_Z3001, dbname, 0, sqlite3_errmsg(conn));
		exit(FAIL);
	}

	/* Do not return SQLITE_BUSY immediately, wait for N ms */
	sqlite3_busy_timeout(conn, 60*1000);

	sqlite_transaction_started = 0;

	path = strdup(dbname);
	if (NULL != (p = strrchr(path, '/')))
		*++p = '\0';
	else
		*path = '\0';

	DBexecute("PRAGMA synchronous = 0"); /* OFF */
	DBexecute("PRAGMA temp_store = 2"); /* MEMORY */
	DBexecute("PRAGMA temp_store_directory = '%s'", path);

	zbx_free(path);

	return ret;
#endif
}
/******************************************************************************
 *                                                                            *
 * Function: zbx_module_docker_discovery                                      *
 *                                                                            *
 * Purpose: container discovery                                               *
 *                                                                            *
 * Return value: SYSINFO_RET_FAIL - function failed, item will be marked      *
 *                                 as not supported by zabbix                 *
 *               SYSINFO_RET_OK - success                                     *
 *                                                                            *
 ******************************************************************************/
int     zbx_module_docker_discovery(AGENT_REQUEST *request, AGENT_RESULT *result)
{
        #include "zbxjson.h"
        zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_discovery()");
        
        struct zbx_json j;
        if (stat_dir == NULL && zbx_docker_stat_detect() == SYSINFO_RET_FAIL) {
            zabbix_log(LOG_LEVEL_DEBUG, "docker.discovery is not available at the moment - no stat directory - empty discovery");
            zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
            zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);
            zbx_json_close(&j);
            SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer));
            zbx_json_free(&j);
            return SYSINFO_RET_OK;
        }        
                
        char            line[MAX_STRING_LEN], *p, *mpoint, *mtype, container;
        FILE            *f;
        DIR             *dir;
        zbx_stat_t      sb;
        char            *file = NULL;
        struct dirent   *d;
        char    *cgroup = "cpuacct/";
        size_t  ddir_size = strlen(base_dir) + strlen(cgroup) + strlen(stat_dir) + 2;
        char    *ddir = malloc(ddir_size);
        zbx_strlcpy(ddir, base_dir, ddir_size);
        zbx_strlcat(ddir, cgroup, ddir_size);
        zbx_strlcat(ddir, stat_dir, ddir_size);


        if (NULL == (dir = opendir(ddir)))
        {
                zbx_error("%s: %s\n", ddir, zbx_strerror(errno));
        }

        zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);

        zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA);

        char    scontainerid[13];

        while (NULL != (d = readdir(dir)))
        {
                if(0 == strcmp(d->d_name, ".") || 0 == strcmp(d->d_name, ".."))
                        continue;

                file = zbx_dsprintf(file, "%s/%s", ddir, d->d_name);

                if (0 != zbx_stat(file, &sb) || 0 == S_ISDIR(sb.st_mode))
                        continue;
        
                zbx_json_addobject(&j, NULL);
                zbx_json_addstring(&j, "{#FCONTAINERID}", d->d_name, ZBX_JSON_TYPE_STRING);
                zbx_strlcpy(scontainerid, d->d_name, 13);
                zbx_json_addstring(&j, "{#SCONTAINERID}", scontainerid, ZBX_JSON_TYPE_STRING);
                zbx_json_close(&j);

        }


        if (0 != closedir(dir))
        {
                zbx_error("%s: %s\n", ddir, zbx_strerror(errno));
        }

        zbx_json_close(&j);

        SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer));

        zbx_json_free(&j);

        return SYSINFO_RET_OK;
}
/******************************************************************************
 *                                                                            *
 * Function: zbx_module_docker_mem                                            *
 *                                                                            *
 * Purpose: container memory metrics                                          *
 *                                                                            *
 * Return value: SYSINFO_RET_FAIL - function failed, item will be marked      *
 *                                 as not supported by zabbix                 *
 *               SYSINFO_RET_OK - success                                     *
 *                                                                            *
 ******************************************************************************/
int     zbx_module_docker_mem(AGENT_REQUEST *request, AGENT_RESULT *result)
{
        // documentation https://www.kernel.org/doc/Documentation/cgroups/memory.txt
        zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_mem()");
        char    *container, *metric;
        int     ret = SYSINFO_RET_FAIL;

        if (2 != request->nparam)
        {
                zabbix_log(LOG_LEVEL_ERR, "Invalid number of parameters: %d",  request->nparam);
                SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
                return SYSINFO_RET_FAIL;
        }
        
        if (stat_dir == NULL) {
                zabbix_log(LOG_LEVEL_DEBUG, "docker.cpu metrics are not available at the moment - no stat directory.");
                SET_MSG_RESULT(result, zbx_strdup(NULL, "docker.cpu metrics are not available at the moment - no stat directory."));
                return SYSINFO_RET_OK;
        }        

        container = get_rparam(request, 0);
        metric = get_rparam(request, 1);
        char    *stat_file = "/memory.stat";
        char    *cgroup = "memory/";
        size_t  filename_size = strlen(base_dir) + strlen(cgroup) + strlen(container) + strlen(stat_dir) + strlen(stat_file) + 2;
        char    *filename = malloc(filename_size);
        zbx_strlcpy(filename, base_dir, filename_size);
        zbx_strlcat(filename, cgroup, filename_size);
        zbx_strlcat(filename, stat_dir, filename_size);
        zbx_strlcat(filename, container, filename_size);
        zbx_strlcat(filename, stat_file, filename_size);
        zabbix_log(LOG_LEVEL_DEBUG, "Metric source file: %s", filename);
        FILE    *file;
        if (NULL == (file = fopen(filename, "r")))
        {
                zabbix_log(LOG_LEVEL_ERR, "Can't open docker container metric file: '%s'", filename);
                SET_MSG_RESULT(result, strdup("Can't open docker container memory.stat file"));
                return SYSINFO_RET_FAIL;
        }

        char    line[MAX_STRING_LEN];
        char    *metric2 = malloc(strlen(metric)+1);
        memcpy(metric2, metric, strlen(metric));
        memcpy(metric2 + strlen(metric), " ", 2);
        zbx_uint64_t    value = 0;
        zabbix_log(LOG_LEVEL_DEBUG, "Looking metric %s in memory.stat file", metric);
        while (NULL != fgets(line, sizeof(line), file))
        {
                if (0 != strncmp(line, metric2, strlen(metric2)))
                        continue;
                // aaa
                if (1 != sscanf(line, "%*s " ZBX_FS_UI64, &value)) {
                        zabbix_log(LOG_LEVEL_ERR, "sscanf failed for matched metric line");
                        continue;
                }
                // production severity only DEBUG
                zabbix_log(LOG_LEVEL_DEBUG, "Container: %s; metric: %s; value: %d", container, metric, value);
                SET_UI64_RESULT(result, value);
                ret = SYSINFO_RET_OK;
                break;
        }
        zbx_fclose(file);

        if (SYSINFO_RET_FAIL == ret)
                SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot find a line with requested metric in docker container memory.stat file."));

        return ret;
}