/*
** Copyright (C) 2001-2024 Zabbix SIA
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
** See the GNU Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see .
**/
/* Enable wide (64-bit) interfaces for narrow (32-bit) applications (see pstat(2) for details). */
/* Without this on some HP-UX systems you can get runtime error when calling pstat_getproc(): */
/* Value too large to be stored in data type */
#ifndef _PSTAT64
# define _PSTAT64
#endif
#include "zbxsysinfo.h"
#include "../sysinfo.h"
#include "zbxregexp.h"
#include "zbxstr.h"
#include
static int check_procstate(struct pst_status pst, int zbx_proc_stat)
{
if (ZBX_PROC_STAT_ALL == zbx_proc_stat)
return SUCCEED;
switch (zbx_proc_stat)
{
case ZBX_PROC_STAT_RUN:
return PS_RUN == pst.pst_stat ? SUCCEED : FAIL;
case ZBX_PROC_STAT_SLEEP:
return PS_SLEEP == pst.pst_stat ? SUCCEED : FAIL;
case ZBX_PROC_STAT_ZOMB:
return PS_ZOMBIE == pst.pst_stat ? SUCCEED : FAIL;
}
return FAIL;
}
int proc_num(AGENT_REQUEST *request, AGENT_RESULT *result)
{
#define ZBX_BURST ((size_t)10)
char *procname, *proccomm, *param, *rxp_error = NULL;
struct passwd *usrinfo;
int proccount = 0, invalid_user = 0, zbx_proc_stat, count, idx = 0;
struct pst_status pst[ZBX_BURST];
zbx_regexp_t *proccomm_rxp = NULL;
if (4 < request->nparam)
{
SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
return SYSINFO_RET_FAIL;
}
procname = get_rparam(request, 0);
if (NULL != procname && '\0' == *procname)
procname = NULL;
param = get_rparam(request, 1);
if (NULL != param && '\0' != *param)
{
errno = 0;
if (NULL == (usrinfo = getpwnam(param)))
{
if (0 != errno)
{
SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain user information: %s",
zbx_strerror(errno)));
return SYSINFO_RET_FAIL;
}
invalid_user = 1;
}
}
else
usrinfo = NULL;
param = get_rparam(request, 2);
if (NULL == param || '\0' == *param || 0 == strcmp(param, "all"))
zbx_proc_stat = ZBX_PROC_STAT_ALL;
else if (0 == strcmp(param, "run"))
zbx_proc_stat = ZBX_PROC_STAT_RUN;
else if (0 == strcmp(param, "sleep"))
zbx_proc_stat = ZBX_PROC_STAT_SLEEP;
else if (0 == strcmp(param, "zomb"))
zbx_proc_stat = ZBX_PROC_STAT_ZOMB;
else
{
SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
return SYSINFO_RET_FAIL;
}
proccomm = get_rparam(request, 3);
if (NULL != proccomm)
{
if ('\0' == *proccomm)
{
proccomm = NULL;
}
else if (SUCCEED != zbx_regexp_compile(proccomm, &proccomm_rxp, &rxp_error))
{
SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Invalid regular expression in fourth parameter: "
"%s", rxp_error));
zbx_free(rxp_error);
return SYSINFO_RET_FAIL;
}
}
if (1 == invalid_user) /* handle 0 for non-existent user after all parameters have been parsed and validated */
goto out;
memset(pst, 0, sizeof(pst));
while (0 < (count = pstat_getproc(pst, sizeof(*pst), ZBX_BURST, idx)))
{
for (int i = 0; i < count; i++)
{
if (NULL != procname && 0 != strcmp(pst[i].pst_ucomm, procname))
continue;
if (NULL != usrinfo && usrinfo->pw_uid != pst[i].pst_uid)
continue;
if (NULL != proccomm)
{
union pstun un;
char cmdline[1024]; /* up to 1020 characters from HP-UX */
/* pstat_getcommandline() is available only from HP-UX 11i v2. */
/* To handle HP-UX 11.11 a popular workaround is used. */
un.pst_command = cmdline;
if (-1 == pstat(PSTAT_GETCOMMANDLINE, un, sizeof(cmdline), 1, pst[i].pst_pid))
continue;
if (0 != zbx_regexp_match_precompiled(cmdline, proccomm_rxp))
continue;
}
if (FAIL == check_procstate(pst[i], zbx_proc_stat))
continue;
proccount++;
}
idx = pst[count - 1].pst_idx + 1;
memset(pst, 0, sizeof(pst));
}
if (-1 == count)
{
SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain process information."));
if (NULL != proccomm_rxp)
zbx_regexp_free(proccomm_rxp);
return SYSINFO_RET_FAIL;
}
out:
SET_UI64_RESULT(result, proccount);
if (NULL != proccomm_rxp)
zbx_regexp_free(proccomm_rxp);
return SYSINFO_RET_OK;
#undef ZBX_BURST
}