예제 #1
0
int
main(int argc, char **argv)
{
    int	n;

    if (argc < 2)  {
	fprintf(stderr, "%s", srv_usage);
	return 1;
    }
    while (argv[1][0] == '-')  {
	if (BU_STR_EQUAL(argv[1], "-d"))  {
	    debug++;
	} else if (BU_STR_EQUAL(argv[1], "-x"))  {
	    sscanf(argv[2], "%x", (unsigned int *)&RTG.debug);
	    argc--; argv++;
	} else if (BU_STR_EQUAL(argv[1], "-X"))  {
	    sscanf(argv[2], "%x", (unsigned int *)&rdebug);
	    argc--; argv++;
	} else {
	    fprintf(stderr, "%s", srv_usage);
	    return 3;
	}
	argc--; argv++;
    }
    if (argc != 3 && argc != 4)  {
	fprintf(stderr, "%s", srv_usage);
	return 2;
    }

    control_host = argv[1];
    tcp_port = argv[2];

    /* Note that the LIBPKG error logger can not be
     * "bu_log", as that can cause bu_log to be entered recursively.
     * Given the special version of bu_log in use here,
     * that will result in a deadlock in bu_semaphore_acquire(res_syscall)!
     *  libpkg will default to stderr via pkg_errlog(), which is fine.
     */
    pcsrv = pkg_open(control_host, tcp_port, "tcp", "", "",
		      pkgswitch, NULL);
    if (pcsrv == PKC_ERROR)  {
	fprintf(stderr, "rtsrv: unable to contact %s, port %s\n",
		control_host, tcp_port);
	return 1;
    }

    if (argc == 4)  {
	/* Slip one command to dispatcher */
	(void)pkg_send(MSG_CMD, argv[3], strlen(argv[3])+1, pcsrv);

	/* Prevent chasing the package with an immediate TCP close */
	sleep(1);

	pkg_close(pcsrv);
	return 0;
    }

#ifdef SO_SNDBUF
    /* increase the default send buffer size to 32k since we're
     * sending pixels more than likely.
     */
    {
	int val = 32767;
	n = setsockopt(pcsrv->pkc_fd, SOL_SOCKET, SO_SNDBUF, (const void *)&val, sizeof(val));
	if (n < 0)  perror("setsockopt: SO_SNDBUF");
    }
#endif

    if (!debug)  {
	/* A fresh process */
	if (fork())
	    return 0;

	/* Go into our own process group */
	n = bu_process_id();

#ifdef HAVE_SETPGID
	if (setpgid(n, n) < 0)
	    perror("setpgid");
#else
	/* SysV uses setpgrp with no args and it can't fail,
	 * obsoleted by setpgid.
	 */
	setpgrp();
#endif

	/*
	 *  Unless controller process has specifically said
	 *  that this is an interactive session, e.g., for a demo,
	 *  drop to the lowest sensible priority.
	 */
	if (!interactive)  {
	    bu_nice_set(19);		/* lowest priority */
	}

	/* Close off the world */
	fclose(stdin);
	fclose(stdout);
	fclose(stderr);

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

	/* For stdio & perror safety, reopen 0, 1, 2 */
	(void)open("/dev/null", 0);	/* to fd 0 */
	n = dup(0);			/* to fd 1 */
	if (n == -1)
	    perror("dup");
	n = dup(0);			/* to fd 2 */
	if (n == -1)
	    perror("dup");

#if defined(HAVE_SYS_IOCTL_H) && defined(TIOCNOTTY)
	n = open("/dev/tty", 2);
	if (n >= 0) {
	    (void)ioctl(n, TIOCNOTTY, 0);
	    (void)close(n);
	}
#endif
    }

    /* Send our version string */
    if (pkg_send(MSG_VERSION,
		   PROTOCOL_VERSION, strlen(PROTOCOL_VERSION)+1, pcsrv) < 0)  {
	fprintf(stderr, "pkg_send MSG_VERSION error\n");
	return 1;
    }
    if (debug)  fprintf(stderr, "PROTOCOL_VERSION='%s'\n", PROTOCOL_VERSION);

    /*
     *  Now that the fork() has been done, it is safe to initialize
     *  the parallel processing support.
     */

    avail_cpus = bu_avail_cpus();

    /* Need to set rtg_parallel non_zero here for RES_INIT to work */
    npsw = avail_cpus;
    if (npsw > 1)  {
	RTG.rtg_parallel = 1;
    } else
	RTG.rtg_parallel = 0;
    bu_semaphore_init(RT_SEM_LAST);

    bu_log("using %d of %d cpus\n",
	   npsw, avail_cpus);

    /*
     *  Initialize the non-parallel memory resource.
     *  The parallel guys are initialized after the rt_dirbuild().
     */
    rt_init_resource(&rt_uniresource, MAX_PSW, NULL);
    bn_rand_init(rt_uniresource.re_randptr, MAX_PSW);

    BU_LIST_INIT(&WorkHead);

    for (;;)  {
	struct pkg_queue	*lp;
	fd_set ifds;
	struct timeval tv;

	/* First, process any packages in library buffers */
	if (pkg_process(pcsrv) < 0)  {
	    bu_log("pkg_get error\n");
	    break;
	}

	/* Second, see if any input to read */
	FD_ZERO(&ifds);
	FD_SET(pcsrv->pkc_fd, &ifds);
	tv.tv_sec = BU_LIST_NON_EMPTY(&WorkHead) ? 0L : 9999L;
	tv.tv_usec = 0L;

	if (select(pcsrv->pkc_fd+1, &ifds, (fd_set *)0, (fd_set *)0,
		    &tv) != 0)  {
	    n = pkg_suckin(pcsrv);
	    if (n < 0)  {
		bu_log("pkg_suckin error\n");
		break;
	    } else if (n == 0)  {
		/* EOF detected */
		break;
	    } else {
		/* All is well */
	    }
	}

	/* Third, process any new packages in library buffers */
	if (pkg_process(pcsrv) < 0)  {
	    bu_log("pkg_get error\n");
	    break;
	}

	/* Finally, more work may have just arrived, check our list */
	if (BU_LIST_NON_EMPTY(&WorkHead))  {
	    lp = BU_LIST_FIRST(pkg_queue, &WorkHead);
	    BU_LIST_DEQUEUE(&lp->l);
	    switch (lp->type)  {
		case MSG_MATRIX:
		    ph_matrix((struct pkg_conn *)0, lp->buf);
		    break;
		case MSG_LINES:
		    ph_lines((struct pkg_conn *)0, lp->buf);
		    break;
		case MSG_OPTIONS:
		    ph_options((struct pkg_conn *)0, lp->buf);
		    break;
		case MSG_GETTREES:
		    ph_gettrees((struct pkg_conn *)0, lp->buf);
		    break;
		default:
		    bu_log("bad list element, type=%d\n", lp->type);
		    return 33;
	    }
	    BU_PUT(lp, struct pkg_queue);
	}
    }

    return 0;		/* bu_exit(0, NULL) */
}
/*
 *  Loop forever handling clients as they come and go.
 *  Access to the framebuffer may be interleaved, if the user
 *  wants it that way.
 */
static void
main_loop(void)
{
    int	nopens = 0;
    int	ncloses = 0;

    while ( !fb_server_got_fb_free ) {
	long refresh_rate = 60000000; /* old default */
	fd_set infds;
	struct timeval tv;
	int	i;

	if (fb_server_fbp) {
	    if (fb_poll_rate(fb_server_fbp) > 0)
		refresh_rate = fb_poll_rate(fb_server_fbp);
	}

	infds = select_list;	/* struct copy */

	tv.tv_sec = 0L;
	tv.tv_usec = refresh_rate;
	if ((select( max_fd+1, &infds, (fd_set *)0, (fd_set *)0, (struct timeval *)&tv ) == 0)) {
	    /* Process fb events while waiting for client */
	    /*printf("select timeout waiting for client\n");*/
	    if (fb_server_fbp) {
		if (fb_poll(fb_server_fbp)) {
		    return;
		}
	    }
	    continue;
	}
	/* Handle any events from the framebuffer */
	if (fb_is_set_fd(fb_server_fbp, &infds)) {
	    fb_poll(fb_server_fbp);
	}

	/* Accept any new client connections */
	if (netfd > 0 && FD_ISSET(netfd, &infds)) {
	    new_client( pkg_getclient( netfd, fb_server_pkg_switch, comm_error, 0 ) );
	    nopens++;
	}

	/* Process arrivals from existing clients */
	/* First, pull the data out of the kernel buffers */
	for (i = MAX_CLIENTS-1; i >= 0; i--) {
	    if (clients[i] == NULL )  continue;
	    if (pkg_process( clients[i] ) < 0) {
		fprintf(stderr, "pkg_process error encountered (1)\n");
	    }
	    if (! FD_ISSET( clients[i]->pkc_fd, &infds )) continue;
	    if (pkg_suckin( clients[i] ) <= 0) {
		/* Probably EOF */
		drop_client( i );
		ncloses++;
		continue;
	    }
	}
	/* Second, process all the finished ones that we just got */
	for (i = MAX_CLIENTS-1; i >= 0; i--) {
	    if (clients[i] == NULL )  continue;
	    if (pkg_process( clients[i] ) < 0) {
		fprintf(stderr, "pkg_process error encountered (2)\n");
	    }
	}
	if (once_only && nopens > 1 && ncloses > 1)
	    return;
    }
}