usr/src/cmd/rad/mod/xport_pipe/mod_pipe.c
changeset 862 f20f2afa6263
parent 852 bcfb754700ce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/rad/mod/xport_pipe/mod_pipe.c	Fri May 18 11:08:12 2012 -0400
@@ -0,0 +1,159 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <bsm/adt_event.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <ucred.h>
+
+#include <rad/adr_stream.h>
+#include "rad_object.h"
+#include "rad_modapi.h"
+#include "rad_modapi_xport.h"
+#include "rad_connection.h"
+#include "rad_xport.h"
+
+#include "api_pipe.h"
+
+static rad_moderr_t
+pipe_listen(rad_thread_t *arg)
+{
+	int fdin;
+	data_t *data = rad_thread_arg(arg);
+	data_t *exitprop = struct_get(data, "exit");
+	rad_subject_t *subject;
+	rad_moderr_t result = rm_ok;
+	ucred_t *uc = ucred_get(P_MYID);
+
+	adr_stream_t *stream;
+	data_t *fdprop = struct_get(data, "fd");
+	if (fdprop) {
+		fdin = data_to_integer(fdprop);
+		stream = adr_stream_create_fd(fdin);
+	} else {
+		fdin = STDIN_FILENO;
+		stream = adr_stream_create_fds(fdin, STDOUT_FILENO);
+	}
+	if (stream == NULL) {
+		rad_log(RL_ERROR, "failed to allocate connection");
+		goto done;
+	}
+
+	if (uc == NULL ||
+	    (subject = rad_subject_create_ucred(uc, B_FALSE, NULL)) == NULL) {
+		rad_log(RL_ERROR, "failed to allocate connection");
+		adr_stream_close(stream);
+		adr_stream_free(stream);
+		result = rm_system;
+		goto done;
+	}
+
+	rad_protocol_t *proto = rad_proto_find("rad");
+	if (proto == NULL) {
+		rad_log(RL_ERROR, "unable to find protocol \"rad\"");
+		rad_subject_unref(subject);
+		adr_stream_close(stream);
+		adr_stream_free(stream);
+		result = rm_config;
+		goto done;
+	}
+
+	radmod_connection_t *conn = rad_conn_create_fd(fdin, B_FALSE);
+	if (conn == NULL) {
+		rad_log(RL_WARN, "failed to allocate connection");
+		rad_subject_unref(subject);
+		adr_stream_close(stream);
+		adr_stream_free(stream);
+		result = rm_system;
+		goto done;
+	}
+	conn->rm_conn_xport = stream;
+	conn->rm_conn_proto_ops = proto;
+
+	if (!rad_conn_setsubject(conn, subject)) {
+		rad_log(RL_WARN, "failed to set connection subject");
+		rad_conn_close(conn);
+		rad_conn_free(conn);
+		result = rm_system;
+		goto done;
+	}
+	rad_thread_ack(arg, rm_ok);
+	rad_proto_handle(conn);
+	rad_conn_free(conn);
+
+done:
+	if (exitprop != NULL) {
+		assert(data_basetype(exitprop) == dt_boolean);
+		if (data_to_boolean(exitprop)) {
+			rad_log(result == rm_ok ? RL_DEBUG : RL_WARN,
+			    "exit triggered by pipe connector");
+			exit(0);
+		}
+	}
+	return (result);
+}
+
+static boolean_t running = B_FALSE;
+
+static rad_moderr_t
+stdin_starter(data_t *data)
+{
+	rad_moderr_t result;
+
+	if (running) {
+		/* Until we permit configuring the fd */
+		rad_log(RL_ERROR,
+		    "Only one stdin transport may be running at a time.\n");
+		return (rm_config);
+	}
+
+	result = rad_thread_create(pipe_listen, data);
+	if (result == rm_ok)
+		running = B_TRUE;
+	return (result);
+}
+
+static rad_moderr_t
+pipe_starter(data_t *data)
+{
+	return (rad_thread_create(pipe_listen, data));
+}
+
+static rad_modinfo_t modinfo = { "xport_pipe", "stdin/pipe transport" };
+
+int
+_rad_init(void *handle)
+{
+	if (rad_module_register(handle, RAD_MODVERSION, &modinfo) == -1)
+		return (-1);
+
+	rad_xport_register("stdin", &t__stdin, stdin_starter);
+	rad_xport_register("pipe", &t__pipe, pipe_starter);
+	return (0);
+}