Commit c2a7f751 authored by Arnaud Blanchard's avatar Arnaud Blanchard
Browse files

Initial files for managing processes

parents
# Copyright ETIS — ENSEA, Université de Cergy-Pontoise, CNRS (2011 - 2016)
# Author: Arnaud Blanchard
# This software is governed by the CeCILL v2.1 license under French law and abiding by the rules of distribution of free software.
# You can use, modify and/ or redistribute the software under the terms of the CeCILL v2.1 license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
# users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability.
# In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge.
# Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured  and, more generally, to use and operate it in the same conditions as regards security.
# The fact that you are presently reading this means that you have had knowledge of the CeCILL v2.1 license and that you accept its terms.
cmake_minimum_required(VERSION 2.6)
project(blc_processes)
add_definitions(-Wall -Wextra -Wno-multichar)
get_filename_component(BLAAR_DIR ${CMAKE_SOURCE_DIR} PATH)
if (NOT TARGET shared_blc_core)
add_subdirectory(${BLAAR_DIR}/blc/blc_core blc_core)
endif()
if (NOT TARGET shared_blc_channel)
add_subdirectory(${BLAAR_DIR}/blc/blc_core blc_core)
endif()
if (NOT TARGET shared_blc_program)
add_subdirectory(${BLAAR_DIR}/blc/blc_core blc_core)
endif()
include_directories(include ${BLC_CORE_INCLUDE_DIR} ${BLC_CHANNEL_INCLUDE_DIR} ${BLC_PROGRAM_INCLUDE_DIR})
#source files
set(sources src/blc_processes.cpp)
#create the library
add_library(shared_blc_processes SHARED ${sources})
add_library(static_blc_processes STATIC ${sources})
target_link_libraries(shared_blc_processes shared_blc_program shared_blc_channel shared_blc_core)
set(BLC_PROCESSES_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
#Both librairies have the same name only the extension will change depending on the OS
set_target_properties(shared_blc_processes PROPERTIES OUTPUT_NAME blc_processes)
set_target_properties(static_blc_processes PROPERTIES OUTPUT_NAME blc_processes)
#Describe what will be to install or in the package
install(DIRECTORY include/ DESTINATION include)
install(TARGETS static_blc_processes shared_blc_processes DESTINATION lib)
#define a rule to make debian .deb package
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Arnaud Blanchard")
include(CPack)
//
// lsof.hpp
// blc_channels
//
// Created by Arnaud Blanchard on 18/04/2016.
//
//
#ifndef BLC_PROCESSES_H
#define BLC_PROCESSES_H
#include "blc_channel.h"
#include <limits.h> //NAME_MAX LINE_MAX
struct file_opening
{
struct blc_process *process;
char access;
char type[8];
};
typedef struct blc_file
{
blc_channel *channel;
struct file_opening *openings;
int openings_nb;
}blc_file;
typedef struct blc_process
{
char command[NAME_MAX+1];
char full_command_line[LINE_MAX];
float cpu_percent, mem_percent;
int mem;
pid_t pid;
blc_channel **input_channels;
int input_channels_nb;
blc_channel **output_channels;
int output_channels_nb;
blc_channel **bidirectional_channels;
int bidirectional_channels_nb;
}blc_process;
extern blc_process *blc_processes;
extern int blc_processes_nb;
blc_file *blc_find_file(char const *name);
blc_process *blc_find_process(pid_t pid);
void blc_update_shared_files(blc_process **processes, int *processes_nb, blc_channel *channels, int channels_nb);
//void blc_update_shared_files(blc_channel *channels, int channels_nb);
void blc_processes_refresh(blc_process *processes, int processes_nb);
#endif /* lsof_hpp */
//
// lsof.cpp
// blc_channels
//
// Created by Arnaud Blanchard on 18/04/2016.
//
//
#include "blc_processes.h"
#include "blc_program.h"
#include "blc_command.h"
#include "blc_core.h"
#include <unistd.h> //read
#include <errno.h> //EINTR
#include <sys/wait.h> //waitpid
blc_file *blc_files=NULL;
int files_nb=0;
blc_process *blc_processes=NULL;
int blc_processes_nb=0;
void destroy_file_infos(blc_file **files_infos, int *files_infos_nb)
{
blc_file *current_file;
FOR_EACH(current_file, *files_infos, *files_infos_nb) FREE(current_file->openings);
FREE(*files_infos);
*files_infos_nb=0;
}
blc_process *blc_find_process(pid_t pid)
{
int i;
FOR_INV(i, blc_processes_nb) if (blc_processes[i].pid==pid) return &blc_processes[i];
return NULL;
}
/*
blc_file *blc_find_file(char const *name)
{
int i;
FOR_INV(i, files_nb) if (strcmp(files[i].channel->name, name)==0) return &files[i];
return NULL;
}*/
void blc_update_shared_files(blc_process **processes, int *processes_nb, blc_channel *channels, int channels_nb)
{
blc_mem mem;
char buf[LINE_MAX];
char *path;
int stdout_pipe[2];
pid_t pid;
char *str=NULL, *previous;
char letter, access;
ssize_t n;
int status, pos, len;
blc_process *process=NULL, tmp_process;
blc_channel tmp_info;
blc_channel *channel;
SYSTEM_ERROR_CHECK(pipe(stdout_pipe), -1, NULL);
pid=fork();
if (pid==0)
{
//SPRINTF(buf, "-p^%d", blaar_pid); Exclude itself
SYSTEM_ERROR_RETRY_ON_SPECIFIC_ERRNO(dup2(stdout_pipe[1], STDOUT_FILENO), -1, EINTR, NULL);
blc_close_pipe(stdout_pipe);
SYSTEM_ERROR_CHECK(execlp("lsof", "lsof", "-wlnP", "-F", "actn", "-d", "1-999", NULL), -1, NULL);
}
else
{
mem.chars=NULL;
close(stdout_pipe[1]);
// destroy_file_infos(&files, &files_nb);
do{
SYSTEM_ERROR_RETRY_ON_SPECIFIC_ERRNO(n=read(stdout_pipe[0], buf, sizeof(buf)), -1, EINTR, "read lsof stdout");
mem.append(buf, n);
}while(n!=0);
waitpid(pid, &status, 0);
close(stdout_pipe[0]);
mem.append("", 1); //end of string
str=mem.chars;
do{
letter=str[0];
pos=0;
str++;
switch (letter){
case 'p':
CLEAR(tmp_process);
SYSTEM_SUCCESS_CHECK(sscanf(str, "%d\n%n", &tmp_process.pid, &pos), 1, NULL);
process=NULL;
break;
case 'c':
SYSTEM_SUCCESS_CHECK(sscanf(str, "%"STRINGIFY_CONTENT(NAME_MAX)"s\n", tmp_process.command), 1, NULL);
str=strchr(str, '\n')+1;
break;
case 'a':
access=str[0];
str+=3; //[acces]\nt
len=0;
if (strncmp(str, "PSXSHM\nn", strlen("PSXSHM\nn"))==0) len=strlen("PSXSHM\nn"); //on OSX it is <channel_name with />
if (strncmp(str, "REG\nn/run/shm", strlen("REG\nn/run/shm"))==0) len=strlen("REG\nn/run/shm"); //On Linux it is /dev/shm<channel_name with />
if(len) {
str+=len;
path=str;
str=strchr(str, '\n');
*str=0;
FOR_EACH_INV(channel, channels, channels_nb){
if (strcmp(channel->name, path)==0){
FOR_EACH_INV(process, *processes, *processes_nb) if (process->pid == tmp_process.pid) break;
if(process==*processes-1){//Process not found
process=(blc_process*)APPEND_ITEM(processes, processes_nb, &tmp_process);
}
switch(access){
case 'r':APPEND_ITEM(&process->input_channels, &process->input_channels_nb, &channel);break;
case 'w':APPEND_ITEM(&process->output_channels, &process->output_channels_nb, &channel);break;
case 'u':APPEND_ITEM(&process->bidirectional_channels, &process->bidirectional_channels_nb, &channel);break;
default :EXIT_ON_ERROR("Acces '%c' for channel '%s' is not managed.", access, channel->name);
}
break;
}
}
str++;
//We have not found channel
/* if (channel != channels-1){
if (process==NULL) // It is a new process session.
{
process=blc_find_process(tmp_process.pid);
if (process==NULL) APPEND_ITEM(&blc_processes, &blc_processes_nb, &tmp_process);
}
file=blc_find_file(path);
if (file==NULL)//the file has never been referenced
{
tmp_file.openings=NULL;
tmp_file.openings_nb=0;
tmp_file.channel=channel;
file=(blc_file*)APPEND_ITEM(&files, &files_nb, &tmp_file);
}
tmp_file_opening.process=process;
APPEND_ITEM(&file->openings, &file->openings_nb, &tmp_file_opening);
}*/
}
else str=strchr(str, '\n')+1; //We pass the non shared memory file
break;
default:
str=strchr(str, '\n')+1;
break;
}
previous=str;
str+=pos;
}while(str[0]!=0);
mem.allocate(0);
}
}
void blc_processes_refresh(blc_process *processes, int processes_nb)
{
blc_mem mem;
char buf[4096];
int stdout_pipe[2], n, status, length, pos;
pid_t pid;
char **argv=NULL;
int argc=0;
int ret;
char *arg;
char *line;
blc_process *process, tmp_process;
char tmp_arg[NAME_MAX];
SYSTEM_ERROR_CHECK(pipe(stdout_pipe), -1, NULL);
pid=fork();
if (pid==0){
blc_add_arg(&argc, &argv, "ps", NULL);
blc_add_arg(&argc, &argv, "-o", "pid");
blc_add_arg(&argc, &argv, "-o", "%cpu");
blc_add_arg(&argc, &argv, "-o", "rss");
blc_add_arg(&argc, &argv, "-o", "%mem");
blc_add_arg(&argc, &argv, "-o", "command");
if (processes==NULL) blc_add_arg(&argc, &argv, "-A", NULL);
else{
FOR_EACH_INV(process, processes, processes_nb){
SPRINTF(tmp_arg, "%d", process->pid);
arg=strdup(tmp_arg); //Do not need to be freed, it will be freed when execvp
blc_add_arg(&argc, &argv, "-p", arg);
}
}
blc_add_arg(&argc, &argv, NULL, NULL);
SYSTEM_ERROR_RETRY_ON_SPECIFIC_ERRNO(dup2(stdout_pipe[1], STDOUT_FILENO), -1, EINTR, NULL);
blc_close_pipe(stdout_pipe);
SYSTEM_ERROR_CHECK(execvp("ps", argv), -1, NULL);
}
else
{
close(stdout_pipe[1]);
do
{
SYSTEM_ERROR_RETRY_ON_SPECIFIC_ERRNO(n=read(stdout_pipe[0], buf, sizeof(buf)), -1, EINTR, "read ps stdout");
mem.append(buf, n);
}while(n!=0);
close(stdout_pipe[0]);
mem.append("", 1); //end of string
waitpid(pid, &status, 0);
sscanf(mem.chars, "%*[^\n]\n%n", &pos); // remove title
if (mem.size>1)
{
line=mem.chars+pos;
while((ret=sscanf(line, " %d %f %d %f %"STRINGIFY_CONTENT(LINE_MAX)"[^\n]\n%n", &tmp_process.pid, &tmp_process.cpu_percent, &tmp_process.mem, &tmp_process.mem_percent, tmp_process.full_command_line, &length))==4){
FOR_EACH_INV(process, processes, processes_nb) if (process->pid == tmp_process.pid) *process=tmp_process; //not very efficient
line+=length;
}
}
mem.allocate(0);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment