Killall

    -- Sebastian Pawlak, 2005.


Przedstawione funkcje umożliwiają odnalezienie w systemie Linux PIDów procesów powiązanych z programem o zadanej nazwie. Zaimplementowane zostały także funkcje umożliwiające wysłanie sygnałów do procesów powiązanych z programem o zadanej nazwie.


Kod źródłowy pliku "kill.h":

/* kill.h: library of functions which allow to kill processes of known names;
 *         it serves processes compressed with UPX or uncompressed run 
 *         by different processes
 *
 * Sebastian Pawlak, 2005.
 */

#ifndef _KILL_H_
#define _KILL_H_

enum {
    MAX_PRG  = 10,   /* max. programs */
    MAX_PIDS = 8,    /* max. PIDs for one name of a program */
    MAX_VAL  = 64    /* max. length of program's name */ 
};

int name2pid(const char *name, pid_t *pid);
void killPrograms(const char name[][MAX_VAL + 1], int signo);
void killProgram(const char *name, int signo);

#endif

Kod źródłowy pliku "kill.c":

/* kill.c: library of functions which allow to kill processes of known names;
 *         it serves processes compressed with UPX or uncompressed run
 *         by different processes
 *
 * Sebastian Pawlak, 2005.
 */
#include <stdio.h>
#include <stdlib.h>      /* for strtol() */
#include <unistd.h>      /* for usleep() */
#include <sys/types.h>   /* for pid_t */
#include <dirent.h>      /* for opendir(), readdir() */
#include <signal.h>
#include "kill.h"

#define DEBUG

/* name2pid: finds PIDs of processes of a program with known name;
 *           returns -1, in case of an error or not found a process;
 *           returns positive value, which stays for number of found PIDs;
 *           found PIDs are written in pids[];
 *           looking for processes is done with use of:
 *           file /proc/XXXX/cmdline and link /proc/XXXX/exe
 */
int name2pid(const char *name, pid_t pids[])
{
    DIR *dir = NULL;
    struct dirent *dire = NULL;
    FILE *f = NULL;
    char s[256], linkName[64 + 1];
    pid_t pidTmp;
    int i = 0, n, isFound;

    /* opens "directory stream" -- a pointer points to a first element in
     * opened directory
     */
    if ((dir = opendir("/proc")) == NULL) {
        fprintf(stderr, "Problem with opendir()!");
        return -1;
    }

    /* looks in subdirectories in a directory /proc */
    while ((dire = readdir(dir)) != NULL) {

        /* if a name of a subdirectory /proc/XXXX is a number */
        if ((pidTmp = strtol(dire->d_name, NULL, 10)) > 0) {

            isFound = 0;

            /* if a link /proc/XXXX/exe contains the name of running program,
             * directory XXXX is the number of PID of process
             */
            sprintf(s, "/proc/%s/exe", dire->d_name);

            /* reads a name of a program pointed by a link "exe" */
            if ((n = readlink(s, linkName, 64)) != -1) {

                linkName[n] = '\0';

                /* if a link points to a file agreed with "name",
                 * we found seeking PID
                 */
                if ((strstr(linkName, name) != NULL) && (i < MAX_PIDS)) {
                    pids[i] = pidTmp;
                    i++;
                    isFound = 1;
                }
            }


            if (isFound == 0) {
                /* if a file /proc/XXXX/cmdline contains a name of run program,
                 * a directory XXXX is a number which stays for PID of process
                 */
                sprintf(s, "/proc/%s/cmdline", dire->d_name);

                if ((f = fopen(s, "r")) != NULL) {

                    if (fgets(s, 255, f) != NULL) {
                        /* if in a file "cmdline" is text agreed with "name",
                         * we found seeking PID
                         */
                        if ((strstr(s, name) != NULL) && (i < MAX_PIDS)) {
                            pids[i] = pidTmp;
                            i++;
                        }
                    }
                                                                                
                    fclose(f);
                }
            }
        }
    }

    closedir(dir);

    if (i == 0)
        return -1;

    return i;
}


/* killPrograms: kills all processes connected with supplied names of programs
 */
void killPrograms(const char name[][MAX_VAL + 1], int signo)
{
    pid_t pids[MAX_PIDS];
    int i, k;

    /* kills a following program */
    for (i = 0; i < MAX_PRG; i++) {

        if (name[i][0] == '\0')
            continue;

        /* converts a name of program to PIDs */
        if ((k = name2pid(name[i], pids)) != -1) {

            /* kills following PIDs for the same name of a program */
            for (--k; k >= 0; k--) {

                if (kill(pids[k], signo) == -1)
                    fprintf(stderr, "Problem with kill()!");
                else {
                    #ifdef DEBUG
                    fprintf(stdout, "Killed a process no.: %d.\n", pids[k]);
                    #endif
                }
            }
        } 
    }
}


/* killProgram: kills all processes connected with supplied name of a program
 */
void killProgram(const char *name, int signo)
{
    pid_t pids[MAX_PIDS];
    int k;

    /* converts a name of a program to PIDs */
    if ((k = name2pid(name, pids)) != -1) {

        /* kills following PIDs for the same name of a program */
        for (--k; k >= 0; k--) {

            if (kill(pids[k], signo) == -1)
                fprintf(stderr, "Problem with kill()!");
            else {
                #ifdef DEBUG
                fprintf(stdout, "Killed a process no.: %d.\n", pids[k]);
                #endif
            }
        }
    }
}

Kod źródłowy pliku "main.c":

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include "kill.h"

#define PROG_NAME "bash"

int main(void)
{
    const char names[MAX_PRG][MAX_VAL + 1] = { "xterm", "xcalc" };
    pid_t pids[MAX_PIDS] = { 0 };
    int pidsCntr = 0;
    int i;

    pidsCntr = name2pid(PROG_NAME, pids);

    if (pidsCntr == -1)
        return -1;

    /* Listing processes which are connected with a program PROG_NAME */
    fprintf(stdout, "PIDs of processes of program \""PROG_NAME"\":\n");
    for (i = 0; i < pidsCntr; i++)
        fprintf(stdout, "pid %d: %d\n", i, pids[i]);


    /* Killing processes which names are stored in "names" */
    killPrograms((const char (*)[])names, SIGKILL);

    return 0;
}
w3cw3c
automatyka przemysłowa