|  | /* | 
|  | * Copyright (C) Tildeslash Ltd. All rights reserved. | 
|  | * | 
|  | * This program is free software: you can redistribute it and/or modify | 
|  | * it under the terms of the GNU Affero General Public License 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 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 <http://www.gnu.org/licenses/>. | 
|  | * | 
|  | * In addition, as a special exception, the copyright holders give | 
|  | * permission to link the code of portions of this program with the | 
|  | * OpenSSL library under certain conditions as described in each | 
|  | * individual source file, and distribute linked combinations | 
|  | * including the two. | 
|  | * | 
|  | * You must obey the GNU Affero General Public License in all respects | 
|  | * for all of the code used other than OpenSSL. | 
|  | */ | 
|  |  | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #ifdef HAVE_STDIO_H | 
|  | #include <stdio.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_TYPES_H | 
|  | #include <sys/types.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_UNISTD_H | 
|  | #include <unistd.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_STAT_H | 
|  | #include <sys/stat.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_FCNTL_H | 
|  | #include <fcntl.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STDLIB_H | 
|  | #include <stdlib.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef TIME_WITH_SYS_TIME | 
|  | #include <time.h> | 
|  |  | 
|  | #ifdef HAVE_SYS_TIME_H | 
|  | #include <sys/time.h> | 
|  | #endif | 
|  | #else | 
|  | #include <time.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STRING_H | 
|  | #include <string.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_STRINGS_H | 
|  | #include <strings.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_ERRNO_H | 
|  | #include <errno.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_PARAM_H | 
|  | #include <sys/param.h> | 
|  | #endif | 
|  |  | 
|  | #define _RUSAGE_EXTENDED | 
|  |  | 
|  | #ifdef HAVE_SYS_PSTAT_H | 
|  | #include <sys/pstat.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_NLIST_H | 
|  | #include <nlist.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_DK_H | 
|  | #include <sys/dk.h> | 
|  | #endif | 
|  |  | 
|  | #ifdef HAVE_SYS_SWAP_H | 
|  | #include <sys/swap.h> | 
|  | #endif | 
|  |  | 
|  | #include "monit.h" | 
|  | #include "process.h" | 
|  | #include "process_sysdep.h" | 
|  |  | 
|  | static int         page_size; | 
|  | static int         nproc; | 
|  | static long        cpu_total_old = 0; | 
|  | static long        cpu_user_old = 0; | 
|  | static long        cpu_syst_old = 0; | 
|  | static long        cpu_wait_old = 0; | 
|  | struct pst_dynamic pst_dyn; | 
|  | struct pst_status *psall; | 
|  |  | 
|  | #define MAXSTRSIZE 80 | 
|  |  | 
|  | /** | 
|  | *  System dependent resource gathering code for HP/UX. | 
|  | * | 
|  | *  @file | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Helpful guide for implematation: | 
|  | * "SunOS to HP-UX 9.05 Porting Guide" at http://www.interex.org/tech/9000/Tech/sun_hpux_port/portguide.html | 
|  | */ | 
|  |  | 
|  | int init_process_info_sysdep(void) { | 
|  | struct pst_dynamic psd; | 
|  | struct pst_static pst; | 
|  |  | 
|  | if (pstat_getdynamic(&psd,sizeof(psd),(size_t)1,0) != -1) | 
|  | systeminfo.cpus=psd.psd_proc_cnt; | 
|  | else | 
|  | return FALSE; | 
|  |  | 
|  | if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) != -1) { | 
|  | systeminfo.mem_kbyte_max=(unsigned long)(pst.physical_memory * (pst.page_size / 1024)); | 
|  | page_size=pst.page_size; | 
|  | } else { | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * This routine returns 'na' double precision floats containing | 
|  | * the load averages in 'a'; at most 3 values will be returned. | 
|  | * @param loadv destination of the load averages | 
|  | * @param nelem number of averages | 
|  | * @return: 0 if successful, -1 if failed (and all load averages are 0). | 
|  | */ | 
|  | int getloadavg_sysdep (double *a, int na) { | 
|  | struct pst_dynamic psd; | 
|  |  | 
|  | if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) { | 
|  | switch (na) { | 
|  | case 3: | 
|  | a[2] = psd.psd_avg_15_min; | 
|  |  | 
|  | case 2: | 
|  | a[1] = psd.psd_avg_5_min; | 
|  |  | 
|  | case 1: | 
|  | a[0] = psd.psd_avg_1_min; | 
|  | } | 
|  | } else { | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Read all processes to initialize the process tree | 
|  | * @param reference  reference of ProcessTree | 
|  | * @return treesize>0 if succeeded otherwise 0. | 
|  | */ | 
|  | int initprocesstree_sysdep(ProcessTree_T ** reference) { | 
|  | int            i; | 
|  | int            treesize; | 
|  | ProcessTree_T *pt; | 
|  |  | 
|  | ASSERT(reference); | 
|  |  | 
|  | pstat_getdynamic(&pst_dyn, sizeof(struct pst_dynamic), 1, 0); | 
|  | nproc = pst_dyn.psd_activeprocs; | 
|  |  | 
|  | if (nproc) | 
|  | RESIZE(psall, nproc * sizeof(struct pst_status)); | 
|  | else | 
|  | return 0; | 
|  |  | 
|  | if ((treesize = pstat_getproc(psall, sizeof(struct pst_status), nproc , 0)) == -1) { | 
|  | LogError("system statistic error 1 -- pstat_getproc failed: %s\n", strerror(errno)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | pt = CALLOC(sizeof(ProcessTree_T), treesize); | 
|  |  | 
|  | for (i = 0; i < treesize; i++) { | 
|  | pt[i].pid         = psall[i].pst_pid; | 
|  | pt[i].ppid        = psall[i].pst_ppid; | 
|  | pt[i].starttime   = psall[i].pst_start; | 
|  | pt[i].time        = get_float_time(); | 
|  | pt[i].cputime     =  psall[i].pst_utime + psall[i].pst_stime * 10; | 
|  | pt[i].cpu_percent = (int)(1000. * psall[i].pst_pctcpu / (float)systeminfo.cpus); | 
|  | pt[i].mem_kbyte   = (unsigned long)(psall[i].pst_rssize * (page_size / 1024.0)); | 
|  | pt[i].cmdline     = (psall[i].pst_cmd && *psall[i].pst_cmd) ? Str_dup(psall[i].pst_cmd) : Str_dup(psall[i].pst_ucomm); | 
|  |  | 
|  | if ( psall[i].pst_stat == PS_ZOMBIE ) | 
|  | pt[i].status_flag |= PROCESS_ZOMBIE; | 
|  | } | 
|  |  | 
|  | *reference = pt; | 
|  |  | 
|  | return treesize; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * This routine returns kbyte of real memory in use. | 
|  | * @return: TRUE if successful, FALSE if failed (or not available) | 
|  | */ | 
|  | int used_system_memory_sysdep(SystemInfo_T *si) { | 
|  | int                 i, n, num; | 
|  | struct pst_static   pst; | 
|  | struct pst_dynamic  psd; | 
|  | struct swaptable   *s; | 
|  | char               *strtab; | 
|  | unsigned long long  total = 0ULL; | 
|  | unsigned long long  used  = 0ULL; | 
|  |  | 
|  | /* Memory */ | 
|  | if(pstat_getstatic(&pst, sizeof(pst), (size_t)1, 0) == -1) { | 
|  | LogError("system statistic error -- pstat_getstatic failed: %s\n", STRERROR); | 
|  | return FALSE; | 
|  | } | 
|  | if(pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) == -1) { | 
|  | LogError("system statistic error -- pstat_getdynamic failed: %s\n", STRERROR); | 
|  | return FALSE; | 
|  | } | 
|  | si->total_mem_kbyte = (unsigned long)((pst.physical_memory - psd.psd_free) * (pst.page_size/1024)); | 
|  |  | 
|  | /* Swap */ | 
|  | again: | 
|  | if ((num = swapctl(SC_GETNSWP, 0)) == -1) { | 
|  | LogError("system statistic error -- swap usage gathering failed: %s\n", STRERROR); | 
|  | return FALSE; | 
|  | } | 
|  | if (num == 0) { | 
|  | DEBUG("system statistic -- no swap configured\n"); | 
|  | si->swap_kbyte_max = 0; | 
|  | return TRUE; | 
|  | } | 
|  | s = (struct swaptable *)ALLOC(num * sizeof(struct swapent) + sizeof(struct swaptable)); | 
|  | strtab = (char *)ALLOC((num + 1) * MAXSTRSIZE); | 
|  | for (i = 0; i < (num + 1); i++) | 
|  | s->swt_ent[i].ste_path = strtab + (i * MAXSTRSIZE); | 
|  | s->swt_n = num + 1; | 
|  | if ((n = swapctl(SC_LIST, s)) < 0) { | 
|  | LogError("system statistic error -- swap usage gathering failed: %s\n", STRERROR); | 
|  | si->swap_kbyte_max = 0; | 
|  | FREE(s); | 
|  | FREE(strtab); | 
|  | return FALSE; | 
|  | } | 
|  | if (n > num) { | 
|  | DEBUG("system statistic -- new swap added: deferring swap usage statistics to next cycle\n"); | 
|  | FREE(s); | 
|  | FREE(strtab); | 
|  | goto again; | 
|  | } | 
|  | for (i = 0; i < n; i++) { | 
|  | if (!(s->swt_ent[i].ste_flags & ST_INDEL) && !(s->swt_ent[i].ste_flags & ST_DOINGDEL)) { | 
|  | total += s->swt_ent[i].ste_pages; | 
|  | used  += s->swt_ent[i].ste_pages - s->swt_ent[i].ste_free; | 
|  | } | 
|  | } | 
|  | FREE(s); | 
|  | FREE(strtab); | 
|  | si->swap_kbyte_max   = (unsigned long)(double)(total * page_size) / 1024.; | 
|  | si->total_swap_kbyte = (unsigned long)(double)(used  * page_size) / 1024.; | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * This routine returns system/user CPU time in use. | 
|  | * @return: TRUE if successful, FALSE if failed (or not available) | 
|  | */ | 
|  | int used_system_cpu_sysdep(SystemInfo_T *si) { | 
|  | int                i; | 
|  | long               cpu_total; | 
|  | long               cpu_total_new = 0; | 
|  | long               cpu_user = 0; | 
|  | long               cpu_syst = 0; | 
|  | long               cpu_wait = 0; | 
|  | struct pst_dynamic psd; | 
|  |  | 
|  | pstat_getdynamic(&psd, sizeof(psd), 1, 0); | 
|  |  | 
|  | for(i = 0; i < CPUSTATES; i++) | 
|  | cpu_total_new += psd.psd_cpu_time[i]; | 
|  | cpu_total     = cpu_total_new - cpu_total_old; | 
|  | cpu_total_old = cpu_total_new; | 
|  | cpu_user      = psd.psd_cpu_time[CP_USER] + psd.psd_cpu_time[CP_NICE]; | 
|  | cpu_syst      = psd.psd_cpu_time[CP_SYS]; | 
|  | cpu_wait      = psd.psd_cpu_time[CP_WAIT]; | 
|  |  | 
|  | si->total_cpu_user_percent = (cpu_total > 0)?(int)(1000 * (double)(cpu_user - cpu_user_old) / cpu_total):-10; | 
|  | si->total_cpu_syst_percent = (cpu_total > 0)?(int)(1000 * (double)(cpu_syst - cpu_syst_old) / cpu_total):-10; | 
|  | si->total_cpu_wait_percent = (cpu_total > 0)?(int)(1000 * (double)(cpu_wait - cpu_wait_old) / cpu_total):-10; | 
|  |  | 
|  | cpu_user_old = cpu_user; | 
|  | cpu_syst_old = cpu_syst; | 
|  | cpu_wait_old = cpu_wait; | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  |