| /* |
| * 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; |
| } |
| |