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/
|