Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Thursday, March 28, 2024

File: [Platon] / ep / src / proctable.c (download)

Revision 1.34, Fri Nov 28 17:35:11 2003 UTC (20 years, 4 months ago) by nepto


Changes since 1.33: +3 -3 lines

Changed URL from www.platon.sk to platon.sk.

/*
 * ep - extended pipelining
 *
 * proctable.c - process table implementation
 * ____________________________________________________________
 *
 * Developed by Ondrej Jombik <nepto@platon.sk>
 *          and Lubomir Host <rajo@platon.sk>
 * Copyright (c) 2000-2003 Platon SDG, http://platon.sk/
 * All rights reserved.
 *
 * See README file for more information about this software.
 * See COPYING file for license information.
 *
 * Download the latest version from
 * http://platon.sk/projects/ep/
 */

/* $Platon: ep/src/proctable.c,v 1.33 2003/05/03 09:58:19 nepto Exp $ */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <stdio.h>
#include <errno.h>

#ifdef STDC_HEADERS
#  include <stdlib.h>
#  include <string.h>
#endif

#if HAVE_UNISTD_H
#  include <sys/types.h>
#  include <unistd.h>
#endif

#if HAVE_SYS_WAIT_H
#  include <sys/wait.h>
#endif

#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h> /* S_IFCHR */
/* #include <sys/time.h> PRIO_PROCESS */
#include <sys/resource.h> /* PRIO_PROCESS */

#include "platon-str.h"

#include "proctable.h"
#include "process.h"
#include "message.h" /* msg_*_print() */
#include "conf.h" /* cfg */


static char buf[BUFSIZE];


    int
proctable_get_size(ptbl)
    PROCTABLE ptbl;
{
    register int i;

    for (i = 0; ptbl[i] != NULL; i++)
        ;

    return i;
}

    PROCTABLE
proctable_create(size)
    const int size;
{
    PROCTABLE ptbl;
    register int i;

    ptbl = (PROCTABLE) malloc((size + 1) * sizeof(struct process *));
    if (ptbl == NULL)
        return NULL;

    ptbl[size] = NULL;

    for (i = 0; i < size; i++) {
        ptbl[i] = (struct process *) malloc(sizeof(struct process));
        if (ptbl[i] == NULL) {
            proctable_destroy(&ptbl);
            return NULL;
        }

        process_init(ptbl[i]);
    }

    return ptbl;
}

    void
proctable_destroy(p_ptbl)
    PROCTABLE *p_ptbl;
{
    if (p_ptbl != NULL) {
        register int i;

        /* TODO:
         * Here was written *p_ptbl[i] instead (*p_ptbl)[i] on several places.
         * I supposed that it is the same. LEARN OPERATOR PRIORITIES ASAP!!
         * -- Nepto [2/12/2001]
         */

        for (i = 0; (*p_ptbl)[i] != NULL; i++) {
            process_destroy((*p_ptbl)[i]);
            free((*p_ptbl)[i]);
        }

        free(*p_ptbl);
        *p_ptbl = NULL;
    }
}

    int
proctable_join(p_dest_ptbl, src_ptbl)
    PROCTABLE *p_dest_ptbl;
    PROCTABLE src_ptbl;
{
    register int i, dest_size, src_size;

    if (p_dest_ptbl == NULL)
        return 0;

    for (i = 0; *p_dest_ptbl != NULL && (*p_dest_ptbl)[i] != NULL; i++)
        ;
    dest_size = i;

    for (i = 0; src_ptbl != NULL && src_ptbl[i] != NULL; i++)
        ;
    src_size = i;

    *p_dest_ptbl = (PROCTABLE) realloc(*p_dest_ptbl,
            sizeof(struct process *) * (dest_size + src_size + 1));
    if (*p_dest_ptbl == NULL)
        return 0;

    for (i = 0; i < src_size; i++)
        (*p_dest_ptbl)[dest_size + i] = src_ptbl[i];

    (*p_dest_ptbl)[dest_size + src_size] = NULL;

    return 1;
}

    int
proctable_get_process_index_by_pid(ptbl, pid)
    PROCTABLE ptbl;
    int       pid;
{
    register int i = 0;

    for (i = 0; ptbl[i] != NULL; i++)
        if (ptbl[i]->pid == pid)
            return i;

    return -1;
}

    int
proctable_get_process_index_by_name(ptbl, name)
    PROCTABLE ptbl;
    char      *name;
{
    register int i = 0;

    for (i = 0; ptbl[i] != NULL; i++)
        if (ptbl[i]->name != NULL
                && ! PLATON_FUNC(strdyn_casecmp)(ptbl[i]->name, name))
            return i;

    return -1;
}


    int
proctable_add_std_process(p_ptbl)
    PROCTABLE *p_ptbl;
{
    register int i;

    i = proctable_get_size(*p_ptbl);

    /* 1 for ending NULL, 1 for new std_process */
    *p_ptbl = (PROCTABLE) realloc(*p_ptbl, (i + 2) * sizeof(struct process *));

    if (*p_ptbl == NULL) {
        msg_error_print("realloc() failure\n");
        return -1;
    }

    for (; i >= 0; i--)
        (*p_ptbl)[i + 1] = (*p_ptbl)[i];

    (*p_ptbl)[0] = (struct process *) malloc(sizeof(struct process));

    if ((*p_ptbl)[0] == NULL) {
        msg_error_print("malloc() failure\n");
        for (i = 1; *p_ptbl[i] != NULL; i++) {
            process_destroy(*p_ptbl[i]);
            free(*p_ptbl[i]);
        }
        free(*p_ptbl);
        return -1;
    }

    process_init((*p_ptbl)[0]);

    return 0;
}


    int
proctable_update(ptbl)
    PROCTABLE ptbl;
{
    register int i, j, k;
    struct proclink link;

    for (i = 0; ptbl[i] != NULL; i++) {
        link.proc_id = i;
        for (k = 0; k < N_FD; k++) {
            link.fd_id = k;
            for (j = 0; j < ptbl[i]->fd[k].n_link; j++) {

                /* Invalid link? */
                if (ptbl[i]->fd[k].link[j].proc_id
                        >= proctable_get_size(ptbl)) {
                    msg_error_print("invalid process number '%d'\n",
                            ptbl[i]->fd[k].link[j].proc_id);
                    return -1;
                }

                /* Selflink? */
                if (i == ptbl[i]->fd[k].link[j].proc_id) {
                    msg_error_print("cannot self link from %d.%s to %d.%s\n",
                            i, fd_id_to_fd_str(k),
                            ptbl[i]->fd[k].link[j].proc_id,
                            fd_id_to_fd_str(ptbl[i]->fd[k].link[j].fd_id));
                    return -1;
                }

                /* Duplicated link? */
                if (fd_is_proclink(&ptbl[i]->fd[k],
                            &ptbl[i]->fd[k].link[j]) - 1 != j) {
                    msg_error_print(
                            "duplicated link from %d.%s to %d.%s\n",
                            i, fd_id_to_fd_str(k),
                            ptbl[i]->fd[k].link[j].proc_id,
                            fd_id_to_fd_str(ptbl[i]->fd[k].link[j].fd_id));
                    return -1;
                }

                /* Linking input to input or output to output? */
                while (1) {
                    if (k == 0) {
                        if (i == 0) {
                            if (ptbl[i]->fd[k].link[j].fd_id == 0)
                                break;
                        }
                        else
                            if (ptbl[i]->fd[k].link[j].fd_id == 0) {
                                if (ptbl[i]->fd[k].link[j].proc_id == 0)
                                    break;
                            }
                            else
                                if (ptbl[i]->fd[k].link[j].proc_id != 0)
                                    break;
                    }
                    else {
                        if (i == 0) {
                            if (ptbl[i]->fd[k].link[j].fd_id != 0)
                                break;
                        }
                        else
                            if (ptbl[i]->fd[k].link[j].fd_id != 0) {
                                if (ptbl[i]->fd[k].link[j].proc_id == 0)
                                    break;
                            }
                            else
                                if (ptbl[i]->fd[k].link[j].proc_id != 0)
                                    break;

                    }

                    msg_error_print(
                            "incorrect link from %d.%s to %d.%s\n",
                            i, fd_id_to_fd_str(k),
                            ptbl[i]->fd[k].link[j].proc_id,
                            fd_id_to_fd_str(ptbl[i]->fd[k].link[j].fd_id));

                    return -1;
                }

                /* If equivalent link doesn't exist, create it. */
                if (fd_is_proclink(&ptbl[ptbl[i]->fd[k].link[j].proc_id]->
                            fd[ptbl[i]->fd[k].link[j].fd_id], &link))
                    ;
                else
                    fd_add_proclink(&ptbl[ptbl[i]->fd[k].link[j].proc_id]->
                            fd[ptbl[i]->fd[k].link[j].fd_id], &link);
            }
        }
    }

    return 0;
}


    int
proctable_create_pipes(ptbl)
    PROCTABLE ptbl;
{
    register int i, k;

    for (i = 0; ptbl[i] != NULL; i++) {
        for (k = 0; k < N_FD; k++) {
            /* XXX: We want to create pipes anyway. */
            if (1 || ptbl[i]->fd[k].n_link != 0) {
                if (i == 0) {
                    /* Set the standart (basic) descriptors. */
                    ptbl[0]->fd[k].pipe[0] = ptbl[0]->fd[k].pipe[1] = k;
                }
                else {
#if DEBUG
                    msg_debug_print("creating pipe ptbl[%d]->fd[%d].pipe",
                            i, k);
#endif

                    if (pipe(ptbl[i]->fd[k].pipe) < 0) {
#if DEBUG
                        msg_print(" - failed\n");
#endif
                        return -1;
                    }

#if DEBUG
                    msg_print(" = (%d, %d)\n",
                            ptbl[i]->fd[k].pipe[0], ptbl[i]->fd[k].pipe[1]);
#endif
                }
            }
        }
    }

    return 0;
}


    int
proctable_exec(ptbl)
    PROCTABLE ptbl;
{
    register int i, j, k;

    for (i = 1; ptbl[i] != NULL; i++) {
        switch (ptbl[i]->pid = fork()) {

            /* Parent process. */
            default:
                break;

                /* Error. */
            case -1:
                return -1;

                /* Child process. */
            case 0:
                for (k = 0; k < N_FD; k++)
                    /* XXX: We want to dup pipe anyway. */
                    if (1 || ptbl[i]->fd[k].n_link != 0) {

                        dup2(ptbl[i]->fd[k].pipe[k ? 1 : 0], k);

                        /* See the '1 ||' below.
                           close(ptbl[i]->fd[k].pipe[0]);
                           close(ptbl[i]->fd[k].pipe[1]);
                           */
                    }
                    else {
#if DEBUG
                        msg_debug_print("proctable_exec(): "
                                "process %d, fd %d, no links defined\n", i, k);
#endif
                    }

                for (j = 1; ptbl[j] != NULL; j++) {
                    if (1 || i != j)
                        for (k = 0; k < N_FD; k++) {
                            close(ptbl[j]->fd[k].pipe[0]);
                            close(ptbl[j]->fd[k].pipe[1]);
                        }
                }
#if 0
                /* setvbuf(stdout, NULL, _IONBF, 0); */
                /* setbuf(stdout, NULL); */

                for (k = 0; k < N_FD; k++) {
                    if (k > 0) {
                        fchmod(k, 030620);
                        fcntl(k, F_SETFL, O_NONBLOCK|O_NDELAY);
                    }
                }
#endif
                if (ptbl[i]->nice != 0
                        && setpriority(PRIO_PROCESS, PRIO_PROCESS,
                            ptbl[i]->nice) == -1
                        && ! cfg.quiet)
                    /* this is probably written to wrong place;
                       fd 2 (stderr) must not be real stderr */
                    msg_warn_print("cannot set priority %d for process %d\n",
                            ptbl[i]->nice, i);

                execvp(ptbl[i]->argv[0], ptbl[i]->argv);

                /*
                 * RETURN VALUES
                 * If  any  of the exec functions returns, an error will have
                 * occurred.  The return value is -1, and the global variable
                 * errno will be set to indicate the error.
                 */

                /* msg_error_print("can't exec: %s\n", strerror(errno)); */

                close(1);
                close(2);
                close(0);

                /* execvp() fails, exiting */
                exit(errno == 0 ? 255 : (errno < 0 ? -errno : errno));
        }
    }

    /*
     * All fork()-s were OK.
     * Returning successfully.
     */

    return 0;
}


    void
proctable_close_2nd_sides_of_pipes(ptbl)
    PROCTABLE ptbl;
{
    register int i;

    for (i = 1; ptbl[i] != NULL; i++)
        process_close_2nd_sides_of_pipes(ptbl[i]);
}

    int
proctable_remove_process(p_ptbl, proc_id)
    PROCTABLE *p_ptbl;
    const int proc_id;
{
    register int i, j, k;

    /*
     * Pri odstraneni procesu je nutne:
     * - odstranit process z tabulky PROCTABLE a posunut vsetky za nim
     * - prepisat vsetky linky v PROCTABLE
     * - zrusit vsetky linky odkazujuce na dany process
     *
     * Nepto [3/4/2001]
     */

#if DEBUG
    msg_debug_print("proctable_remove_process(%p [%p], %d)\n",
            p_ptbl, *p_ptbl, proc_id);
#endif

    for (k = 0; k < N_FD; k++) {
        if (proctable_remove_process_fd_links(*p_ptbl, proc_id, k) == -1)
            return -1;
    }

    for (i = 0; (*p_ptbl)[i] != NULL; i++) {
        for (k = 0; k < N_FD; k++) {
#if DEBUG
            msg_debug_print("  process %d fd %d n_link %d\n",
                    i, k, (*p_ptbl)[i]->fd[k].n_link);
#endif
            for (j = 0; j < (*p_ptbl)[i]->fd[k].n_link; /* empty */) {

                if ((*p_ptbl)[i]->fd[k].link[j].proc_id == proc_id) {
                    /* This removing stuff was moved to begin of function. */
                    /* fd_remove_proclink_by_index(&(*p_ptbl)[i]->fd[k], j); */
                }
                else {
                    if ((*p_ptbl)[i]->fd[k].link[j].proc_id > proc_id)
                        (*p_ptbl)[i]->fd[k].link[j].proc_id--;
                    j++;
                }
            }
        }
    }

    process_destroy((*p_ptbl)[proc_id]);

    for (i = proc_id; (*p_ptbl)[i] != NULL; i++) {
        (*p_ptbl)[i] = (*p_ptbl)[i + 1];
    }

    /* Process table is a list of process ended with NULL.        */
    /* Resizing process table: '-1' is for size down by 1         */
    /*                         '+1' cause we already go down by 1 */
    /*                              see the for () above          */
    /*                         '+1' is for ending NULL            */
    /* So the final is '+1'.                                      */

    *p_ptbl = (PROCTABLE) realloc(*p_ptbl,
            (proctable_get_size(*p_ptbl) + 1) * sizeof(struct process *));

    if (*p_ptbl == NULL) {
        msg_error_print("proctable_remove_process(): realloc() failure\n");
        return -1;
    }

#if DEBUG
    msg_debug_print("proctable_remove_process(%p [%p])\n",
            p_ptbl, *p_ptbl);
#endif

    return 0;
}

    int
proctable_remove_process_fd_links(ptbl, proc_id, fd_id)
    PROCTABLE ptbl;
    int       proc_id;
    int       fd_id;
{
    while (ptbl[proc_id]->fd[fd_id].n_link > 0) {
        register int a_proc_id, a_fd_id;

        /* 0 means the first proclink;
           we want remove them all continuosly */
        a_proc_id = ptbl[proc_id]->fd[fd_id].link[0].proc_id;
        a_fd_id   = ptbl[proc_id]->fd[fd_id].link[0].fd_id;

        /* Process 1: id: i,       fd: k     */
        /* Process 2: id: proc_id, fd: fd_id */

        if (
                fd_remove_proclink2(
                    &((ptbl[a_proc_id])->fd[a_fd_id]),
                    proc_id, fd_id) == 0
                ||
                fd_remove_proclink2(
                    &((ptbl[proc_id])->fd[fd_id]),
                    a_proc_id, a_fd_id) == 0
           )
            return -1;
    }

    return 0;
}

    void
proctable_print(ptbl)
    PROCTABLE ptbl;
{
    register int i, j, k;

    for (i = 0; ptbl[i] != NULL; i++) {
        msg_print("Process %d (", i);
        process_print_names(ptbl[i]);
        msg_print("): ");
        process_print_cmdline(ptbl[i]);
        msg_print("\n");

        for (k = 0; k < N_FD; k++) {
            msg_print("  %s = (%d, %d)\n", fd_id_to_fd_str(k),
                    ptbl[i]->fd[k].pipe[0], ptbl[i]->fd[k].pipe[1]);
            for (j = 0; j < ptbl[i]->fd[k].n_link; j++)
                msg_print("    [%d].%s %s [%d].%s\n",
                        i, fd_id_to_fd_str(k),
                        ((i&&k) || (!i&&!k)) ? "->" : "<-",
                        ptbl[i]->fd[k].link[j].proc_id,
                        fd_id_to_fd_str(ptbl[i]->fd[k].link[j].fd_id));
        }
    }
}

    int
proctable_read(p_ptbl, p_rfds, p_wfds, p_efds)
    PROCTABLE *p_ptbl;
    fd_set    *p_rfds;
    fd_set    *p_wfds;
    fd_set    *p_efds;
{
    register int i, k, datasize = 1;

    for (i = 0; (*p_ptbl)[i] != NULL; i++) {
        for (k = 0; k < N_FD; k++) {
            if (FD_ISSET((*p_ptbl)[i]->fd[k].pipe[0], p_efds)) {
                FD_CLR((*p_ptbl)[i]->fd[k].pipe[0], p_efds);
#if DEBUG
                msg_debug_print("proctable_read(): exception:"
                        " process %d, fd %d, real fd %d\n",
                        i, k, (*p_ptbl)[i]->fd[k].pipe[0]);
#endif
            }
        }

        for (k = (i ? 1 : 0); k < (i ? N_FD : 1); k++) {
            if (FD_ISSET((*p_ptbl)[i]->fd[k].pipe[0], p_rfds)) {
                register int j;

                FD_CLR((*p_ptbl)[i]->fd[k].pipe[0], p_rfds);

                datasize = read((*p_ptbl)[i]->fd[k].pipe[0],
                        buf, BUFSIZE);

#if DEBUG
                msg_debug_print("proctable_read(): descriptor change:"
                        " process %d, fd %d, datasize %d\n",
                        i, k, datasize);
#endif

                if (datasize == 0) {
                    /* TODO: multi reads from one fd doesn't work!!! */
                    close((*p_ptbl)[i]->fd[k].pipe[0]);
#if DEBUG
                    msg_debug_print("proctable_read(): close(%d)\n",
                            (*p_ptbl)[i]->fd[k].pipe[0]);
#endif
                }

                if (datasize < 0) {
#if DEBUG
                    msg_debug_print("proctable_read(): "
                            "read() failure, %d returned\n",
                            datasize);
#endif
                    msg_errno_print();
                    msg_print("Terminating...");
                    exit(1);
                }

                if (datasize == 0) {
                    /* Variable datasize is 0, filedescriptor is closed.
                       Now we are going to remove all proclinks from/to this
                       filedescriptor. */

                    proctable_remove_process_fd_links(*p_ptbl, i, k);
                }
                else {
                    /* Variable datasize is not 0. Data were recieved.
                       We are going to transfer datasize bytes to linked
                       filedescriptors. */

                    for (j = 0; j < (*p_ptbl)[i]->fd[k].n_link; j++) {
                        register int proc_id, fd_id;
                        register int fd_write;

                        proc_id  = (*p_ptbl)[i]->fd[k].link[j].proc_id;
                        fd_id    = (*p_ptbl)[i]->fd[k].link[j].fd_id;
                        fd_write = (*p_ptbl)[proc_id]->fd[fd_id].pipe[1];
#if 0 && DEBUG
                        msg_debug_print("proctable_read(): descriptor write:"
                                " process %d, fd %d, datasize %d\n",
                                proc_idx, fd_write, datasize);
#endif
                        switch (write(fd_write, buf, datasize)) {
                            case -1:
                                /* This is some special case. We are writting
                                   to filedescriptor,which probably desn't exists
                                   (ie. due to child exit). With signal handling
                                   and appropriate testing after select() return
                                   we should never get here. But if signals are
                                   not used, this situation is quite common

ep: debug: proctable_read(): write() failed: Broken pipe

So that descriptor is not usable anymore.
We will remove its proclinks.  */

#if DEBUG
                                msg_debug_print("proctable_read(): "
                                        "write() failed: %s\n",
                                        strerror(errno));
#endif

                                proctable_remove_process_fd_links(*p_ptbl, proc_id, fd_id);
                                break;
                            case 0: /* Similar situation as -1 above */
#if DEBUG
                                msg_debug_print("proctable_read(): "
                                        "write() returns 0: %s\n",
                                        strerror(errno));
#endif
                                proctable_remove_process_fd_links(*p_ptbl, proc_id, fd_id);
                                break;
                            default:
                                break;
                        }
                    }
                }
            } /* if (FD_ISSET()) */
            else
                datasize = 1;

            if (! datasize)
                break;
        }
        if (! datasize)
            break;
    }

    /* Returns 0 if process was removed, 1 elsewhere. */
    return datasize;
}

    int
proctable_wait(p_ptbl)
    PROCTABLE *p_ptbl;
{
    int pid = 0;
    int status;

#if DEBUG
    msg_debug_print("proctable_wait(): f_wait_call == 1, calling wait()\n");
#endif
    /*
     * Parameters in waitpid():
     * 1. Value -1 means wait for any child process
     * 2. Constant WNOHANG means return immediately if no child has exited.
     */
    pid = waitpid(-1, &status, WNOHANG);

    switch (pid) {
        case -1:
#if 0
            msg_error_print("proctable_wait(): "
                    "waitpid() failure: %s\n", strerror(errno));
#endif
            break;

        case 0:
#if DEBUG
            msg_warn_print("proctable_wait(): "
                    "waitpid() warning: no child available\n");
#endif

            /* We will check if there is a process which should be
               terminated. If it is, we will return 1 and than main
               program will call us again after select() timeout. */
            {
                register int i, k, proc_n_link = 1;

                for (i = 1; (*p_ptbl)[i] != NULL; i++) {

                    for (proc_n_link = 0, k = 0; k < N_FD; k++)
                        proc_n_link += (*p_ptbl)[i]->fd[k].n_link;

                    if (proc_n_link == 0) {
#if DEBUG
                        msg_debug_print("proctable_wait(): candidate index = %d\n", i);
#endif
                        /* Don't need to browse the process table more. */
                        /* THIS IS WRONG! */
                        break;
                    }
                }

                if (proc_n_link == 0)
                    pid = 1;
            }
            break;

        default:
            {
                register int index;

                index = proctable_get_process_index_by_pid(*p_ptbl, pid);
#if DEBUG
                msg_debug_print("proctable_wait(): "
                        "pid = %d, index = %d\n",
                        pid, index);

                msg_debug_print("proctable_wait(): "
                        "proctable_get_size() = %d\n",
                        proctable_get_size(*p_ptbl));
#endif

                if (! cfg.quiet) {
                    msg_print("[%d] ", pid);

                    if (WIFEXITED(status)) {
                        msg_print("Exit");
                        if (WEXITSTATUS(status))
                            msg_print(" %d", WEXITSTATUS(status));
                    }
                    else if (WIFSIGNALED(status)) {
                        register int sig_n = WTERMSIG(status);

                        switch (sig_n) {
                            case SIGKILL:
                                msg_print("Killed");
                                break;
                            case SIGTERM:
                                msg_print("Terminated");
                                break;
                            case SIGSEGV:
                                msg_print("Segmentation fault");
                                break;
                            default:
                                msg_print("Received signal %d", sig_n);
                                break;
                        };
                    }
                    else {
                        msg_print("Aborted", pid);
                    }

                    msg_print("\t\t\t\t");
                    msg_array_print((*p_ptbl)[index]->argv);
                    msg_print("\n");
                } /* if (! cfg.quiet) */
#if DEBUG
                msg_debug_print("proctable_wait(): "
                        "removing process from process table\n");
#endif
                proctable_remove_process(p_ptbl, index);
#if DEBUG
                msg_debug_print("proctable_wait(): "
                        "proctable_get_size() = %d\n",
                        proctable_get_size(*p_ptbl));
#endif
            }

            break;
    } /* switch (pid) */

    return pid;
}

    int
proctable_wait2(p_ptbl)
    PROCTABLE *p_ptbl;
{
    register int i, k, proc_n_link = 1;
    int pid = 0;
    int status;

    for (i = 1; (*p_ptbl)[i] != NULL; i++) {

        for (proc_n_link = 0, k = 0; k < N_FD; k++)
            proc_n_link += (*p_ptbl)[i]->fd[k].n_link;

        if (proc_n_link == 0) {
#if DEBUG
            msg_debug_print("proctable_wait2(): candidate index = %d\n", i);
#endif
            pid = waitpid((*p_ptbl)[i]->pid, &status, WNOHANG);

            switch (pid) {
                case -1:
#if 0
                    msg_error_print("proctable_wait2(): "
                            "waitpid() failure: %s\n", strerror(errno));
#endif

                    return pid;
                    break;

                case 0:
#if DEBUG
                    msg_warn_print("proctable_wait2(): "
                            "waitpid() warning: no child available\n");
#endif
                    break;
                default:
                    if (! cfg.quiet) {
                        msg_print("[%d] ", pid);

                        if (WIFEXITED(status)) {
                            msg_print("Exit");
                            if (WEXITSTATUS(status))
                                msg_print(" %d", WEXITSTATUS(status));
                        }
                        else if (WIFSIGNALED(status)) {
                            register int sig_n = WTERMSIG(status);

                            switch (sig_n) {
                                case SIGKILL:
                                    msg_print("Killed");
                                    break;
                                case SIGTERM:
                                    msg_print("Terminated");
                                    break;
                                case SIGSEGV:
                                    msg_print("Segmentation fault");
                                    break;
                                default:
                                    msg_print("Received signal %d", sig_n);
                                    break;
                            };
                        }
                        else {
                            msg_print("Aborted", pid);
                        }

                        msg_print("\t\t\t\t");
                        msg_array_print((*p_ptbl)[i]->argv);
                        msg_print("\n");
                    } /* if (! cfg.quiet) */

                    proctable_remove_process(p_ptbl, i);
                    return pid;

                    break;
            }
        }
    }

    return 0;
}


Platon Group <platon@platon.org> http://platon.org/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top