Skip to content

Instantly share code, notes, and snippets.

@StefanoBelli
Last active March 30, 2017 19:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StefanoBelli/0de64b63a14cdfa244999331408d6a91 to your computer and use it in GitHub Desktop.
Save StefanoBelli/0de64b63a14cdfa244999331408d6a91 to your computer and use it in GitHub Desktop.
Various process control calls
#include <sys/utsname.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <signal.h>
#include "procutils.h"
#define MODE_RDONLY "r"
#define SSIGN_EVERY_PROCESS(pids,kc,cnt,sig,err) \
int i; \
for(i=0;i<cnt;++i) { \
if(kill(pids[i],sig) == -1) { \
err = FINISHED_WITH_KILL_FAILURE; \
continue; \
} \
kc++; \
}
static inline bool strdgt(const char* name)
{
while(*name) {
if(!isdigit(*name))
return false;
*(name++);
}
return true;
}
proc_err pidof(const char* name, int* count, pid_t** pids_out)
{
*count = 0;
*pids_out = NULL;
/* compatibility reason */
struct utsname sysinfo;
if(uname(&sysinfo) == -1)
return FATAL_UNAME_FAILURE;
if(strcmp(sysinfo.sysname,"Linux"))
return FATAL_COMPAT_OS;
DIR* procd = opendir("/proc");
if(!procd)
return FATAL_PROC_OPENDIR;
proc_err status = FINISHED_OK;
struct dirent* entry = NULL;
char path[PATH_MAX], comm[256];
while((entry = readdir(procd))) {
if(entry->d_type != DT_DIR)
continue;
if(!strdgt(entry->d_name))
continue;
snprintf(path,PATH_MAX,"/proc/%s/comm",entry->d_name);
FILE* commfp = fopen(path,MODE_RDONLY);
if(!commfp)
continue;
fgets(comm,256,commfp);
fclose(commfp);
comm[strlen(comm)-1] = 0;
if(strcmp(comm,name))
continue;
*pids_out = (!*count) ? (pid_t*) malloc(sizeof(pid_t)) :
(pid_t*) realloc(*pids_out, sizeof(pid_t) + (*count + 1));
if(!*pids_out) {
status = FATAL_MEMORY_EXHAUSTED;
break;
}
(*pids_out)[*count] = (pid_t) atoi(entry->d_name);
(*count)++;
}
closedir(procd);
return status;
}
proc_err killall(pid_t* pids, int* killed_count, const int howmany, const int nsig)
{
*killed_count = 0;
if(!pids)
return FATAL_NULLPIDS;
proc_err status = FINISHED_OK;
SSIGN_EVERY_PROCESS(pids,(*killed_count),howmany,nsig,status);
return status;
}
proc_err killall_byname(const char* name, int* killed_count, const int nsig)
{
*killed_count = 0;
proc_err status = FINISHED_OK;
int procs = 0;
pid_t *pids = NULL;
if((status = pidof(name,&procs,&pids)) != FINISHED_OK)
return status;
SSIGN_EVERY_PROCESS(pids,(*killed_count),procs,nsig,status);
if(pids)
free(pids);
return status;
}
#ifndef __PROC_UTILS_H
#define __PROC_UTILS_H
#include <sys/types.h>
typedef enum {
FINISHED_OK,
FINISHED_WITH_KILL_FAILURE,
FATAL_COMPAT_OS,
FATAL_PROC_OPENDIR,
FATAL_UNAME_FAILURE,
FATAL_MEMORY_EXHAUSTED,
FATAL_NULLPIDS
} proc_err;
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
proc_err pidof(const char* name, int* count, pid_t** pids_out);
proc_err killall(pid_t* pids, int* killed_count, const int howmany, const int nsig);
proc_err killall_byname(const char* name, int* killed_count, const int nsig);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif //__PROC_UTILS_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment