Platon Technologies
neprihlásený Prihlásiť Registrácia
SlovakEnglish
open source software development oslavujeme 10 rokov vývoja otvoreného softvéru! Piatok, 29. marec 2024

Súbor: [Platon] / ep / src / main.c (stiahnutie)

Revízia 1.35, Fri Nov 28 17:35:11 2003 UTC (20 years, 4 months ago) by nepto


Zmeny od 1.34: +3 -3 [lines]

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

/*
 * ep - extended pipelining
 *
 * main.c - main implemetation
 * ____________________________________________________________
 *
 * 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/main.c,v 1.34 2003/07/16 16:09:13 nepto Exp $ */

/*
 * ep - extended pipelining
 * coding start date: 11.11.2000
 * authors: Ondrej Jombik
 *          Lubomir Host
 *            Martin Karas
 * Copyright (c) 2000-2003 Platon Software Development Group
 * license: GNU General Public License
 */

/* Notes:

 * Now signal handler for every signal is installed. If SIG_CHLD detected, gloal
 variable sig_chld is set. This change is printed out in main() in debug mode.
 No other usage of sig_chld variable is currently used.

 * When write() syscall fails (that means returning -1 or 0), particular
 proclinks to failed fd are removed and fd is closed.

*/

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

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

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

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

#if TIME_WITH_SYS_TIME
#  include <sys/time.h>
#  include <time.h>
#else
#  if HAVE_SYS_TIME_H
#    include <sys/time.h>
#  else
#    include <time.h>
#  endif
#endif

#if HAVE_SYS_WAIT_H
#  include <sys/wait.h>
#endif
#ifndef WEXITSTATUS
#  define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
#  define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif

#if MENU
#  include <curses.h>
#endif

#include "main.h"

#include "process.h"
#include "proctable.h"
#include "fd.h"
#include "message.h"
#include "sigserv.h"
#include "conf.h"

#if MENU
#  include "menu.h"
#endif

/*
 * Global variables
 */

/* Global pointer to argv[0] (program name). */
char *argv0;
/* Configration filenames (shouldn't be static in conf.c?). */
char *conf_global_filename = "/etc/ep.conf";
char *conf_user_filename   = ".ep.conf";
/* Program configuration structure. */
struct conf_struct_global cfg;


    void
exit_fnc(void)
{
    conf_destroy();

#if DEBUG
    msg_debug_print("exit_fnc(): %s terminating\n", argv0);
#endif

    free(argv0);

#if MENU
    endwin();
#endif
}

    int
main(argc, argv)
    int  argc;
    char **argv;
{
    register int i, k;
    register int ret, pid = 0;
    struct timeval tv;
    fd_set rfds;
    fd_set wfds;
    fd_set efds;
    PROCTABLE ptbl;

    /*
     * Creating global variable argv0.
     */
    argv0 = strrchr(argv[0], '/') == NULL
        ? strdup(argv[0])
        : strdup(strrchr(argv[0], '/') + 1);

    if (argv0 == NULL) {
        fprintf(stderr, "fatal-error: not enough memory\n");
        return 1;
    }

    /*
     * Registering atexit() function.
     */
    if (atexit(exit_fnc) < 0) {
        msg_error_print("cannot register atexit() function\n");
        return 1;
    }

    if (argc < 2) {
        msg_usage_print();
        return 1;
    }

#if MENU
    /*
     * Ncurses menu initialization
     */
    menu_curses_init();
#endif

    /*
     * Initializing configuration module
     */
    if (! conf_init()) {
        msg_error_print("cannot init configuration parsing structures\n");
        return 1;
    }

    /*
     * Parsing command line and all config files (global, user and specified)
     */
    ptbl = conf_parse_all(argc, argv);

    if (ptbl == NULL) {
        return 1;
    }
#if DEBUG
    else
        msg_debug_print("configuration parsing: OK\n");
#endif

    if (/* proctable_add_std_process(&ptbl) < 0 ||*/ 
            proctable_update(ptbl) < 0) {
        return 1;
    }
#if DEBUG
    else
        msg_debug_print("proctable check: OK\n");
#endif
    /*
     * Creating pipes via pipe() syscalls
     */
    if (proctable_create_pipes(ptbl) < 0) {
        msg_error_print("cannot create pipes\n");
        return 1;
    }
#if DEBUG
    else
        msg_debug_print("creating pipes: OK\n");
#endif

    /*
     * Fork processes and dup pipes.
     * Exec the processes via execvp().
     */
    if (proctable_exec(ptbl) < 0) {
        msg_error_print("fork() failure: %s\n", strerror(errno));
        return 1;
    }
#if DEBUG
    else
        msg_debug_print("%d times fork(): OK\n", proctable_get_size(ptbl));
#endif


    /*
     * Closing 2nd sides of pipes.
     */
    proctable_close_2nd_sides_of_pipes(ptbl);

    /*
     * Instaling signal handler.
     */
    sigserv_init(ptbl);

#if DEBUG
    /*
     * Proctable print.
     */
    proctable_print(ptbl);
#endif

    /*
     * Main loop
     */
    while (1) {
        register int size;

        /* Set rfds and efds. */
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        FD_ZERO(&efds);

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

            for (k = 0; k < N_FD; k++) {
                if (ptbl[i]->fd[k].n_link != 0) {
                    if ((!i && !k) || (i && k)) {
                        FD_SET(ptbl[i]->fd[k].pipe[0], &rfds);
                    }
                    else {
                        /* FD_SET(ptbl[i]->fd[k].pipe[1], &wfds); */
                    }

                    /* FD_SET(ptbl[i]->fd[k].pipe[k ? 0 : 1], &efds); */
                }
            }
        }

        /* TODO: if closed fd 0, always use timeout */
        if (pid == 1) {
            tv.tv_sec  = 0;
            tv.tv_usec = 1000;
        }

#if DEBUG
        if (sig_chld) {
            msg_debug_print("main(): SIG_CHLD detected\n");
            sig_chld = 0;
        }
#endif

        ret = select(FD_SETSIZE, &rfds, &wfds, &efds, pid == 1 ? &tv : NULL);

        if (ret < 0) {
            /* NOTE: this stuff around EBADF will be probably neccessary
               in the future. Although this, it is commented now, for
               better extended pipelinign debugging. */

            if (1 || errno != EBADF) {
                msg_error_print("select() failure: %s\n", strerror(errno));
                break;
            }

            sleep(1);
        }
#if DEBUG
        /*if (FD_ISSET(0, &rfds) && getchar() == 12)
          proctable_print(ptbl);*/
#endif
#if MENU
        if (FD_ISSET(0, &rfds)) {
            int c;
            c = getch();
            switch (c) {
                case '\033':                /* ESC */
                case KEY_F(9):                /* F9  */
                    menu_main(&ptbl);
                    touchwin(stdscr);
                    refresh();
                    break;
                case 12:                    /* ^l */
                    touchwin(stdscr);
                    refresh();
                    break;
                default:
                    break;

            }
        }
#endif /* #if HAVE_MENU */

        /*
         * Read and transfer data.
         */

        if (ret > 0) {
            while (proctable_read(&ptbl, &rfds, &wfds, &efds) == 0) {
#if DEBUG
                msg_debug_print("main(): repeating proctable_read()\n");
#endif
            }
        }

        /*
         * Check if processes still running.
         */

        while (1) {
            pid = proctable_wait2(&ptbl);
            /* printf("pid = %d\n", pid);sleep(1); */

            if (pid < 0) {
                msg_error_print("waitpid() failure: %s\n", strerror(errno));
                break;
            }

            size = proctable_get_size(ptbl);
            /* printf("size = %d\n", size);sleep(1); */
            if (size < 2 /* and 0 is closed */) {
                pid = -1;
                break;
            }

            if (pid == 0 || pid == 1)
                break;
            /*
               if (pid == 1) {
               if (proctable_wait(&ptbl) <= 1)
               break;
               }
               */
        }

        if (pid < 0)
            break;

    } /* while (1) */

    /*
     * Destroying used process table.
     */

    proctable_destroy(&ptbl);

    return errno == 0 ? 0 : (errno < 0 ? -errno : errno);
}


Platon Group <platon@platon.sk> http://platon.sk/
Copyright © 2002-2006 Platon Group
Stránka používa redakčný systém Metafox
Na začiatok