blob: 921cd4bb22dd1f11df0b0f4552eeda091a4de962 [file] [log] [blame] [edit]
/*
* 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.
*/
/**
* System independent /proc & kvm methods.
*
* @file
*/
#include "config.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_LOADAVG_H
#include <sys/loadavg.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "monit.h"
#include "process.h"
#include "process_sysdep.h"
/**
* Reads an process dependent entry or the proc filesystem
* @param buf buffer to write to
* @param buf_size size of buffer "buf"
* @param name name of proc service
* @param pid number of the process / or <0 if main directory
* @param bytes_read number of bytes read to buffer
* @return TRUE if succeeded otherwise FALSE.
*/
int read_proc_file(char *buf, int buf_size, char *name, int pid, int *bytes_read) {
int fd;
char filename[STRLEN];
int bytes;
int rv = FALSE;
ASSERT(buf);
ASSERT(name);
if (pid < 0)
snprintf(filename, STRLEN, "/proc/%s", name);
else
snprintf(filename, STRLEN, "/proc/%d/%s", pid, name);
if ((fd = open(filename, O_RDONLY)) < 0) {
DEBUG("%s: Cannot open proc file %s -- %s\n", prog, filename, STRERROR);
return rv;
}
if ((bytes = (int)read(fd, buf, buf_size-1)) < 0) {
DEBUG("%s: Cannot read proc file %s -- %s\n", prog, filename, STRERROR);
goto error;
}
if (bytes_read)
*bytes_read = bytes;
/* In case it is a string we have to 0 terminate it our self */
buf[bytes]='\0';
rv = TRUE;
error:
if (close(fd) < 0)
LogError("%s: Socket close failed -- %s\n", prog, STRERROR);
return rv;
}
/**
* Get the actual time as a floating point number
* @return time in seconds
*/
double get_float_time(void) {
struct timeval t;
gettimeofday(&t, NULL);
return (double) t.tv_sec * 10 + (double) t.tv_usec / 100000.0;
}
/**
* Connects child and parent in a process tree
* @param pt process tree
* @param parent index
* @param child index
* @return TRUE if succeeded otherwise FALSE.
*/
int connectchild(ProcessTree_T *pt, int parent, int child) {
ASSERT(pt);
if (pt[parent].pid == pt[child].pid)
return FALSE;
RESIZE(pt[parent].children, sizeof(ProcessTree_T *) * (pt[parent].children_num + 1));
pt[parent].children[pt[parent].children_num] = child;
pt[parent].children_num++;
return TRUE;
}
/**
* Fill data in the process tree by recusively walking through it
* @param pt process tree
* @param i process index
* @return TRUE if succeeded otherwise FALSE.
*/
void fillprocesstree(ProcessTree_T *pt, int index) {
int i;
ProcessTree_T *parent_pt;
ASSERT(pt);
if (pt[index].visited == 1)
return;
pt[index].visited = 1;
pt[index].children_sum = pt[index].children_num;
pt[index].mem_kbyte_sum = pt[index].mem_kbyte;
pt[index].cpu_percent_sum = pt[index].cpu_percent;
for (i = 0; i < pt[index].children_num; i++)
fillprocesstree(pt, pt[index].children[i]);
if (pt[index].parent != -1 && pt[index].parent != index) {
parent_pt = &pt[pt[index].parent];
parent_pt->children_sum += pt[index].children_sum;
parent_pt->mem_kbyte_sum += pt[index].mem_kbyte_sum;
parent_pt->cpu_percent_sum += pt[index].cpu_percent_sum;
parent_pt->cpu_percent_sum = (pt[index].cpu_percent_sum > 1000) ? 1000 : parent_pt->cpu_percent_sum;
}
}