예제 #1
0
int main(int argc, char **argv)
{
	unsigned char buf[256];
	int size, s, cntrl_s, cntrl_fd;
	socklen_t cntrl_len;
	struct sockaddr_un cntrl_addr;
	fd_set read_fds, write_fds;
	int fd_max;

	if (ax25_config_load_ports() == 0) {
		fprintf(stderr, "ax25rtd: no AX.25 port configured\n");
		return 1;
	}

	load_config();
	load_cache();

	if (fork())
		return 0;

	if ((s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_AX25))) == -1) {
		perror("AX.25 socket");
		return 1;
	}

	if ((cntrl_s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
		perror("Control socket");
		return 1;
	}

	unlink(DATA_AX25ROUTED_CTL_SOCK);

	cntrl_addr.sun_family = AF_UNIX;
	strcpy(cntrl_addr.sun_path, DATA_AX25ROUTED_CTL_SOCK);
	cntrl_len =
	    sizeof(cntrl_addr.sun_family) +
	    strlen(DATA_AX25ROUTED_CTL_SOCK);

	if (bind(cntrl_s, (struct sockaddr *) &cntrl_addr, cntrl_len) < 0) {
		perror("bind Control socket");
		daemon_shutdown(1);
	}

	chmod(DATA_AX25ROUTED_CTL_SOCK, 0600);
	listen(cntrl_s, 1);

	signal(SIGUSR1, sig_debug);
	signal(SIGHUP, sig_reload);
	signal(SIGTERM, sig_term);

	cntrl_fd = -1;

	for (;;) {
		fd_max = 0;
		FD_ZERO(&read_fds);
		FD_ZERO(&write_fds);
		FD_MAX(s);
		if (cntrl_fd > 0) {
			FD_MAX(cntrl_fd);
			FD_SET(cntrl_fd, &write_fds);
		} else {
			FD_MAX(cntrl_s);
		}

		if (select(fd_max + 1, &read_fds, NULL, &write_fds, NULL) < 0) {
			if (errno == EINTR)	/* woops! */
				continue;

			if (!FD_ISSET(cntrl_fd, &write_fds)) {
				perror("select");
				save_cache();
				daemon_shutdown(1);
			} else {
				close(cntrl_fd);
				cntrl_fd = -1;
				continue;
			}
		}

		if (cntrl_fd > 0) {
			if (FD_ISSET(cntrl_fd, &read_fds)) {
				size = read(cntrl_fd, buf, sizeof(buf));
				if (size > 0) {
					buf[size] = '\0';
					interpret_command(cntrl_fd, buf);
				} else {
					close(cntrl_fd);
					cntrl_fd = -1;
				}
			}
		} else if (FD_ISSET(cntrl_s, &read_fds)) {
			if ((cntrl_fd =
			     accept(cntrl_s,
				    (struct sockaddr *) &cntrl_addr,
				    &cntrl_len)) < 0) {
				perror("accept Control");
				save_cache();
				daemon_shutdown(1);
			}
		}

		if (reload)
			reload_config();

		if (FD_ISSET(s, &read_fds))
			ax25_receive(s);
	}

	return 0;		/* what ?! */
}
예제 #2
0
파일: echidna.c 프로젝트: hyeshik/echidna
static int
main_loop(SESSION *sess)
{
    fd_set rfds, wfds, exfds;
    int i, stdin_closed;

    sess->inbuf = queue_new(INLET_QUEUE_SIZE);
    sess->outbuf = queue_new(OUTLET_QUEUE_SIZE);
    if (sess->inbuf == NULL || sess->outbuf == NULL)
        error(1, "Can't allocate the mainstream queues.\n");

    for (i = 0; i < sess->num_workers; i++) {
        sess->workers[i].inbuf = queue_new(INQUEUE_SIZE);
        sess->workers[i].outbuf = queue_new(OUTQUEUE_SIZE);
        if (sess->workers[i].inbuf == NULL || sess->workers[i].outbuf == NULL)
            error(1, "Failed to allocate buffer queues.\n");
    }

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&exfds);

    stdin_closed = 0;

    for (;;) {
        int maxfd=-1, nevents;
        struct timeval tv, *timeout;

        if (stdin_closed || is_queue_full(sess->inbuf))
            FD_CLR(STDIN_FILENO, &rfds);
        else {
            FD_SET(STDIN_FILENO, &rfds);
            maxfd = FD_MAX(maxfd, STDIN_FILENO);
        }

        if (!is_queue_empty(sess->outbuf)) {
            FD_SET(STDOUT_FILENO, &wfds);
            maxfd = FD_MAX(maxfd, STDOUT_FILENO);
        }
        else
            FD_CLR(STDOUT_FILENO, &wfds);

        for (i = 0; i < sess->num_workers; i++) {
            WORKER *w=&sess->workers[i];

            if (!IS_STDOUT_ALIVE(w) || is_queue_full(w->inbuf))
                FD_CLR(w->stdout_fd, &rfds);
            else {
                FD_SET(w->stdout_fd, &rfds);
                maxfd = FD_MAX(maxfd, w->stdout_fd);
            }

            if (IS_STDIN_ALIVE(w) && !is_queue_empty(w->outbuf)) {
                FD_SET(w->stdin_fd, &wfds);
                maxfd = FD_MAX(maxfd, w->stdin_fd);
            }
            else
                FD_CLR(w->stdin_fd, &wfds);
        }

        if (maxfd < 0 && sess->running_workers <= 0)
            break;

        tv.tv_sec = 0;
        tv.tv_usec = 500000;
        timeout = &tv;

        if ((nevents = select(maxfd + 1, &rfds, &wfds, &exfds, timeout)) == -1) {
            if (errno == EINTR)
                continue;

            perror("echidna");
            error(1, "Error on select()\n");
        }

        if (nevents == 0) { /* select timed out. */
            if (!is_queue_full(sess->outbuf)) {
                /* Traverse all workers and try processing for blocked output queues. */
                for (i = 0; i < sess->num_workers; i++) {
                    WORKER *w=&sess->workers[i];

                    if (w->status == STATUS_RUNNING && !is_queue_empty(w->inbuf))
                        w->input_handler(sess, w);
                }
            }
            continue;
        }

        if (FD_ISSET(STDIN_FILENO, &rfds)) {
            char *bufstart;
            qsize_t bufsize;
            ssize_t rsize;

            bufsize = queue_num_continuous_vacant(sess->inbuf, &bufstart);

            if ((rsize = read(STDIN_FILENO, bufstart, bufsize)) < 0)
                error(1, "Error on reading from stdin.\n");

            if (rsize == 0)
                stdin_closed = 1;
            else
                queue_queued(sess->inbuf, rsize);

            sess->input_handler(sess);
        }

        if (FD_ISSET(STDOUT_FILENO, &wfds)) {
            char *bufstart;
            qsize_t bufsize;
            ssize_t wsize;

            bufsize = queue_num_continuous_filled(sess->outbuf, &bufstart);

            if ((wsize = write(STDOUT_FILENO, bufstart, bufsize)) < 0) {
                if (errno != EAGAIN)
                    error(1, "Error on writing to stdout.\n");
            }

            queue_consumed(sess->outbuf, wsize);

            for (i = 0; i < sess->num_workers; i++) {
                WORKER *w=&sess->workers[i];
                if (!is_queue_empty(w->inbuf))
                    w->input_handler(sess, w);
            }
        }

        for (i = 0; i < sess->num_workers; i++) {
            WORKER *w=&sess->workers[i];

            if (FD_ISSET(w->stdout_fd, &rfds)) {
                char *bufstart;
                qsize_t bufsize;
                ssize_t rsize;

                bufsize = queue_num_continuous_vacant(w->inbuf, &bufstart);

                if ((rsize = read(w->stdout_fd, bufstart, bufsize)) < 0)
                    error(1, "Error on reading from worker %d.\n", i);

                if (rsize == 0)
                    w->status = STATUS_TERMINATED;
                else
                    queue_queued(w->inbuf, rsize);

                w->input_handler(sess, w);
            }

            if (FD_ISSET(w->stdin_fd, &wfds)) {
                char *bufstart;
                qsize_t bufsize;
                ssize_t wsize;

                bufsize = queue_num_continuous_filled(w->outbuf, &bufstart);

                if ((wsize = write(w->stdin_fd, bufstart, bufsize)) < 0) {
                    if (errno != EAGAIN)
                        error(1, "Error on writing to worker %d.\n", i);
                }

                queue_consumed(w->outbuf, wsize);

                sess->input_handler(sess);
            }
            else if (stdin_closed && w->status == STATUS_RUNNING &&
                     is_queue_empty(w->outbuf)) {
                w->status = STATUS_FLUSHING;
                if (close(w->stdin_fd) == -1)
                    perror("close");
            }
        }
    }

    for (i = 0; i < sess->num_workers; i++) {
        queue_destroy(sess->workers[i].inbuf);
        queue_destroy(sess->workers[i].outbuf);
    }

    queue_destroy(sess->inbuf);
    queue_destroy(sess->outbuf);

    return 0;
}