[Midnightbsd-cvs] src [7701] trunk/lib: mach/launchd support libs
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu Aug 11 21:16:45 EDT 2016
Revision: 7701
http://svnweb.midnightbsd.org/src/?rev=7701
Author: laffer1
Date: 2016-08-11 21:16:44 -0400 (Thu, 11 Aug 2016)
Log Message:
-----------
mach/launchd support libs
Added Paths:
-----------
trunk/lib/libSystem/
trunk/lib/libSystem/Makefile
trunk/lib/liblaunch/
trunk/lib/liblaunch/Makefile
trunk/lib/liblaunch/bootstrap.h
trunk/lib/liblaunch/bootstrap_priv.h
trunk/lib/liblaunch/helper.defs
trunk/lib/liblaunch/job.defs
trunk/lib/liblaunch/job_types.defs
trunk/lib/liblaunch/launch.h
trunk/lib/liblaunch/launch_internal.h
trunk/lib/liblaunch/launch_priv.h
trunk/lib/liblaunch/launchd.ops
trunk/lib/liblaunch/libbootstrap.c
trunk/lib/liblaunch/liblaunch.c
trunk/lib/liblaunch/libvproc.c
trunk/lib/liblaunch/reboot2.h
trunk/lib/liblaunch/vproc.h
trunk/lib/liblaunch/vproc_internal.h
trunk/lib/liblaunch/vproc_priv.h
trunk/lib/libmach/
trunk/lib/libmach/Makefile
trunk/lib/libmach/mach/
trunk/lib/libmach/mach/err_ipc.sub
trunk/lib/libmach/mach/err_kern.sub
trunk/lib/libmach/mach/err_mach_ipc.sub
trunk/lib/libmach/mach/err_server.sub
trunk/lib/libmach/mach/err_us.sub
trunk/lib/libmach/mach/error_codes.c
trunk/lib/libmach/mach/errorlib.h
trunk/lib/libmach/mach/externs.h
trunk/lib/libmach/mach/mach_error_string.c
trunk/lib/libmach/mach/mach_init.c
trunk/lib/libmach/mach/mach_misc.c
trunk/lib/libmach/mach/mach_msg.c
trunk/lib/libmach/mach/mig_allocate.c
trunk/lib/libmach/mach/mig_deallocate.c
trunk/lib/libmach/mach/mig_reply_setup.c
trunk/lib/libmach/mach/mig_strncpy.c
trunk/lib/libmach/mach/mig_support.c
trunk/lib/libmach/test/
trunk/lib/libmach/test/kqueue_tests/
trunk/lib/libmach/test/kqueue_tests/Makefile
trunk/lib/libmach/test/kqueue_tests/kqueue_tests.c
Added: trunk/lib/libSystem/Makefile
===================================================================
--- trunk/lib/libSystem/Makefile (rev 0)
+++ trunk/lib/libSystem/Makefile 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,6 @@
+# $MidnightBSD$
+
+BINDIR?=/usr/lib
+FILES= libSystem.so
+
+.include <bsd.prog.mk>
Property changes on: trunk/lib/libSystem/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/Makefile
===================================================================
--- trunk/lib/liblaunch/Makefile (rev 0)
+++ trunk/lib/liblaunch/Makefile 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,32 @@
+.include <bsd.init.mk>
+
+LIB= launch
+
+.PATH: .
+.PATH: ../../sbin/launchd
+
+BASE_INCLUDE= -I${.CURDIR}/../../include/apple -I${MACHINE_INCLUDES}
+BASE_INCLUDE+= -I${.CURDIR} -I${.CURDIR}/../../sbin/launchd -I.
+BASE_INCLUDE+= -I${.CURDIR}/../../include -I${.CURDIR}/../../sys
+DEFINES= -D__APPLE__ -fblocks -DLIBC_NO_LIBCRASHREPORTERCLIENT -DPRIVATE
+MIG_FLAGS= ${BASE_INCLUDE} ${DEFINES}
+CFLAGS+= ${MIG_FLAGS} -D__MigTypeCheck
+CFLAGS+= -I${.CURDIR}/../../contrib/openbsm -I.
+
+helper.h launchd_helperUser.c launchd_helperServer.c helperServer.h: helper.defs
+ mig ${MIG_FLAGS} -header helper.h -sheader helperServer.h ${.CURDIR}/helper.defs
+
+job.h jobUser.c jobServer.h: job.defs
+ mig ${MIG_FLAGS} -sheader jobServer.h ${.CURDIR}/job.defs
+
+SRCS= jobUser.c \
+ launchd_helperUser.c \
+ launchd_helperServer.c \
+ libbootstrap.c \
+ liblaunch.c \
+ libvproc.c
+INCS= launch.h
+
+CLEANFILES+= *User.c *Server.c job.h helper.h *Server.h launchd_helper.h *~
+
+.include <bsd.lib.mk>
Property changes on: trunk/lib/liblaunch/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/bootstrap.h
===================================================================
--- trunk/lib/liblaunch/bootstrap.h (rev 0)
+++ trunk/lib/liblaunch/bootstrap.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,358 @@
+#ifndef __BOOTSTRAP_H__
+#define __BOOTSTRAP_H__
+/*
+ * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * bootstrap -- fundamental service initiator and port server
+ * Mike DeMoney, NeXT, Inc.
+ * Copyright, 1990. All rights reserved.
+ */
+
+/*
+ * Interface: Bootstrap server
+ *
+ * The bootstrap server is the first user-mode task initiated by the Mach
+ * kernel at system boot time. The bootstrap server provides two services,
+ * it initiates other system tasks, and manages a table of name-port bindings
+ * for fundamental system services (e.g. lookupd, Window Manager, etc...).
+ *
+ * Name-port bindings can be established with the bootstrap server by either
+ * of two mechanisms:
+ *
+ * 1. The binding can be indicated, in advance of the service that backs it
+ * being available, via a "service create" request. In this case, bootstrap
+ * will immediately create a port and bind the indicated name with that port.
+ * At a later time, a service may "checkin" for the name-port
+ * binding and will be returned receive rights for the bound port. Lookup's
+ * on bindings created by this mechanism will return send rights to the port,
+ * even if no service has "checked-in". In this case, requests sent to the
+ * bound port will be queued until a server has checked-in and can satisfy the
+ * request.
+ *
+ * 2. Bindings can be established dynamically via a "register" request. In
+ * this case, the register request provides bootstrap with a name and send
+ * rights for a port. Bootstrap will provide send rights for the bound port
+ * to any requestor via the lookup request.
+ *
+ * Bootstrap provides its service port to descendant tasks via the Mach
+ * "bootstrap" special task port. All direct descendants of bootstrap receive
+ * a "privileged" bootstrap service port. System services that initiate
+ * untrusted tasks should replace the Mach bootstrap task special port with
+ * a subset bootstrap port to prevent them from infecting the namespace.
+ *
+ * The bootstrap server creates a "backup" port for each service that it
+ * creates. This is used to detect when a checked out service is no longer
+ * being served. The bootstrap server regains all rights to the port and
+ * it is marked available for check-out again. This allows crashed servers to
+ * resume service to previous clients. Lookup's on this named port will
+ * continue to be serviced by bootstrap while holding receive rights for the
+ * bound port. A client may detect that the service is inactive via the
+ * bootstrap status request. If an inactive service re-registers rather
+ * than "checking-in" the original bound port is destroyed.
+ *
+ * The status of a named service may be obtained via the "status" request.
+ * A service is "active" if a name-port binding exists and receive rights
+ * to the bound port are held by a task other than bootstrap.
+ *
+ * The bootstrap server may also (re)start server processes associated with
+ * with a set of services. The definition of the server process is done
+ * through the "create server" request. The server will be launched in the
+ * same bootstrap context in which it was registered.
+ */
+#include <AvailabilityMacros.h>
+#include <mach/std_types.h>
+#include <mach/message.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+#pragma GCC visibility push(default)
+
+#define BOOTSTRAP_MAX_NAME_LEN 128
+#define BOOTSTRAP_MAX_CMD_LEN 512
+
+typedef char name_t[BOOTSTRAP_MAX_NAME_LEN];
+typedef char cmd_t[BOOTSTRAP_MAX_CMD_LEN];
+typedef name_t *name_array_t;
+typedef int bootstrap_status_t;
+typedef bootstrap_status_t *bootstrap_status_array_t;
+typedef unsigned int bootstrap_property_t;
+typedef bootstrap_property_t * bootstrap_property_array_t;
+
+typedef boolean_t *bool_array_t;
+
+#define BOOTSTRAP_MAX_LOOKUP_COUNT 20
+
+#define BOOTSTRAP_SUCCESS 0
+#define BOOTSTRAP_NOT_PRIVILEGED 1100
+#define BOOTSTRAP_NAME_IN_USE 1101
+#define BOOTSTRAP_UNKNOWN_SERVICE 1102
+#define BOOTSTRAP_SERVICE_ACTIVE 1103
+#define BOOTSTRAP_BAD_COUNT 1104
+#define BOOTSTRAP_NO_MEMORY 1105
+#define BOOTSTRAP_NO_CHILDREN 1106
+
+#define BOOTSTRAP_STATUS_INACTIVE 0
+#define BOOTSTRAP_STATUS_ACTIVE 1
+#define BOOTSTRAP_STATUS_ON_DEMAND 2
+
+/*
+ * After main() starts, it is safe to assume that this variable is always set.
+ */
+extern mach_port_t bootstrap_port;
+
+/*
+ * bootstrap_create_server()
+ *
+ * Declares a server that mach_init will re-spawn within the specified
+ * bootstrap context. The server is considered already "active"
+ * (i.e. will not be re-spawned) until the returned server_port is
+ * deallocated.
+ *
+ * In the meantime, services can be declared against the server,
+ * by using the server_port as the privileged bootstrap target of
+ * subsequent bootstrap_create_service() calls.
+ *
+ * When mach_init re-spawns the server, its task bootstrap port
+ * is set to the privileged sever_port. Through this special
+ * bootstrap port, it can access all of parent bootstrap's context
+ * (and all services are created in the parent's namespace). But
+ * all additional service declarations (and declaration removals)
+ * will be associated with this particular server.
+ *
+ * Only a holder of the server_port privilege bootstrap port can
+ * check in or register over those services.
+ *
+ * When all services associated with a server are deleted, and the server
+ * exits, it will automatically be deleted itself.
+ *
+ * If the server is declared "on_demand," then a non-running server
+ * will be re-launched on first use of one of the service ports
+ * registered against it. Otherwise, it will be re-launched
+ * immediately upon exiting (whether any client is actively using
+ * any of the service ports or not).
+ *
+ * Errors: Returns appropriate kernel errors on rpc failure.
+ * Returns BOOTSTRAP_NOT_PRIVILEGED, bootstrap or uid invalid.
+ */
+kern_return_t bootstrap_create_server(
+ mach_port_t bp,
+ cmd_t server_cmd,
+ uid_t server_uid,
+ boolean_t on_demand,
+ mach_port_t *server_port);
+
+/*
+ * bootstrap_subset()
+ *
+ * Returns a new port to use as a bootstrap port. This port behaves
+ * exactly like the previous bootstrap_port, except that ports dynamically
+ * registered via bootstrap_register() are available only to users of this
+ * specific subset_port. Lookups on the subset_port will return ports
+ * registered with this port specifically, and ports registered with
+ * ancestors of this subset_port. Duplications of services already
+ * registered with an ancestor port may be registered with the subset port
+ * are allowed. Services already advertised may then be effectively removed
+ * by registering PORT_NULL for the service.
+ * When it is detected that the requestor_port is destroyed the subset
+ * port and all services advertized by it are destroyed as well.
+ *
+ * Errors: Returns appropriate kernel errors on rpc failure.
+ */
+kern_return_t bootstrap_subset(
+ mach_port_t bp,
+ mach_port_t requestor_port,
+ mach_port_t *subset_port);
+
+/*
+ * bootstrap_unprivileged()
+ *
+ * Given a bootstrap port, return its unprivileged equivalent. If
+ * the port is already unprivileged, another reference to the same
+ * port is returned.
+ *
+ * This is most often used by servers, which are launched with their
+ * bootstrap port set to the privileged port for the server, to get
+ * an unprivileged version of the same port for use by its unprivileged
+ * children (or any offspring that it does not want to count as part
+ * of the "server" for mach_init registration and re-launch purposes).
+ *
+ * Native launchd jobs are always started with an unprivileged port.
+ */
+kern_return_t bootstrap_unprivileged(
+ mach_port_t bp,
+ mach_port_t *unpriv_port)
+ AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5;
+
+/*
+ * bootstrap_parent()
+ *
+ * Given a bootstrap subset port, return the parent bootstrap port.
+ * If the specified bootstrap port is already the root subset,
+ * the same port will be returned. Much like "." and ".." are the same
+ * in the file system name space for the root directory ("/").
+ *
+ * Errors:
+ * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running
+ * with an effective user id of root (as determined by the security
+ * token in the message trailer).
+ */
+kern_return_t bootstrap_parent(
+ mach_port_t bp,
+ mach_port_t *parent_port);
+
+/*
+ * bootstrap_register()
+ *
+ * Registers a send right for service_port with the service identified by
+ * service_name. Attempts to register a service where an active binding
+ * already exists are rejected.
+ *
+ * If the service was previously declared with bootstrap_create_service(),
+ * but is not currently active, this call can be used to undeclare the
+ * service. The bootstrap port used must have sufficient privilege to
+ * do so. (Registering MACH_PORT_NULL is especially useful for shutting
+ * down declared services).
+ *
+ * This API is deprecated. Old scenarios and recommendations:
+ *
+ * 1) Code that used to call bootstrap_check_in() and then bootstrap_register()
+ * can now always call bootstrap_check_in().
+ *
+ * 2) If the code was registering a well known name, please switch to launchd.
+ *
+ * 3) If the code was registering a dynamically generated string and passing
+ * the string to other applications, please rewrite the code to send a Mach
+ * send-right directly.
+ *
+ * 4) If the launchd job maintained an optional Mach service, please reserve
+ * the name with launchd and control the presense of the service through
+ * ownership of the Mach receive right like so.
+ *
+ * <key>MachServices</key>
+ * <dict>
+ * <key>com.apple.windowserver</key>
+ * <true/>
+ * <key>com.apple.windowserver.active</key>
+ * <dict>
+ * <key>HideUntilCheckIn</key>
+ * <true/>
+ * </dict>
+ * </dict>
+ *
+ *
+ * Errors: Returns appropriate kernel errors on rpc failure.
+ * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
+ * bootstrap port without privilege.
+ * Returns BOOTSTRAP_NAME_IN_USE, if service has already been
+ * register or checked-in.
+ */
+AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5
+kern_return_t
+bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp);
+
+/*
+ * bootstrap_create_service()
+ *
+ * Creates a service named "service_name" and returns a send right to that
+ * port in "service_port." The port may later be checked in as if this
+ * port were configured in the bootstrap configuration file.
+ *
+ * This API is deprecated. Please call bootstrap_check_in() instead.
+ *
+ * Errors: Returns appropriate kernel errors on rpc failure.
+ * Returns BOOTSTRAP_SERVICE_ACTIVE, if service already exists.
+ */
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6
+AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6
+#endif
+kern_return_t
+bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp);
+
+/*
+ * bootstrap_check_in()
+ *
+ * Returns the receive right for the service named by service_name. The
+ * service must have been declared in the launchd.plist(5) file associated
+ * with the job. Attempts to check_in a service which is already active
+ * are not allowed.
+ *
+ * If the service was declared as being associated with a server, the
+ * check_in must come from the server's privileged port (server_port).
+ *
+ * Errors: Returns appropriate kernel errors on rpc failure.
+ * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
+ * bootstrap port without privilege.
+ * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
+ * registered or checked-in.
+ */
+kern_return_t bootstrap_check_in(
+ mach_port_t bp,
+ const name_t service_name,
+ mach_port_t *sp);
+
+/*
+ * bootstrap_look_up()
+ *
+ * Returns a send right for the service port declared/registered under the
+ * name service_name. The service is not guaranteed to be active. Use the
+ * bootstrap_status call to determine the status of the service.
+ *
+ * Errors: Returns appropriate kernel errors on rpc failure.
+ * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ */
+kern_return_t bootstrap_look_up(
+ mach_port_t bp,
+ const name_t service_name,
+ mach_port_t *sp);
+
+/*
+ * bootstrap_status()
+ *
+ * In practice, this call was used to preflight whether the following two
+ * APIs would succeed.
+ *
+ * bootstrap_look_up()
+ * bootstrap_check_in()
+ *
+ * Please don't bother. Just call the above two APIs directly and check
+ * for failure.
+ */
+kern_return_t bootstrap_status(
+ mach_port_t bp,
+ name_t service_name,
+ bootstrap_status_t *service_active)
+ AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5;
+
+/* bootstrap_strerror()
+ *
+ * Translate a return value from the bootstrap_*() APIs to a string.
+ */
+const char *bootstrap_strerror(kern_return_t r) __attribute__((__nothrow__, __pure__, __warn_unused_result__));
+
+#pragma GCC visibility pop
+
+__END_DECLS
+
+#endif /* __BOOTSTRAP_H__ */
Property changes on: trunk/lib/liblaunch/bootstrap.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/bootstrap_priv.h
===================================================================
--- trunk/lib/liblaunch/bootstrap_priv.h (rev 0)
+++ trunk/lib/liblaunch/bootstrap_priv.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __BOOTSTRAP_PRIVATE_H__
+#define __BOOTSTRAP_PRIVATE_H__
+
+#include <servers/bootstrap.h>
+#include <sys/types.h>
+#include <uuid/uuid.h>
+
+__BEGIN_DECLS
+
+#pragma GCC visibility push(default)
+
+#define BOOTSTRAP_PER_PID_SERVICE (1 << 0)
+#define BOOTSTRAP_ALLOW_LOOKUP (1 << 1)
+#define BOOTSTRAP_DENY_JOB_CREATION (1 << 2)
+#define BOOTSTRAP_PRIVILEGED_SERVER (1 << 3)
+#define BOOTSTRAP_FORCE_LOCAL (1 << 4)
+#define BOOTSTRAP_SPECIFIC_INSTANCE (1 << 5)
+#define BOOTSTRAP_STRICT_CHECKIN (1 << 6)
+#define BOOTSTRAP_STRICT_LOOKUP (1 << 7)
+
+#define BOOTSTRAP_PROPERTY_EXPLICITSUBSET (1 << 0) /* Created via bootstrap_subset(). */
+#define BOOTSTRAP_PROPERTY_IMPLICITSUBSET (1 << 1) /* Created via _vprocmgr_switch_to_session(). */
+#define BOOTSTRAP_PROPERTY_MOVEDSUBSET (1 << 2) /* Created via _vprocmgr_move_subset_to_user(). */
+#define BOOTSTRAP_PROPERTY_PERUSER (1 << 3) /* A per-user launchd's root bootstrap. */
+#define BOOTSTRAP_PROPERTY_XPC_DOMAIN (1 << 4) /* An XPC domain. Duh. */
+#define BOOTSTRAP_PROPERTY_XPC_SINGLETON (1 << 5) /* A singleton XPC domain. */
+
+void bootstrap_init(void);
+
+kern_return_t bootstrap_register2(mach_port_t bp, name_t service_name, mach_port_t sp, uint64_t flags);
+
+kern_return_t bootstrap_look_up2(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, uint64_t flags);
+
+kern_return_t bootstrap_check_in2(mach_port_t bp, const name_t service_name, mach_port_t *sp, uint64_t flags);
+
+kern_return_t bootstrap_look_up_per_user(mach_port_t bp, const name_t service_name, uid_t target_user, mach_port_t *sp);
+
+kern_return_t bootstrap_lookup_children(mach_port_t bp, mach_port_array_t *children, name_array_t *names, bootstrap_property_array_t *properties, mach_msg_type_number_t *n_children);
+
+kern_return_t bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags);
+
+kern_return_t bootstrap_check_in3(mach_port_t bp, const name_t service_name, mach_port_t *sp, uuid_t instance_id, uint64_t flags);
+
+kern_return_t bootstrap_get_root(mach_port_t bp, mach_port_t *root);
+
+#pragma GCC visibility pop
+
+__END_DECLS
+
+#endif /* __BOOTSTRAP_PRIVATE_H__ */
Property changes on: trunk/lib/liblaunch/bootstrap_priv.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/helper.defs
===================================================================
--- trunk/lib/liblaunch/helper.defs (rev 0)
+++ trunk/lib/liblaunch/helper.defs 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,19 @@
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+import "vproc.h";
+import "vproc_priv.h";
+import "vproc_internal.h";
+
+subsystem launchd_helper 4241011;
+
+userprefix helper_downcall_;
+serverprefix helper_recv_;
+
+skip;
+
+/* For coreservicesd to harvest exit status, not actually for UserEventAgent. */
+simpleroutine
+wait(
+ p : mach_port_move_send_once_t;
+ status : int
+);
Added: trunk/lib/liblaunch/job.defs
===================================================================
--- trunk/lib/liblaunch/job.defs (rev 0)
+++ trunk/lib/liblaunch/job.defs 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+/*
+ * bootstrap -- fundamental service initiator and port server
+ * Mike DeMoney, NeXT, Inc.
+ * Copyright, 1990. All rights reserved.
+ */
+
+subsystem job 400;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+#include "job_types.defs"
+
+import "vproc.h";
+import "vproc_priv.h";
+import "vproc_internal.h";
+
+userprefix vproc_mig_;
+serverprefix job_mig_;
+
+routine
+create_server(
+ j : job_t;
+ servercmd : cmd_t;
+ serveruid : uid_t;
+ ondemand : boolean_t;
+out serverport : mach_port_make_send_t
+);
+
+routine
+reboot2(
+ j : job_t;
+ flags : uint64_t
+);
+
+routine
+check_in2(
+ j : job_t;
+ servicename : name_t;
+out serviceport : mach_port_move_receive_t;
+out instanceid : uuid_t;
+ flags : uint64_t
+);
+
+routine
+register2(
+ j : job_t;
+ servicename : name_t;
+ serviceport : mach_port_t;
+ flags : uint64_t
+);
+
+routine
+look_up2(
+ j : job_t;
+sreplyport rp : mach_port_make_send_once_t;
+ servicename : name_t;
+out serviceport : mach_port_t;
+UserAuditToken servercreds : audit_token_t;
+ targetpid : pid_t;
+ instanceid : uuid_t;
+ flags : uint64_t
+);
+
+routine
+send_signal(
+ j : job_t;
+sreplyport rp : mach_port_make_send_once_t;
+ label : name_t;
+ sig : integer_t
+);
+
+routine
+parent(
+ j : job_t;
+sreplyport rp : mach_port_make_send_once_t;
+out parentport : mach_port_make_send_t
+);
+
+routine
+post_fork_ping(
+ j : job_t;
+ taskport : task_t;
+out asport : mach_port_t
+);
+
+routine
+info(
+ j : job_t;
+out names : name_array_t, dealloc;
+out jobs : name_array_t, dealloc;
+out actives : bootstrap_status_array_t, dealloc;
+ flags : uint64_t
+);
+
+routine
+subset(
+ j : job_t;
+ reqport : mach_port_t;
+out subsetport : mach_port_make_send_t
+);
+
+skip; /* Formerly setup_shmem. */
+
+routine
+take_subset(
+ j : job_t;
+out reqport : mach_port_move_send_t;
+out recvport : mach_port_move_receive_t;
+out jobs : pointer_t, dealloc;
+out ports : mach_port_move_send_array_t, dealloc
+);
+
+routine
+getsocket(
+ j : job_t;
+out sockpath : name_t
+);
+
+skip; /* Formerly spawn. */
+
+skip; /* Formerly wait. */
+
+skip; /* Formerly uncork_fork. */
+
+routine
+swap_integer(
+ j : job_t;
+ inkey : vproc_gsk_t;
+ outkey : vproc_gsk_t;
+ inval : int64_t;
+out outval : int64_t
+);
+
+routine
+log(
+ j : job_t;
+ pri : integer_t;
+ err : integer_t;
+ message : logmsg_t
+);
+
+routine
+lookup_per_user_context(
+ j : job_t;
+ uid : uid_t;
+out userbport : mach_port_t
+);
+
+routine
+move_subset(
+ j : job_t;
+ targetport : mach_port_t;
+ session : name_t;
+ asport : mach_port_t;
+ flags : uint64_t
+);
+
+routine
+swap_complex(
+ j : job_t;
+ inkey : vproc_gsk_t;
+ outkey : vproc_gsk_t;
+ inval : pointer_t;
+out outval : pointer_t, dealloc
+);
+
+routine
+log_drain(
+ j : job_t;
+sreplyport rp : mach_port_make_send_once_t;
+out outval : pointer_t, dealloc
+);
+
+routine
+log_forward(
+ j : job_t;
+ inval : pointer_t
+);
+
+routine
+kickstart(
+ j : job_t;
+ label : name_t;
+out pid : pid_t;
+ flags : natural_t
+);
+
+skip; /* Formerly embedded_wait. */
+
+routine
+lookup_children(
+ j : job_t;
+out childports : mach_port_move_send_array_t, dealloc;
+out childnames : name_array_t, dealloc;
+out childprops : bootstrap_property_array_t, dealloc
+);
+
+routine
+switch_to_session(
+ j : job_t;
+ reqport : mach_port_t;
+ session : name_t;
+ asport : mach_port_t;
+out newbsport : mach_port_make_send_t
+);
+
+skip; /* Formerly transaction_count_for_pid. */
+
+routine
+pid_is_managed(
+ j : job_t;
+ pid : pid_t;
+out managed : boolean_t
+);
+
+routine
+port_for_label(
+ j : job_t;
+ label : name_t;
+out jport : mach_port_make_send_t
+);
+
+routine
+init_session(
+ j : job_t;
+ session : name_t;
+ asport : mach_port_t
+);
+
+routine
+set_security_session(
+ j : job_t;
+ uuid : uuid_t;
+ asport : mach_port_t
+);
+
+skip; /* Formerly wait2. */
+
+skip; /* Formerly event_source_check_in. */
+
+skip; /* Formerly event_set_state. */
+
+routine
+spawn2(
+ j : job_t;
+sreplyport rp : mach_port_make_send_once_t;
+ job : pointer_t;
+ asport : mach_port_t;
+out outpid : pid_t;
+out obsrvport : mach_port_move_receive_t
+);
+
+routine
+get_root_bootstrap(
+ j : job_t;
+out rootbs : mach_port_move_send_t
+);
+
+#ifdef SHOW_LEGACY
+routine
+legacy_ipc_request(
+ j : job_t;
+ request : pointer_t;
+ request_fds : mach_port_move_send_array_t;
+out reply : pointer_t, dealloc;
+out reply_fds : mach_port_move_send_array_t, dealloc;
+ asport : mach_port_t
+);
+#endif
+
+routine
+get_listener_port_rights(
+ j : job_t;
+out sports : mach_port_make_send_array_t, dealloc
+);
+
+routine
+register_gui_session(
+ j : job_t;
+ asport : mach_port_t
+);
Added: trunk/lib/liblaunch/job_types.defs
===================================================================
--- trunk/lib/liblaunch/job_types.defs (rev 0)
+++ trunk/lib/liblaunch/job_types.defs 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+/*
+ * bootstrap -- fundamental service initiator and port server
+ * Mike DeMoney, NeXT, Inc.
+ * Copyright, 1990. All rights reserved.
+ */
+
+/* These really should be a part of the standard types... */
+type mach_port_move_send_array_t = array[] of mach_port_move_send_t
+ ctype: mach_port_array_t;
+type mach_port_make_send_array_t = array[] of mach_port_make_send_t
+ ctype: mach_port_array_t;
+
+type pid_t = integer_t;
+type pid_array_t = ^array [] of pid_t;
+type uid_t = natural_t;
+type gid_t = natural_t;
+type vproc_gsk_t = integer_t;
+type logmsg_t = c_string[*:2048];
+type cmd_t = c_string[512];
+type name_t = c_string[128];
+type name_array_t = ^array [] of name_t;
+type bootstrap_property_t = natural_t;
+type bootstrap_property_array_t = ^array [] of bootstrap_property_t;
+type bootstrap_status_t = integer_t;
+type bootstrap_status_array_t = ^array [] of bootstrap_status_t;
+type uuid_t = array [16] of MACH_MSG_TYPE_BYTE;
+
+type job_t = mach_port_t
+ intran : job_t job_mig_intran(mach_port_t)
+ outtran : mach_port_t job_mig_outtran(job_t)
+ destructor : job_mig_destructor(job_t)
+ cusertype : vproc_mig_t;
Added: trunk/lib/liblaunch/launch.h
===================================================================
--- trunk/lib/liblaunch/launch.h (rev 0)
+++ trunk/lib/liblaunch/launch.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,412 @@
+#ifndef __XPC_LAUNCH_H__
+#define __XPC_LAUNCH_H__
+
+/*!
+ * @header
+ * These interfaces were only ever documented for the purpose of allowing a
+ * launchd job to obtain file descriptors associated with the sockets it
+ * advertised in its launchd.plist(5). That functionality is now available in a
+ * much more straightforward fashion through the {@link launch_activate_socket}
+ * API.
+ *
+ * There are currently no replacements for other uses of the {@link launch_msg}
+ * API, including submitting, removing, starting, stopping and listing jobs.
+ */
+
+#ifndef __XPC_INDIRECT__
+#define __XPC_INDIRECT__
+#endif // __XPC_INDIRECT__
+
+#if XPC_BUILDING_LAUNCHD
+// Temporary hack to resolve conflicting availability with launchd's existing
+// internal headers.
+#pragma GCC diagnostic ignored "-Wavailability"
+#endif // XPC_BUILDING_LAUNCHD
+
+#include <xpc/base.h>
+#include <Availability.h>
+
+#include <mach/mach.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#define LAUNCH_KEY_SUBMITJOB "SubmitJob"
+#define LAUNCH_KEY_REMOVEJOB "RemoveJob"
+#define LAUNCH_KEY_STARTJOB "StartJob"
+#define LAUNCH_KEY_STOPJOB "StopJob"
+#define LAUNCH_KEY_GETJOB "GetJob"
+#define LAUNCH_KEY_GETJOBS "GetJobs"
+#define LAUNCH_KEY_CHECKIN "CheckIn"
+
+#define LAUNCH_JOBKEY_LABEL "Label"
+#define LAUNCH_JOBKEY_DISABLED "Disabled"
+#define LAUNCH_JOBKEY_USERNAME "UserName"
+#define LAUNCH_JOBKEY_GROUPNAME "GroupName"
+#define LAUNCH_JOBKEY_TIMEOUT "TimeOut"
+#define LAUNCH_JOBKEY_EXITTIMEOUT "ExitTimeOut"
+#define LAUNCH_JOBKEY_INITGROUPS "InitGroups"
+#define LAUNCH_JOBKEY_SOCKETS "Sockets"
+#define LAUNCH_JOBKEY_MACHSERVICES "MachServices"
+#define LAUNCH_JOBKEY_MACHSERVICELOOKUPPOLICIES "MachServiceLookupPolicies"
+#define LAUNCH_JOBKEY_INETDCOMPATIBILITY "inetdCompatibility"
+#define LAUNCH_JOBKEY_ENABLEGLOBBING "EnableGlobbing"
+#define LAUNCH_JOBKEY_PROGRAMARGUMENTS "ProgramArguments"
+#define LAUNCH_JOBKEY_PROGRAM "Program"
+#define LAUNCH_JOBKEY_ONDEMAND "OnDemand"
+#define LAUNCH_JOBKEY_KEEPALIVE "KeepAlive"
+#define LAUNCH_JOBKEY_LIMITLOADTOHOSTS "LimitLoadToHosts"
+#define LAUNCH_JOBKEY_LIMITLOADFROMHOSTS "LimitLoadFromHosts"
+#define LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE "LimitLoadToSessionType"
+#define LAUNCH_JOBKEY_LIMITLOADTOHARDWARE "LimitLoadToHardware"
+#define LAUNCH_JOBKEY_LIMITLOADFROMHARDWARE "LimitLoadFromHardware"
+#define LAUNCH_JOBKEY_RUNATLOAD "RunAtLoad"
+#define LAUNCH_JOBKEY_ROOTDIRECTORY "RootDirectory"
+#define LAUNCH_JOBKEY_WORKINGDIRECTORY "WorkingDirectory"
+#define LAUNCH_JOBKEY_ENVIRONMENTVARIABLES "EnvironmentVariables"
+#define LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES "UserEnvironmentVariables"
+#define LAUNCH_JOBKEY_UMASK "Umask"
+#define LAUNCH_JOBKEY_NICE "Nice"
+#define LAUNCH_JOBKEY_HOPEFULLYEXITSFIRST "HopefullyExitsFirst"
+#define LAUNCH_JOBKEY_HOPEFULLYEXITSLAST "HopefullyExitsLast"
+#define LAUNCH_JOBKEY_LOWPRIORITYIO "LowPriorityIO"
+#define LAUNCH_JOBKEY_LOWPRIORITYBACKGROUNDIO "LowPriorityBackgroundIO"
+#define LAUNCH_JOBKEY_SESSIONCREATE "SessionCreate"
+#define LAUNCH_JOBKEY_STARTONMOUNT "StartOnMount"
+#define LAUNCH_JOBKEY_SOFTRESOURCELIMITS "SoftResourceLimits"
+#define LAUNCH_JOBKEY_HARDRESOURCELIMITS "HardResourceLimits"
+#define LAUNCH_JOBKEY_STANDARDINPATH "StandardInPath"
+#define LAUNCH_JOBKEY_STANDARDOUTPATH "StandardOutPath"
+#define LAUNCH_JOBKEY_STANDARDERRORPATH "StandardErrorPath"
+#define LAUNCH_JOBKEY_DEBUG "Debug"
+#define LAUNCH_JOBKEY_WAITFORDEBUGGER "WaitForDebugger"
+#define LAUNCH_JOBKEY_QUEUEDIRECTORIES "QueueDirectories"
+#define LAUNCH_JOBKEY_WATCHPATHS "WatchPaths"
+#define LAUNCH_JOBKEY_STARTINTERVAL "StartInterval"
+#define LAUNCH_JOBKEY_STARTCALENDARINTERVAL "StartCalendarInterval"
+#define LAUNCH_JOBKEY_BONJOURFDS "BonjourFDs"
+#define LAUNCH_JOBKEY_LASTEXITSTATUS "LastExitStatus"
+#define LAUNCH_JOBKEY_PID "PID"
+#define LAUNCH_JOBKEY_THROTTLEINTERVAL "ThrottleInterval"
+#define LAUNCH_JOBKEY_LAUNCHONLYONCE "LaunchOnlyOnce"
+#define LAUNCH_JOBKEY_ABANDONPROCESSGROUP "AbandonProcessGroup"
+#define LAUNCH_JOBKEY_IGNOREPROCESSGROUPATSHUTDOWN \
+ "IgnoreProcessGroupAtShutdown"
+#define LAUNCH_JOBKEY_LEGACYTIMERS "LegacyTimers"
+#define LAUNCH_JOBKEY_ENABLEPRESSUREDEXIT "EnablePressuredExit"
+#define LAUNCH_JOBKEY_DRAINMESSAGESONFAILEDINIT "DrainMessagesOnFailedInit"
+
+#define LAUNCH_JOBKEY_POLICIES "Policies"
+#define LAUNCH_JOBKEY_ENABLETRANSACTIONS "EnableTransactions"
+#define LAUNCH_JOBKEY_CFBUNDLEIDENTIFIER "CFBundleIdentifier"
+#define LAUNCH_JOBKEY_PROCESSTYPE "ProcessType"
+#define LAUNCH_KEY_PROCESSTYPE_APP "App"
+#define LAUNCH_KEY_PROCESSTYPE_STANDARD "Standard"
+#define LAUNCH_KEY_PROCESSTYPE_BACKGROUND "Background"
+#define LAUNCH_KEY_PROCESSTYPE_INTERACTIVE "Interactive"
+#define LAUNCH_KEY_PROCESSTYPE_ADAPTIVE "Adaptive"
+
+#define LAUNCH_JOBPOLICY_DENYCREATINGOTHERJOBS "DenyCreatingOtherJobs"
+
+#define LAUNCH_JOBINETDCOMPATIBILITY_WAIT "Wait"
+
+#define LAUNCH_JOBKEY_MACH_RESETATCLOSE "ResetAtClose"
+#define LAUNCH_JOBKEY_MACH_HIDEUNTILCHECKIN "HideUntilCheckIn"
+#define LAUNCH_JOBKEY_MACH_DRAINMESSAGESONCRASH "DrainMessagesOnCrash"
+#define LAUNCH_JOBKEY_MACH_PINGEVENTUPDATES "PingEventUpdates"
+
+#define LAUNCH_JOBKEY_KEEPALIVE_SUCCESSFULEXIT "SuccessfulExit"
+#define LAUNCH_JOBKEY_KEEPALIVE_NETWORKSTATE "NetworkState"
+#define LAUNCH_JOBKEY_KEEPALIVE_PATHSTATE "PathState"
+#define LAUNCH_JOBKEY_KEEPALIVE_OTHERJOBACTIVE "OtherJobActive"
+#define LAUNCH_JOBKEY_KEEPALIVE_OTHERJOBENABLED "OtherJobEnabled"
+#define LAUNCH_JOBKEY_KEEPALIVE_AFTERINITIALDEMAND "AfterInitialDemand"
+#define LAUNCH_JOBKEY_KEEPALIVE_CRASHED "Crashed"
+
+#define LAUNCH_JOBKEY_LAUNCHEVENTS "LaunchEvents"
+
+#define LAUNCH_JOBKEY_CAL_MINUTE "Minute"
+#define LAUNCH_JOBKEY_CAL_HOUR "Hour"
+#define LAUNCH_JOBKEY_CAL_DAY "Day"
+#define LAUNCH_JOBKEY_CAL_WEEKDAY "Weekday"
+#define LAUNCH_JOBKEY_CAL_MONTH "Month"
+
+#define LAUNCH_JOBKEY_RESOURCELIMIT_CORE "Core"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_CPU "CPU"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_DATA "Data"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_FSIZE "FileSize"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_MEMLOCK "MemoryLock"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_NOFILE "NumberOfFiles"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_NPROC "NumberOfProcesses"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_RSS "ResidentSetSize"
+#define LAUNCH_JOBKEY_RESOURCELIMIT_STACK "Stack"
+
+#define LAUNCH_JOBKEY_DISABLED_MACHINETYPE "MachineType"
+#define LAUNCH_JOBKEY_DISABLED_MODELNAME "ModelName"
+
+#define LAUNCH_JOBSOCKETKEY_TYPE "SockType"
+#define LAUNCH_JOBSOCKETKEY_PASSIVE "SockPassive"
+#define LAUNCH_JOBSOCKETKEY_BONJOUR "Bonjour"
+#define LAUNCH_JOBSOCKETKEY_SECUREWITHKEY "SecureSocketWithKey"
+#define LAUNCH_JOBSOCKETKEY_PATHNAME "SockPathName"
+#define LAUNCH_JOBSOCKETKEY_PATHMODE "SockPathMode"
+#define LAUNCH_JOBSOCKETKEY_PATHOWNER "SockPathOwner"
+#define LAUNCH_JOBSOCKETKEY_PATHGROUP "SockPathGroup"
+#define LAUNCH_JOBSOCKETKEY_NODENAME "SockNodeName"
+#define LAUNCH_JOBSOCKETKEY_SERVICENAME "SockServiceName"
+#define LAUNCH_JOBSOCKETKEY_FAMILY "SockFamily"
+#define LAUNCH_JOBSOCKETKEY_PROTOCOL "SockProtocol"
+#define LAUNCH_JOBSOCKETKEY_MULTICASTGROUP "MulticastGroup"
+
+#define LAUNCH_JOBKEY_PROCESSTYPE "ProcessType"
+#define LAUNCH_KEY_PROCESSTYPE_APP "App"
+#define LAUNCH_KEY_PROCESSTYPE_STANDARD "Standard"
+#define LAUNCH_KEY_PROCESSTYPE_BACKGROUND "Background"
+#define LAUNCH_KEY_PROCESSTYPE_INTERACTIVE "Interactive"
+#define LAUNCH_KEY_PROCESSTYPE_ADAPTIVE "Adaptive"
+
+/*!
+ * @function launch_activate_socket
+ *
+ * @abstract
+ * Retrieves the file descriptors for sockets specified in the process'
+ * launchd.plist(5).
+ *
+ * @param name
+ * The name of the socket entry in the service's Sockets dictionary.
+ *
+ * @param fds
+ * On return, this parameter will be populated with an array of file
+ * descriptors. One socket can have many descriptors associated with it
+ * depending on the characteristics of the network interfaces on the system.
+ * The descriptors in this array are the results of calling getaddrinfo(3) with
+ * the parameters described in launchd.plist(5).
+ *
+ * The caller is responsible for calling free(3) on the returned pointer.
+ *
+ * @param cnt
+ * The number of file descriptor entries in the returned array.
+ *
+ * @result
+ * On success, zero is returned. Otherwise, an appropriate POSIX-domain is
+ * returned. Possible error codes are:
+ *
+ * ENOENT -> There was no socket of the specified name owned by the caller.
+ * ESRCH -> The caller is not a process managed by launchd.
+ * EALREADY -> The socket has already been activated by the caller.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL2 XPC_NONNULL3
+int
+launch_activate_socket(const char *name, int **fds, size_t *cnt);
+
+typedef struct _launch_data *launch_data_t;
+typedef void (*launch_data_dict_iterator_t)(const launch_data_t lval,
+ const char *key, void *ctx);
+
+typedef enum {
+ LAUNCH_DATA_DICTIONARY = 1,
+ LAUNCH_DATA_ARRAY,
+ LAUNCH_DATA_FD,
+ LAUNCH_DATA_INTEGER,
+ LAUNCH_DATA_REAL,
+ LAUNCH_DATA_BOOL,
+ LAUNCH_DATA_STRING,
+ LAUNCH_DATA_OPAQUE,
+ LAUNCH_DATA_ERRNO,
+ LAUNCH_DATA_MACHPORT,
+} launch_data_type_t;
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_alloc(launch_data_type_t type);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT XPC_NONNULL1
+launch_data_t
+launch_data_copy(launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+launch_data_type_t
+launch_data_get_type(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+void
+launch_data_free(launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1 XPC_NONNULL2 XPC_NONNULL3
+bool
+launch_data_dict_insert(launch_data_t ldict, const launch_data_t lval,
+ const char *key);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL2
+launch_data_t
+launch_data_dict_lookup(const launch_data_t ldict, const char *key);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1 XPC_NONNULL2
+bool
+launch_data_dict_remove(launch_data_t ldict, const char *key);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1 XPC_NONNULL2
+void
+launch_data_dict_iterate(const launch_data_t ldict,
+ launch_data_dict_iterator_t iterator, void *ctx);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+size_t
+launch_data_dict_get_count(const launch_data_t ldict);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_array_set_index(launch_data_t larray, const launch_data_t lval,
+ size_t idx);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+launch_data_t
+launch_data_array_get_index(const launch_data_t larray, size_t idx);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+size_t
+launch_data_array_get_count(const launch_data_t larray);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_fd(int fd);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_machport(mach_port_t val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_integer(long long val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_bool(bool val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_real(double val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_string(const char *val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT
+launch_data_t
+launch_data_new_opaque(const void *bytes, size_t sz);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_fd(launch_data_t ld, int fd);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_machport(launch_data_t ld, mach_port_t mp);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_integer(launch_data_t ld, long long val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_bool(launch_data_t ld, bool val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_real(launch_data_t ld, double val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_string(launch_data_t ld, const char *val);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_NONNULL1
+bool
+launch_data_set_opaque(launch_data_t ld, const void *bytes, size_t sz);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+int
+launch_data_get_fd(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+mach_port_t
+launch_data_get_machport(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+long long
+launch_data_get_integer(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+bool
+launch_data_get_bool(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+double
+launch_data_get_real(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+const char *
+launch_data_get_string(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+void *
+launch_data_get_opaque(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+size_t
+launch_data_get_opaque_size(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1
+int
+launch_data_get_errno(const launch_data_t ld);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_WARN_RESULT
+int
+launch_get_fd(void);
+
+__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_10, __IPHONE_2_0, __IPHONE_8_0)
+XPC_EXPORT XPC_MALLOC XPC_WARN_RESULT XPC_NONNULL1
+launch_data_t
+launch_msg(const launch_data_t request);
+
+__END_DECLS
+
+#endif // __XPC_LAUNCH_H__
Property changes on: trunk/lib/liblaunch/launch.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/launch_internal.h
===================================================================
--- trunk/lib/liblaunch/launch_internal.h (rev 0)
+++ trunk/lib/liblaunch/launch_internal.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LAUNCH_INTERNAL_H__
+#define __LAUNCH_INTERNAL_H__
+
+#pragma clang diagnostic ignored "-Wcast-qual"
+
+#include "vproc_priv.h"
+
+#include <paths.h>
+#include <dispatch/dispatch.h>
+#include <pthread.h>
+
+#if __has_include(<os/alloc_once_private.h>)
+#include <os/alloc_once_private.h>
+#if defined(OS_ALLOC_ONCE_KEY_LIBLAUNCH)
+#define _LIBLAUNCH_HAS_ALLOC_ONCE 1
+#endif
+#endif
+
+typedef struct _launch *launch_t;
+
+struct launch_globals_s {
+ // liblaunch.c
+ pthread_once_t lc_once;
+ pthread_mutex_t lc_mtx;
+ launch_t l;
+ launch_data_t async_resp;
+
+ launch_t in_flight_msg_recv_client;
+
+ int64_t s_am_embedded_god;
+
+ // libvproc.c
+ dispatch_queue_t _vproc_gone2zero_queue;
+ _vproc_transaction_callout _vproc_gone2zero_callout;
+ void *_vproc_gone2zero_ctx;
+
+ dispatch_once_t _vproc_transaction_once;
+ uint64_t _vproc_transaction_enabled;
+ dispatch_queue_t _vproc_transaction_queue;
+ int64_t _vproc_transaction_cnt;
+};
+typedef struct launch_globals_s *launch_globals_t;
+
+void _launch_init_globals(launch_globals_t globals);
+
+#if !_LIBLAUNCH_HAS_ALLOC_ONCE
+launch_globals_t _launch_globals_impl(void);
+#endif
+
+__attribute__((__pure__))
+static inline launch_globals_t
+_launch_globals(void) {
+#if _LIBLAUNCH_HAS_ALLOC_ONCE
+ return (launch_globals_t)os_alloc_once(OS_ALLOC_ONCE_KEY_LIBLAUNCH,
+ sizeof(struct launch_globals_s),
+ (void*)&_launch_init_globals);
+#else
+ return _launch_globals_impl();
+#endif
+}
+
+#pragma GCC visibility push(default)
+
+#define LAUNCHD_DB_PREFIX "/var/db/launchd"
+#define LAUNCHD_LOG_PREFIX "/var/log"
+
+#define LAUNCHD_JOB_DEFAULTS "Defaults"
+#define LAUNCHD_JOB_DEFAULTS_CACHED "CachedDefaults"
+
+launch_t launchd_fdopen(int, int);
+int launchd_getfd(launch_t);
+void launchd_close(launch_t, __typeof__(close) closefunc);
+
+launch_data_t launch_data_new_errno(int);
+bool launch_data_set_errno(launch_data_t, int);
+
+int launchd_msg_send(launch_t, launch_data_t);
+int launchd_msg_recv(launch_t, void (*)(launch_data_t, void *), void *);
+
+size_t launch_data_pack(launch_data_t d, uint8_t *where, size_t len, int *fd_where, size_t *fdslotsleft);
+launch_data_t launch_data_unpack(uint8_t *data, size_t data_size, int *fds, size_t fd_cnt, size_t *data_offset, size_t *fdoffset);
+
+#pragma GCC visibility pop
+
+#endif /* __LAUNCH_INTERNAL_H__*/
Property changes on: trunk/lib/liblaunch/launch_internal.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/launch_priv.h
===================================================================
--- trunk/lib/liblaunch/launch_priv.h (rev 0)
+++ trunk/lib/liblaunch/launch_priv.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __LAUNCH_PRIVATE_H__
+#define __LAUNCH_PRIVATE_H__
+
+#include <mach/mach.h>
+#include <sys/types.h>
+#include <launch.h>
+#include <unistd.h>
+#include <paths.h>
+#include <uuid/uuid.h>
+
+#pragma GCC visibility push(default)
+
+__BEGIN_DECLS
+
+#define LAUNCH_EXITSTATUS_FAIRPLAY_FAIL (INT64_MAX)
+
+#define LAUNCH_KEY_SETUSERENVIRONMENT "SetUserEnvironment"
+#define LAUNCH_KEY_UNSETUSERENVIRONMENT "UnsetUserEnvironment"
+#define LAUNCH_KEY_SHUTDOWN "Shutdown"
+#define LAUNCH_KEY_SINGLEUSER "SingleUser"
+#define LAUNCH_KEY_GETRESOURCELIMITS "GetResourceLimits"
+#define LAUNCH_KEY_SETRESOURCELIMITS "SetResourceLimits"
+#define LAUNCH_KEY_GETRUSAGESELF "GetResourceUsageSelf"
+#define LAUNCH_KEY_GETRUSAGECHILDREN "GetResourceUsageChildren"
+
+#define LAUNCHD_SOCKET_ENV "LAUNCHD_SOCKET"
+#define LAUNCHD_SOCK_PREFIX _PATH_VARTMP "launchd"
+#define LAUNCHD_TRUSTED_FD_ENV "__LAUNCHD_FD"
+#define LAUNCHD_ASYNC_MSG_KEY "_AsyncMessage"
+#define LAUNCH_KEY_BATCHCONTROL "BatchControl"
+#define LAUNCH_KEY_BATCHQUERY "BatchQuery"
+
+#define LAUNCH_JOBKEY_TRANSACTIONCOUNT "TransactionCount"
+#define LAUNCH_JOBKEY_QUARANTINEDATA "QuarantineData"
+#define LAUNCH_JOBKEY_SANDBOXPROFILE "SandboxProfile"
+#define LAUNCH_JOBKEY_SANDBOXFLAGS "SandboxFlags"
+#define LAUNCH_JOBKEY_SANDBOX_NAMED "Named"
+#define LAUNCH_JOBKEY_SANDBOXCONTAINER "SandboxContainer"
+#define LAUNCH_JOBKEY_JETSAMPROPERTIES "JetsamProperties"
+#define LAUNCH_JOBKEY_JETSAMPRIORITY "JetsamPriority"
+#define LAUNCH_JOBKEY_JETSAMMEMORYLIMIT "JetsamMemoryLimit"
+#define LAUNCH_JOBKEY_JETSAMMEMORYLIMITBACKGROUND "JetsamMemoryLimitBackground"
+#define LAUNCH_JOBKEY_SECURITYSESSIONUUID "SecuritySessionUUID"
+#define LAUNCH_JOBKEY_DISABLEASLR "DisableASLR"
+#define LAUNCH_JOBKEY_XPCDOMAIN "XPCDomain"
+#define LAUNCH_JOBKEY_POSIXSPAWNTYPE "POSIXSpawnType"
+
+#define LAUNCH_KEY_JETSAMLABEL "JetsamLabel"
+#define LAUNCH_KEY_JETSAMFRONTMOST "JetsamFrontmost"
+#define LAUNCH_KEY_JETSAMACTIVE "JetsamActive"
+#define LAUNCH_KEY_JETSAMPRIORITY LAUNCH_JOBKEY_JETSAMPRIORITY
+#define LAUNCH_KEY_JETSAMMEMORYLIMIT LAUNCH_JOBKEY_JETSAMMEMORYLIMIT
+
+#define LAUNCH_KEY_POSIXSPAWNTYPE_APP LAUNCH_KEY_PROCESSTYPE_APP
+#define LAUNCH_KEY_POSIXSPAWNTYPE_SYSTEMAPP "SystemApp"
+#define LAUNCH_KEY_POSIXSPAWNTYPE_STANDARD LAUNCH_KEY_PROCESSTYPE_STANDARD
+#define LAUNCH_KEY_POSIXSPAWNTYPE_BACKGROUND LAUNCH_KEY_PROCESSTYPE_BACKGROUND
+#define LAUNCH_KEY_POSIXSPAWNTYPE_INTERACTIVE LAUNCH_KEY_PROCESSTYPE_INTERACTIVE
+#define LAUNCH_KEY_POSIXSPAWNTYPE_ADAPTIVE LAUNCH_KEY_PROCESSTYPE_ADAPTIVE
+#define LAUNCH_KEY_POSIXSPAWNTYPE_TALAPP "TALApp"
+
+#define LAUNCH_JOBKEY_EMBEDDEDPRIVILEGEDISPENSATION "EmbeddedPrivilegeDispensation"
+#define LAUNCH_JOBKEY_EMBEDDEDHOMESCREEN "EmbeddedHomeScreen"
+#define LAUNCH_JOBKEY_EMBEDDEDMAINTHREADPRIORITY "EmbeddedMainThreadPriority"
+
+#define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL "EnterKernelDebuggerBeforeKill"
+#define LAUNCH_JOBKEY_PERJOBMACHSERVICES "PerJobMachServices"
+#define LAUNCH_JOBKEY_SERVICEIPC "ServiceIPC"
+#define LAUNCH_JOBKEY_BINARYORDERPREFERENCE "BinaryOrderPreference"
+#define LAUNCH_JOBKEY_MACHEXCEPTIONHANDLER "MachExceptionHandler"
+#define LAUNCH_JOBKEY_MULTIPLEINSTANCES "MultipleInstances"
+#define LAUNCH_JOBKEY_EVENTMONITOR "EventMonitor"
+#define LAUNCH_JOBKEY_SHUTDOWNMONITOR "ShutdownMonitor"
+#define LAUNCH_JOBKEY_BEGINTRANSACTIONATSHUTDOWN "BeginTransactionAtShutdown"
+#define LAUNCH_JOBKEY_XPCDOMAINBOOTSTRAPPER "XPCDomainBootstrapper"
+#define LAUNCH_JOBKEY_ASID "AuditSessionID"
+#define LAUNCH_JOBKEY_JOINGUISESSION "JoinGUISession"
+
+#define LAUNCH_JOBKEY_MACH_KUNCSERVER "kUNCServer"
+#define LAUNCH_JOBKEY_MACH_EXCEPTIONSERVER "ExceptionServer"
+#define LAUNCH_JOBKEY_MACH_TASKSPECIALPORT "TaskSpecialPort"
+#define LAUNCH_JOBKEY_MACH_HOSTSPECIALPORT "HostSpecialPort"
+#define LAUNCH_JOBKEY_MACH_ENTERKERNELDEBUGGERONCLOSE "EnterKernelDebuggerOnClose"
+#define LAUNCH_JOBKEY_LOWPRIORITYBACKGROUNDIO "LowPriorityBackgroundIO"
+#define LAUNCH_JOBKEY_LEGACYTIMERS "LegacyTimers"
+
+#define LAUNCH_ENV_INSTANCEID "LaunchInstanceID"
+
+#define JETSAM_PROPERTY_PRIORITY "Priority"
+#define JETSAM_PROPERTY_MEMORYLIMIT "MemoryLimitMB"
+
+/* For LoginWindow.
+ *
+ * After this call, the task's bootstrap port is set to the per session launchd.
+ *
+ * This returns 1 on success (it used to return otherwise), and -1 on failure.
+ */
+#define LOAD_ONLY_SAFEMODE_LAUNCHAGENTS (1 << 0)
+#define LAUNCH_GLOBAL_ON_DEMAND (1 << 1)
+pid_t
+create_and_switch_to_per_session_launchd(const char *, int flags, ...);
+
+/* Also for LoginWindow.
+ *
+ * This is will load jobs at the LoginWindow prompt.
+ */
+void
+load_launchd_jobs_at_loginwindow_prompt(int flags, ...);
+
+/* For CoreProcesses */
+#define SPAWN_VIA_LAUNCHD_STOPPED 0x0001
+#define SPAWN_VIA_LAUNCHD_TALAPP 0x0002
+#define SPAWN_VIA_LAUNCHD_WIDGET 0x0004
+#define SPAWN_VIA_LAUNCHD_DISABLE_ASLR 0x0008
+
+struct spawn_via_launchd_attr {
+ uint64_t spawn_flags;
+ const char *spawn_path;
+ const char *spawn_chdir;
+ const char * const * spawn_env;
+ const mode_t *spawn_umask;
+ mach_port_t *spawn_observer_port;
+ const cpu_type_t *spawn_binpref;
+ size_t spawn_binpref_cnt;
+ void * spawn_quarantine;
+ const char *spawn_seatbelt_profile;
+ const uint64_t *spawn_seatbelt_flags;
+};
+
+#define spawn_via_launchd(a, b, c) _spawn_via_launchd(a, b, c, 3)
+pid_t
+_spawn_via_launchd(const char *label, const char * const *argv,
+ const struct spawn_via_launchd_attr *spawn_attrs, int struct_version);
+
+int
+launch_wait(mach_port_t port);
+
+/* The mpm_*() APIs no longer do anything. */
+kern_return_t
+mpm_wait(mach_port_t ajob, int *wstatus);
+
+kern_return_t
+mpm_uncork_fork(mach_port_t ajob);
+
+launch_data_t
+launch_socket_service_check_in(void);
+
+__END_DECLS
+
+#pragma GCC visibility pop
+
+
+#endif /* __LAUNCH_PRIVATE_H__ */
Property changes on: trunk/lib/liblaunch/launch_priv.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/launchd.ops
===================================================================
--- trunk/lib/liblaunch/launchd.ops (rev 0)
+++ trunk/lib/liblaunch/launchd.ops 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,2 @@
+< mach* >
+ mach-per-user-lookup
Added: trunk/lib/liblaunch/libbootstrap.c
===================================================================
--- trunk/lib/liblaunch/libbootstrap.c (rev 0)
+++ trunk/lib/liblaunch/libbootstrap.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "config.h"
+#include "launch.h"
+#include "launch_priv.h"
+#include "launch_internal.h"
+#include "bootstrap.h"
+#include "bootstrap_priv.h"
+#include "vproc.h"
+#include "vproc_priv.h"
+
+#include <mach/mach.h>
+#include <mach/mach_port.h>
+#include <sys/types.h>
+#include <sys/syslog.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+
+#include "job.h"
+
+void
+bootstrap_init(void)
+{
+ kern_return_t kr = task_get_special_port(task_self_trap(), TASK_BOOTSTRAP_PORT, &bootstrap_port);
+ if (kr != KERN_SUCCESS) {
+ abort();
+ }
+}
+
+kern_return_t
+bootstrap_create_server(mach_port_t bp, cmd_t server_cmd, uid_t server_uid, boolean_t on_demand, mach_port_t *server_port)
+{
+ kern_return_t kr;
+
+ kr = vproc_mig_create_server(bp, server_cmd, server_uid, on_demand, server_port);
+
+ if (kr == VPROC_ERR_TRY_PER_USER) {
+ mach_port_t puc;
+
+ if (vproc_mig_lookup_per_user_context(bp, 0, &puc) == 0) {
+ kr = vproc_mig_create_server(puc, server_cmd, server_uid, on_demand, server_port);
+ mach_port_deallocate(mach_task_self(), puc);
+ }
+ }
+
+ return kr;
+}
+
+kern_return_t
+bootstrap_subset(mach_port_t bp, mach_port_t requestor_port, mach_port_t *subset_port)
+{
+ return vproc_mig_subset(bp, requestor_port, subset_port);
+}
+
+kern_return_t
+bootstrap_unprivileged(mach_port_t bp, mach_port_t *unpriv_port)
+{
+ kern_return_t kr;
+
+ *unpriv_port = MACH_PORT_NULL;
+
+ kr = mach_port_mod_refs(mach_task_self(), bp, MACH_PORT_RIGHT_SEND, 1);
+
+ if (kr == KERN_SUCCESS) {
+ *unpriv_port = bp;
+ }
+
+ return kr;
+}
+
+kern_return_t
+bootstrap_parent(mach_port_t bp, mach_port_t *parent_port)
+{
+ return vproc_mig_parent(bp, parent_port);
+}
+
+kern_return_t
+bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp)
+{
+ return bootstrap_register2(bp, service_name, sp, 0);
+}
+
+kern_return_t
+bootstrap_register2(mach_port_t bp, name_t service_name, mach_port_t sp, uint64_t flags)
+{
+ kern_return_t kr = vproc_mig_register2(bp, service_name, sp, flags);
+
+ if (kr == VPROC_ERR_TRY_PER_USER) {
+ mach_port_t puc;
+
+ if (vproc_mig_lookup_per_user_context(bp, 0, &puc) == 0) {
+ kr = vproc_mig_register2(puc, service_name, sp, flags);
+ mach_port_deallocate(mach_task_self(), puc);
+ }
+ }
+
+ return kr;
+}
+
+kern_return_t
+bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp)
+{
+ kern_return_t kr;
+
+ if ((kr = bootstrap_check_in(bp, service_name, sp))) {
+ return kr;
+ }
+
+ if ((kr = mach_port_mod_refs(mach_task_self(), *sp, MACH_PORT_RIGHT_RECEIVE, -1))) {
+ return kr;
+ }
+
+ return bootstrap_look_up(bp, service_name, sp);
+}
+
+kern_return_t
+bootstrap_check_in(mach_port_t bp, const name_t service_name, mach_port_t *sp)
+{
+ uuid_t junk;
+ (void)bzero(junk, sizeof(junk));
+ return vproc_mig_check_in2(bp, (char *)service_name, sp, junk, 0);
+}
+
+kern_return_t
+bootstrap_check_in2(mach_port_t bp, const name_t service_name, mach_port_t *sp, uint64_t flags)
+{
+ uuid_t junk;
+ (void)bzero(junk, sizeof(junk));
+ return vproc_mig_check_in2(bp, (char *)service_name, sp, junk, flags);
+}
+
+kern_return_t
+bootstrap_look_up_per_user(mach_port_t bp, const name_t service_name, uid_t target_user, mach_port_t *sp)
+{
+ audit_token_t au_tok;
+ kern_return_t kr;
+ mach_port_t puc;
+
+ /* See rdar://problem/4890134. */
+
+ if ((kr = vproc_mig_lookup_per_user_context(bp, target_user, &puc)) != 0) {
+ return kr;
+ }
+
+ if (!service_name) {
+ *sp = puc;
+ } else {
+ uuid_t junk;
+ kr = vproc_mig_look_up2(puc, (char *)service_name, sp, &au_tok, 0, junk, 0);
+ mach_port_deallocate(mach_task_self(), puc);
+ }
+
+ return kr;
+}
+
+kern_return_t
+bootstrap_lookup_children(mach_port_t bp, mach_port_array_t *children, name_array_t *names, bootstrap_property_array_t *properties, mach_msg_type_number_t *n_children)
+{
+ mach_msg_type_number_t junk = 0;
+ return vproc_mig_lookup_children(bp, children, &junk, names, n_children, properties, &junk);
+}
+
+kern_return_t
+bootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp)
+{
+ return bootstrap_look_up2(bp, service_name, sp, 0, 0);
+}
+
+kern_return_t
+bootstrap_look_up2(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, uint64_t flags)
+{
+ uuid_t instance_id;
+ return bootstrap_look_up3(bp, service_name, sp, target_pid, instance_id, flags);
+}
+
+kern_return_t
+bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags)
+{
+ audit_token_t au_tok;
+ bool privileged_server_lookup = flags & BOOTSTRAP_PRIVILEGED_SERVER;
+ kern_return_t kr = 0;
+ mach_port_t puc;
+
+ // We have to cast instance_id here because the MIG-generated method
+ // doesn't expect a const parameter.
+ if ((kr = vproc_mig_look_up2(bp, (char *)service_name, sp, &au_tok, target_pid, (unsigned char*)instance_id, flags)) != VPROC_ERR_TRY_PER_USER) {
+ goto out;
+ }
+
+ if ((kr = vproc_mig_lookup_per_user_context(bp, 0, &puc)) != 0) {
+ goto out;
+ }
+
+ kr = vproc_mig_look_up2(puc, (char *)service_name, sp, &au_tok, target_pid, (unsigned char*)instance_id, flags);
+ mach_port_deallocate(mach_task_self(), puc);
+
+out:
+ if ((kr == 0) && privileged_server_lookup) {
+ uid_t server_euid;
+
+ /*
+ * The audit token magic is dependent on the per-user launchd
+ * forwarding MIG requests to the root launchd when it cannot
+ * find the answer locally.
+ */
+
+ /* This API should be in Libsystem, but is not */
+ //audit_token_to_au32(au_tok, NULL, &server_euid, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ server_euid = au_tok.val[1];
+
+ if (server_euid) {
+ mach_port_deallocate(mach_task_self(), *sp);
+ *sp = MACH_PORT_NULL;
+ kr = BOOTSTRAP_NOT_PRIVILEGED;
+ }
+ }
+
+ return kr;
+}
+
+kern_return_t
+bootstrap_check_in3(mach_port_t bp, const name_t service_name, mach_port_t *sp, uuid_t instance_id, uint64_t flags)
+{
+ return vproc_mig_check_in2(bp, (char *)service_name, sp, instance_id, flags);
+}
+
+kern_return_t
+bootstrap_get_root(mach_port_t bp, mach_port_t *root)
+{
+ return vproc_mig_get_root_bootstrap(bp, root);
+}
+
+kern_return_t
+bootstrap_status(mach_port_t bp, name_t service_name, bootstrap_status_t *service_active)
+{
+ kern_return_t kr;
+ mach_port_t p;
+
+ if ((kr = bootstrap_look_up(bp, service_name, &p))) {
+ return kr;
+ }
+
+ mach_port_deallocate(mach_task_self(), p);
+ *service_active = BOOTSTRAP_STATUS_ACTIVE;
+
+ if (bootstrap_check_in(bp, service_name, &p) == BOOTSTRAP_SUCCESS) {
+ mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1);
+ *service_active = BOOTSTRAP_STATUS_ON_DEMAND;
+ }
+
+ return BOOTSTRAP_SUCCESS;
+}
+
+kern_return_t
+bootstrap_info(mach_port_t bp,
+ name_array_t *service_names, mach_msg_type_number_t *service_namesCnt,
+ name_array_t *service_jobs, mach_msg_type_number_t *service_jobsCnt,
+ bootstrap_status_array_t *service_active, mach_msg_type_number_t *service_activeCnt,
+ uint64_t flags)
+{
+ return vproc_mig_info(bp, service_names, service_namesCnt, service_jobs, service_jobsCnt, service_active, service_activeCnt, flags);
+}
+
+const char *
+bootstrap_strerror(kern_return_t r)
+{
+ switch (r) {
+ case BOOTSTRAP_SUCCESS:
+ return "Success";
+ case BOOTSTRAP_NOT_PRIVILEGED:
+ return "Permission denied";
+ case BOOTSTRAP_NAME_IN_USE:
+ case BOOTSTRAP_SERVICE_ACTIVE:
+ return "Service name already exists";
+ case BOOTSTRAP_UNKNOWN_SERVICE:
+ return "Unknown service name";
+ case BOOTSTRAP_BAD_COUNT:
+ return "Too many lookups were requested in one request";
+ case BOOTSTRAP_NO_MEMORY:
+ return "Out of memory";
+ default:
+ return mach_error_string(r);
+ }
+}
Property changes on: trunk/lib/liblaunch/libbootstrap.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/liblaunch.c
===================================================================
--- trunk/lib/liblaunch/liblaunch.c (rev 0)
+++ trunk/lib/liblaunch/liblaunch.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,1471 @@
+/*
+ * Copyright (c) 2005-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "config.h"
+#include "launch.h"
+#include "launch_priv.h"
+#include "launch_internal.h"
+#include "ktrace.h"
+
+#include <mach/mach.h>
+#include <mach/mach_port.h>
+#include <libkern/OSByteOrder.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/fcntl.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+#include <assert.h>
+#include <uuid/uuid.h>
+#include <sys/syscall.h>
+#include <dlfcn.h>
+
+struct _launch_data {
+ uint64_t type;
+ union {
+ struct {
+ union {
+ launch_data_t *_array;
+ char *string;
+ void *opaque;
+ int64_t __junk;
+ };
+ union {
+ uint64_t _array_cnt;
+ uint64_t string_len;
+ uint64_t opaque_size;
+ };
+ };
+ int64_t fd;
+ uint64_t mp;
+ uint64_t err;
+ int64_t number;
+ uint64_t boolean; /* We'd use 'bool' but this struct needs to be used under Rosetta, and sizeof(bool) is different between PowerPC and Intel */
+ double float_num;
+ };
+};
+
+#include "bootstrap.h"
+#include "vproc.h"
+#include "vproc_priv.h"
+#include "vproc_internal.h"
+
+/* __OSBogusByteSwap__() must not really exist in the symbol namespace
+ * in order for the following to generate an error at build time.
+ */
+extern void __OSBogusByteSwap__(void);
+
+#define host2wire(x) \
+ ({ typeof (x) _X, _x = (x); \
+ switch (sizeof(_x)) { \
+ case 8: \
+ _X = OSSwapHostToLittleInt64(_x); \
+ break; \
+ case 4: \
+ _X = OSSwapHostToLittleInt32(_x); \
+ break; \
+ case 2: \
+ _X = OSSwapHostToLittleInt16(_x); \
+ break; \
+ case 1: \
+ _X = _x; \
+ break; \
+ default: \
+ __OSBogusByteSwap__(); \
+ break; \
+ } \
+ _X; \
+ })
+
+
+#define big2wire(x) \
+ ({ typeof (x) _X, _x = (x); \
+ switch (sizeof(_x)) { \
+ case 8: \
+ _X = OSSwapLittleToHostInt64(_x); \
+ break; \
+ case 4: \
+ _X = OSSwapLittleToHostInt32(_x); \
+ break; \
+ case 2: \
+ _X = OSSwapLittleToHostInt16(_x); \
+ break; \
+ case 1: \
+ _X = _x; \
+ break; \
+ default: \
+ __OSBogusByteSwap__(); \
+ break; \
+ } \
+ _X; \
+ })
+
+union _launch_double_u {
+ uint64_t iv;
+ double dv;
+};
+
+#define host2wire_f(x) ({ \
+ typeof(x) _F, _f = (x); \
+ union _launch_double_u s; \
+ s.dv = _f; \
+ s.iv = host2wire(s.iv); \
+ _F = s.dv; \
+ _F; \
+})
+
+#define big2wire_f(x) ({ \
+ typeof(x) _F, _f = (x); \
+ union _launch_double_u s; \
+ s.dv = _f; \
+ s.iv = big2wire(s.iv); \
+ _F = s.dv; \
+ _F; \
+})
+
+
+struct launch_msg_header {
+ uint64_t magic;
+ uint64_t len;
+};
+
+#define LAUNCH_MSG_HEADER_MAGIC 0xD2FEA02366B39A41ull
+
+enum {
+ LAUNCHD_USE_CHECKIN_FD,
+ LAUNCHD_USE_OTHER_FD,
+};
+struct _launch {
+ uint8_t *sendbuf;
+ int *sendfds;
+ uint8_t *recvbuf;
+ int *recvfds;
+ size_t sendlen;
+ size_t sendfdcnt;
+ size_t recvlen;
+ size_t recvfdcnt;
+ int which;
+ int cifd;
+ int fd;
+};
+
+static launch_data_t launch_data_array_pop_first(launch_data_t where);
+static int _fd(int fd);
+static void launch_client_init(void);
+static void launch_msg_getmsgs(launch_data_t m, void *context);
+static launch_data_t launch_msg_internal(launch_data_t d);
+static void launch_mach_checkin_service(launch_data_t obj, const char *key, void *context);
+
+void
+_launch_init_globals(launch_globals_t globals)
+{
+ pthread_once_t once = PTHREAD_ONCE_INIT;
+ globals->lc_once = once;
+ pthread_mutex_init(&globals->lc_mtx, NULL);
+}
+
+#if !_LIBLAUNCH_HAS_ALLOC_ONCE
+static launch_globals_t __launch_globals;
+
+static void
+_launch_globals_init(void)
+{
+ __launch_globals = calloc(1, sizeof(struct launch_globals_s));
+ _launch_init_globals(__launch_globals);
+}
+
+launch_globals_t
+_launch_globals_impl(void)
+{
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+ pthread_once(&once, &_launch_globals_init);
+ return __launch_globals;
+}
+#endif
+
+void
+launch_client_init(void)
+{
+ struct sockaddr_un sun;
+ char *where = getenv(LAUNCHD_SOCKET_ENV);
+ char *_launchd_fd = getenv(LAUNCHD_TRUSTED_FD_ENV);
+ int dfd, lfd = -1, cifd = -1;
+ kern_return_t kr;
+ name_t spath;
+
+ if (_launchd_fd) {
+ cifd = strtol(_launchd_fd, NULL, 10);
+ if ((dfd = dup(cifd)) >= 0) {
+ close(dfd);
+ _fd(cifd);
+ } else {
+ cifd = -1;
+ }
+ unsetenv(LAUNCHD_TRUSTED_FD_ENV);
+ }
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+
+ /* The rules are as follows.
+ * - All users (including root) talk to their per-user launchd's by default.
+ * - If we have been invoked under sudo, talk to the system launchd.
+ * - If we're the root user and the __USE_SYSTEM_LAUNCHD environment variable is set, then
+ * talk to the system launchd.
+ */
+ if (where && where[0] != '\0') {
+ strncpy(sun.sun_path, where, sizeof(sun.sun_path));
+ } else {
+ kr = _vprocmgr_getsocket(spath);
+ if (kr == 0) {
+ if ((getenv("SUDO_COMMAND") || getenv("__USE_SYSTEM_LAUNCHD")) && geteuid() == 0) {
+ /* Talk to the system launchd. */
+ strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path));
+ } else {
+ /* Talk to our per-user launchd. */
+ size_t min_len;
+
+ min_len = sizeof(sun.sun_path) < sizeof(spath) ? sizeof(sun.sun_path) : sizeof(spath);
+
+ strncpy(sun.sun_path, spath, min_len);
+ }
+ } else
+ fprintf(stderr, "_vprocmgr_getsocket(): 0x%x\n", kr);
+ }
+
+ launch_globals_t globals = _launch_globals();
+ if ((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) == -1) {
+ goto out_bad;
+ }
+
+#if TARGET_OS_EMBEDDED
+ (void)vproc_swap_integer(NULL, VPROC_GSK_EMBEDDEDROOTEQUIVALENT, NULL, &globals->s_am_embedded_god);
+#endif
+ if (-1 == connect(lfd, (struct sockaddr *)&sun, sizeof(sun))) {
+ if (cifd != -1 || globals->s_am_embedded_god) {
+ /* There is NO security enforced by this check. This is just a hint to our
+ * library that we shouldn't error out due to failing to open this socket. If
+ * we inherited a trusted file descriptor, we shouldn't fail. This should be
+ * adequate for clients' expectations.
+ */
+ close(lfd);
+ lfd = -1;
+ } else {
+ goto out_bad;
+ }
+ }
+
+ if (!(globals->l = launchd_fdopen(lfd, cifd))) {
+ goto out_bad;
+ }
+
+ if (!(globals->async_resp = launch_data_alloc(LAUNCH_DATA_ARRAY))) {
+ goto out_bad;
+ }
+
+ return;
+out_bad:
+ if (globals->l) {
+ launchd_close(globals->l, close);
+ globals->l = NULL;
+ } else if (lfd != -1) {
+ close(lfd);
+ }
+ if (cifd != -1) {
+ close(cifd);
+ }
+}
+
+launch_data_t
+launch_data_alloc(launch_data_type_t t)
+{
+ launch_data_t d = calloc(1, sizeof(struct _launch_data));
+
+ if (d) {
+ d->type = t;
+ switch (t) {
+ case LAUNCH_DATA_DICTIONARY:
+ case LAUNCH_DATA_ARRAY:
+ d->_array = malloc(0);
+ break;
+ case LAUNCH_DATA_OPAQUE:
+ d->opaque = malloc(0);
+ default:
+ break;
+ }
+ }
+
+ return d;
+}
+
+launch_data_type_t
+launch_data_get_type(launch_data_t d)
+{
+ return d->type;
+}
+
+void
+launch_data_free(launch_data_t d)
+{
+ size_t i;
+
+ switch (d->type) {
+ case LAUNCH_DATA_DICTIONARY:
+ case LAUNCH_DATA_ARRAY:
+ for (i = 0; i < d->_array_cnt; i++) {
+ if (d->_array[i]) {
+ launch_data_free(d->_array[i]);
+ }
+ }
+ free(d->_array);
+ break;
+ case LAUNCH_DATA_STRING:
+ if (d->string)
+ free(d->string);
+ break;
+ case LAUNCH_DATA_OPAQUE:
+ if (d->opaque)
+ free(d->opaque);
+ break;
+ default:
+ break;
+ }
+ free(d);
+}
+
+size_t
+launch_data_dict_get_count(launch_data_t dict)
+{
+ return dict->_array_cnt / 2;
+}
+
+bool
+launch_data_dict_insert(launch_data_t dict, launch_data_t what, const char *key)
+{
+ size_t i;
+ launch_data_t thekey = launch_data_alloc(LAUNCH_DATA_STRING);
+
+ launch_data_set_string(thekey, key);
+
+ for (i = 0; i < dict->_array_cnt; i += 2) {
+ if (!strcasecmp(key, dict->_array[i]->string)) {
+ launch_data_array_set_index(dict, thekey, i);
+ launch_data_array_set_index(dict, what, i + 1);
+ return true;
+ }
+ }
+ launch_data_array_set_index(dict, thekey, i);
+ launch_data_array_set_index(dict, what, i + 1);
+ return true;
+}
+
+launch_data_t
+launch_data_dict_lookup(launch_data_t dict, const char *key)
+{
+ size_t i;
+
+ if (LAUNCH_DATA_DICTIONARY != dict->type)
+ return NULL;
+
+ for (i = 0; i < dict->_array_cnt; i += 2) {
+ if (!strcasecmp(key, dict->_array[i]->string))
+ return dict->_array[i + 1];
+ }
+
+ return NULL;
+}
+
+bool
+launch_data_dict_remove(launch_data_t dict, const char *key)
+{
+ size_t i;
+
+ for (i = 0; i < dict->_array_cnt; i += 2) {
+ if (!strcasecmp(key, dict->_array[i]->string))
+ break;
+ }
+ if (i == dict->_array_cnt)
+ return false;
+ launch_data_free(dict->_array[i]);
+ launch_data_free(dict->_array[i + 1]);
+ memmove(dict->_array + i, dict->_array + i + 2, (dict->_array_cnt - (i + 2)) * sizeof(launch_data_t));
+ dict->_array_cnt -= 2;
+ return true;
+}
+
+void
+launch_data_dict_iterate(launch_data_t dict, void (*cb)(launch_data_t, const char *, void *), void *context)
+{
+ size_t i;
+
+ if (LAUNCH_DATA_DICTIONARY != dict->type) {
+ return;
+ }
+
+ for (i = 0; i < dict->_array_cnt; i += 2) {
+ cb(dict->_array[i + 1], dict->_array[i]->string, context);
+ }
+}
+
+bool
+launch_data_array_set_index(launch_data_t where, launch_data_t what, size_t ind)
+{
+ if ((ind + 1) >= where->_array_cnt) {
+ where->_array = reallocf(where->_array, (ind + 1) * sizeof(launch_data_t));
+ memset(where->_array + where->_array_cnt, 0, (ind + 1 - where->_array_cnt) * sizeof(launch_data_t));
+ where->_array_cnt = ind + 1;
+ }
+
+ if (where->_array[ind]) {
+ launch_data_free(where->_array[ind]);
+ }
+
+ where->_array[ind] = what;
+ return true;
+}
+
+launch_data_t
+launch_data_array_get_index(launch_data_t where, size_t ind)
+{
+ if (LAUNCH_DATA_ARRAY != where->type || ind >= where->_array_cnt) {
+ return NULL;
+ } else {
+ return where->_array[ind];
+ }
+}
+
+launch_data_t
+launch_data_array_pop_first(launch_data_t where)
+{
+ launch_data_t r = NULL;
+
+ if (where->_array_cnt > 0) {
+ r = where->_array[0];
+ memmove(where->_array, where->_array + 1, (where->_array_cnt - 1) * sizeof(launch_data_t));
+ where->_array_cnt--;
+ }
+ return r;
+}
+
+size_t
+launch_data_array_get_count(launch_data_t where)
+{
+ if (LAUNCH_DATA_ARRAY != where->type)
+ return 0;
+ return where->_array_cnt;
+}
+
+bool
+launch_data_set_errno(launch_data_t d, int e)
+{
+ d->err = e;
+ return true;
+}
+
+bool
+launch_data_set_fd(launch_data_t d, int fd)
+{
+ d->fd = fd;
+ return true;
+}
+
+bool
+launch_data_set_machport(launch_data_t d, mach_port_t p)
+{
+ d->mp = p;
+ return true;
+}
+
+bool
+launch_data_set_integer(launch_data_t d, long long n)
+{
+ d->number = n;
+ return true;
+}
+
+bool
+launch_data_set_bool(launch_data_t d, bool b)
+{
+ d->boolean = b;
+ return true;
+}
+
+bool
+launch_data_set_real(launch_data_t d, double n)
+{
+ d->float_num = n;
+ return true;
+}
+
+bool
+launch_data_set_string(launch_data_t d, const char *s)
+{
+ if (d->string)
+ free(d->string);
+ d->string = strdup(s);
+ if (d->string) {
+ d->string_len = strlen(d->string);
+ return true;
+ }
+ return false;
+}
+
+bool
+launch_data_set_opaque(launch_data_t d, const void *o, size_t os)
+{
+ d->opaque_size = os;
+ if (d->opaque)
+ free(d->opaque);
+ d->opaque = malloc(os);
+ if (d->opaque) {
+ memcpy(d->opaque, o, os);
+ return true;
+ }
+ return false;
+}
+
+int
+launch_data_get_errno(launch_data_t d)
+{
+ return d->err;
+}
+
+int
+launch_data_get_fd(launch_data_t d)
+{
+ return d->fd;
+}
+
+mach_port_t
+launch_data_get_machport(launch_data_t d)
+{
+ return d->mp;
+}
+
+long long
+launch_data_get_integer(launch_data_t d)
+{
+ return d->number;
+}
+
+bool
+launch_data_get_bool(launch_data_t d)
+{
+ return d->boolean;
+}
+
+double
+launch_data_get_real(launch_data_t d)
+{
+ return d->float_num;
+}
+
+const char *
+launch_data_get_string(launch_data_t d)
+{
+ if (LAUNCH_DATA_STRING != d->type)
+ return NULL;
+ return d->string;
+}
+
+void *
+launch_data_get_opaque(launch_data_t d)
+{
+ if (LAUNCH_DATA_OPAQUE != d->type)
+ return NULL;
+ return d->opaque;
+}
+
+size_t
+launch_data_get_opaque_size(launch_data_t d)
+{
+ return d->opaque_size;
+}
+
+int
+launchd_getfd(launch_t l)
+{
+ return (l->which == LAUNCHD_USE_CHECKIN_FD) ? l->cifd : l->fd;
+}
+
+launch_t
+launchd_fdopen(int fd, int cifd)
+{
+ launch_t c;
+
+ c = calloc(1, sizeof(struct _launch));
+ if (!c)
+ return NULL;
+
+ c->fd = fd;
+ c->cifd = cifd;
+
+ if (c->fd == -1 || (c->fd != -1 && c->cifd != -1)) {
+ c->which = LAUNCHD_USE_CHECKIN_FD;
+ } else if (c->cifd == -1) {
+ c->which = LAUNCHD_USE_OTHER_FD;
+ }
+
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ fcntl(cifd, F_SETFL, O_NONBLOCK);
+
+ if ((c->sendbuf = malloc(0)) == NULL)
+ goto out_bad;
+ if ((c->sendfds = malloc(0)) == NULL)
+ goto out_bad;
+ if ((c->recvbuf = malloc(0)) == NULL)
+ goto out_bad;
+ if ((c->recvfds = malloc(0)) == NULL)
+ goto out_bad;
+
+ return c;
+
+out_bad:
+ if (c->sendbuf)
+ free(c->sendbuf);
+ if (c->sendfds)
+ free(c->sendfds);
+ if (c->recvbuf)
+ free(c->recvbuf);
+ if (c->recvfds)
+ free(c->recvfds);
+ free(c);
+ return NULL;
+}
+
+void
+launchd_close(launch_t lh, typeof(close) closefunc)
+{
+ launch_globals_t globals = _launch_globals();
+
+ if (globals->in_flight_msg_recv_client == lh) {
+ globals->in_flight_msg_recv_client = NULL;
+ }
+
+ if (lh->sendbuf)
+ free(lh->sendbuf);
+ if (lh->sendfds)
+ free(lh->sendfds);
+ if (lh->recvbuf)
+ free(lh->recvbuf);
+ if (lh->recvfds)
+ free(lh->recvfds);
+ closefunc(lh->fd);
+ closefunc(lh->cifd);
+ free(lh);
+}
+
+#define ROUND_TO_64BIT_WORD_SIZE(x) ((x + 7) & ~7)
+
+size_t
+launch_data_pack(launch_data_t d, uint8_t *where, size_t len, int *fd_where, size_t *fd_cnt)
+{
+ launch_data_t o_in_w = (void *)where;
+ size_t i, rsz, node_data_len = sizeof(struct _launch_data);
+
+ if (node_data_len > len) {
+ return 0;
+ }
+
+ where += node_data_len;
+
+ o_in_w->type = host2wire(d->type);
+
+ size_t pad_len = 0;
+ switch (d->type) {
+ case LAUNCH_DATA_INTEGER:
+ o_in_w->number = host2wire(d->number);
+ break;
+ case LAUNCH_DATA_REAL:
+ o_in_w->float_num = host2wire_f(d->float_num);
+ break;
+ case LAUNCH_DATA_BOOL:
+ o_in_w->boolean = host2wire(d->boolean);
+ break;
+ case LAUNCH_DATA_ERRNO:
+ o_in_w->err = host2wire(d->err);
+ break;
+ case LAUNCH_DATA_FD:
+ o_in_w->fd = host2wire(d->fd);
+ if (fd_where && d->fd != -1) {
+ fd_where[*fd_cnt] = d->fd;
+ (*fd_cnt)++;
+ }
+ break;
+ case LAUNCH_DATA_STRING:
+ o_in_w->string_len = host2wire(d->string_len);
+ node_data_len += ROUND_TO_64BIT_WORD_SIZE(d->string_len + 1);
+
+ if (node_data_len > len) {
+ return 0;
+ }
+ memcpy(where, d->string, d->string_len + 1);
+
+ /* Zero padded data. */
+ pad_len = ROUND_TO_64BIT_WORD_SIZE(d->string_len + 1) - (d->string_len + 1);
+ bzero(where + d->string_len + 1, pad_len);
+
+ break;
+ case LAUNCH_DATA_OPAQUE:
+ o_in_w->opaque_size = host2wire(d->opaque_size);
+ node_data_len += ROUND_TO_64BIT_WORD_SIZE(d->opaque_size);
+ if (node_data_len > len) {
+ return 0;
+ }
+ memcpy(where, d->opaque, d->opaque_size);
+
+ /* Zero padded data. */
+ pad_len = ROUND_TO_64BIT_WORD_SIZE(d->opaque_size) - d->opaque_size;
+ bzero(where + d->opaque_size, pad_len);
+
+ break;
+ case LAUNCH_DATA_DICTIONARY:
+ case LAUNCH_DATA_ARRAY:
+ o_in_w->_array_cnt = host2wire(d->_array_cnt);
+ node_data_len += d->_array_cnt * sizeof(uint64_t);
+ if (node_data_len > len) {
+ return 0;
+ }
+
+ where += d->_array_cnt * sizeof(uint64_t);
+
+ for (i = 0; i < d->_array_cnt; i++) {
+ rsz = launch_data_pack(d->_array[i], where, len - node_data_len, fd_where, fd_cnt);
+ if (rsz == 0) {
+ return 0;
+ }
+ where += rsz;
+ node_data_len += rsz;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return node_data_len;
+}
+
+launch_data_t
+launch_data_unpack(uint8_t *data, size_t data_size, int *fds, size_t fd_cnt, size_t *data_offset, size_t *fdoffset)
+{
+ launch_data_t r = (void*)(data + *data_offset);
+ size_t i, tmpcnt;
+
+ //Check for integer underflow
+ if (data_size < *data_offset)
+ return NULL;
+
+ if ((data_size - *data_offset) < sizeof(struct _launch_data))
+ return NULL;
+ *data_offset += sizeof(struct _launch_data);
+
+ switch (big2wire(r->type)) {
+ case LAUNCH_DATA_DICTIONARY:
+ case LAUNCH_DATA_ARRAY:
+ tmpcnt = big2wire(r->_array_cnt);
+
+ //Check for integer overflows
+ if (tmpcnt > SIZE_MAX / sizeof(uint64_t)) {
+ errno = EAGAIN;
+ return NULL;
+ }
+
+ if ((data_size - *data_offset) < (tmpcnt * sizeof(uint64_t))) {
+ errno = EAGAIN;
+ return NULL;
+ }
+ r->_array = (void *)(data + *data_offset);
+ *data_offset += tmpcnt * sizeof(uint64_t);
+ for (i = 0; i < tmpcnt; i++) {
+ r->_array[i] = launch_data_unpack(data, data_size, fds, fd_cnt, data_offset, fdoffset);
+ if (r->_array[i] == NULL)
+ return NULL;
+ }
+ r->_array_cnt = tmpcnt;
+ break;
+ case LAUNCH_DATA_STRING:
+ tmpcnt = big2wire(r->string_len);
+ if ((data_size - *data_offset) < (tmpcnt + 1)) {
+ errno = EAGAIN;
+ return NULL;
+ }
+ r->string = data + *data_offset;
+ r->string_len = tmpcnt;
+ *data_offset += ROUND_TO_64BIT_WORD_SIZE(tmpcnt + 1);
+ break;
+ case LAUNCH_DATA_OPAQUE:
+ tmpcnt = big2wire(r->opaque_size);
+ if ((data_size - *data_offset) < tmpcnt) {
+ errno = EAGAIN;
+ return NULL;
+ }
+ r->opaque = data + *data_offset;
+ r->opaque_size = tmpcnt;
+ *data_offset += ROUND_TO_64BIT_WORD_SIZE(tmpcnt);
+ break;
+ case LAUNCH_DATA_FD:
+ if (r->fd != -1 && fd_cnt > *fdoffset) {
+ r->fd = _fd(fds[*fdoffset]);
+ *fdoffset += 1;
+ }
+ break;
+ case LAUNCH_DATA_INTEGER:
+ r->number = big2wire(r->number);
+ break;
+ case LAUNCH_DATA_REAL:
+ r->float_num = big2wire_f(r->float_num);
+ break;
+ case LAUNCH_DATA_BOOL:
+ r->boolean = big2wire(r->boolean);
+ break;
+ case LAUNCH_DATA_ERRNO:
+ r->err = big2wire(r->err);
+ case LAUNCH_DATA_MACHPORT:
+ break;
+ default:
+ errno = EINVAL;
+ return NULL;
+ break;
+ }
+
+ r->type = big2wire(r->type);
+
+ return r;
+}
+
+int
+launchd_msg_send(launch_t lh, launch_data_t d)
+{
+ struct launch_msg_header lmh;
+ struct cmsghdr *cm = NULL;
+ struct msghdr mh;
+ struct iovec iov[2];
+ size_t sentctrllen = 0;
+ int r;
+
+ int fd2use = launchd_getfd(lh);
+ if (fd2use == -1) {
+ errno = EPERM;
+ return -1;
+ }
+
+ memset(&mh, 0, sizeof(mh));
+
+ /* confirm that the next hack works */
+ assert((d && lh->sendlen == 0) || (!d && lh->sendlen));
+
+ if (d) {
+ size_t fd_slots_used = 0;
+ size_t good_enough_size = 10 * 1024 * 1024;
+ uint64_t msglen;
+
+ /* hack, see the above assert to verify "correctness" */
+ free(lh->sendbuf);
+ lh->sendbuf = malloc(good_enough_size);
+ if (!lh->sendbuf) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ free(lh->sendfds);
+ lh->sendfds = malloc(4 * 1024);
+ if (!lh->sendfds) {
+ free(lh->sendbuf);
+ lh->sendbuf = NULL;
+ errno = ENOMEM;
+ return -1;
+ }
+
+ lh->sendlen = launch_data_pack(d, lh->sendbuf, good_enough_size, lh->sendfds, &fd_slots_used);
+
+ if (lh->sendlen == 0) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ lh->sendfdcnt = fd_slots_used;
+
+ msglen = lh->sendlen + sizeof(struct launch_msg_header); /* type promotion to make the host2wire() macro work right */
+ lmh.len = host2wire(msglen);
+ lmh.magic = host2wire(LAUNCH_MSG_HEADER_MAGIC);
+
+ iov[0].iov_base = &lmh;
+ iov[0].iov_len = sizeof(lmh);
+ mh.msg_iov = iov;
+ mh.msg_iovlen = 2;
+ } else {
+ mh.msg_iov = iov + 1;
+ mh.msg_iovlen = 1;
+ }
+
+ iov[1].iov_base = lh->sendbuf;
+ iov[1].iov_len = lh->sendlen;
+
+
+ if (lh->sendfdcnt > 0) {
+ sentctrllen = mh.msg_controllen = CMSG_SPACE(lh->sendfdcnt * sizeof(int));
+ cm = alloca(mh.msg_controllen);
+ mh.msg_control = cm;
+
+ memset(cm, 0, mh.msg_controllen);
+
+
+ cm->cmsg_len = CMSG_LEN(lh->sendfdcnt * sizeof(int));
+ cm->cmsg_level = SOL_SOCKET;
+ cm->cmsg_type = SCM_RIGHTS;
+
+ memcpy(CMSG_DATA(cm), lh->sendfds, lh->sendfdcnt * sizeof(int));
+ }
+
+ if ((r = sendmsg(fd2use, &mh, 0)) == -1) {
+ return -1;
+ } else if (r == 0) {
+ errno = ECONNRESET;
+ return -1;
+ } else if (sentctrllen != mh.msg_controllen) {
+ errno = ECONNRESET;
+ return -1;
+ }
+
+ if (d) {
+ r -= sizeof(struct launch_msg_header);
+ }
+
+ lh->sendlen -= r;
+ if (lh->sendlen > 0) {
+ memmove(lh->sendbuf, lh->sendbuf + r, lh->sendlen);
+ } else {
+ free(lh->sendbuf);
+ lh->sendbuf = malloc(0);
+ }
+
+ lh->sendfdcnt = 0;
+ free(lh->sendfds);
+ lh->sendfds = malloc(0);
+
+ if (lh->sendlen > 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+launch_get_fd(void)
+{
+ launch_globals_t globals = _launch_globals();
+ pthread_once(&globals->lc_once, launch_client_init);
+
+ if (!globals->l) {
+ errno = ENOTCONN;
+ return -1;
+ }
+
+ return globals->l->fd;
+}
+
+void
+launch_msg_getmsgs(launch_data_t m, void *context)
+{
+ launch_data_t async_resp, *sync_resp = context;
+
+ launch_globals_t globals = _launch_globals();
+
+ if ((LAUNCH_DATA_DICTIONARY == launch_data_get_type(m)) && (async_resp = launch_data_dict_lookup(m, LAUNCHD_ASYNC_MSG_KEY))) {
+ launch_data_array_set_index(globals->async_resp, launch_data_copy(async_resp), launch_data_array_get_count(globals->async_resp));
+ } else {
+ *sync_resp = launch_data_copy(m);
+ }
+}
+
+void
+launch_mach_checkin_service(launch_data_t obj, const char *key, void *context __attribute__((unused)))
+{
+ kern_return_t result;
+ mach_port_t p;
+ name_t srvnm;
+
+ strlcpy(srvnm, key, sizeof(srvnm));
+
+ result = bootstrap_check_in(bootstrap_port, srvnm, &p);
+
+ if (result == BOOTSTRAP_SUCCESS)
+ launch_data_set_machport(obj, p);
+}
+
+launch_data_t
+launch_msg(launch_data_t d)
+{
+ launch_data_t mps, r = launch_msg_internal(d);
+
+ if (launch_data_get_type(d) == LAUNCH_DATA_STRING) {
+ if (strcmp(launch_data_get_string(d), LAUNCH_KEY_CHECKIN) != 0)
+ return r;
+ if (r == NULL)
+ return r;
+ if (launch_data_get_type(r) != LAUNCH_DATA_DICTIONARY)
+ return r;
+ mps = launch_data_dict_lookup(r, LAUNCH_JOBKEY_MACHSERVICES);
+ if (mps == NULL)
+ return r;
+ launch_data_dict_iterate(mps, launch_mach_checkin_service, NULL);
+ }
+
+ return r;
+}
+
+extern kern_return_t vproc_mig_set_security_session(mach_port_t, uuid_t, mach_port_t);
+
+static inline bool
+uuid_data_is_null(launch_data_t d)
+{
+ bool result = false;
+ if (launch_data_get_type(d) == LAUNCH_DATA_OPAQUE && launch_data_get_opaque_size(d) == sizeof(uuid_t)) {
+ uuid_t existing_uuid;
+ memcpy(existing_uuid, launch_data_get_opaque(d), sizeof(uuid_t));
+
+ /* A NULL UUID tells us to keep the session inherited from the parent. */
+ result = (bool)uuid_is_null(existing_uuid);
+ }
+
+ return result;
+}
+
+launch_data_t
+launch_msg_internal(launch_data_t d)
+{
+ launch_data_t resp = NULL;
+
+#ifdef notyet
+ if (d && (launch_data_get_type(d) == LAUNCH_DATA_STRING)
+ && (strcmp(launch_data_get_string(d), LAUNCH_KEY_GETJOBS) == 0)
+ && vproc_swap_complex(NULL, VPROC_GSK_ALLJOBS, NULL, &resp) == NULL) {
+ return resp;
+ }
+#endif
+
+ launch_globals_t globals = _launch_globals();
+ pthread_once(&globals->lc_once, launch_client_init);
+ if (!globals->l) {
+ errno = ENOTCONN;
+ return NULL;
+ }
+
+ int fd2use = -1;
+ if ((launch_data_get_type(d) == LAUNCH_DATA_STRING && strcmp(launch_data_get_string(d), LAUNCH_KEY_CHECKIN) == 0) || globals->s_am_embedded_god) {
+ globals->l->which = LAUNCHD_USE_CHECKIN_FD;
+ } else {
+ globals->l->which = LAUNCHD_USE_OTHER_FD;
+ }
+
+ fd2use = launchd_getfd(globals->l);
+
+ if (fd2use == -1) {
+ errno = EPERM;
+ return NULL;
+ }
+
+#if !TARGET_OS_EMBEDDED
+ uuid_t uuid;
+ launch_data_t uuid_d = NULL;
+ size_t jobs_that_need_sessions = 0;
+ if (d && launch_data_get_type(d) == LAUNCH_DATA_DICTIONARY) {
+ launch_data_t v = launch_data_dict_lookup(d, LAUNCH_KEY_SUBMITJOB);
+
+ if (v && launch_data_get_type(v) == LAUNCH_DATA_ARRAY) {
+ size_t cnt = launch_data_array_get_count(v);
+ size_t i = 0;
+
+ uuid_generate(uuid);
+ for (i = 0; i < cnt; i++) {
+ launch_data_t ji = launch_data_array_get_index(v, i);
+ if (launch_data_get_type(ji) == LAUNCH_DATA_DICTIONARY) {
+ launch_data_t existing_v = launch_data_dict_lookup(ji, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+ if (!existing_v) {
+ /* I really wish these were reference-counted. Sigh... */
+ uuid_d = launch_data_new_opaque(uuid, sizeof(uuid));
+ launch_data_dict_insert(ji, uuid_d, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+ jobs_that_need_sessions++;
+ } else if (launch_data_get_type(existing_v) == LAUNCH_DATA_OPAQUE) {
+ jobs_that_need_sessions += uuid_data_is_null(existing_v) ? 0 : 1;
+ }
+ }
+ }
+ } else if (v && launch_data_get_type(v) == LAUNCH_DATA_DICTIONARY) {
+ launch_data_t existing_v = launch_data_dict_lookup(v, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+ if (!existing_v) {
+ uuid_generate(uuid);
+ uuid_d = launch_data_new_opaque(uuid, sizeof(uuid));
+ launch_data_dict_insert(v, uuid_d, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+ jobs_that_need_sessions++;
+ } else {
+ jobs_that_need_sessions += uuid_data_is_null(existing_v) ? 0 : 1;
+ }
+ }
+ }
+#endif
+
+ pthread_mutex_lock(&globals->lc_mtx);
+
+ if (d && launchd_msg_send(globals->l, d) == -1) {
+ do {
+ if (errno != EAGAIN)
+ goto out;
+ } while (launchd_msg_send(globals->l, NULL) == -1);
+ }
+
+ while (resp == NULL) {
+ if (d == NULL && launch_data_array_get_count(globals->async_resp) > 0) {
+ resp = launch_data_array_pop_first(globals->async_resp);
+ goto out;
+ }
+ if (launchd_msg_recv(globals->l, launch_msg_getmsgs, &resp) == -1) {
+ if (errno != EAGAIN) {
+ goto out;
+ } else if (d == NULL) {
+ errno = 0;
+ goto out;
+ } else {
+ fd_set rfds;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd2use, &rfds);
+
+ select(fd2use + 1, &rfds, NULL, NULL, NULL);
+ }
+ }
+ }
+
+out:
+#if !TARGET_OS_EMBEDDED
+ if (!uuid_is_null(uuid) && resp && jobs_that_need_sessions > 0) {
+ mach_port_t session_port = _audit_session_self();
+ launch_data_type_t resp_type = launch_data_get_type(resp);
+
+ bool set_session = false;
+ if (resp_type == LAUNCH_DATA_ERRNO) {
+ set_session = (launch_data_get_errno(resp) == ENEEDAUTH);
+ } else if (resp_type == LAUNCH_DATA_ARRAY) {
+ set_session = true;
+ }
+
+ kern_return_t kr = KERN_FAILURE;
+ if (set_session) {
+ kr = vproc_mig_set_security_session(bootstrap_port, uuid, session_port);
+ }
+
+ if (kr == KERN_SUCCESS) {
+ if (resp_type == LAUNCH_DATA_ERRNO) {
+ launch_data_set_errno(resp, 0);
+ } else {
+ size_t i = 0;
+ for (i = 0; i < launch_data_array_get_count(resp); i++) {
+ launch_data_t ri = launch_data_array_get_index(resp, i);
+
+ int recvd_err = 0;
+ if (launch_data_get_type(ri) == LAUNCH_DATA_ERRNO && (recvd_err = launch_data_get_errno(ri))) {
+ launch_data_set_errno(ri, recvd_err == ENEEDAUTH ? 0 : recvd_err);
+ }
+ }
+ }
+ }
+
+ mach_port_deallocate(mach_task_self(), session_port);
+ }
+#endif
+
+ pthread_mutex_unlock(&globals->lc_mtx);
+
+ return resp;
+}
+
+int
+launchd_msg_recv(launch_t lh, void (*cb)(launch_data_t, void *), void *context)
+{
+ struct cmsghdr *cm = alloca(4096);
+ launch_data_t rmsg = NULL;
+ size_t data_offset, fd_offset;
+ struct msghdr mh;
+ struct iovec iov;
+ int r;
+
+ printf("launchd_msg_recv(lh=%p, context=%p)\n", lh, context);
+
+ int fd2use = launchd_getfd(lh);
+ if (fd2use == -1) {
+ errno = EPERM;
+ return -1;
+ }
+
+ memset(&mh, 0, sizeof(mh));
+ mh.msg_iov = &iov;
+ mh.msg_iovlen = 1;
+
+ lh->recvbuf = reallocf(lh->recvbuf, lh->recvlen + 8*1024);
+
+ iov.iov_base = lh->recvbuf + lh->recvlen;
+ iov.iov_len = 8*1024;
+ mh.msg_control = cm;
+ mh.msg_controllen = 4096;
+
+ if ((r = recvmsg(fd2use, &mh, 0)) == -1)
+ return -1;
+ if (r == 0) {
+ errno = ECONNRESET;
+ return -1;
+ }
+ if (mh.msg_flags & MSG_CTRUNC) {
+ errno = ECONNABORTED;
+ return -1;
+ }
+ lh->recvlen += r;
+ if (mh.msg_controllen > 0) {
+ lh->recvfds = reallocf(lh->recvfds, lh->recvfdcnt * sizeof(int) + mh.msg_controllen - sizeof(struct cmsghdr));
+ memcpy(lh->recvfds + lh->recvfdcnt, CMSG_DATA(cm), mh.msg_controllen - sizeof(struct cmsghdr));
+ lh->recvfdcnt += (mh.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
+ }
+
+ r = 0;
+
+ while (lh->recvlen > 0) {
+ struct launch_msg_header *lmhp = (void *)lh->recvbuf;
+ uint64_t tmplen;
+ data_offset = sizeof(struct launch_msg_header);
+ fd_offset = 0;
+
+ if (lh->recvlen < sizeof(struct launch_msg_header))
+ goto need_more_data;
+
+ tmplen = big2wire(lmhp->len);
+
+ if (big2wire(lmhp->magic) != LAUNCH_MSG_HEADER_MAGIC || tmplen <= sizeof(struct launch_msg_header)) {
+ errno = EBADRPC;
+ goto out_bad;
+ }
+
+ if (lh->recvlen < tmplen) {
+ goto need_more_data;
+ }
+
+ if ((rmsg = launch_data_unpack(lh->recvbuf, lh->recvlen, lh->recvfds, lh->recvfdcnt, &data_offset, &fd_offset)) == NULL) {
+ errno = EBADRPC;
+ goto out_bad;
+ }
+
+ launch_globals_t globals = _launch_globals();
+
+ globals->in_flight_msg_recv_client = lh;
+
+ cb(rmsg, context);
+
+ /* launchd and only launchd can call launchd_close() as a part of the callback */
+ if (globals->in_flight_msg_recv_client == NULL) {
+ r = 0;
+ break;
+ }
+
+ lh->recvlen -= data_offset;
+ if (lh->recvlen > 0) {
+ memmove(lh->recvbuf, lh->recvbuf + data_offset, lh->recvlen);
+ } else {
+ free(lh->recvbuf);
+ lh->recvbuf = malloc(0);
+ }
+
+ lh->recvfdcnt -= fd_offset;
+ if (lh->recvfdcnt > 0) {
+ memmove(lh->recvfds, lh->recvfds + fd_offset, lh->recvfdcnt * sizeof(int));
+ } else {
+ free(lh->recvfds);
+ lh->recvfds = malloc(0);
+ }
+ }
+
+ return r;
+
+need_more_data:
+ errno = EAGAIN;
+out_bad:
+ return -1;
+}
+
+launch_data_t
+launch_data_copy(launch_data_t o)
+{
+ launch_data_t r = launch_data_alloc(o->type);
+ size_t i;
+
+ free(r->_array);
+ memcpy(r, o, sizeof(struct _launch_data));
+
+ switch (o->type) {
+ case LAUNCH_DATA_DICTIONARY:
+ case LAUNCH_DATA_ARRAY:
+ r->_array = calloc(1, o->_array_cnt * sizeof(launch_data_t));
+ for (i = 0; i < o->_array_cnt; i++) {
+ if (o->_array[i])
+ r->_array[i] = launch_data_copy(o->_array[i]);
+ }
+ break;
+ case LAUNCH_DATA_STRING:
+ r->string = strdup(o->string);
+ break;
+ case LAUNCH_DATA_OPAQUE:
+ r->opaque = malloc(o->opaque_size);
+ memcpy(r->opaque, o->opaque, o->opaque_size);
+ break;
+ default:
+ break;
+ }
+
+ return r;
+}
+
+int
+_fd(int fd)
+{
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ return fd;
+}
+
+launch_data_t
+launch_data_new_errno(int e)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_ERRNO);
+
+ if (r)
+ launch_data_set_errno(r, e);
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_fd(int fd)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_FD);
+
+ if (r)
+ launch_data_set_fd(r, fd);
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_machport(mach_port_t p)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_MACHPORT);
+
+ if (r)
+ launch_data_set_machport(r, p);
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_integer(long long n)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_INTEGER);
+
+ if (r)
+ launch_data_set_integer(r, n);
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_bool(bool b)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_BOOL);
+
+ if (r)
+ launch_data_set_bool(r, b);
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_real(double d)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_REAL);
+
+ if (r)
+ launch_data_set_real(r, d);
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_string(const char *s)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_STRING);
+
+ if (r == NULL)
+ return NULL;
+
+ if (!launch_data_set_string(r, s)) {
+ launch_data_free(r);
+ return NULL;
+ }
+
+ return r;
+}
+
+launch_data_t
+launch_data_new_opaque(const void *o, size_t os)
+{
+ launch_data_t r = launch_data_alloc(LAUNCH_DATA_OPAQUE);
+
+ if (r == NULL)
+ return NULL;
+
+ if (!launch_data_set_opaque(r, o, os)) {
+ launch_data_free(r);
+ return NULL;
+ }
+
+ return r;
+}
+
+void
+load_launchd_jobs_at_loginwindow_prompt(int flags __attribute__((unused)), ...)
+{
+ _vprocmgr_init(VPROCMGR_SESSION_LOGINWINDOW);
+}
+
+pid_t
+create_and_switch_to_per_session_launchd(const char *login __attribute__((unused)), int flags, ...)
+{
+ uid_t target_user = geteuid() ? geteuid() : getuid();
+ if (_vprocmgr_move_subset_to_user(target_user, VPROCMGR_SESSION_AQUA, flags)) {
+ return -1;
+ }
+
+ return 1;
+}
Property changes on: trunk/lib/liblaunch/liblaunch.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/libvproc.c
===================================================================
--- trunk/lib/liblaunch/libvproc.c (rev 0)
+++ trunk/lib/liblaunch/libvproc.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (c) 1999-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "config.h"
+#include "vproc.h"
+#include "vproc_priv.h"
+#include "vproc_internal.h"
+
+#include <dispatch/dispatch.h>
+#include <libproc.h>
+#include <mach/mach.h>
+#include <mach/mach_port.h>
+#include <mach/mig.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <pthread.h>
+#include <signal.h>
+#include <assert.h>
+#include <sys/syscall.h>
+#include <sys/event.h>
+#include <System/sys/fileport.h>
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+
+#include <os/assumes.h>
+
+#if HAVE_QUARANTINE
+#include <quarantine.h>
+#endif
+
+#include "launch.h"
+#include "launch_priv.h"
+#include "launch_internal.h"
+#include "ktrace.h"
+
+#include "job.h"
+
+#include "helper.h"
+#include "helperServer.h"
+
+#include "reboot2.h"
+
+#define likely(x) __builtin_expect((bool)(x), true)
+#define unlikely(x) __builtin_expect((bool)(x), false)
+
+#define _vproc_set_crash_log_message(x)
+
+void _vproc_transactions_enable_internal(void *arg);
+void _vproc_transaction_begin_internal(void *arg __unused);
+void _vproc_transaction_end_internal(void *arg __unused);
+
+#pragma mark vproc Object
+struct vproc_s {
+ int32_t refcount;
+ mach_port_t j_port;
+};
+
+vproc_t
+vprocmgr_lookup_vproc(const char *label)
+{
+ struct vproc_s *vp = NULL;
+
+ mach_port_t mp = MACH_PORT_NULL;
+ kern_return_t kr = vproc_mig_port_for_label(bootstrap_port, (char *)label, &mp);
+ if (kr == BOOTSTRAP_SUCCESS) {
+ vp = (struct vproc_s *)calloc(1, sizeof(struct vproc_s));
+ if (vp) {
+ vp->refcount = 1;
+ mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_SEND, 1);
+ vp->j_port = mp;
+ }
+ (void)mach_port_deallocate(mach_task_self(), mp);
+ }
+
+ return vp;
+}
+
+vproc_t
+vproc_retain(vproc_t vp)
+{
+ int32_t orig = atomic_fetchadd_int(&vp->refcount, 1) - 1;
+ if (orig <= 0) {
+ _vproc_set_crash_log_message("Under-retain / over-release of vproc_t.");
+ abort();
+ }
+
+ return vp;
+}
+
+void
+vproc_release(vproc_t vp)
+{
+ int32_t newval = atomic_fetchadd_int(&vp->refcount, -1);
+ if (newval < 0) {
+ _vproc_set_crash_log_message("Over-release of vproc_t.");
+ abort();
+ } else if (newval == 0) {
+ mach_port_deallocate(mach_task_self(), vp->j_port);
+ free(vp);
+ }
+}
+
+#pragma mark Transactions
+static void
+_vproc_transaction_init_once(void *arg __unused)
+{
+ launch_globals_t globals = _launch_globals();
+
+ int64_t enable_transactions = 0;
+ (void)vproc_swap_integer(NULL, VPROC_GSK_TRANSACTIONS_ENABLED, 0, &enable_transactions);
+ if (enable_transactions != 0) {
+ (void)os_assumes_zero(proc_track_dirty(getpid(), PROC_DIRTY_TRACK));
+ globals->_vproc_transaction_enabled = 1;
+ }
+ globals->_vproc_transaction_queue = dispatch_queue_create("com.apple.idle-exit-queue", NULL);
+}
+
+void
+_vproc_transactions_enable_internal(void *arg __unused)
+{
+ launch_globals_t globals = _launch_globals();
+
+ if (!globals->_vproc_transaction_enabled) {
+ (void)os_assumes_zero(proc_track_dirty(getpid(), PROC_DIRTY_TRACK));
+ globals->_vproc_transaction_enabled = 1;
+ }
+
+ if (globals->_vproc_transaction_cnt > 0) {
+ (void)os_assumes_zero(proc_set_dirty(getpid(), true));
+ }
+}
+
+void
+_vproc_transactions_enable(void)
+{
+ launch_globals_t globals = _launch_globals();
+
+ dispatch_once_f(&globals->_vproc_transaction_once, NULL, _vproc_transaction_init_once);
+ dispatch_sync_f(globals->_vproc_transaction_queue, NULL, _vproc_transactions_enable_internal);
+}
+
+void
+_vproc_transaction_begin_internal(void *ctx __unused)
+{
+ launch_globals_t globals = _launch_globals();
+
+ int64_t new = ++globals->_vproc_transaction_cnt;
+ if (!globals->_vproc_transaction_enabled || new > 1) {
+ return;
+ }
+
+ if (new < 1) {
+ _vproc_set_crash_log_message("Underflow of transaction count.");
+ abort();
+ }
+
+ (void)os_assumes_zero(proc_set_dirty(getpid(), true));
+}
+
+void
+_vproc_transaction_begin(void)
+{
+ launch_globals_t globals = _launch_globals();
+
+ dispatch_once_f(&globals->_vproc_transaction_once, NULL, _vproc_transaction_init_once);
+ dispatch_sync_f(globals->_vproc_transaction_queue, NULL, _vproc_transaction_begin_internal);
+}
+
+vproc_transaction_t
+vproc_transaction_begin(vproc_t vp __unused)
+{
+ _vproc_transaction_begin();
+
+ /* Return non-NULL on success. Originally, there were dreams of returning
+ * an object or something, but those never panned out.
+ */
+ return (vproc_transaction_t)vproc_transaction_begin;
+}
+
+void _vproc_transaction_end_flush(void);
+
+static void
+_vproc_transaction_end_internal2(void *ctx)
+{
+ launch_globals_t globals = _launch_globals();
+
+ globals->_vproc_gone2zero_callout(ctx);
+ _vproc_transaction_end_flush();
+}
+
+void
+_vproc_transaction_end_internal(void *arg)
+{
+ launch_globals_t globals = _launch_globals();
+
+ int64_t new = --globals->_vproc_transaction_cnt;
+ if (!globals->_vproc_transaction_enabled || new > 0) {
+ return;
+ }
+
+ if (new < 0) {
+ _vproc_set_crash_log_message("Underflow of transaction count.");
+ abort();
+ }
+
+ if (globals->_vproc_gone2zero_callout && !arg) {
+ globals->_vproc_transaction_cnt = 1;
+ dispatch_async_f(globals->_vproc_gone2zero_queue, globals->_vproc_gone2zero_ctx, _vproc_transaction_end_internal2);
+ } else {
+ (void)os_assumes_zero(proc_set_dirty(getpid(), false));
+ }
+}
+
+static void
+_vproc_transaction_end_flush2(void *ctx __unused)
+{
+ _vproc_transaction_end_internal((void *)1);
+}
+
+void
+_vproc_transaction_end_flush(void)
+{
+ launch_globals_t globals = _launch_globals();
+
+ dispatch_sync_f(globals->_vproc_transaction_queue, NULL, _vproc_transaction_end_flush2);
+}
+
+void
+_vproc_transaction_end(void)
+{
+ launch_globals_t globals = _launch_globals();
+
+ dispatch_once_f(&globals->_vproc_transaction_once, NULL, _vproc_transaction_init_once);
+ dispatch_sync_f(globals->_vproc_transaction_queue, NULL, _vproc_transaction_end_internal);
+}
+
+void
+vproc_transaction_end(vproc_t vp __unused, vproc_transaction_t vpt __unused)
+{
+ _vproc_transaction_end();
+}
+
+size_t
+_vproc_transaction_count(void)
+{
+ launch_globals_t globals = _launch_globals();
+
+ return globals->_vproc_transaction_cnt;
+}
+
+size_t
+_vproc_standby_count(void)
+{
+ return 0;
+}
+
+size_t
+_vproc_standby_timeout(void)
+{
+ return 0;
+}
+
+bool
+_vproc_pid_is_managed(pid_t p)
+{
+ boolean_t result = false;
+ vproc_mig_pid_is_managed(bootstrap_port, p, &result);
+
+ return result;
+}
+
+kern_return_t
+_vproc_transaction_count_for_pid(pid_t p, int32_t *count, bool *condemned)
+{
+ /* Activity Monitor relies on us returning this error code when the process
+ * is not opted into Instant Off.
+ */
+ kern_return_t error = BOOTSTRAP_NO_MEMORY;
+
+ if (condemned) {
+ *condemned = false;
+ }
+
+ if (count) {
+ uint32_t flags;
+ int ret = proc_get_dirty(p, &flags);
+ if (ret == 0) {
+ if (flags & PROC_DIRTY_TRACKED) {
+ *count = (flags & PROC_DIRTY_IS_DIRTY) ? 1 : 0;
+ error = BOOTSTRAP_SUCCESS;
+ } else {
+ error = BOOTSTRAP_NO_MEMORY;
+ }
+ } else if (ret == ENOTSUP) {
+ error = BOOTSTRAP_NO_MEMORY;
+ } else if (ret == ESRCH) {
+ error = BOOTSTRAP_UNKNOWN_SERVICE;
+ } else if (ret == EPERM) {
+ error = BOOTSTRAP_NOT_PRIVILEGED;
+ } else {
+ error = ret;
+ }
+ }
+ return error;
+}
+void
+_vproc_transaction_try_exit(int status)
+{
+#if !TARGET_OS_EMBEDDED
+ launch_globals_t globals = _launch_globals();
+ if (globals->_vproc_transaction_cnt == 0) {
+ _exit(status);
+ }
+#else
+ _exit(status);
+#endif
+}
+
+void
+_vproc_standby_begin(void)
+{
+
+}
+
+vproc_standby_t
+vproc_standby_begin(vproc_t vp __unused)
+{
+ return (vproc_standby_t)vproc_standby_begin;
+}
+
+void
+_vproc_standby_end(void)
+{
+
+}
+
+void
+_vproc_transaction_set_clean_callback(dispatch_queue_t targetq, void *ctx, dispatch_function_t func)
+{
+ launch_globals_t globals = _launch_globals();
+
+ globals->_vproc_gone2zero_queue = targetq;
+ dispatch_retain(targetq);
+
+ globals->_vproc_gone2zero_callout = func;
+ globals->_vproc_gone2zero_ctx = ctx;
+}
+
+void
+vproc_standby_end(vproc_t vp __unused, vproc_standby_t vpt __unused)
+{
+
+}
+
+#pragma mark Miscellaneous SPI
+kern_return_t
+_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright,
+ launch_data_t *outval, mach_port_array_t *ports,
+ mach_msg_type_number_t *portCnt)
+{
+ mach_msg_type_number_t outdata_cnt;
+ vm_offset_t outdata = 0;
+ size_t data_offset = 0;
+ launch_data_t out_obj;
+ kern_return_t kr;
+
+ if ((kr = vproc_mig_take_subset(bp, reqport, rcvright, &outdata, &outdata_cnt, ports, portCnt))) {
+ goto out;
+ }
+
+ if ((out_obj = launch_data_unpack((void *)outdata, outdata_cnt, NULL, 0, &data_offset, NULL))) {
+ *outval = launch_data_copy(out_obj);
+ } else {
+ kr = 1;
+ }
+
+out:
+ if (outdata) {
+ mig_deallocate(outdata, outdata_cnt);
+ }
+
+ return kr;
+}
+
+vproc_err_t
+_vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type, uint64_t flags)
+{
+ kern_return_t kr = 0;
+ bool is_bkgd = (strcmp(session_type, VPROCMGR_SESSION_BACKGROUND) == 0);
+ int64_t ldpid, lduid;
+
+ if (vproc_swap_integer(NULL, VPROC_GSK_MGR_PID, 0, &ldpid) != 0) {
+ return (vproc_err_t)_vprocmgr_move_subset_to_user;
+ }
+
+ if (vproc_swap_integer(NULL, VPROC_GSK_MGR_UID, 0, &lduid) != 0) {
+ return (vproc_err_t)_vprocmgr_move_subset_to_user;
+ }
+
+ if (!is_bkgd && ldpid != 1) {
+ if (lduid == getuid()) {
+ return NULL;
+ }
+ /*
+ * Not all sessions can be moved.
+ * We should clean up this mess someday.
+ */
+ return (vproc_err_t)_vprocmgr_move_subset_to_user;
+ }
+
+ mach_port_t puc = 0;
+ mach_port_t rootbs = MACH_PORT_NULL;
+ (void)bootstrap_get_root(bootstrap_port, &rootbs);
+
+ if (vproc_mig_lookup_per_user_context(rootbs, target_user, &puc) != 0) {
+ return (vproc_err_t)_vprocmgr_move_subset_to_user;
+ }
+
+ if (is_bkgd) {
+ task_set_bootstrap_port(mach_task_self(), puc);
+ mach_port_deallocate(mach_task_self(), bootstrap_port);
+ bootstrap_port = puc;
+ } else {
+ kr = vproc_mig_move_subset(puc, bootstrap_port, (char *)session_type, _audit_session_self(), flags);
+ mach_port_deallocate(mach_task_self(), puc);
+ }
+
+ if (kr) {
+ return (vproc_err_t)_vprocmgr_move_subset_to_user;
+ }
+
+ return _vproc_post_fork_ping();
+}
+
+vproc_err_t
+_vprocmgr_switch_to_session(const char *target_session, vproc_flags_t flags __attribute__((unused)))
+{
+ mach_port_t new_bsport = MACH_PORT_NULL;
+ kern_return_t kr = KERN_FAILURE;
+
+ mach_port_t tnp = MACH_PORT_NULL;
+ task_name_for_pid(mach_task_self(), getpid(), &tnp);
+ if ((kr = vproc_mig_switch_to_session(bootstrap_port, tnp, (char *)target_session, _audit_session_self(), &new_bsport)) != KERN_SUCCESS) {
+ _vproc_log(LOG_NOTICE, "_vprocmgr_switch_to_session(): kr = 0x%x", kr);
+ return (vproc_err_t)_vprocmgr_switch_to_session;
+ }
+
+ task_set_bootstrap_port(mach_task_self(), new_bsport);
+ mach_port_deallocate(mach_task_self(), bootstrap_port);
+ bootstrap_port = new_bsport;
+
+ return !issetugid() ? _vproc_post_fork_ping() : NULL;
+}
+
+vproc_err_t
+_vprocmgr_detach_from_console(vproc_flags_t flags __attribute__((unused)))
+{
+ return _vprocmgr_switch_to_session(VPROCMGR_SESSION_BACKGROUND, 0);
+}
+
+vproc_err_t
+_vproc_post_fork_ping(void)
+{
+ mach_port_t session = MACH_PORT_NULL;
+ kern_return_t kr = vproc_mig_post_fork_ping(bootstrap_port, mach_task_self(), &session);
+ if (kr) {
+ syslog(LOG_DEBUG, "vproc_mig_post_fork_ping kr=%x bootstrap_port=%d\n", kr, bootstrap_port);
+ return _vproc_post_fork_ping;
+ }
+
+ if (session) {
+ (void)_audit_session_join(session);
+ (void)mach_port_deallocate(mach_task_self(), session);
+ }
+
+ return NULL;
+}
+
+vproc_err_t
+_vprocmgr_init(const char *session_type)
+{
+ if (vproc_mig_init_session(bootstrap_port, (char *)session_type, _audit_session_self()) == 0) {
+ return NULL;
+ }
+
+ return (vproc_err_t)_vprocmgr_init;
+}
+
+pid_t
+_spawn_via_launchd(const char *label, const char *const *argv, const struct spawn_via_launchd_attr *spawn_attrs, int struct_version)
+{
+ size_t i, good_enough_size = 10*1024*1024;
+ mach_msg_type_number_t indata_cnt = 0;
+ vm_offset_t indata = 0;
+ mach_port_t obsvr_port = MACH_PORT_NULL;
+ launch_data_t tmp, tmp_array, in_obj;
+ const char *const *tmpp;
+ kern_return_t kr = 1;
+ void *buf = NULL;
+ pid_t p = -1;
+
+ if ((in_obj = launch_data_alloc(LAUNCH_DATA_DICTIONARY)) == NULL) {
+ goto out;
+ }
+
+ if ((tmp = launch_data_new_string(label)) == NULL) {
+ goto out;
+ }
+
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_LABEL);
+
+ if ((tmp_array = launch_data_alloc(LAUNCH_DATA_ARRAY)) == NULL) {
+ goto out;
+ }
+
+ for (i = 0; *argv; i++, argv++) {
+ tmp = launch_data_new_string(*argv);
+ if (tmp == NULL) {
+ goto out;
+ }
+
+ launch_data_array_set_index(tmp_array, tmp, i);
+ }
+
+ launch_data_dict_insert(in_obj, tmp_array, LAUNCH_JOBKEY_PROGRAMARGUMENTS);
+
+ if (spawn_attrs) switch (struct_version) {
+ case 3:
+ case 2:
+#if HAVE_QUARANTINE
+ if (spawn_attrs->spawn_quarantine) {
+ char qbuf[QTN_SERIALIZED_DATA_MAX];
+ size_t qbuf_sz = QTN_SERIALIZED_DATA_MAX;
+
+ if (qtn_proc_to_data(spawn_attrs->spawn_quarantine, qbuf, &qbuf_sz) == 0) {
+ tmp = launch_data_new_opaque(qbuf, qbuf_sz);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_QUARANTINEDATA);
+ }
+ }
+#endif
+
+ if (spawn_attrs->spawn_seatbelt_profile) {
+ tmp = launch_data_new_string(spawn_attrs->spawn_seatbelt_profile);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_SANDBOXPROFILE);
+ }
+
+ if (spawn_attrs->spawn_seatbelt_flags) {
+ tmp = launch_data_new_integer(*spawn_attrs->spawn_seatbelt_flags);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_SANDBOXFLAGS);
+ }
+
+ /* fall through */
+ case 1:
+ if (spawn_attrs->spawn_binpref) {
+ tmp_array = launch_data_alloc(LAUNCH_DATA_ARRAY);
+ for (i = 0; i < spawn_attrs->spawn_binpref_cnt; i++) {
+ tmp = launch_data_new_integer(spawn_attrs->spawn_binpref[i]);
+ launch_data_array_set_index(tmp_array, tmp, i);
+ }
+ launch_data_dict_insert(in_obj, tmp_array, LAUNCH_JOBKEY_BINARYORDERPREFERENCE);
+ }
+ /* fall through */
+ case 0:
+ if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_STOPPED) {
+ tmp = launch_data_new_bool(true);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_WAITFORDEBUGGER);
+ }
+ if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_TALAPP) {
+ tmp = launch_data_new_string(LAUNCH_KEY_POSIXSPAWNTYPE_TALAPP);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_POSIXSPAWNTYPE);
+ }
+ if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_DISABLE_ASLR) {
+ tmp = launch_data_new_bool(true);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_DISABLEASLR);
+ }
+
+ if (spawn_attrs->spawn_env) {
+ launch_data_t tmp_dict = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
+
+ for (tmpp = spawn_attrs->spawn_env; *tmpp; tmpp++) {
+ char *eqoff, tmpstr[strlen(*tmpp) + 1];
+
+ strcpy(tmpstr, *tmpp);
+
+ eqoff = strchr(tmpstr, '=');
+
+ if (!eqoff) {
+ goto out;
+ }
+
+ *eqoff = '\0';
+
+ launch_data_dict_insert(tmp_dict, launch_data_new_string(eqoff + 1), tmpstr);
+ }
+
+ launch_data_dict_insert(in_obj, tmp_dict, LAUNCH_JOBKEY_ENVIRONMENTVARIABLES);
+ }
+
+ if (spawn_attrs->spawn_path) {
+ tmp = launch_data_new_string(spawn_attrs->spawn_path);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_PROGRAM);
+ }
+
+ if (spawn_attrs->spawn_chdir) {
+ tmp = launch_data_new_string(spawn_attrs->spawn_chdir);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_WORKINGDIRECTORY);
+ }
+
+ if (spawn_attrs->spawn_umask) {
+ tmp = launch_data_new_integer(*spawn_attrs->spawn_umask);
+ launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_UMASK);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ if (!(buf = malloc(good_enough_size))) {
+ goto out;
+ }
+
+ if ((indata_cnt = launch_data_pack(in_obj, buf, good_enough_size, NULL, NULL)) == 0) {
+ goto out;
+ }
+
+ indata = (vm_offset_t)buf;
+
+ if (struct_version == 3) {
+ kr = vproc_mig_spawn2(bootstrap_port, indata, indata_cnt, _audit_session_self(), &p, &obsvr_port);
+ } else {
+ _vproc_set_crash_log_message("Bogus version passed to _spawn_via_launchd(). For this release, the only valid version is 3.");
+ }
+
+ if (kr == VPROC_ERR_TRY_PER_USER) {
+ mach_port_t puc;
+
+ if (vproc_mig_lookup_per_user_context(bootstrap_port, 0, &puc) == 0) {
+ if (struct_version == 3) {
+ kr = vproc_mig_spawn2(puc, indata, indata_cnt, _audit_session_self(), &p, &obsvr_port);
+ }
+ mach_port_deallocate(mach_task_self(), puc);
+ }
+ }
+
+out:
+ if (in_obj) {
+ launch_data_free(in_obj);
+ }
+
+ if (buf) {
+ free(buf);
+ }
+
+ switch (kr) {
+ case BOOTSTRAP_SUCCESS:
+ if (spawn_attrs && spawn_attrs->spawn_observer_port) {
+ *spawn_attrs->spawn_observer_port = obsvr_port;
+ } else {
+ if (struct_version == 3) {
+ mach_port_mod_refs(mach_task_self(), obsvr_port, MACH_PORT_RIGHT_RECEIVE, -1);
+ } else {
+ mach_port_deallocate(mach_task_self(), obsvr_port);
+ }
+ }
+ return p;
+ case BOOTSTRAP_NOT_PRIVILEGED:
+ errno = EPERM; break;
+ case BOOTSTRAP_NO_MEMORY:
+ errno = ENOMEM; break;
+ case BOOTSTRAP_NAME_IN_USE:
+ errno = EEXIST; break;
+ case 1:
+ errno = EIO; break;
+ default:
+ errno = EINVAL; break;
+ }
+
+ return -1;
+}
+
+kern_return_t
+mpm_wait(mach_port_t ajob __attribute__((unused)), int *wstatus)
+{
+ *wstatus = 0;
+ return 0;
+}
+
+kern_return_t
+mpm_uncork_fork(mach_port_t ajob __attribute__((unused)))
+{
+ return KERN_FAILURE;
+}
+
+kern_return_t
+_vprocmgr_getsocket(name_t sockpath)
+{
+ return vproc_mig_getsocket(bootstrap_port, sockpath);
+}
+
+vproc_err_t
+_vproc_get_last_exit_status(int *wstatus)
+{
+ int64_t val;
+
+ if (vproc_swap_integer(NULL, VPROC_GSK_LAST_EXIT_STATUS, 0, &val) == 0) {
+ *wstatus = (int)val;
+ return NULL;
+ }
+
+ return (vproc_err_t)_vproc_get_last_exit_status;
+}
+
+vproc_err_t
+_vproc_send_signal_by_label(const char *label, int sig)
+{
+ if (vproc_mig_send_signal(bootstrap_port, (char *)label, sig) == 0) {
+ return NULL;
+ }
+
+ return _vproc_send_signal_by_label;
+}
+
+vproc_err_t
+_vprocmgr_log_forward(mach_port_t mp, void *data, size_t len)
+{
+ if (vproc_mig_log_forward(mp, (vm_offset_t)data, len) == 0) {
+ return NULL;
+ }
+
+ return _vprocmgr_log_forward;
+}
+
+vproc_err_t
+_vprocmgr_log_drain(vproc_t vp __attribute__((unused)), pthread_mutex_t *mutex, _vprocmgr_log_drain_callback_t func)
+{
+ mach_msg_type_number_t outdata_cnt, tmp_cnt;
+ vm_offset_t outdata = 0;
+ struct timeval tv;
+ struct logmsg_s *lm;
+
+ if (!func) {
+ return _vprocmgr_log_drain;
+ }
+
+ if (vproc_mig_log_drain(bootstrap_port, &outdata, &outdata_cnt) != 0) {
+ return _vprocmgr_log_drain;
+ }
+
+ tmp_cnt = outdata_cnt;
+
+ if (mutex) {
+ pthread_mutex_lock(mutex);
+ for (lm = (struct logmsg_s *)outdata; tmp_cnt > 0; lm = (void *)((uint64_t *)lm + lm->obj_sz/8)) {
+ lm->from_name = (char *)lm + lm->from_name_offset;
+ lm->about_name = (char *)lm + lm->about_name_offset;
+ lm->msg = (char *)lm + lm->msg_offset;
+ lm->session_name = (char *)lm + lm->session_name_offset;
+
+ tv.tv_sec = lm->when / USEC_PER_SEC;
+ tv.tv_usec = lm->when % USEC_PER_SEC;
+
+ func(&tv, lm->from_pid, lm->about_pid, lm->sender_uid, lm->sender_gid, lm->pri,
+ lm->from_name, lm->about_name, lm->session_name, lm->msg);
+
+ tmp_cnt -= lm->obj_sz;
+ }
+ pthread_mutex_unlock(mutex);
+ } else {
+ /* the compiler can't tell that mutex isn't modified
+ * in the function so we duplicate :(
+ */
+ for (lm = (struct logmsg_s *)outdata; tmp_cnt > 0; lm = (void *)((uint64_t *)lm + lm->obj_sz/8)) {
+ lm->from_name = (char *)lm + lm->from_name_offset;
+ lm->about_name = (char *)lm + lm->about_name_offset;
+ lm->msg = (char *)lm + lm->msg_offset;
+ lm->session_name = (char *)lm + lm->session_name_offset;
+
+ tv.tv_sec = lm->when / USEC_PER_SEC;
+ tv.tv_usec = lm->when % USEC_PER_SEC;
+
+ func(&tv, lm->from_pid, lm->about_pid, lm->sender_uid, lm->sender_gid, lm->pri,
+ lm->from_name, lm->about_name, lm->session_name, lm->msg);
+
+ tmp_cnt -= lm->obj_sz;
+ }
+ }
+
+ if (outdata) {
+ mig_deallocate(outdata, outdata_cnt);
+ }
+
+ return NULL;
+}
+
+vproc_err_t
+vproc_swap_integer(vproc_t vp, vproc_gsk_t key, int64_t *inval, int64_t *outval)
+{
+ kern_return_t kr = KERN_FAILURE;
+ int64_t dummyval = 0;
+ mach_port_t mp = vp ? vp->j_port : bootstrap_port;
+ if ((kr = vproc_mig_swap_integer(mp, inval ? key : 0, outval ? key : 0, inval ? *inval : 0, outval ? outval : &dummyval)) == 0) {
+ switch (key) {
+ case VPROC_GSK_PERUSER_SUSPEND:
+ if (dummyval) {
+ /* Wait for the per-user launchd to exit before returning. */
+ int kq = kqueue();
+ struct kevent kev;
+ EV_SET(&kev, dummyval, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, 0);
+ int r = kevent(kq, &kev, 1, &kev, 1, NULL);
+ (void)close(kq);
+ if (r != 1) {
+ return NULL;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return NULL;
+ }
+
+ return (vproc_err_t)vproc_swap_integer;
+}
+
+vproc_err_t
+vproc_swap_complex(vproc_t vp, vproc_gsk_t key, launch_data_t inval, launch_data_t *outval)
+{
+ size_t data_offset = 0, good_enough_size = 10*1024*1024;
+ mach_msg_type_number_t indata_cnt = 0, outdata_cnt;
+ vm_offset_t indata = 0, outdata = 0;
+ launch_data_t out_obj;
+ void *rval = vproc_swap_complex;
+ void *buf = NULL;
+
+ if (inval) {
+ if (!(buf = malloc(good_enough_size))) {
+ goto out;
+ }
+
+ if ((indata_cnt = launch_data_pack(inval, buf, good_enough_size, NULL, NULL)) == 0) {
+ goto out;
+ }
+
+ indata = (vm_offset_t)buf;
+ }
+
+ mach_port_t mp = vp ? vp->j_port : bootstrap_port;
+ if (vproc_mig_swap_complex(mp, inval ? key : 0, outval ? key : 0, indata, indata_cnt, &outdata, &outdata_cnt) != 0) {
+ goto out;
+ }
+
+ if (outval) {
+ if (!(out_obj = launch_data_unpack((void *)outdata, outdata_cnt, NULL, 0, &data_offset, NULL))) {
+ goto out;
+ }
+
+ if (!(*outval = launch_data_copy(out_obj))) {
+ goto out;
+ }
+ }
+
+ rval = NULL;
+out:
+ if (buf) {
+ free(buf);
+ }
+
+ if (outdata) {
+ mig_deallocate(outdata, outdata_cnt);
+ }
+
+ return rval;
+}
+
+vproc_err_t
+vproc_swap_string(vproc_t vp, vproc_gsk_t key, const char *instr, const char **outstr)
+{
+ launch_data_t instr_data = instr ? launch_data_new_string(instr) : NULL;
+ launch_data_t outstr_data = NULL;
+
+ vproc_err_t verr = vproc_swap_complex(vp, key, instr_data, &outstr_data);
+ if (!verr && outstr) {
+ if (launch_data_get_type(outstr_data) == LAUNCH_DATA_STRING) {
+ *outstr = strdup(launch_data_get_string(outstr_data));
+ } else {
+ verr = (vproc_err_t)vproc_swap_string;
+ }
+ launch_data_free(outstr_data);
+ }
+ if (instr_data) {
+ launch_data_free(instr_data);
+ }
+
+ return verr;
+}
+
+void *
+reboot2(uint64_t flags)
+{
+ mach_port_t rootbs = MACH_PORT_NULL;
+ (void)bootstrap_get_root(bootstrap_port, &rootbs);
+ if (vproc_mig_reboot2(rootbs, flags) == 0) {
+ (void)mach_port_deallocate(mach_task_self(), rootbs);
+ return NULL;
+ }
+
+ return reboot2;
+}
+
+vproc_err_t
+_vproc_kickstart_by_label(const char *label, pid_t *out_pid,
+ mach_port_t *out_port_name __unused, mach_port_t *out_obsrvr_port __unused,
+ vproc_flags_t flags)
+{
+ /* Ignore the two port parameters. This SPI isn't long for this world, and
+ * all the current clients just leak them anyway.
+ */
+ kern_return_t kr = vproc_mig_kickstart(bootstrap_port, (char *)label, out_pid, flags);
+ if (kr == KERN_SUCCESS) {
+ return NULL;
+ }
+
+ return (vproc_err_t)_vproc_kickstart_by_label;
+}
+
+vproc_err_t
+_vproc_set_global_on_demand(bool state)
+{
+ int64_t val = state ? ~0 : 0;
+
+ if (vproc_swap_integer(NULL, VPROC_GSK_GLOBAL_ON_DEMAND, &val, NULL) == 0) {
+ return NULL;
+ }
+
+ return (vproc_err_t)_vproc_set_global_on_demand;
+}
+
+void
+_vproc_logv(int pri, int err, const char *msg, va_list ap)
+{
+ char flat_msg[3000];
+
+ vsnprintf(flat_msg, sizeof(flat_msg), msg, ap);
+
+ vproc_mig_log(bootstrap_port, pri, err, flat_msg);
+}
+
+void
+_vproc_log(int pri, const char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ _vproc_logv(pri, 0, msg, ap);
+ va_end(ap);
+}
+
+void
+_vproc_log_error(int pri, const char *msg, ...)
+{
+ int saved_errno = errno;
+ va_list ap;
+
+ va_start(ap, msg);
+ _vproc_logv(pri, saved_errno, msg, ap);
+ va_end(ap);
+}
+
+/* The type naming convention is as follows:
+ * For requests...
+ * union __RequestUnion__<userprefix><subsystem>_subsystem
+ * For replies...
+ * union __ReplyUnion__<userprefix><subsystem>_subsystem
+ */
+union maxmsgsz {
+ union __RequestUnion__helper_downcall_launchd_helper_subsystem req;
+ union __ReplyUnion__helper_downcall_launchd_helper_subsystem rep;
+};
+
+static const size_t vprocmgr_helper_maxmsgsz = sizeof(union maxmsgsz);
+
+kern_return_t
+helper_recv_wait(mach_port_t p, int status)
+{
+#if __LAUNCH_MACH_PORT_CONTEXT_T_DEFINED__
+ mach_port_context_t ctx = status;
+#else
+ mach_vm_address_t ctx = status;
+#endif
+
+ return (errno = mach_port_set_context(mach_task_self(), p, ctx));
+}
+
+int
+launch_wait(mach_port_t port)
+{
+ int status = -1;
+ errno = mach_msg_server_once(launchd_helper_server, vprocmgr_helper_maxmsgsz, port, 0);
+ if (errno == MACH_MSG_SUCCESS) {
+#if __LAUNCH_MACH_PORT_CONTEXT_T_DEFINED__
+ mach_port_context_t ctx = 0;
+#else
+ mach_vm_address_t ctx = 0;
+#endif
+ if ((errno = mach_port_get_context(mach_task_self(), port, &ctx)) == KERN_SUCCESS) {
+ status = ctx;
+ }
+ }
+
+ return status;
+}
+
+#ifndef __FreeBSD__
+launch_data_t
+launch_socket_service_check_in(void)
+{
+ launch_data_t reply = NULL;
+
+ size_t big_enough = 10 * 1024;
+ void *buff = malloc(big_enough);
+ if (buff) {
+ launch_data_t req = launch_data_new_string(LAUNCH_KEY_CHECKIN);
+ if (req) {
+ size_t sz = launch_data_pack(req, buff, big_enough, NULL, NULL);
+ if (sz) {
+ vm_address_t sreply = 0;
+ mach_msg_size_t sreplyCnt = 0;
+ mach_port_array_t fdps = NULL;
+ mach_msg_size_t fdpsCnt = 0;
+ kern_return_t kr = vproc_mig_legacy_ipc_request(bootstrap_port, (vm_address_t)buff, sz, NULL, 0, &sreply, &sreplyCnt, &fdps, &fdpsCnt, _audit_session_self());
+ if (kr == BOOTSTRAP_SUCCESS) {
+ int fds[128];
+
+ size_t i = 0;
+ size_t nfds = fdpsCnt / sizeof(fdps[0]);
+ for (i = 0; i < nfds; i++) {
+ fds[i] = fileport_makefd(fdps[i]);
+ (void)mach_port_deallocate(mach_task_self(), fdps[i]);
+ }
+
+ size_t dataoff = 0;
+ size_t fdoff = 0;
+ reply = launch_data_unpack((void *)sreply, sreplyCnt, fds, nfds, &dataoff, &fdoff);
+ reply = launch_data_copy(reply);
+
+ mig_deallocate(sreply, sreplyCnt);
+ mig_deallocate((vm_address_t)fdps, fdpsCnt);
+ }
+ }
+
+ launch_data_free(req);
+ }
+
+ free(buff);
+ }
+
+ return reply;
+}
+#endif
Property changes on: trunk/lib/liblaunch/libvproc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/reboot2.h
===================================================================
--- trunk/lib/liblaunch/reboot2.h (rev 0)
+++ trunk/lib/liblaunch/reboot2.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __REBOOT2_H__
+#define __REBOOT2_H__
+
+#include <sys/cdefs.h>
+#include <sys/reboot.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+#define RB2_FULLREBOOT 0x8000000000000000llu
+
+/* Returns NULL on success. Not NULL on failure */
+
+__attribute__((visibility("default")))
+void *reboot2(uint64_t flags);
+
+__END_DECLS
+
+#endif /* __REBOOT2_H__ */
Property changes on: trunk/lib/liblaunch/reboot2.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/vproc.h
===================================================================
--- trunk/lib/liblaunch/vproc.h (rev 0)
+++ trunk/lib/liblaunch/vproc.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __VPROC_H__
+#define __VPROC_H__
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <Availability.h>
+
+#ifndef VPROC_HAS_TRANSACTIONS
+ #define VPROC_HAS_TRANSACTIONS
+#endif
+
+__BEGIN_DECLS
+
+#pragma GCC visibility push(default)
+
+typedef void * vproc_err_t;
+
+typedef struct vproc_s * vproc_t;
+typedef void * vprocmgr_t;
+
+const char *vproc_strerror(vproc_err_t r);
+
+/*!
+ * @header vproc
+ *
+ * Processes have two reference counts associated with them:
+ *
+ * Transactions Tracks unfinished work. For example: saving a modified
+ * document.
+ * Standby Tracks outstanding callbacks from external subsystems.
+ *
+ * Descriptive aliases:
+ *
+ * A process with no outstanding transactions is called "clean."
+ * A process with outstanding transactions is called "dirty."
+ * A process with no standby work is called "idle."
+ *
+ * Sometimes, the operating system needs processes to exit. Unix has two
+ * primary signals to kill applications:
+ *
+ * SIGKILL Not catchable by the application.
+ * SIGTERM Catchable by the application.
+ *
+ * If a process is clean, the operating system is free to SIGKILL it at
+ * shutdown or logout. This behavior is opt in.
+ *
+ * If a process is clean and idle, the operating system may send SIGKILL after
+ * a application specified timeout. This behavior is opt in.
+ *
+ * If a process is dirty and idle, the operating system may send SIGTERM after
+ * a application specified timeout. This behavior is opt in.
+ *
+ *
+ * launchd jobs should update their property lists accordingly.
+ *
+ * We plan to have LaunchServices use private methods to coordinate
+ * whether GUI applications have opted into this design.
+ */
+
+/*!
+ * @typedef vproc_transaction_t
+ *
+ * @abstract
+ * An opaque handle used to track outstanding transactions.
+ */
+typedef struct vproc_transaction_s *vproc_transaction_t;
+
+/*!
+ * @function vproc_transaction_begin
+ *
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
+ * @result
+ * Returns an opaque handle to be passed to vproc_transaction_end().
+ *
+ * @abstract
+ * Call this API before creating data that needs to be saved via I/O later.
+ */
+vproc_transaction_t
+vproc_transaction_begin(vproc_t virtual_proc) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0);
+
+/*!
+ * @function vproc_transaction_end
+ *
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
+ * @param handle
+ * The handle previously created with vproc_transaction_begin().
+ *
+ * @abstract
+ * Call this API after the data has either been flushed or otherwise resolved.
+ *
+ * @discussion
+ * Calling this API with the same handle more than once is undefined.
+ */
+void
+vproc_transaction_end(vproc_t virtual_proc, vproc_transaction_t handle) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0);
+
+/*!
+ * @typedef vproc_standby_t
+ *
+ * @abstract
+ * An opaque handle used to track outstanding standby requests.
+ */
+typedef struct vproc_standby_s *vproc_standby_t;
+
+/*!
+ * @function vproc_standby_begin
+ *
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
+ * @result
+ * Returns an opaque handle to be passed to vproc_standby_end().
+ *
+ * @abstract
+ * Call this API before registering notifications. For example: timers network
+ * state change, or when monitoring keyboard/mouse events.
+ *
+ * @discussion
+ * This API is undefined and is currently a no-op.
+ */
+vproc_standby_t
+vproc_standby_begin(vproc_t virtual_proc) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_NA);
+
+/*!
+ * @function vproc_standby_end
+ *
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
+ * @param handle
+ * The handle previously created with vproc_standby_begin().
+ *
+ * @abstract
+ * Call this API when deregistering notifications.
+ *
+ * @discussion
+ * Calling this API with the same handle more than once is undefined.
+ * This API is undefined and is currently a no-op.
+ */
+void
+vproc_standby_end(vproc_t virtual_proc, vproc_standby_t handle) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_NA);
+
+#pragma GCC visibility pop
+
+__END_DECLS
+
+#endif /* __VPROC_H__ */
Property changes on: trunk/lib/liblaunch/vproc.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/vproc_internal.h
===================================================================
--- trunk/lib/liblaunch/vproc_internal.h (rev 0)
+++ trunk/lib/liblaunch/vproc_internal.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __VPROC_INTERNAL_H__
+#define __VPROC_INTERNAL_H__
+
+#include <mach/mach.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+#include <stdarg.h>
+#include <sys/syscall.h>
+#include <bsm/audit.h>
+#include "launch.h"
+#include "bootstrap_priv.h"
+#include "vproc.h"
+
+typedef char * _internal_string_t;
+typedef char * logmsg_t;
+typedef pid_t * pid_array_t;
+typedef mach_port_t vproc_mig_t;
+
+#if defined(job_MSG_COUNT) || defined (xpc_domain_MSG_COUNT)
+/* HACK */
+#include "core.h"
+#endif
+
+#define VPROC_ERR_TRY_PER_USER 1099
+
+#pragma GCC visibility push(default)
+
+vproc_err_t _vprocmgr_init(const char *session_type);
+vproc_err_t _vproc_post_fork_ping(void);
+
+#if !TARGET_OS_EMBEDDED
+#define _audit_session_self(v) (mach_port_t)syscall(SYS_audit_session_self)
+#define _audit_session_join(s) (au_asid_t)syscall(SYS_audit_session_join, session)
+#else
+#define _audit_session_self(v) MACH_PORT_NULL
+#define _audit_session_join(s) 0
+#endif
+
+#define __LAUNCH_MACH_PORT_CONTEXT_T_DEFINED__ 0
+
+#define SPAWN_HAS_PATH 0x0001
+#define SPAWN_HAS_WDIR 0x0002
+#define SPAWN_HAS_UMASK 0x0004
+#define SPAWN_WANTS_WAIT4DEBUGGER 0x0008
+
+kern_return_t
+_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright, launch_data_t *outval,
+ mach_port_array_t *ports, mach_msg_type_number_t *portCnt);
+
+kern_return_t _vprocmgr_getsocket(name_t);
+
+struct logmsg_s {
+ union {
+ STAILQ_ENTRY(logmsg_s) sqe;
+ uint64_t __pad;
+ };
+ int64_t when;
+ pid_t from_pid;
+ pid_t about_pid;
+ uid_t sender_uid;
+ gid_t sender_gid;
+ int err_num;
+ int pri;
+ union {
+ const char *from_name;
+ uint64_t from_name_offset;
+ };
+ union {
+ const char *about_name;
+ uint64_t about_name_offset;
+ };
+ union {
+ const char *session_name;
+ uint64_t session_name_offset;
+ };
+ union {
+ const char *msg;
+ uint64_t msg_offset;
+ };
+ uint64_t obj_sz;
+ char data[0];
+};
+
+
+vproc_err_t _vprocmgr_log_forward(mach_port_t mp, void *data, size_t len);
+
+kern_return_t
+bootstrap_info(mach_port_t bp,
+ name_array_t *service_names,
+ mach_msg_type_number_t *service_namesCnt,
+ name_array_t *service_jobs,
+ mach_msg_type_number_t *service_jobsCnt,
+ bootstrap_status_array_t *service_active,
+ mach_msg_type_number_t *service_activeCnt,
+ uint64_t flags);
+
+#pragma GCC visibility pop
+
+#endif /* __VPROC_INTERNAL_H__ */
Property changes on: trunk/lib/liblaunch/vproc_internal.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/liblaunch/vproc_priv.h
===================================================================
--- trunk/lib/liblaunch/vproc_priv.h (rev 0)
+++ trunk/lib/liblaunch/vproc_priv.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __VPROC_PRIVATE_H__
+#define __VPROC_PRIVATE_H__
+
+#include <Availability.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/syslog.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include <launch.h>
+#include <vproc.h>
+#include <uuid/uuid.h>
+#include <servers/bootstrap.h>
+#include <dispatch/dispatch.h>
+
+#ifndef VPROC_HAS_TRANSACTIONS
+#define VPROC_HAS_TRANSACTIONS 1
+#endif
+
+__BEGIN_DECLS
+
+#define VPROCMGR_SESSION_LOGINWINDOW "LoginWindow"
+#define VPROCMGR_SESSION_BACKGROUND "Background"
+#define VPROCMGR_SESSION_AQUA "Aqua"
+#define VPROCMGR_SESSION_STANDARDIO "StandardIO"
+#define VPROCMGR_SESSION_SYSTEM "System"
+
+#define XPC_DOMAIN_TYPE_SYSTEM "XPCSystem"
+#define XPC_DOMAIN_TYPE_PERUSER "XPCPerUser"
+#define XPC_DOMAIN_TYPE_PERSESSION "XPCPerSession"
+#define XPC_DOMAIN_TYPE_PERAPPLICATION "XPCPerApplication"
+
+#pragma GCC visibility push(default)
+
+/* DO NOT use this. This is a hack for 'launchctl' */
+#define VPROC_MAGIC_UNLOAD_SIGNAL 0x4141504C
+
+typedef void (*_vproc_transaction_callout)(void *);
+
+typedef enum {
+ VPROC_GSK_ZERO,
+ VPROC_GSK_LAST_EXIT_STATUS,
+ VPROC_GSK_GLOBAL_ON_DEMAND,
+ VPROC_GSK_MGR_UID,
+ VPROC_GSK_MGR_PID,
+ VPROC_GSK_IS_MANAGED,
+ VPROC_GSK_MGR_NAME,
+ VPROC_GSK_BASIC_KEEPALIVE,
+ VPROC_GSK_START_INTERVAL,
+ VPROC_GSK_IDLE_TIMEOUT,
+ VPROC_GSK_EXIT_TIMEOUT,
+ VPROC_GSK_ENVIRONMENT,
+ VPROC_GSK_ALLJOBS,
+ VPROC_GSK_GLOBAL_LOG_MASK,
+ VPROC_GSK_GLOBAL_UMASK,
+ VPROC_GSK_ABANDON_PROCESS_GROUP,
+ VPROC_GSK_TRANSACTIONS_ENABLED,
+ VPROC_GSK_WEIRD_BOOTSTRAP,
+ VPROC_GSK_WAITFORDEBUGGER,
+ VPROC_GSK_SECURITYSESSION,
+ VPROC_GSK_SHUTDOWN_DEBUGGING,
+ VPROC_GSK_VERBOSE_BOOT,
+ VPROC_GSK_PERUSER_SUSPEND,
+ VPROC_GSK_PERUSER_RESUME,
+ VPROC_GSK_JOB_OVERRIDES_DB,
+ VPROC_GSK_JOB_CACHE_DB,
+ VPROC_GSK_EMBEDDEDROOTEQUIVALENT,
+} vproc_gsk_t;
+
+typedef unsigned int vproc_flags_t;
+/* For _vproc_kickstart_by_label() -- instructs launchd to kickstart the job to stall before exec(2). */
+#define VPROCFLAG_STALL_JOB_EXEC 1 << 1
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+vproc_t
+vprocmgr_lookup_vproc(const char *label);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+vproc_t
+vproc_retain(vproc_t vp);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+void
+vproc_release(vproc_t vp);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0)
+vproc_err_t
+vproc_swap_integer(vproc_t vp, vproc_gsk_t key,
+ int64_t *inval, int64_t *outval);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0)
+vproc_err_t
+vproc_swap_complex(vproc_t vp, vproc_gsk_t key,
+ launch_data_t inval, launch_data_t *outval);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_4_0)
+vproc_err_t
+vproc_swap_string(vproc_t vp, vproc_gsk_t key,
+ const char *instr, const char **outstr);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA)
+vproc_err_t
+_vproc_get_last_exit_status(int *wstatus);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0)
+vproc_err_t
+_vproc_set_global_on_demand(bool val);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0)
+vproc_err_t
+_vproc_send_signal_by_label(const char *label, int sig);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_3_0)
+vproc_err_t
+_vproc_kickstart_by_label(const char *label, pid_t *out_pid,
+ mach_port_t *out_port_name, mach_port_t *out_obsrvr_port,
+ vproc_flags_t flags);
+
+/* _vprocmgr_log_drain() is specific to syslogd. It is not for general use. */
+typedef void (*_vprocmgr_log_drain_callback_t)(struct timeval *when, pid_t
+ from_pid, pid_t about_pid, uid_t sender_uid, gid_t sender_gid, int priority,
+ const char *from_name, const char *about_name, const char *session_name,
+ const char *msg);
+
+vproc_err_t
+_vprocmgr_log_drain(vproc_t vp, pthread_mutex_t *optional_mutex_around_callback,
+ _vprocmgr_log_drain_callback_t func);
+
+__attribute__((format(printf, 2, 3)))
+void
+_vproc_log(int pri, const char *msg, ...);
+
+__attribute__((format(printf, 2, 3)))
+void
+_vproc_log_error(int pri, const char *msg, ...);
+
+__attribute__((format(printf, 3, 0)))
+void
+_vproc_logv(int pri, int err, const char *msg, va_list ap);
+
+/* One day, we'll be able to get rid of this... */
+vproc_err_t
+_vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type,
+ uint64_t flags);
+
+vproc_err_t
+_vprocmgr_switch_to_session(const char *target_session, vproc_flags_t flags);
+
+vproc_err_t
+_vprocmgr_detach_from_console(vproc_flags_t flags);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+void
+_vproc_standby_begin(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+void
+_vproc_standby_end(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+size_t
+_vproc_standby_count(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+size_t
+_vproc_standby_timeout(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+kern_return_t
+_vproc_transaction_count_for_pid(pid_t p, int32_t *count, bool *condemned);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+bool
+_vproc_pid_is_managed(pid_t p);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+void
+_vproc_transaction_try_exit(int status);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0)
+void
+_vproc_transaction_begin(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0)
+void
+_vproc_transaction_end(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA)
+size_t
+_vproc_transaction_count(void);
+
+void
+_vproc_transaction_set_clean_callback(dispatch_queue_t targetq, void *ctx,
+ dispatch_function_t func);
+
+void
+_vproc_transactions_enable(void);
+
+#pragma GCC visibility pop
+
+__END_DECLS
+
+#endif /* __VPROC_PRIVATE_H__ */
Property changes on: trunk/lib/liblaunch/vproc_priv.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/Makefile
===================================================================
--- trunk/lib/libmach/Makefile (rev 0)
+++ trunk/lib/libmach/Makefile 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,73 @@
+# $MidnightBSD$
+
+.include <bsd.init.mk>
+
+LIB= mach
+
+
+A= ${.CURDIR}/${MACHINE_CPUARCH}
+H= ${.CURDIR}/../../include/mach
+DEFS=${.CURDIR}/../../sys/compat/mach/defs
+
+
+.PATH: ${.CURDIR}/mach
+.PATH: ${A}
+.PATH: ${A}/sys
+
+.for _dir in ${.CURDIR}/../.. ${.CURDIR}/../../sys ${.CURDIR}/../../.. /sys /usr/src/sys
+.if !defined(SYSDIR) && exists(${_dir}/kern/)
+SYSDIR= ${_dir}
+.endif
+.endfor
+.if !defined(SYSDIR) || !exists(${SYSDIR}/kern/)
+.error "can't find kernel source tree"
+.endif
+
+CFLAGS+= -I${.CURDIR}/../../include -I. -I${A} -I${.CURDIR} -I./include
+CFLAGS+= -I${SYSDIR} -I${.CURDIR}/../../apsl/include -I${MACHINE_INCLUDES}
+CFLAGS+= -fPIC -DPRIVATE -D__MigTypeCheck=1 -DLIBSYSCALL_INTERFACE=1
+DEBUG_FLAGS= -g -O0
+mach_port.h mach_portUser.c: ${DEFS}/mach_port.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/mach_port.defs
+ cp mach_port.h ${H}/mach_port.h
+task.h taskUser.c: ${DEFS}/task.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/task.defs
+ cp task.h ${H}/task.h
+host_priv.h host_privUser.c: ${DEFS}/host_priv.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/host_priv.defs
+ cp host_priv.h ${H}/host_priv.h
+mach_host.h mach_hostUser.c: ${DEFS}/mach_host.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/mach_host.defs
+ cp mach_host.h ${H}/mach_host.h
+vm_map.h vm_mapUser.c: ${DEFS}/vm_map.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/vm_map.defs
+ cp vm_map.h ${H}/vm_map.h
+mach_vm.h mach_vmUser.c: ${DEFS}/mach_vm.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/mach_vm.defs
+ cp mach_vm.h ${H}/mach_vm.h
+clock.h clockUser.c: ${DEFS}/clock.defs
+ mig ${CFLAGS} -server /dev/null ${DEFS}/clock.defs
+ cp clock.h ${H}/clock.h
+SRCS= \
+ clockUser.c \
+ mach_portUser.c \
+ taskUser.c \
+ host_privUser.c \
+ mach_hostUser.c \
+ vm_mapUser.c \
+ mach_vmUser.c \
+ error_codes.c \
+ mach_error_string.c \
+ mach_init.c \
+ mach_msg.c \
+ mach_misc.c \
+ mig_allocate.c \
+ mig_deallocate.c \
+ mig_reply_setup.c \
+ mig_strncpy.c \
+ mig_support.c
+
+CLEANFILES+= machine *~ mach_port.h task.h host_priv.h mach_host.h
+CLEANFILES+= cscope.* vm_map.h *User.c
+
+.include <bsd.lib.mk>
Property changes on: trunk/lib/libmach/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/err_ipc.sub
===================================================================
--- trunk/lib/libmach/mach/err_ipc.sub (rev 0)
+++ trunk/lib/libmach/mach/err_ipc.sub 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,117 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * File: err_ipc.sub
+ * Author: Douglas Orr, Carnegie Mellon University
+ * Date: Mar, 1988
+ *
+ * Definitions of error strings for original IPC
+ */
+
+static const char * err_codes_send[] = {
+ "(ipc/send) unknown error", /* -100 */
+ "(ipc/send) invalid memory", /* -101 */
+ "(ipc/send) invalid port", /* -102 */
+ "(ipc/send) timed out", /* -103 */
+ "(ipc/send) unused error", /* -104 */
+ "(ipc/send) will notify", /* -105 */
+ "(ipc/send) notify in progress", /* -106 */
+ "(ipc/send) kernel refused message", /* -107 */
+ "(ipc/send) send interrupted", /* -108 */
+ "(ipc/send) send message too large", /* -109 */
+ "(ipc/send) send message too small", /* -110 */
+ "(ipc/send) message size changed while being copied", /* -111 */
+};
+
+static const char * err_codes_rcv[] = {
+ "(ipc/rcv) unknown error", /* -200 */
+ "(ipc/rcv) invalid memory", /* -201 */
+ "(ipc/rcv) invalid port", /* -202 */
+ "(ipc/rcv) receive timed out", /* -203 */
+ "(ipc/rcv) message too large", /* -204 */
+ "(ipc/rcv) no space for message data", /* -205 */
+ "(ipc/rcv) only sender remaining", /* -206 */
+ "(ipc/rcv) receive interrupted", /* -207 */
+ "(ipc/rcv) port receiver changed or port became enabled", /* -208 */
+};
+
+static const char * err_codes_mig[] = {
+ "(ipc/mig) type check failure in message interface", /* 0 (-300) */
+ "(ipc/mig) wrong return message ID", /* 1 */
+ "(ipc/mig) server detected error", /* 2 */
+ "(ipc/mig) bad message ID", /* 3 */
+ "(ipc/mig) server found wrong arguments", /* 4 */
+ "(ipc/mig) no reply should be sent", /* 5 */
+ "(ipc/mig) server raised exception", /* 6 */
+ "(ipc/mig) user specified array not large enough for return info", /* 7 */
+};
+
+/* err_ipc subsystems */
+static struct error_subsystem err_ipc_sub[] = {
+ /* ipc/0; */
+ {
+ "(ipc/send)",
+ errlib_count(err_codes_send),
+ err_codes_send,
+ },
+ /* ipc/1; */
+ {
+ "(ipc/rcv)",
+ errlib_count(err_codes_rcv),
+ err_codes_rcv,
+
+ },
+ /* ipc/2 */
+ {
+ "(ipc/mig)",
+ errlib_count(err_codes_mig),
+ err_codes_mig,
+ },
+
+};
Added: trunk/lib/libmach/mach/err_kern.sub
===================================================================
--- trunk/lib/libmach/mach/err_kern.sub (rev 0)
+++ trunk/lib/libmach/mach/err_kern.sub 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,202 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * File: err_kern.sub
+ * Author: Douglas Orr, Carnegie Mellon University
+ * Date: Mar, 1988
+ *
+ * error codes for Mach and Unix kernels
+ */
+
+static const char * err_codes_kern[] = {
+ "(os/kern) successful", /* 0 */
+ "(os/kern) invalid address",
+ "(os/kern) protection failure",
+ "(os/kern) no space available",
+ "(os/kern) invalid argument",
+ "(os/kern) failure", /* 5 */
+ "(os/kern) resource shortage",
+ "(os/kern) not receiver",
+ "(os/kern) no access",
+ "(os/kern) memory failure",
+ "(os/kern) memory error", /* 10 */
+ "(os/kern) already in set",
+ "(os/kern) not in set",
+ "(os/kern) name exists",
+ "(os/kern) aborted",
+ "(os/kern) invalid name", /* 15 */
+ "(os/kern) invalid task",
+ "(os/kern) invalid right",
+ "(os/kern) invalid value",
+ "(os/kern) urefs overflow",
+ "(os/kern) invalid capability", /* 20 */
+ "(os/kern) right exists",
+ "(os/kern) invalid host",
+ "(os/kern) memory present",
+ "(os/kern) memory data moved",
+ "(os/kern) memory restart copy", /* 25 */
+ "(os/kern) invalid processor set",
+ "(os/kern) policy limit",
+ "(os/kern) invalid policy",
+ "(os/kern) invalid object",
+ "(os/kern) already waiting", /* 30 */
+ "(os/kern) default set",
+ "(os/kern) exception protected",
+ "(os/kern) invalid ledger",
+ "(os/kern) invalid memory control",
+ "(os/kern) invalid security", /* 35 */
+ "(os/kern) not depressed",
+ "(os/kern) object terminated",
+ "(os/kern) lock set destroyed",
+ "(os/kern) lock unstable",
+ "(os/kern) lock owned by another", /* 40 */
+ "(os/kern) lock owned by self",
+ "(os/kern) semaphore destroyed",
+ "(os/kern) RPC terminated",
+ "(os/kern) terminate orphan",
+ "(os/kern) let orphan continue", /* 45 */
+ "(os/kern) empty thread activation",
+ "(os/kern) remote node down",
+};
+
+static const char * err_codes_unix[] = {
+ NO_SUCH_ERROR,
+ "(os/unix) no rights to object",
+ "(os/unix) file or directory does not exist",
+ "(os/unix) no such process",
+ "(os/unix) interrupted system call",
+ "(os/unix) i/o error",
+ "(os/unix) device does not exist",
+ "(os/unix) argument list is too long",
+ "(os/unix) invalid executable object format",
+ "(os/unix) bad file descriptor number",
+ "(os/unix) no child processes are present",
+ "(os/unix) no more processes are available",
+ "(os/unix) insufficient memory",
+ "(os/unix) access denied",
+ "(os/unix) memory access fault",
+ "(os/unix) block device required for operation",
+ "(os/unix) mount device busy",
+ "(os/unix) file already exists",
+ "(os/unix) cross device link",
+ "(os/unix) device does not exist",
+ "(os/unix) object is not a directory",
+ "(os/unix) object is a directory",
+ "(os/unix) invalid argument",
+ "(os/unix) internal file table overflow",
+ "(os/unix) maximum number of open files reached",
+ "(os/unix) object is not a tty-like device",
+ "(os/unix) executable object is in use",
+ "(os/unix) file is too large",
+ "(os/unix) no space is left on device",
+ "(os/unix) illegal seek attempt",
+ "(os/unix) read-only file system",
+ "(os/unix) too many links",
+ "(os/unix) broken pipe",
+ "(os/unix) argument is too large",
+ "(os/unix) result is out of range",
+ "(os/unix) operation on device would block",
+ "(os/unix) operation is now in progress",
+ "(os/unix) operation is already in progress",
+ "(os/unix) socket operation attempted on non-socket object",
+ "(os/unix) destination address is required",
+ "(os/unix) message is too long",
+ "(os/unix) protocol type is incorrect for socket",
+ "(os/unix) protocol type is not availaible",
+ "(os/unix) protocol type is not supported",
+ "(os/unix) socket type is not supported",
+ "(os/unix) operation is not supported on sockets",
+ "(os/unix) protocol family is not supported",
+ "(os/unix) address family is not supported by protocol family",
+ "(os/unix) address is already in use",
+ "(os/unix) can't assign requested address",
+ "(os/unix) network is down",
+ "(os/unix) network is unreachable",
+ "(os/unix) network dropped connection on reset",
+ "(os/unix) software aborted connection",
+ "(os/unix) connection reset by peer",
+ "(os/unix) no buffer space is available",
+ "(os/unix) socket is already connected",
+ "(os/unix) socket is not connected",
+ "(os/unix) can't send after socket shutdown",
+ "(os/unix) too many references; can't splice",
+ "(os/unix) connection timed out",
+ "(os/unix) connection was refused",
+ "(os/unix) too many levels of symbolic links",
+ "(os/unix) file name exceeds system maximum limit",
+ "(os/unix) host is down",
+ "(os/unix) there is no route to host",
+ "(os/unix) directory is not empty",
+ "(os/unix) quota on number of processes exceeded",
+ "(os/unix) quota on number of users exceeded",
+ "(os/unix) quota on available disk space exceeded",
+};
+
+static struct error_subsystem err_os_sub[] = {
+ {
+ "(os/kern)",
+ errlib_count(err_codes_kern),
+ err_codes_kern,
+ },
+ {
+ "(os/?)",
+ 0,
+ 0,
+ },
+ {
+ "(os/?)",
+ 0,
+ 0,
+ },
+ {
+ "(os/unix)",
+ errlib_count(err_codes_unix),
+ err_codes_unix,
+ },
+};
Added: trunk/lib/libmach/mach/err_mach_ipc.sub
===================================================================
--- trunk/lib/libmach/mach/err_mach_ipc.sub (rev 0)
+++ trunk/lib/libmach/mach/err_mach_ipc.sub 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,137 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * File: err_mach_ipc.sub
+ * Author: Richard Draves, Carnegie Mellon University
+ * Date: Jan, 1990
+ *
+ * Error string definitions for the new Mach IPC
+ */
+
+static const char * err_codes_mach_send[] = {
+ /* 0 */ "(ipc/send) no error",
+ /* 1 */ "(ipc/send) send in progress",
+ /* 2 */ "(ipc/send) invalid data",
+ /* 3 */ "(ipc/send) invalid destination port",
+ /* 4 */ "(ipc/send) timed out",
+ /* 5 */ "(ipc/send) will notify",
+ /* 6 */ "(ipc/send) notify in progress",
+ /* 7 */ "(ipc/send) interrupted",
+ /* 8 */ "(ipc/send) msg too small",
+ /* 9 */ "(ipc/send) invalid reply port",
+ /* 10 */ "(ipc/send) invalid port right",
+ /* 11 */ "(ipc/send) invalid notify port",
+ /* 12 */ "(ipc/send) invalid memory",
+ /* 13 */ "(ipc/send) no msg buffer",
+ /* 14 */ "(ipc/send) no notify possible",
+ /* 15 */ "(ipc/send) invalid msg-type",
+ /* 16 */ "(ipc/send) invalid msg-header",
+ /* 17 */ "(ipc/send) invalid msg-trailer",
+ /* 18 */ "(ipc/send) DIPC transport failure",
+ /* 19 */ "(ipc/send) DIPC port migrated",
+ /* 20 */ "(ipc/send) DIPC resend failed",
+ /* 21 */ "(ipc/send) out-of-line buffer too large",
+};
+
+static const char * err_codes_mach_rcv[] = {
+ /* 0 */ "(ipc/rcv) no error",
+ /* 1 */ "(ipc/rcv) receive in progress",
+ /* 2 */ "(ipc/rcv) invalid name",
+ /* 3 */ "(ipc/rcv) timed out",
+ /* 4 */ "(ipc/rcv) msg too large",
+ /* 5 */ "(ipc/rcv) interrupted",
+ /* 6 */ "(ipc/rcv) port changed",
+ /* 7 */ "(ipc/rcv) invalid notify port",
+ /* 8 */ "(ipc/rcv) invalid data",
+ /* 9 */ "(ipc/rcv) port died",
+ /* 10 */ "(ipc/rcv) port in set",
+ /* 11 */ "(ipc/rcv) header error",
+ /* 12 */ "(ipc/rcv) body error",
+ /* 13 */ "(ipc/rcv) invalid scatter list entry",
+ /* 14 */ "(ipc/rcv) overwrite region too small",
+ /* 15 */ "(ipc/rcv) invalid msg-trailer",
+ /* 16 */ "(ipc/rcv) DIPC transport error",
+};
+
+static const char * err_codes_mach_mig[] = {
+ /* 0 */ "(ipc/mig) client type check failure",
+ /* 1 */ "(ipc/mig) wrong reply message ID",
+ /* 2 */ "(ipc/mig) server detected error",
+ /* 3 */ "(ipc/mig) bad request message ID",
+ /* 4 */ "(ipc/mig) server type check failure",
+ /* 5 */ "(ipc/mig) no reply should be sent",
+ /* 6 */ "(ipc/mig) server raised exception",
+ /* 7 */ "(ipc/mig) array not large enough",
+ /* 8 */ "(ipc/mig) server died",
+ /* 9 */ "(ipc/mig) unknown trailer format",
+};
+
+/* err_mach_ipc subsystems */
+static struct error_subsystem err_mach_ipc_sub[] = {
+ /* ipc/0; */
+ {
+ "(ipc/send)",
+ errlib_count(err_codes_mach_send),
+ err_codes_mach_send,
+ },
+ /* ipc/1; */
+ {
+ "(ipc/rcv)",
+ errlib_count(err_codes_mach_rcv),
+ err_codes_mach_rcv,
+
+ },
+ /* ipc/2 */
+ {
+ "(ipc/mig)",
+ errlib_count(err_codes_mach_mig),
+ err_codes_mach_mig,
+ },
+
+};
Added: trunk/lib/libmach/mach/err_server.sub
===================================================================
--- trunk/lib/libmach/mach/err_server.sub (rev 0)
+++ trunk/lib/libmach/mach/err_server.sub 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,375 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * File: err_server.sub
+ * Author: Douglas Orr, Carnegie Mellon University
+ * Date: Mar, 1988
+ *
+ * Definitions of Servers error strings
+ */
+
+static const char * err_codes_netname[] = { /* 0 */
+ "(server/netname) name is not yours",
+ "(server/netname) name not checked in",
+ "(server/netname) no such host",
+ "(server/netname) host not found",
+};
+static const char * err_codes_env_mgr[] = { /* 1 */
+ NO_SUCH_ERROR,
+ "(server/env_mgr) variable not found",
+ "(server/env_mgr) wrong type of variable",
+ "(server/env_mgr) unknown port",
+ "(server/env_mgr) read only environment",
+ "(server/env_mgr) no more connections available",
+ "(server/env_mgr) port table full",
+ "(server/env_mgr) attempting to enter a null port ",
+};
+static const char * err_codes_execd[] = { /* 2 */
+ NO_SUCH_ERROR,
+ "(server/execd) could not find file to run",
+ "(server/execd) userid or password incorrect",
+ "(server/execd) fork failed",
+};
+static const char * err_codes_netmemory[] = { /* 3 */
+ "(server/netmemory) successful",
+ "(server/netmemory) invalid argument",
+ "(server/netmemory) resource shortage",
+};
+static const char * err_codes_ufs[] = { /* 4 */
+ NO_SUCH_ERROR,
+/* XXX "(server/ufs) invalid port", */
+};
+
+static const char * err_codes_task_master[] = { /* 5 */
+ "(server/task_master) GENERIC ERROR",
+ "(server/task_master) invalid tm_task port",
+ "(server/task_master) invalid task id",
+ "(server/task_master) invalid kernel port",
+ "(server/task_master) invalid job group",
+ "(server/task_master) invalid action",
+};
+
+static const char * err_codes_ns[] = { /* 6 */
+ "(server/ns) GENERIC ERROR",
+ "(server/ns) invalid handle",
+ "(server/ns) name not found",
+ "(server/ns) name already exists",
+ "(server/ns) name too long",
+ "(server/ns) path too long",
+ "(server/ns) invalid name",
+ "(server/ns) not a directory",
+ "(server/ns) is a directory",
+ "(server/ns) directory not empty",
+ "(server/ns) infinite retry loop in resolver",
+ "(server/ns) infinite forwarding loop in resolver",
+ "(server/ns) invalid prefix",
+ "(server/ns) prefix table overflow",
+ "(server/ns) bad format for directory",
+ "(server/ns) unknown entry type",
+ "(server/ns) invalid generation",
+ "(server/ns) entry not reserved",
+};
+
+static const char * err_codes_io[] = { /* 7 */
+ "(server/io) GENERIC ERROR",
+ "(server/io) invalid offset",
+ "(server/io) invalid size",
+ "(server/io) invalid mode",
+ "(server/io) invalid strategy",
+ "(server/io) operation rejected under current I/O strategy",
+};
+
+static const char * err_codes_auth[] = { /* 8 */
+ "(server/auth) GENERIC ERROR",
+ "(server/auth) bad private port",
+ "(server/auth) bad name",
+ "(server/auth) not primary",
+ "(server/auth) bad pauthsword",
+ "(server/auth) bad group",
+ "(server/auth) duplicate id",
+ "(server/auth) duplicate name",
+ "(server/auth) not secondary",
+};
+
+static const char * err_codes_us[] = { /* 9 */
+ "(server/us) GENERIC ERROR",
+ "(server/us) unknown error",
+ "(server/us) object not found",
+ "(server/us) object exists",
+ "(server/us) object busy",
+ "(server/us) object not started",
+ "(server/us) object dead",
+ "(server/us) invalid args",
+ "(server/us) invalid access",
+ "(server/us) invalid format",
+ "(server/us) invalid buffer size",
+ "(server/us) access denied",
+ "(server/us) resource exhausted",
+ "(server/us) quota exceeded",
+ "(server/us) limit exceeded",
+ "(server/us) not implemented",
+ "(server/us) not supported",
+ "(server/us) hardware error",
+ "(server/us) retry required",
+ "(server/us) not authenticated",
+ "(server/us) exclusive access",
+ "(server/us) timeout",
+ "(server/us) bad reference count",
+ "(server/us) internal error",
+};
+
+static const char * err_codes_sunrpc[] = { /* 10 */
+ "(server/sunrpc) GENERIC ERROR",
+ "(server/sunrpc) cannot encode arguments",
+ "(server/sunrpc) cannot decode results",
+ "(server/sunrpc) failure in sending call",
+ "(server/sunrpc) failure in receiving result",
+ "(server/sunrpc) call timed out",
+ "(server/sunrpc) rpc versions not compatible",
+ "(server/sunrpc) authentication error",
+ "(server/sunrpc) program not available",
+ "(server/sunrpc) program version mismatched",
+ "(server/sunrpc) procedure unavailable",
+ "(server/sunrpc) decode arguments error",
+ "(server/sunrpc) generic other problem",
+ "(server/sunrpc) unknown host name",
+ "(server/sunrpc) portmapper failed",
+ "(server/sunrpc) remote program not registered",
+ "(server/sunrpc) unspecified error",
+ "(server/sunrpc) unknown protocol",
+};
+
+static const char * err_codes_machobj[] = { /* 11 */
+ "(server/object system) GENERIC ERROR",
+ "(server/object system) object not found",
+ "(server/object system) no such operation",
+ "(server/object system) undefined ipc method arguments",
+ "(server/object system) too many arguments to method",
+ "(server/object system) bad ipc message format",
+};
+
+static const char * err_codes_loader[] = { /* 12 */
+ "(server/loader) GENERIC ERROR",
+ "(server/loader) object file not relocated",
+ "(server/loader) unknown file type",
+ "(server/loader) symbol not found",
+ "(server/loader) symbol multiply defined",
+ "(server/loader) memory region overlap",
+};
+
+
+static const char * err_codes_exception[] = { /* 13 */
+ "(server/exception) GENERIC ERROR",
+ "(server/exception) invalid access",
+ "(server/exception) invalid instruction",
+ "(server/exception) arithmetic exception",
+ "(server/exception) emulation exception",
+ "(server/exception) software exception",
+ "(server/exception) breakpoint exception",
+};
+
+static const char * err_codes_ux_signal[] = { /* 14 */
+ "(server/unix-signal) GENERIC ERROR",
+ "(server/unix-signal) hangup",
+ "(server/unix-signal) interrupt",
+ "(server/unix-signal) quit",
+ "(server/unix-signal) undefined",
+ "(server/unix-signal) undefined",
+ "(server/unix-signal) undefined",
+ "(server/unix-signal) undefined",
+ "(server/unix-signal) kill",
+ "(server/unix-signal) undefined",
+ "(server/unix-signal) undefined",
+ "(server/unix-signal) system error",
+ "(server/unix-signal) pipe signal",
+ "(server/unix-signal) alarm",
+ "(server/unix-signal) terminate",
+ "(server/unix-signal) urgent i/o",
+ "(server/unix-signal) stop",
+ "(server/unix-signal) terminal stop",
+ "(server/unix-signal) continue",
+ "(server/unix-signal) child death",
+ "(server/unix-signal) tty input",
+ "(server/unix-signal) tty output",
+ "(server/unix-signal) i/o signal",
+ "(server/unix-signal) cpu time limit exceeded",
+ "(server/unix-signal) file size exceeded",
+ "(server/unix-signal) virtual alarm",
+ "(server/unix-signal) profile signal",
+ "(server/unix-signal) window size change",
+ "(server/unix-signal) user-defined signal 1",
+ "(server/unix-signal) user-defined signal 2",
+};
+
+static const char * err_codes_xkernel[] = { /* 15 */
+ "(server/xkernel) GENERIC ERROR",
+ "(server/xkernel) map full",
+ "(server/xkernel) inconsistent bind",
+ "(server/xkernel) cannot resolve",
+ "(server/xkernel) cannot unbind",
+ "(server/xkernel) invalid type",
+ "(server/xkernel) invalid opcode",
+ "(server/xkernel) buffer too small",
+ "(server/xkernel) invalid ev code",
+ "(server/xkernel) event not registered",
+ "(server/xkernel) invalid open",
+ "(server/xkernel) already open",
+ "(server/xkernel) bad addr",
+};
+
+
+/* err_server subsystems */
+static struct error_subsystem err_server_sub[] = {
+ /* server/0; */
+ {
+ "(server/netname)",
+ errlib_count(err_codes_netname),
+ err_codes_netname,
+ },
+ /* server/1; */
+ {
+ "(server/env_mgr)",
+ errlib_count(err_codes_env_mgr),
+ err_codes_env_mgr,
+ },
+ /* server/2; */
+ {
+ "(server/execd)",
+ errlib_count(err_codes_execd),
+ err_codes_execd,
+ },
+ /* server/3; */
+ {
+ "(server/netmemory)",
+ errlib_count(err_codes_netmemory),
+ err_codes_netmemory,
+ },
+ /* server/4; */
+ {
+ "(server/ufs)",
+ errlib_count(err_codes_ufs),
+ err_codes_ufs,
+ },
+ /* server/5; */
+ {
+ "(server/task_master)",
+ errlib_count(err_codes_task_master),
+ err_codes_task_master,
+ },
+ /* server/6; */
+ {
+ "(server/ns)",
+ errlib_count(err_codes_ns),
+ err_codes_ns,
+ },
+
+ /* server/7; i/o subsystem */
+ {
+ "(server/io)",
+ errlib_count(err_codes_io),
+ err_codes_io,
+ },
+
+ /* server/8; authentication server */
+ {
+ "(server/auth)",
+ errlib_count(err_codes_auth),
+ err_codes_auth,
+ },
+
+ /* server/9; generic US system */
+ {
+ "(server/us)",
+ errlib_count(err_codes_us),
+ err_codes_us,
+ },
+
+ /* server/10; SUN RPC package */
+ {
+ "(server/sunrpc)",
+ errlib_count(err_codes_sunrpc),
+ err_codes_sunrpc,
+ },
+
+ /* server/11; MachObject system */
+ {
+ "(server/object system)",
+ errlib_count(err_codes_machobj),
+ err_codes_machobj,
+ },
+
+ /* server/12; loader */
+ {
+ "(server/loader)",
+ errlib_count(err_codes_loader),
+ err_codes_loader,
+ },
+
+ /* server/13; mach exception */
+ {
+ "(server/exception)",
+ errlib_count(err_codes_exception),
+ err_codes_exception,
+ },
+
+ /* server/14; unix signal */
+ {
+ "(server/unix-signal)",
+ errlib_count(err_codes_ux_signal),
+ err_codes_ux_signal,
+ },
+
+ /* server/15; xkernel */
+ {
+ "(server/xkernel)",
+ errlib_count(err_codes_xkernel),
+ err_codes_xkernel,
+ },
+
+};
Added: trunk/lib/libmach/mach/err_us.sub
===================================================================
--- trunk/lib/libmach/mach/err_us.sub (rev 0)
+++ trunk/lib/libmach/mach/err_us.sub 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * File: err_us.sub
+ * Author: Douglas Orr, Carnegie Mellon University
+ * Date: Mar, 1988
+ *
+ * A place to define User errors
+ */
+
+
+/* err_us subsystems */
+static struct error_subsystem err_us_sub[] = {
+ {
+ 0,
+ 0,
+ 0
+ },
+
+};
Added: trunk/lib/libmach/mach/error_codes.c
===================================================================
--- trunk/lib/libmach/mach/error_codes.c (rev 0)
+++ trunk/lib/libmach/mach/error_codes.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,99 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * File: error_codes.c
+ * Author: Douglas Orr, Carnegie Mellon University
+ * Date: Mar, 1988
+ *
+ * Generic error code interface
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <mach/error.h>
+#include "errorlib.h"
+#include "err_server.sub"
+#include "err_ipc.sub"
+#include "err_mach_ipc.sub"
+#include "err_kern.sub"
+#include "err_us.sub"
+
+struct error_system errors[err_max_system+1] = {
+ /* 0; err_kern */
+ {
+ errlib_count(err_os_sub),
+ "(operating system/?) unknown subsystem error",
+ err_os_sub,
+ },
+ /* 1; err_us */
+ {
+ errlib_count(err_us_sub),
+ "(user space/?) unknown subsystem error",
+ err_us_sub,
+ },
+ /* 2; err_server */
+ {
+ errlib_count(err_server_sub),
+ "(server/?) unknown subsystem error",
+ err_server_sub,
+ },
+ /* 3 (& 3f); err_ipc */
+ {
+ errlib_count(err_ipc_sub),
+ "(ipc/?) unknown subsystem error",
+ err_ipc_sub,
+ },
+ /* 4; err_mach_ipc */
+ {
+ errlib_count(err_mach_ipc_sub),
+ "(ipc/?) unknown subsystem error",
+ err_mach_ipc_sub,
+ },
+};
+
Property changes on: trunk/lib/libmach/mach/error_codes.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/errorlib.h
===================================================================
--- trunk/lib/libmach/mach/errorlib.h (rev 0)
+++ trunk/lib/libmach/mach/errorlib.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * File: errorlib.h
+ * Author: Douglas Orr, Carnegie Mellon University
+ * Date: Mar. 1988
+ *
+ * Error bases for subsytems errors.
+ */
+
+#include <mach/error.h>
+
+#define MACH_IPC_SEND_MOD (err_mach_ipc|err_sub(0))
+#define MACH_IPC_RCV_MOD (err_mach_ipc|err_sub(1))
+#define MACH_IPC_MIG_MOD (err_mach_ipc|err_sub(2))
+
+#define IPC_SEND_MOD (err_ipc|err_sub(0))
+#define IPC_RCV_MOD (err_ipc|err_sub(1))
+#define IPC_MIG_MOD (err_ipc|err_sub(2))
+
+#define SERV_NETNAME_MOD (err_server|err_sub(0))
+#define SERV_ENV_MOD (err_server|err_sub(1))
+#define SERV_EXECD_MOD (err_server|err_sub(2))
+
+
+#define NO_SUCH_ERROR "unknown error code"
+
+struct error_subsystem {
+ const char * subsys_name;
+ int max_code;
+ const char * * codes;
+};
+
+struct error_system {
+ int max_sub;
+ const char * bad_sub;
+ struct error_subsystem * subsystem;
+};
+
+extern struct error_system errors[err_max_system+1];
+
+#define errlib_count(s) (sizeof(s)/sizeof(s[0]))
Property changes on: trunk/lib/libmach/mach/errorlib.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/externs.h
===================================================================
--- trunk/lib/libmach/mach/externs.h (rev 0)
+++ trunk/lib/libmach/mach/externs.h 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * MkLinux
+ */
+
+#include <mach/boolean.h>
+#include <mach/error.h>
+#include <mach/message.h>
+#include <mach/vm_types.h>
+
+extern void mig_init(void *);
+extern void mach_init_ports(void);
+extern void mig_allocate(vm_address_t *, vm_size_t);
+extern void mig_deallocate(vm_address_t, vm_size_t);
+
+extern const char *mach_error_string_int(mach_error_t, boolean_t *);
Property changes on: trunk/lib/libmach/mach/externs.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mach_error_string.c
===================================================================
--- trunk/lib/libmach/mach/mach_error_string.c (rev 0)
+++ trunk/lib/libmach/mach/mach_error_string.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,132 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+
+#include <mach/boolean.h>
+#include <mach/error.h>
+#include <mach/mach_error.h>
+#include "errorlib.h"
+#include "externs.h"
+
+static void do_compat(mach_error_t *);
+
+static void
+do_compat(mach_error_t *org_err)
+{
+ mach_error_t err = *org_err;
+
+ /*
+ * map old error numbers to
+ * to new error sys & subsystem
+ */
+
+ if ((-200 < err) && (err <= -100))
+ err = -(err + 100) | IPC_SEND_MOD;
+ else if ((-300 < err) && (err <= -200))
+ err = -(err + 200) | IPC_RCV_MOD;
+ else if ((-400 < err) && (err <= -300))
+ err = -(err + 300) | MACH_IPC_MIG_MOD;
+ else if ((1000 <= err) && (err < 1100))
+ err = (err - 1000) | SERV_NETNAME_MOD;
+ else if ((1600 <= err) && (err < 1700))
+ err = (err - 1600) | SERV_ENV_MOD;
+ else if ((27600 <= err) && (err < 27700))
+ err = (err - 27600) | SERV_EXECD_MOD;
+
+ *org_err = err;
+}
+
+const char *
+mach_error_type(mach_error_t err)
+{
+ int sub, system;
+
+ do_compat( &err );
+
+ sub = err_get_sub(err);
+ system = err_get_system(err);
+
+ if (system > err_max_system || sub >= errors[system].max_sub)
+ return((const char *)"(?/?)");
+ return(errors[system].subsystem[sub].subsys_name);
+}
+
+static boolean_t mach_error_full_diag = FALSE;
+
+const char *
+mach_error_string_int(mach_error_t err, boolean_t *diag)
+{
+ int sub, system, code;
+
+ do_compat( &err );
+
+ sub = err_get_sub(err);
+ system = err_get_system(err);
+ code = err_get_code(err);
+
+ *diag = TRUE;
+
+ if (system > err_max_system)
+ return((const char *)"(?/?) unknown error system");
+ if (sub >= errors[system].max_sub)
+ return(errors[system].bad_sub);
+ if (code >= errors[system].subsystem[sub].max_code)
+ return ((const char *)NO_SUCH_ERROR);
+
+ *diag = mach_error_full_diag;
+ return( errors[system].subsystem[sub].codes[code] );
+}
+
+const char *
+mach_error_string(mach_error_t err)
+{
+ boolean_t diag;
+
+ return mach_error_string_int( err, &diag );
+
+}
Property changes on: trunk/lib/libmach/mach/mach_error_string.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mach_init.c
===================================================================
--- trunk/lib/libmach/mach/mach_init.c (rev 0)
+++ trunk/lib/libmach/mach/mach_init.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,67 @@
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <pthread.h>
+
+#include <mach/mach.h>
+#include <mach/boolean.h>
+#include <mach/mach_traps.h>
+#include <mach/mach_init.h>
+#include <mach/mach_types.h>
+#include <mach/mach_port.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+
+#include <syslog.h>
+#include <stdarg.h>
+
+#include <sys/mach/ndr_def.h>
+void mach_init(void) __attribute__((constructor));
+mach_port_t mach_reply_port(void);
+mach_port_t task_self_trap(void);
+
+extern mach_port_t _task_reply_port;
+mach_port_t bootstrap_port = 0;
+mach_port_t mach_task_self_ = 0;
+
+ __attribute__((visibility("hidden"))) mach_port_t _task_reply_port;
+extern void mig_init(void);
+
+void
+mach_init(void)
+{
+ pid_t pid;
+ char *root_flag;
+ int root_bootstrap;
+ kern_return_t kr;
+ static int mach_inited_pid = 0;
+
+ /* we may need to call this again after fork */
+ if (mach_inited_pid != (pid = getpid())) {
+ mig_init();
+ root_flag = getenv("ROOT_BOOTSTRAP");
+ root_bootstrap = (root_flag != NULL) && (strcmp(root_flag, "T") == 0);
+
+ /* Only call pthread_atfork when not in the fork handler */
+ if (mach_inited_pid == 0)
+ pthread_atfork(NULL, NULL, mach_init);
+
+ mach_task_self_ = task_self_trap();
+ _task_reply_port = mach_reply_port();
+ if (pid != 1 && root_bootstrap == false) {
+ kr = task_get_special_port(mach_task_self_, TASK_BOOTSTRAP_PORT, &bootstrap_port);
+ if (kr != KERN_SUCCESS) {
+ syslog(LOG_EMERG, "get_special_port failed - mach_task_self_: %d", mach_task_self_);
+ return;
+ }
+ }
+ if (root_bootstrap == true) {
+ syslog(LOG_ERR, "skip bootstrap port fetch");
+ unsetenv("ROOT_BOOTSTRAP");
+ }
+ mach_inited_pid = pid;
+ }
+}
Property changes on: trunk/lib/libmach/mach/mach_init.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mach_misc.c
===================================================================
--- trunk/lib/libmach/mach/mach_misc.c (rev 0)
+++ trunk/lib/libmach/mach/mach_misc.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,208 @@
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <mach/mach.h>
+#include <mach/boolean.h>
+#include <mach/mach_traps.h>
+#include <mach/mach_init.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/mach_port.h>
+#include <mach/mach_vm.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define HAVE_MACH
+#include <pthread.h>
+
+kern_return_t _kernelrpc_mach_port_allocate_trap(
+ ipc_space_t task,
+ mach_port_right_t right,
+ mach_port_name_t *name
+);
+kern_return_t _kernelrpc_mach_port_deallocate_trap(
+ ipc_space_t task,
+ mach_port_name_t name
+);
+
+kern_return_t _kernelrpc_mach_port_insert_right_trap(
+ ipc_space_t task,
+ mach_port_name_t name,
+ mach_port_t poly,
+ mach_msg_type_name_t polyPoly
+);
+kern_return_t _kernelrpc_mach_port_extract_right_trap(
+ ipc_space_t task,
+ mach_port_name_t name,
+ mach_msg_type_name_t msgt_name,
+ mach_port_t *poly,
+ mach_msg_type_name_t *polyPoly
+);
+
+kern_return_t _kernelrpc_mach_vm_allocate_trap(
+ mach_vm_map_t target,
+ mach_vm_address_t *address,
+ mach_vm_size_t size,
+ int flags
+ );
+kern_return_t _kernelrpc_mach_vm_deallocate_trap(
+ mach_vm_map_t target,
+ vm_address_t address,
+ mach_vm_size_t size
+);
+kern_return_t _kernelrpc_mach_vm_map_trap(
+ mach_vm_map_t target,
+ vm_address_t *address,
+ mach_vm_offset_t mask,
+ mach_vm_size_t size,
+ int flags,
+ vm_prot_t cur_protection
+ );
+
+mach_port_t host_self_trap(void);
+mach_port_t thread_self_trap(void);
+
+
+kern_return_t vm_allocate(mach_port_name_t target, vm_address_t *addr, vm_size_t size, int flags);
+kern_return_t vm_deallocate(mach_port_name_t target, vm_address_t addr, vm_size_t size);
+
+
+
+kern_return_t
+mach_port_allocate(mach_port_name_t target, mach_port_right_t right,
+ mach_port_name_t *name)
+{
+
+ return (_kernelrpc_mach_port_allocate_trap(target, right, name));
+}
+
+kern_return_t
+mach_port_deallocate(mach_port_name_t target, mach_port_name_t name)
+{
+
+ return (_kernelrpc_mach_port_deallocate_trap(target, name));
+}
+
+kern_return_t
+mach_port_extract_right(mach_port_name_t target __unused,
+ mach_port_name_t name __unused,
+ mach_msg_type_name_t msgt_name __unused,
+ mach_port_name_t *poly __unused,
+ mach_msg_type_name_t *polyPoly __unused)
+{
+
+ /* no syscall for this - needs to go through the normal RPC glue */
+ return (ENOSYS);
+}
+
+kern_return_t
+mach_port_insert_right(mach_port_name_t target, mach_port_name_t name,
+ mach_port_name_t poly, mach_msg_type_name_t polyPoly)
+{
+
+ return (_kernelrpc_mach_port_insert_right_trap(target, name, poly, polyPoly));
+}
+
+kern_return_t
+mach_port_mod_refs(mach_port_name_t target, mach_port_name_t name,
+ mach_port_right_t right, mach_port_delta_t delta)
+{
+
+ return (_kernelrpc_mach_port_mod_refs_trap(target, name, right, delta));
+}
+
+mach_port_t
+mach_host_self(void)
+{
+
+ return (host_self_trap());
+}
+
+kern_return_t
+mach_vm_allocate(mach_port_name_t target, vm_address_t *addr, vm_size_t size, int flags)
+{
+
+ return (_kernelrpc_mach_vm_allocate_trap(target, addr, size, flags));
+}
+
+kern_return_t
+vm_allocate(mach_port_name_t target, vm_address_t *addr, vm_size_t size, int flags)
+{
+
+ return (_kernelrpc_mach_vm_allocate_trap(target, addr, size, flags));
+}
+
+kern_return_t
+mach_vm_deallocate(mach_port_name_t target, vm_address_t addr, vm_size_t size)
+{
+
+ return (_kernelrpc_mach_vm_deallocate_trap(target, addr, size));
+}
+
+kern_return_t
+vm_deallocate(mach_port_name_t target, vm_address_t addr, vm_size_t size)
+{
+
+ return (_kernelrpc_mach_vm_deallocate_trap(target, addr, size));
+}
+
+
+kern_return_t
+mach_vm_map(mach_vm_map_t target, mach_vm_address_t *address, mach_vm_offset_t mask,
+ mach_vm_size_t size, int flags, mem_entry_name_port_t object __unused,
+ memory_object_offset_t offset __unused, boolean_t copy __unused,
+ vm_prot_t cur_protection, vm_prot_t max_protection __unused,
+ vm_inherit_t inheritance __unused)
+{
+
+ return (_kernelrpc_mach_vm_map_trap(target, address, size, mask, flags, cur_protection));
+}
+
+kern_return_t
+mach_port_move_member(mach_port_name_t target, mach_port_name_t member, mach_port_name_t after)
+{
+
+ return (_kernelrpc_mach_port_move_member_trap(target, member, after));
+}
+
+kern_return_t
+mach_port_insert_member(mach_port_name_t target, mach_port_name_t name, mach_port_name_t pset)
+{
+
+ return (_kernelrpc_mach_port_insert_member_trap(target, name, pset));
+}
+
+
+kern_return_t
+mach_port_extract_member(mach_port_name_t target, mach_port_name_t name, mach_port_name_t pset)
+{
+
+ return (_kernelrpc_mach_port_extract_member_trap(target, name, pset));
+}
+
+#include <time.h>
+#include <mach/mach_time.h>
+uint64_t
+mach_absolute_time(void)
+{
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_REALTIME_FAST, &tp))
+ return (0);
+
+ return (tp.tv_sec*NSEC_PER_SEC + tp.tv_nsec);
+}
+
+mach_port_t
+pthread_mach_thread_np(uintptr_t self)
+{
+
+ if ((pthread_t)self != pthread_self()) {
+ printf("invalid pthread_mach_thread_np usage");
+ abort();
+ }
+
+ return (thread_self_trap());
+}
Property changes on: trunk/lib/libmach/mach/mach_misc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mach_msg.c
===================================================================
--- trunk/lib/libmach/mach/mach_msg.c (rev 0)
+++ trunk/lib/libmach/mach/mach_msg.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,576 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <sys/queue.h>
+
+#include <mach/mach.h>
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+#include <mach/mach_port.h>
+#include <mach/mach_vm.h>
+
+#define LIBMACH_OPTIONS (MACH_SEND_INTERRUPT|MACH_RCV_INTERRUPT)
+
+mach_msg_return_t
+mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify)
+ mach_msg_header_t *msg;
+ mach_msg_option_t option;
+ mach_msg_size_t send_size;
+ mach_msg_size_t rcv_size;
+ mach_port_t rcv_name;
+ mach_msg_timeout_t timeout;
+ mach_port_t notify;
+{
+ mach_msg_return_t mr;
+
+ /*
+ * Consider the following cases:
+ * 1) Errors in pseudo-receive (eg, MACH_SEND_INTERRUPTED
+ * plus special bits).
+ * 2) Use of MACH_SEND_INTERRUPT/MACH_RCV_INTERRUPT options.
+ * 3) RPC calls with interruptions in one/both halves.
+ *
+ * We refrain from passing the option bits that we implement
+ * to the kernel. This prevents their presence from inhibiting
+ * the kernel's fast paths (when it checks the option value).
+ */
+
+ mr = mach_msg_overwrite_trap(msg, option &~ LIBMACH_OPTIONS,
+ send_size, rcv_size, rcv_name,
+ timeout, notify, MACH_MSG_NULL, 0);
+ if (mr == MACH_MSG_SUCCESS)
+ return MACH_MSG_SUCCESS;
+
+ if ((option & MACH_SEND_INTERRUPT) == 0)
+ while (mr == MACH_SEND_INTERRUPTED)
+ mr = mach_msg_overwrite_trap(msg,
+ option &~ LIBMACH_OPTIONS,
+ send_size, rcv_size, rcv_name,
+ timeout, notify, MACH_MSG_NULL, 0);
+
+ if ((option & MACH_RCV_INTERRUPT) == 0)
+ while (mr == MACH_RCV_INTERRUPTED)
+ mr = mach_msg_overwrite_trap(msg,
+ option &~ (LIBMACH_OPTIONS|MACH_SEND_MSG),
+ 0, rcv_size, rcv_name,
+ timeout, notify, MACH_MSG_NULL, 0);
+
+ return mr;
+}
+
+mach_msg_return_t
+mach_msg_overwrite(msg, option, send_size, rcv_limit, rcv_name, timeout,
+ notify, rcv_msg, rcv_msg_size)
+ mach_msg_header_t *msg;
+ mach_msg_option_t option;
+ mach_msg_size_t send_size;
+ mach_msg_size_t rcv_limit;
+ mach_port_t rcv_name;
+ mach_msg_timeout_t timeout;
+ mach_port_t notify;
+ mach_msg_header_t *rcv_msg;
+ mach_msg_size_t rcv_msg_size;
+{
+ mach_msg_return_t mr;
+
+ /*
+ * Consider the following cases:
+ * 1) Errors in pseudo-receive (eg, MACH_SEND_INTERRUPTED
+ * plus special bits).
+ * 2) Use of MACH_SEND_INTERRUPT/MACH_RCV_INTERRUPT options.
+ * 3) RPC calls with interruptions in one/both halves.
+ *
+ * We refrain from passing the option bits that we implement
+ * to the kernel. This prevents their presence from inhibiting
+ * the kernel's fast paths (when it checks the option value).
+ */
+
+ mr = mach_msg_overwrite_trap(msg, option &~ LIBMACH_OPTIONS,
+ send_size, rcv_limit, rcv_name,
+ timeout, notify, rcv_msg, rcv_msg_size);
+ if (mr == MACH_MSG_SUCCESS)
+ return MACH_MSG_SUCCESS;
+
+ if ((option & MACH_SEND_INTERRUPT) == 0)
+ while (mr == MACH_SEND_INTERRUPTED)
+ mr = mach_msg_overwrite_trap(msg,
+ option &~ LIBMACH_OPTIONS,
+ send_size, rcv_limit, rcv_name,
+ timeout, notify, rcv_msg, rcv_msg_size);
+
+ if ((option & MACH_RCV_INTERRUPT) == 0)
+ while (mr == MACH_RCV_INTERRUPTED)
+ mr = mach_msg_overwrite_trap(msg,
+ option &~ (LIBMACH_OPTIONS|MACH_SEND_MSG),
+ 0, rcv_limit, rcv_name,
+ timeout, notify, rcv_msg, rcv_msg_size);
+
+ return mr;
+}
+
+mach_msg_return_t
+mach_msg_send(mach_msg_header_t *msg)
+{
+ return mach_msg(msg, MACH_SEND_MSG,
+ msg->msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
+mach_msg_return_t
+mach_msg_receive(mach_msg_header_t *msg)
+{
+ return mach_msg(msg, MACH_RCV_MSG,
+ 0, msg->msgh_size, msg->msgh_local_port,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
+static void
+mach_msg_destroy_port(mach_port_t port, mach_msg_type_name_t type)
+{
+ if (MACH_PORT_VALID(port)) switch (type) {
+ case MACH_MSG_TYPE_MOVE_SEND:
+ case MACH_MSG_TYPE_MOVE_SEND_ONCE:
+ /* destroy the send/send-once right */
+ (void) mach_port_deallocate(mach_task_self(), port);
+ break;
+
+ case MACH_MSG_TYPE_MOVE_RECEIVE:
+ /* destroy the receive right */
+ (void) mach_port_mod_refs(mach_task_self(), port,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ break;
+
+ case MACH_MSG_TYPE_MAKE_SEND:
+ /* create a send right and then destroy it */
+ (void) mach_port_insert_right(mach_task_self(), port,
+ port, MACH_MSG_TYPE_MAKE_SEND);
+ (void) mach_port_deallocate(mach_task_self(), port);
+ break;
+
+ case MACH_MSG_TYPE_MAKE_SEND_ONCE:
+ /* create a send-once right and then destroy it */
+ (void) mach_port_extract_right(mach_task_self(), port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &port, &type);
+ (void) mach_port_deallocate(mach_task_self(), port);
+ break;
+ }
+}
+
+static void
+mach_msg_destroy_memory(vm_offset_t addr, vm_size_t size)
+{
+ if (size != 0)
+ (void) mach_vm_deallocate(mach_task_self(), addr, size);
+}
+
+/*
+ * Routine: mach_msg_destroy
+ * Purpose:
+ * mach_msg_destroy is useful in two contexts.
+ *
+ * First, it can deallocate all port rights and
+ * out-of-line memory in a received message.
+ * When a server receives a request it doesn't want,
+ * it needs this functionality.
+ *
+ * Second, it can mimic the side-effects of a msg-send
+ * operation. The effect is as if the message were sent
+ * and then destroyed inside the kernel. When a server
+ * can't send a reply (because the client died),
+ * it needs this functionality.
+ */
+void
+mach_msg_destroy(mach_msg_header_t *msg)
+{
+ mach_msg_bits_t mbits = msg->msgh_bits;
+
+ /*
+ * The msgh_local_port field doesn't hold a port right.
+ * The receive operation consumes the destination port right.
+ */
+
+ mach_msg_destroy_port(msg->msgh_remote_port, MACH_MSGH_BITS_REMOTE(mbits));
+
+ if (mbits & MACH_MSGH_BITS_COMPLEX) {
+ mach_msg_base_t base __aligned(8);
+ mach_msg_base_t *basep;
+ mach_msg_body_t *body;
+ mach_msg_descriptor_t *saddr, *eaddr;
+
+ basep = &base;
+ memcpy(basep, msg, sizeof(base));
+ body = (mach_msg_body_t *) (msg + 1);
+ saddr = (mach_msg_descriptor_t *) (uintptr_t)(basep + 1);
+ eaddr = saddr + body->msgh_descriptor_count;
+
+ for ( ; saddr < eaddr; saddr++) {
+ switch (saddr->type.type) {
+
+ case MACH_MSG_PORT_DESCRIPTOR: {
+ mach_msg_port_descriptor_t *dsc;
+
+ /*
+ * Destroy port rights carried in the message
+ */
+ dsc = &saddr->port;
+ mach_msg_destroy_port(dsc->name, dsc->disposition);
+ break;
+ }
+
+ case MACH_MSG_OOL_DESCRIPTOR : {
+ mach_msg_ool_descriptor_t *dsc;
+
+ /*
+ * Destroy memory carried in the message
+ */
+ dsc = &saddr->out_of_line;
+ if (dsc->deallocate) {
+ mach_msg_destroy_memory((vm_offset_t)dsc->address,
+ dsc->size);
+ }
+ break;
+ }
+
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
+ mach_port_t *ports;
+ mach_msg_ool_ports_descriptor_t *dsc;
+ mach_msg_type_number_t j;
+
+ /*
+ * Destroy port rights carried in the message
+ */
+ dsc = &saddr->ool_ports;
+ ports = (mach_port_t *) dsc->address;
+ for (j = 0; j < dsc->count; j++, ports++) {
+ mach_msg_destroy_port(*ports, dsc->disposition);
+ }
+
+ /*
+ * Destroy memory carried in the message
+ */
+ if (dsc->deallocate) {
+ mach_msg_destroy_memory((vm_offset_t)dsc->address,
+ dsc->count * sizeof(mach_port_t));
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Routine: mach_msg_server_once
+ * Purpose:
+ * A simple generic server function. It allows more flexibility
+ * than mach_msg_server by processing only one message request
+ * and then returning to the user. Note that more in the way
+ * of error codes are returned to the user; specifically, any
+ * failing error from mach_msg_overwrite_trap will be returned
+ * (though errors from the demux routine or the routine it calls
+ * will not be).
+ */
+mach_msg_return_t
+mach_msg_server_once(
+ boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *),
+ mach_msg_size_t max_size,
+ mach_port_t rcv_name,
+ mach_msg_options_t options)
+{
+ mig_reply_error_t *bufRequest = 0, *bufReply = 0, *bufTemp;
+ boolean_t allocatedRequest = FALSE, allocatedReply = FALSE, allocatedTemp;
+ register mach_msg_return_t mr;
+ register kern_return_t kr;
+
+ if ((kr = mach_vm_allocate(mach_task_self(),
+ (vm_address_t *)&bufRequest,
+ max_size + MAX_TRAILER_SIZE,
+ TRUE)) != KERN_SUCCESS)
+ goto cleanup;
+ allocatedRequest = TRUE;
+
+ if ((kr = mach_vm_allocate(mach_task_self(),
+ (vm_address_t *)&bufReply,
+ max_size + MAX_TRAILER_SIZE,
+ TRUE)) != KERN_SUCCESS)
+ goto cleanup;
+ allocatedReply = TRUE;
+
+ mr = mach_msg_overwrite_trap(&bufRequest->Head, MACH_RCV_MSG|options,
+ 0, max_size, rcv_name,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL,
+ (mach_msg_header_t *) 0, 0);
+ if (mr == MACH_MSG_SUCCESS) {
+ /* we have a request message */
+
+ (void) (*demux)(&bufRequest->Head, &bufReply->Head);
+
+ if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
+ bufReply->RetCode != KERN_SUCCESS) {
+ if (bufReply->RetCode == MIG_NO_REPLY) {
+ /*
+ * This return code is a little tricky--
+ * it appears that the demux routine found an
+ * error of some sort, but since that error
+ * would not normally get returned either to
+ * the local user or the remote one, we pretend it's
+ * ok.
+ */
+
+ kr = KERN_SUCCESS;
+ goto cleanup;
+ }
+
+ /* don't destroy the reply port right,
+ so we can send an error message */
+ bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
+ mach_msg_destroy(&bufRequest->Head);
+ }
+
+ if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) {
+ /* no reply port, so destroy the reply */
+ if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
+ mach_msg_destroy(&bufReply->Head);
+
+ kr = KERN_SUCCESS;
+ goto cleanup;
+ }
+
+ /* send reply. */
+
+ bufTemp = bufRequest;
+ bufRequest = bufReply;
+ bufReply = bufTemp;
+
+ allocatedTemp = allocatedRequest;
+ allocatedRequest = allocatedReply;
+ allocatedReply = allocatedRequest;
+
+ /*
+ * We don't want to block indefinitely because the client
+ * isn't receiving messages from the reply port.
+ * If we have a send-once right for the reply port, then
+ * this isn't a concern because the send won't block.
+ * If we have a send right, we need to use MACH_SEND_TIMEOUT.
+ * To avoid falling off the kernel's fast RPC path unnecessarily,
+ * we only supply MACH_SEND_TIMEOUT when absolutely necessary.
+ */
+
+ mr = mach_msg_overwrite_trap(&bufRequest->Head,
+ (MACH_MSGH_BITS_REMOTE(bufRequest->Head.msgh_bits) ==
+ MACH_MSG_TYPE_MOVE_SEND_ONCE) ?
+ MACH_SEND_MSG|options :
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT|options,
+ bufRequest->Head.msgh_size, 0, MACH_PORT_NULL,
+ 0, MACH_PORT_NULL, (mach_msg_header_t *) 0, 0);
+ }
+ /* Has a message error occurred? */
+
+ switch (mr) {
+ case MACH_SEND_INVALID_DEST:
+ case MACH_SEND_TIMED_OUT:
+ /* the reply can't be delivered, so destroy it */
+ mach_msg_destroy(&bufRequest->Head);
+ kr = KERN_SUCCESS; /* Matches error hiding behavior in
+ mach_msg_server. */
+ goto cleanup;
+
+
+ case MACH_RCV_TOO_LARGE:
+ kr = KERN_SUCCESS; /* Matches error hiding behavior in
+ mach_msg_server. */
+ goto cleanup;
+
+ default:
+ /* Includes success case. */
+ kr = mr;
+ goto cleanup;
+ }
+
+cleanup:
+ if ( allocatedRequest == TRUE )
+ (void)mach_vm_deallocate(mach_task_self(),
+ (vm_address_t) bufRequest,
+ max_size + MAX_TRAILER_SIZE);
+ if ( allocatedReply == TRUE )
+ (void)mach_vm_deallocate(mach_task_self(),
+ (vm_address_t) bufReply,
+ max_size + MAX_TRAILER_SIZE);
+ return kr;
+
+}
+
+/*
+ * Routine: mach_msg_server
+ * Purpose:
+ * A simple generic server function. Note that changes here
+ * should be considered for duplication above.
+ */
+mach_msg_return_t
+mach_msg_server(
+ boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *),
+ mach_msg_size_t max_size,
+ mach_port_t rcv_name,
+ mach_msg_options_t options)
+{
+ mig_reply_error_t *bufRequest = 0, *bufReply = 0, *bufTemp;
+ boolean_t allocatedRequest = FALSE, allocatedReply = FALSE, allocatedTemp;
+ register mach_msg_return_t mr;
+ register kern_return_t kr;
+
+ if ((kr = mach_vm_allocate(mach_task_self(),
+ (vm_address_t *)&bufRequest,
+ max_size + MAX_TRAILER_SIZE,
+ TRUE)) != KERN_SUCCESS)
+ goto cleanup;
+ allocatedRequest = TRUE;
+
+ if ((kr = mach_vm_allocate(mach_task_self(),
+ (vm_address_t *)&bufReply,
+ max_size + MAX_TRAILER_SIZE,
+ TRUE)) != KERN_SUCCESS)
+ goto cleanup;
+ allocatedReply = TRUE;
+
+ for (;;) {
+ get_request:
+ mr = mach_msg_overwrite_trap(&bufRequest->Head, MACH_RCV_MSG|options,
+ 0, max_size, rcv_name,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL,
+ (mach_msg_header_t *) 0, 0);
+ while (mr == MACH_MSG_SUCCESS) {
+ /* we have a request message */
+
+ (void) (*demux)(&bufRequest->Head, &bufReply->Head);
+
+ if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
+ bufReply->RetCode != KERN_SUCCESS) {
+ if (bufReply->RetCode == MIG_NO_REPLY)
+ goto get_request;
+
+ /* don't destroy the reply port right,
+ so we can send an error message */
+ bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
+ mach_msg_destroy(&bufRequest->Head);
+ }
+
+ if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) {
+ /* no reply port, so destroy the reply */
+ if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
+ mach_msg_destroy(&bufReply->Head);
+
+ goto get_request;
+ }
+
+ /* send reply and get next request */
+
+ bufTemp = bufRequest;
+ bufRequest = bufReply;
+ bufReply = bufTemp;
+
+ allocatedTemp = allocatedRequest;
+ allocatedRequest = allocatedReply;
+ allocatedReply = allocatedTemp;
+
+ /*
+ * We don't want to block indefinitely because the client
+ * isn't receiving messages from the reply port.
+ * If we have a send-once right for the reply port, then
+ * this isn't a concern because the send won't block.
+ * If we have a send right, we need to use MACH_SEND_TIMEOUT.
+ * To avoid falling off the kernel's fast RPC path unnecessarily,
+ * we only supply MACH_SEND_TIMEOUT when absolutely necessary.
+ */
+
+ mr = mach_msg_overwrite_trap(&bufRequest->Head,
+ (MACH_MSGH_BITS_REMOTE(bufRequest->Head.msgh_bits) ==
+ MACH_MSG_TYPE_MOVE_SEND_ONCE) ?
+ MACH_SEND_MSG|MACH_RCV_MSG|options :
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT|MACH_RCV_MSG|options,
+ bufRequest->Head.msgh_size, max_size, rcv_name,
+ 0, MACH_PORT_NULL, (mach_msg_header_t *) 0, 0);
+ }
+
+ /* a message error occurred */
+
+ switch (mr) {
+ case MACH_SEND_INVALID_DEST:
+ case MACH_SEND_TIMED_OUT:
+ /* the reply can't be delivered, so destroy it */
+ mach_msg_destroy(&bufRequest->Head);
+ goto cleanup;
+
+ case MACH_RCV_TOO_LARGE:
+ /* the kernel destroyed the request */
+ goto cleanup;
+
+ default:
+ /* should only happen if the server is buggy */
+ kr = mr;
+ goto cleanup;
+ }
+
+cleanup:
+ if ( allocatedRequest == TRUE )
+ (void)mach_vm_deallocate(mach_task_self(),
+ (vm_address_t) bufRequest,
+ max_size + MAX_TRAILER_SIZE);
+ if ( allocatedReply == TRUE )
+ (void)mach_vm_deallocate(mach_task_self(),
+ (vm_address_t) bufReply,
+ max_size + MAX_TRAILER_SIZE);
+ }
+}
Property changes on: trunk/lib/libmach/mach/mach_msg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mig_allocate.c
===================================================================
--- trunk/lib/libmach/mach/mig_allocate.c (rev 0)
+++ trunk/lib/libmach/mach/mig_allocate.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * MkLinux
+ */
+
+/*
+ * Memory allocation routine for MiG interfaces.
+ */
+#include <mach/mach.h>
+#include "externs.h"
+
+void
+mig_allocate(vm_address_t *addr_p, vm_size_t size)
+{
+ if (mach_vm_allocate(mach_task_self(),
+ addr_p,
+ size,
+ TRUE)
+ != KERN_SUCCESS)
+ *addr_p = 0;
+}
Property changes on: trunk/lib/libmach/mach/mig_allocate.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mig_deallocate.c
===================================================================
--- trunk/lib/libmach/mach/mig_deallocate.c (rev 0)
+++ trunk/lib/libmach/mach/mig_deallocate.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * MkLinux
+ */
+
+/*
+ * Memory deallocation routine for MiG interfaces.
+ */
+#include <mach/mach.h>
+#include "externs.h"
+
+void
+mig_deallocate(vm_address_t addr, vm_size_t size)
+{
+ (void) mach_vm_deallocate(mach_task_self(),
+ addr,
+ size);
+}
Property changes on: trunk/lib/libmach/mach/mig_deallocate.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mig_reply_setup.c
===================================================================
--- trunk/lib/libmach/mach/mig_reply_setup.c (rev 0)
+++ trunk/lib/libmach/mach/mig_reply_setup.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,77 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * Routine to set up a MiG reply message from a request message.
+ *
+ * Knows about the MiG reply message ID convention:
+ * reply_id = request_id + 100
+ *
+ * For typed IPC sets up the RetCode type field. Does NOT set a
+ * return code value.
+ */
+
+#include <mach/mach.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+
+void
+mig_reply_setup(mach_msg_header_t *request, mach_msg_header_t *reply)
+{
+#define InP (request)
+#define OutP ((mig_reply_error_t *) reply)
+
+ OutP->Head.msgh_bits =
+ MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
+ OutP->Head.msgh_size = sizeof(mig_reply_error_t);
+ OutP->Head.msgh_remote_port = InP->msgh_local_port;
+ OutP->Head.msgh_local_port = MACH_PORT_NULL;
+ OutP->Head.msgh_id = InP->msgh_id + 100;
+ OutP->NDR = NDR_record;
+}
Property changes on: trunk/lib/libmach/mach/mig_reply_setup.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mig_strncpy.c
===================================================================
--- trunk/lib/libmach/mach/mig_strncpy.c (rev 0)
+++ trunk/lib/libmach/mach/mig_strncpy.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,87 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * mig_strncpy.c - by Joshua Block
+ *
+ * mig_strncpy -- Bounded string copy. Does what the library routine strncpy
+ * OUGHT to do: Copies the (null terminated) string in src into dest, a
+ * buffer of length len. Assures that the copy is still null terminated
+ * and doesn't overflow the buffer, truncating the copy if necessary.
+ *
+ * Parameters:
+ *
+ * dest - Pointer to destination buffer.
+ *
+ * src - Pointer to source string.
+ *
+ * len - Length of destination buffer.
+ *
+ * Result:
+ * length of string copied, INCLUDING the trailing 0.
+ */
+#include <mach/mig_errors.h>
+
+int
+mig_strncpy(
+ register char *dest,
+ register char *src,
+ register int len)
+{
+ register int i;
+
+ if (len <= 0)
+ return 0;
+
+ for (i=1; i<len; i++)
+ if (! (*dest++ = *src++))
+ return i;
+
+ *dest = '\0';
+ return i;
+}
Property changes on: trunk/lib/libmach/mach/mig_strncpy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/mach/mig_support.c
===================================================================
--- trunk/lib/libmach/mach/mig_support.c (rev 0)
+++ trunk/lib/libmach/mach/mig_support.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,114 @@
+/*
+ * Copyright 1991-1998 by Open Software Foundation, Inc.
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+ * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution at CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * MkLinux
+ */
+/*
+ * Abstract:
+ * Routines to set and deallocate the mig reply port.
+ * They are called from mig generated interfaces.
+ *
+ */
+
+#include <mach/mach.h>
+#include <mach/mach_traps.h>
+#include "externs.h"
+
+static mach_port_t mig_reply_port = MACH_PORT_NULL;
+
+/*****************************************************
+ * Called by mach_init. This is necessary after
+ * a fork to get rid of bogus port number.
+ ****************************************************/
+
+void
+mig_init(void * arg __unused)
+{
+ mig_reply_port = MACH_PORT_NULL;
+}
+
+/********************************************************
+ * Called by mig interfaces whenever they need a reply port.
+ * Used to provide the same interface as multi-threaded tasks need.
+ ********************************************************/
+
+mach_port_t
+mig_get_reply_port()
+{
+ if (mig_reply_port == MACH_PORT_NULL)
+ mig_reply_port = mach_reply_port();
+
+ return mig_reply_port;
+}
+
+/*************************************************************
+ * Called by mig interfaces after a timeout on the port.
+ * Could be called by user.
+ ***********************************************************/
+
+void
+mig_dealloc_reply_port(
+ mach_port_t reply_port __unused)
+{
+ mach_port_t port;
+
+ port = mig_reply_port;
+ mig_reply_port = MACH_PORT_NULL;
+
+ (void) mach_port_mod_refs(mach_task_self(), port,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+}
+
+/*************************************************************
+ * Called by mig interfaces after each RPC.
+ * Could be called by user.
+ ***********************************************************/
+
+void
+mig_put_reply_port(
+ mach_port_t reply_port __unused)
+{
+}
Property changes on: trunk/lib/libmach/mach/mig_support.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/test/kqueue_tests/Makefile
===================================================================
--- trunk/lib/libmach/test/kqueue_tests/Makefile (rev 0)
+++ trunk/lib/libmach/test/kqueue_tests/Makefile 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,10 @@
+
+PROG= kqueue_tests
+SRCS= kqueue_tests.c
+
+#MK_MAN=no
+CFLAGS+= -g
+CFLAGS+= -I. -I../../../../include -D__APPLE__ -O0
+LDADD+= -lmach -pthread
+
+.include <bsd.prog.mk>
Property changes on: trunk/lib/libmach/test/kqueue_tests/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/lib/libmach/test/kqueue_tests/kqueue_tests.c
===================================================================
--- trunk/lib/libmach/test/kqueue_tests/kqueue_tests.c (rev 0)
+++ trunk/lib/libmach/test/kqueue_tests/kqueue_tests.c 2016-08-12 01:16:44 UTC (rev 7701)
@@ -0,0 +1,615 @@
+/*
+ * tests.c
+ * xnu_quick_test
+ *
+ * Created by Jerry Cottingham on 3/25/05.
+ * Copyright 2005 Apple Computer Inc. All rights reserved.
+ *
+ */
+
+typedef int boolean_t;
+#include <sys/types.h>
+#include "tests.h"
+#include <pthread.h>
+#include <assert.h>
+#include <sys/event.h> /* for kqueue tests */
+#include <sys/sysctl.h> /* for determining hw */
+#include <mach/mach.h>
+#include <mach/mach_traps.h>
+#include <AvailabilityMacros.h> /* for determination of Mac OS X version (tiger, leopard, etc.) */
+
+
+char g_target_path[ PATH_MAX ];
+extern int g_skip_setuid_tests;
+
+int msg_count = 14;
+int last_msg_seen = 0;
+pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define VM_MAKE_TAG(tag) ((tag) << 24)
+#define VM_MEMORY_MACH_MSG 20
+
+/*
+ * create_random_name - creates a file with a random / unique name in the given directory.
+ * when do_open is true we create a file else we generaate a name that does not exist in the
+ * given directory (we do not create anything when do_open is 0).
+ * WARNING - caller provides enough space in path buffer for longest possible name.
+ * WARNING - assumes caller has appended a trailing '/' on the path passed to us.
+ * RAND_MAX is currently 2147483647 (ten characters plus one for a slash)
+ */
+int create_random_name( char *the_pathp, int do_open ) {
+ int i, my_err;
+ int my_fd = -1;
+
+ for ( i = 0; i < 1; i++ ) {
+ int my_rand;
+ char *myp;
+ char my_name[32];
+
+ my_rand = rand( );
+ sprintf( &my_name[0], "%d", my_rand );
+ if ( (strlen( &my_name[0] ) + strlen( the_pathp ) + 2) > PATH_MAX ) {
+ printf( "%s - path to test file greater than PATH_MAX \n", __FUNCTION__ );
+ return( -1 );
+ }
+
+ // append generated file name onto our path
+ myp = strrchr( the_pathp, '/' );
+ *(myp + 1) = 0x00;
+ strcat( the_pathp, &my_name[0] );
+ if ( do_open ) {
+ /* create a file with this name */
+ my_fd = open( the_pathp, (O_RDWR | O_CREAT | O_EXCL),
+ (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) );
+ if ( my_fd == -1 ) {
+ if ( errno != EEXIST ) {
+ printf( "%s - open failed with errno %d - %s \n",
+ __FUNCTION__, errno, strerror( errno ) );
+ return( -1 );
+ }
+ // name already exists, try another
+ i--;
+ continue;
+ }
+ }
+ else {
+ /* make sure the name is unique */
+ struct stat my_sb;
+ my_err = stat( the_pathp, &my_sb );
+ if ( my_err != 0 ) {
+ if ( errno == ENOENT ) {
+ break;
+ }
+ else {
+ printf( "%s - open failed with errno %d - %s \n",
+ __FUNCTION__, errno, strerror( errno ) );
+ return( -1 );
+ }
+ }
+ /* name already exists, try another */
+ i--;
+ continue;
+ }
+ }
+
+ if ( my_fd != -1 )
+ close( my_fd );
+
+ return( 0 );
+
+} /* create_random_name */
+
+static kern_return_t
+kmsg_send(mach_port_t remote_port, int index)
+{
+ int msgh_id = 1000 + index;
+ kern_return_t my_kr;
+ mach_msg_header_t * my_kmsg = NULL;
+ mach_msg_size_t size = sizeof(mach_msg_header_t) + sizeof(int)*index;
+
+ my_kr = mach_vm_allocate( mach_task_self(),
+ (vm_address_t *)&my_kmsg,
+ size,
+ VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE );
+ if (my_kr != KERN_SUCCESS)
+ return my_kr;
+ my_kmsg->msgh_bits =
+ MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0);
+ my_kmsg->msgh_size = size;
+ my_kmsg->msgh_remote_port = remote_port;
+ my_kmsg->msgh_local_port = MACH_PORT_NULL;
+ my_kmsg->msgh_voucher_port = MACH_PORT_NULL;
+ my_kmsg->msgh_id = msgh_id;
+ my_kr = mach_msg( my_kmsg,
+ MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
+ size,
+ 0, /* receive size */
+ MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL );
+ mach_vm_deallocate( mach_task_self(), (vm_address_t)my_kmsg, size );
+ return my_kr;
+}
+
+static kern_return_t
+kmsg_recv(mach_port_t portset, mach_port_t port, int * msgh_id_return)
+{
+ kern_return_t my_kr;
+ mach_msg_header_t * my_kmsg = NULL;
+
+ my_kr = mach_vm_allocate( mach_task_self(),
+ (vm_address_t *)&my_kmsg,
+ PAGE_SIZE,
+ VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE );
+ if (my_kr != KERN_SUCCESS)
+ return my_kr;
+ my_kr = mach_msg( my_kmsg,
+ MACH_RCV_MSG | MACH_MSG_OPTION_NONE,
+ 0, /* send size */
+ PAGE_SIZE, /* receive size */
+ port,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL );
+ if ( my_kr == KERN_SUCCESS &&
+ msgh_id_return != NULL )
+ *msgh_id_return = my_kmsg->msgh_id;
+ mach_vm_deallocate( mach_task_self(), (vm_address_t)my_kmsg, PAGE_SIZE );
+ return my_kr;
+}
+
+static void *
+kmsg_consumer_thread(void * arg)
+{
+ int my_kqueue = *(int *)arg;
+ int my_err;
+ kern_return_t my_kr;
+ struct kevent my_keventv[3];
+ int msgid;
+
+ EV_SET( &my_keventv[0], 0, 0, 0, 0, 0, 0 );
+ while ( !(my_keventv[0].filter == EVFILT_USER &&
+ my_keventv[0].ident == 0)) {
+ /* keep getting events */
+ my_err = kevent( my_kqueue, NULL, 0, my_keventv, 1, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call from consumer thread failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ return (void *)-1;
+ }
+ if ( my_err == 0 ) {
+ printf( "kevent call from consumer thread did not return any events when it should have \n" );
+ return (void *)-1;
+ }
+ if ( my_keventv[0].filter == EVFILT_MACHPORT ) {
+ if ( my_keventv[0].data == 0 ) {
+ printf( "kevent call to get machport event returned 0 msg_size \n" );
+ return (void *)-1;
+ }
+ my_kr = kmsg_recv( my_keventv[0].ident, my_keventv[0].data, &msgid );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "kmsg_recv failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ return (void *)-1;
+ }
+ my_keventv[0].flags = EV_ENABLE;
+ my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to re-enable machport events failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ return (void *)-1;
+ }
+ if (msgid == 1000 + msg_count) {
+ pthread_mutex_lock(&my_mutex);
+ last_msg_seen = 1;
+ pthread_cond_signal(&my_cond);
+ pthread_mutex_unlock(&my_mutex);
+ }
+ }
+ }
+ return (void *)0;
+}
+
+
+
+/* **************************************************************************************************************
+ * Test kevent, kqueue system calls.
+ * **************************************************************************************************************
+ */
+int kqueue_tests( void * the_argp )
+{
+ int my_err, my_status;
+ void *my_pthread_join_status;
+ int my_kqueue = -1;
+ int my_kqueue64 = -1;
+ int my_fd = -1;
+ char * my_pathp = NULL;
+ pid_t my_pid, my_wait_pid;
+ size_t my_count, my_index;
+ int my_sockets[ 2 ] = {-1, -1};
+ struct kevent my_keventv[3];
+ struct kevent64_s my_kevent64;
+ struct timespec my_timeout;
+ char my_buffer[ 16 ];
+ kern_return_t kr;
+
+ kr = mach_vm_allocate((mach_vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
+ if(kr != KERN_SUCCESS){
+ printf( "vm_allocate failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ *my_pathp = 0x00;
+ strcat( my_pathp, &g_target_path[0] );
+ strcat( my_pathp, "/" );
+
+ /* create a test file */
+ my_err = create_random_name( my_pathp, 1 );
+ if ( my_err != 0 ) {
+ goto test_failed_exit;
+ }
+
+ my_fd = open( my_pathp, O_RDWR, 0 );
+ if ( my_fd == -1 ) {
+ printf( "open call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ my_err = socketpair( AF_UNIX, SOCK_STREAM, 0, &my_sockets[0] );
+ if ( my_err == -1 ) {
+ printf( "socketpair failed with errno %d - %s \n", errno, strerror( errno ) );
+ goto test_failed_exit;
+ }
+
+ /* fork here and use pipe to communicate */
+ my_pid = fork( );
+ if ( my_pid == -1 ) {
+ printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
+ goto test_failed_exit;
+ }
+ else if ( my_pid == 0 ) {
+ /*
+ * child process - tell parent we are ready to go.
+ */
+ my_count = write( my_sockets[1], "r", 1 );
+ if ( my_count == -1 ) {
+ printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) );
+ exit( -1 );
+ }
+
+ my_count = read( my_sockets[1], &my_buffer[0], 1 );
+ if ( my_count == -1 ) {
+ printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ exit( -1 );
+ }
+ if ( my_buffer[0] != 'g' ) {
+ printf( "read call on socket failed to get \"all done\" message \n" );
+ exit( -1 );
+ }
+
+ /* now do some work that will trigger events our parent will track */
+ my_count = write( my_fd, "11111111", 8 );
+ if ( my_count == -1 ) {
+ printf( "write call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ exit( -1 );
+ }
+
+ my_err = unlink( my_pathp );
+ if ( my_err == -1 ) {
+ printf( "unlink failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ exit( -1 );
+ }
+
+ /* wait for parent to tell us to exit */
+ my_count = read( my_sockets[1], &my_buffer[0], 1 );
+ if ( my_count == -1 ) {
+ printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ exit( -1 );
+ }
+ if ( my_buffer[0] != 'e' ) {
+ printf( "read call on socket failed to get \"all done\" message \n" );
+ exit( -1 );
+ }
+ exit(0);
+ }
+
+ /* parent process - wait for child to spin up */
+ my_count = read( my_sockets[0], &my_buffer[0], sizeof(my_buffer) );
+ if ( my_count == -1 ) {
+ printf( "read call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+ if ( my_buffer[0] != 'r' ) {
+ printf( "read call on socket failed to get \"ready to go message\" \n" );
+ goto test_failed_exit;
+ }
+
+ /* set up a kqueue and register for some events */
+ my_kqueue = kqueue( );
+ if ( my_kqueue == -1 ) {
+ printf( "kqueue call failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ /* look for our test file to get unlinked or written to */
+ EV_SET( &my_keventv[0], my_fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR), (NOTE_DELETE | NOTE_WRITE), 0, 0 );
+ /* also keep an eye on our child process while we're at it */
+ EV_SET( &my_keventv[1], my_pid, EVFILT_PROC, (EV_ADD | EV_ONESHOT), NOTE_EXIT, 0, 0 );
+
+ my_timeout.tv_sec = 0;
+ my_timeout.tv_nsec = 0;
+ my_err = kevent( my_kqueue, my_keventv, 2, NULL, 0, &my_timeout);
+ if ( my_err == -1 ) {
+ printf( "kevent call to register events failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ /* use kevent64 to test EVFILT_PROC */
+ EV_SET64( &my_kevent64, my_pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, 0, 0, 0 );
+ my_err = kevent64( my_kqueue, &my_kevent64, 1, NULL, 0, 0, 0);
+ if ( my_err != -1 && errno != EINVAL ) {
+ printf( "kevent64 call should fail with kqueue used for kevent() - %d\n", my_err);
+ /* goto test_failed_exit; */
+ }
+
+ my_kqueue64 = kqueue();
+ EV_SET64( &my_kevent64, my_pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, 0, 0, 0 );
+ my_err = kevent64( my_kqueue64, &my_kevent64, 1, NULL, 0, 0, 0);
+ if ( my_err == -1 ) {
+ printf( "kevent64 call to get proc exit failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ /* tell child to get to work */
+ my_count = write( my_sockets[0], "g", 1 );
+ if ( my_count == -1 ) {
+ printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) );
+ goto test_failed_exit;
+ }
+
+ /* go get vnode events */
+ EV_SET( &my_keventv[0], my_fd, EVFILT_VNODE, (EV_CLEAR), 0, 0, 0 );
+ my_err = kevent( my_kqueue, NULL, 0, my_keventv, 1, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to get vnode events failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+ if ( my_err == 0 ) {
+ printf( "kevent call to get vnode events did not return any when it should have \n" );
+ goto test_failed_exit;
+ }
+ if ( (my_keventv[0].fflags & (NOTE_DELETE | NOTE_WRITE)) == 0 ) {
+ printf( "kevent call to get vnode events did not return NOTE_DELETE or NOTE_WRITE \n" );
+ printf( "fflags 0x%02X \n", my_keventv[0].fflags );
+ goto test_failed_exit;
+ }
+
+ /* tell child to exit */
+ my_count = write( my_sockets[0], "e", 1 );
+ if ( my_count == -1 ) {
+ printf( "write call failed. got errno %d - %s. \n", errno, strerror( errno ) );
+ goto test_failed_exit;
+ }
+
+ /* look for child exit notification after unregistering for vnode events */
+ EV_SET( &my_keventv[0], my_fd, EVFILT_VNODE, EV_DELETE, 0, 0, 0 );
+ my_err = kevent( my_kqueue, my_keventv, 1, my_keventv, 1, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to get proc exit event failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+ if ( my_err == 0 ) {
+ printf( "kevent call to get proc exit event did not return any when it should have \n" );
+ goto test_failed_exit;
+ }
+ if ( my_keventv[0].filter != EVFILT_PROC ) {
+ printf( "kevent call to get proc exit event did not return EVFILT_PROC \n" );
+ printf( "filter %i \n", my_keventv[0].filter );
+ goto test_failed_exit;
+ }
+ if ( (my_keventv[0].fflags & NOTE_EXIT) == 0 ) {
+ printf( "kevent call to get proc exit event did not return NOTE_EXIT \n" );
+ printf( "fflags 0x%02X \n", my_keventv[0].fflags );
+ goto test_failed_exit;
+ }
+
+ /* look for child exit notification on the kevent64 kqueue */
+ EV_SET64( &my_kevent64, my_pid, EVFILT_PROC, EV_CLEAR, NOTE_EXIT, 0, 0, 0, 0 );
+ my_err = kevent64( my_kqueue64, NULL, 0, &my_kevent64, 1, 0, 0);
+ if ( my_err == -1 ) {
+ printf( "kevent64 call to get child exit failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+ if ( my_err == 0 ) {
+ printf( "kevent64 call to get proc exit event did not return any when it should have \n" );
+ goto test_failed_exit;
+ }
+ if ( my_kevent64.filter != EVFILT_PROC ) {
+ printf( "kevent64 call to get proc exit event did not return EVFILT_PROC \n" );
+ printf( "filter %i \n", my_kevent64.filter );
+ goto test_failed_exit;
+ }
+ if ( (my_kevent64.fflags & NOTE_EXIT) == 0 ) {
+ printf( "kevent64 call to get proc exit event did not return NOTE_EXIT \n" );
+ printf( "fflags 0x%02X \n", my_kevent64.fflags );
+ goto test_failed_exit;
+ }
+
+ my_wait_pid = wait4( my_pid, &my_status, 0, NULL );
+ if ( my_wait_pid == -1 ) {
+ printf( "wait4 failed with errno %d - %s \n", errno, strerror( errno ) );
+ goto test_failed_exit;
+ }
+
+ /* wait4 should return our child's pid when it exits */
+ if ( my_wait_pid != my_pid ) {
+ printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid, my_pid );
+ goto test_failed_exit;
+ }
+
+ if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
+ printf( "wait4 returned wrong exit status - 0x%02X \n", my_status );
+ goto test_failed_exit;
+ }
+
+ /* now try out EVFILT_MACHPORT and EVFILT_USER */
+ mach_port_t my_pset = MACH_PORT_NULL;
+ mach_port_t my_port = MACH_PORT_NULL;
+ kern_return_t my_kr;
+
+ my_kr = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &my_pset );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "mach_port_allocate failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ goto test_failed_exit;
+ }
+
+ my_kr = mach_port_allocate( mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &my_port );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "mach_port_allocate failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ goto test_failed_exit;
+ }
+
+ /* try to register for events on my_port directly -- this should fail */
+ EV_SET( &my_keventv[0], my_port, EVFILT_MACHPORT, (EV_ADD | EV_DISPATCH), 0, 0, 0 );
+ my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL );
+ if ( my_err != -1 || (errno != ENOTCAPABLE && errno != ENOTSUP) ) {
+ printf( "kevent call to register my_port should have failed, but got %s \n", strerror(errno) );
+ goto test_failed_exit;
+ }
+
+ /* now register for events on my_pset and user 0 */
+ EV_SET( &my_keventv[0], my_pset, EVFILT_MACHPORT, (EV_ADD | EV_CLEAR | EV_DISPATCH), 0, 0, 0 );
+ EV_SET( &my_keventv[1], 0, EVFILT_USER, EV_ADD, 0, 0, 0 );
+ my_err = kevent( my_kqueue, my_keventv, 2, NULL, 0, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to register my_pset and user 0 failed with error %d - %s \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ pthread_t my_threadv[3];
+
+ for (my_index = 0;
+ my_index < 3;
+ my_index++) {
+ my_err = pthread_create( &my_threadv[my_index], NULL, kmsg_consumer_thread, (void *)&my_kqueue );
+ if ( my_err != 0 ) {
+ printf( "pthread_create failed with error %d - %s \n", my_err, strerror(my_err) );
+ goto test_failed_exit;
+ }
+ }
+
+ /* insert my_port into my_pset */
+ my_kr = mach_port_insert_member( mach_task_self(), my_port, my_pset );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "mach_port_insert_member failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ goto test_failed_exit;
+ }
+
+ my_kr = mach_port_insert_right( mach_task_self(), my_port, my_port, MACH_MSG_TYPE_MAKE_SEND );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "mach_port_insert_right failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ goto test_failed_exit;
+ }
+
+ /* send some Mach messages */
+ for (my_index = 1;
+ my_index <= msg_count;
+ my_index++) {
+ my_kr = kmsg_send( my_port, my_index );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "kmsg_send failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ goto test_failed_exit;
+ }
+ }
+
+ /* make sure the last message eventually gets processed */
+ pthread_mutex_lock(&my_mutex);
+ while (last_msg_seen == 0)
+ pthread_cond_wait(&my_cond, &my_mutex);
+ pthread_mutex_unlock(&my_mutex);
+
+ /* trigger the user 0 event, telling consumer threads to exit */
+ EV_SET( &my_keventv[0], 0, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0 );
+ my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to trigger user 0 failed with error %d - %s \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ for (my_index = 0;
+ my_index < 3;
+ my_index++) {
+ my_err = pthread_join( my_threadv[my_index], &my_pthread_join_status );
+ if ( my_err != 0 ) {
+ printf( "pthread_join failed with error %d - %s \n", my_err, strerror(my_err) );
+ goto test_failed_exit;
+ }
+ if ( my_pthread_join_status != 0 ) {
+ goto test_failed_exit;
+ }
+ }
+
+ /* clear the user 0 event */
+ EV_SET( &my_keventv[0], 0, EVFILT_USER, EV_CLEAR, 0, 0, 0 );
+ my_err = kevent( my_kqueue, my_keventv, 1, NULL, 0, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to trigger user 0 failed with error %d - %s \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+
+ /* delibrately destroy my_pset while it's still registered for events */
+ my_kr = mach_port_mod_refs( mach_task_self(), my_pset, MACH_PORT_RIGHT_PORT_SET, -1 );
+ if ( my_kr != KERN_SUCCESS ) {
+ printf( "mach_port_mod_refs failed with error %d - %s \n", my_kr, mach_error_string(my_kr) );
+ goto test_failed_exit;
+ }
+
+ /* look for the event to trigger with a zero msg_size */
+ my_err = kevent( my_kqueue, NULL, 0, my_keventv, 1, NULL );
+ if ( my_err == -1 ) {
+ printf( "kevent call to get machport event failed with error %d - \"%s\" \n", errno, strerror( errno) );
+ goto test_failed_exit;
+ }
+ if ( my_err == 0 ) {
+ printf( "kevent call to get machport event did not return any when it should have \n" );
+ goto test_failed_exit;
+ }
+ if ( my_keventv[0].filter != EVFILT_MACHPORT ) {
+ printf( "kevent call to get machport event did not return EVFILT_MACHPORT \n" );
+ printf( "filter %i \n", my_keventv[0].filter );
+ goto test_failed_exit;
+ }
+ if ( my_keventv[0].data != 0 ) {
+ printf( "kevent call to get machport event did not return 0 msg_size \n" );
+ printf( "data %ld \n", (long int) my_keventv[0].data );
+ goto test_failed_exit;
+ }
+
+ my_err = 0;
+ goto test_passed_exit;
+
+test_failed_exit:
+ my_err = -1;
+
+test_passed_exit:
+ if ( my_sockets[0] != -1 )
+ close( my_sockets[0] );
+ if ( my_sockets[1] != -1 )
+ close( my_sockets[1] );
+ if ( my_kqueue != -1 )
+ close( my_kqueue );
+ if ( my_kqueue64 != -1 )
+ close( my_kqueue );
+ if ( my_fd != -1 )
+ close( my_fd );
+ if ( my_pathp != NULL ) {
+ remove( my_pathp );
+ mach_vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);
+ }
+ return( my_err );
+}
+
+
+int
+main(int argc, char *argv[]) {
+
+ return (kqueue_tests(NULL));
+}
+
Property changes on: trunk/lib/libmach/test/kqueue_tests/kqueue_tests.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
More information about the Midnightbsd-cvs
mailing list