[launchd-changes] [23264] trunk/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Fri May 25 13:44:01 PDT 2007


Revision: 23264
          http://trac.macosforge.org/projects/launchd/changeset/23264
Author:   zarzycki at apple.com
Date:     2007-05-25 13:44:01 -0700 (Fri, 25 May 2007)

Log Message:
-----------
<rdar://problem/4991686> spawn_via_launchd: specify quarantine and seatbelt information

Modified Paths:
--------------
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/launchd_mig_types.defs
    trunk/launchd/src/liblaunch_private.h
    trunk/launchd/src/libvproc.c
    trunk/launchd/src/libvproc_internal.h
    trunk/launchd/src/protocol_job.defs

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2007-05-24 20:54:19 UTC (rev 23263)
+++ trunk/launchd/src/launchd_core_logic.c	2007-05-25 20:44:01 UTC (rev 23264)
@@ -72,6 +72,7 @@
 #include <ctype.h>
 #include <glob.h>
 #include <spawn.h>
+#include <sandbox.h>
 
 #include "liblaunch_public.h"
 #include "liblaunch_private.h"
@@ -194,6 +195,7 @@
 static bool limititem_update(job_t j, int w, rlim_t r);
 static void limititem_delete(job_t j, struct limititem *li);
 static void limititem_setup(launch_data_t obj, const char *key, void *context);
+static void seatbelt_setup_flags(launch_data_t obj, const char *key, void *context);
 
 typedef enum {
 	NETWORK_UP = 1,
@@ -297,7 +299,7 @@
 #if DO_RUSAGE_SUMMATION
 	struct rusage ru;
 #endif
-	binpref_t j_binpref;
+	cpu_type_t *j_binpref;
 	size_t j_binpref_cnt;
 	mach_port_t j_port;
 	mach_port_t wait_reply_port;
@@ -313,6 +315,10 @@
 	char *stderrpath;
 	struct machservice *lastlookup;
 	unsigned int lastlookup_gennum;
+	char *seatbelt_profile;
+	uint64_t seatbelt_flags;
+	void *quarantine_data;
+	size_t quarantine_data_sz;
 	pid_t p;
 	int argc;
 	int last_exit_status;
@@ -354,6 +360,7 @@
 static void job_import_integer(job_t j, const char *key, long long value);
 static void job_import_dictionary(job_t j, const char *key, launch_data_t value);
 static void job_import_array(job_t j, const char *key, launch_data_t value);
+static void job_import_opaque(job_t j, const char *key, launch_data_t value);
 static bool job_set_global_on_demand(job_t j, bool val);
 static void job_watch(job_t j);
 static void job_ignore(job_t j);
@@ -376,7 +383,6 @@
 static void job_callback_read(job_t j, int ident);
 static job_t job_new_anonymous(jobmgr_t jm, pid_t anonpid);
 static job_t job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv);
-static job_t job_new_spawn(job_t j, const char *label, const char *path, const char *workingdir, const char *const *argv, const char *const *env, mode_t *u_mask, bool w4d);
 static job_t job_new_via_mach_init(job_t j, const char *cmd, uid_t uid, bool ond);
 static const char *job_prog(job_t j);
 static pid_t job_get_pid(job_t j);
@@ -773,6 +779,12 @@
 	if (j->stderrpath) {
 		free(j->stderrpath);
 	}
+	if (j->seatbelt_profile) {
+		free(j->seatbelt_profile);
+	}
+	if (j->quarantine_data) {
+		free(j->quarantine_data);
+	}
 	if (j->start_interval) {
 		job_assumes(j, kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_DELETE, 0, 0, NULL) != -1);
 	}
@@ -921,64 +933,6 @@
 	return 0;
 }
 
-job_t 
-job_new_spawn(job_t j, const char *label, const char *path, const char *workingdir, const char *const *argv, const char *const *env, mode_t *u_mask, bool w4d)
-{
-	job_t jr;
-	size_t i;
-
-	if ((jr = job_find(label)) != NULL) {
-		errno = EEXIST;
-		return NULL;
-	}
-
-	jr = job_new(j->mgr, label, path, argv);
-
-	if (!jr) {
-		return NULL;
-	}
-
-	job_reparent_hack(jr, NULL);
-
-	if (getpid() == 1) {
-		struct ldcred ldc;
-
-		runtime_get_caller_creds(&ldc);
-		jr->mach_uid = ldc.uid;
-	}
-
-	jr->unload_at_exit = true;
-	jr->wait4pipe_eof = true;
-	jr->stall_before_exec = w4d;
-
-	if (workingdir) {
-		jr->workingdir = strdup(workingdir);
-	}
-
-	if (u_mask) {
-		jr->mask = *u_mask;
-		jr->setmask = true;
-	}
-
-	if (env) for (i = 0; env[i]; i++) {
-		char *eqoff, tmpstr[strlen(env[i]) + 1];
-
-		strcpy(tmpstr, env[i]);
-
-		eqoff = strchr(tmpstr, '=');
-
-		if (!eqoff) {
-			job_log(jr, LOG_WARNING, "Environmental variable missing '=' separator: %s", tmpstr);
-			continue;
-		}
-
-		*eqoff = '\0';
-		envitem_new(jr, tmpstr, eqoff + 1, false);
-	}
-
-	return jr;
-}
-
 job_t
 job_new_anonymous(jobmgr_t jm, pid_t anonpid)
 {
@@ -1357,6 +1311,8 @@
 			where2put = &j->stdoutpath;
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_STANDARDERRORPATH) == 0) {
 			where2put = &j->stderrpath;
+		} else if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOXPROFILE) == 0) {
+			where2put = &j->seatbelt_profile;
 		}
 		break;
 	default:
@@ -1426,7 +1382,10 @@
 			if (-1 == kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_ADD, NOTE_SECONDS, value, j)) {
 				job_log_error(j, LOG_ERR, "adding kevent timer");
 			}
+		} else if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOXFLAGS) == 0) {
+			j->seatbelt_flags = value;
 		}
+
 		break;
 	default:
 		job_log(j, LOG_WARNING, "Unknown key for integer: %s", key);
@@ -1435,6 +1394,26 @@
 }
 
 void
+job_import_opaque(job_t j, const char *key, launch_data_t value)
+{
+	switch (key[0]) {
+	case 'q':
+	case 'Q':
+		if (strcasecmp(key, LAUNCH_JOBKEY_QUARANTINEDATA) == 0) {
+			size_t tmpsz = launch_data_get_opaque_size(value);
+
+			if (job_assumes(j, j->quarantine_data = malloc(tmpsz))) {
+				memcpy(j->quarantine_data, launch_data_get_opaque(value), tmpsz);
+				j->quarantine_data_sz = tmpsz;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void
 job_import_dictionary(job_t j, const char *key, launch_data_t value)
 {
 	launch_data_t tmp;
@@ -1477,6 +1456,8 @@
 			calendarinterval_new_from_obj(j, value);
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_SOFTRESOURCELIMITS) == 0) {
 			launch_data_dict_iterate(value, limititem_setup, j);
+		} else if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOXFLAGS) == 0) {
+			launch_data_dict_iterate(value, seatbelt_setup_flags, j);
 		}
 		break;
 	case 'h':
@@ -1552,6 +1533,13 @@
 	case 'B':
 		if (strcasecmp(key, LAUNCH_JOBKEY_BONJOURFDS) == 0) {
 			socketgroup_setup(value, LAUNCH_JOBKEY_BONJOURFDS, j);
+		} else if (strcasecmp(key, LAUNCH_JOBKEY_BINARYORDERPREFERENCE) == 0) {
+			if (job_assumes(j, j->j_binpref = malloc(value_cnt * sizeof(*j->j_binpref)))) {
+				j->j_binpref_cnt = value_cnt;
+				for (i = 0; i < value_cnt; i++) {
+					j->j_binpref[i] = launch_data_get_integer(launch_data_array_get_index(value, i));
+				}
+			}
 		}
 		break;
 	case 's':
@@ -1596,6 +1584,9 @@
 	case LAUNCH_DATA_ARRAY:
 		job_import_array(j, key, obj);
 		break;
+	case LAUNCH_DATA_OPAQUE:
+		job_import_opaque(j, key, obj);
+		break;
 	default:
 		job_log(j, LOG_WARNING, "Unknown value type '%d' for key: %s", kind, key);
 		break;
@@ -2374,6 +2365,27 @@
 		signal(i, SIG_DFL);
 	}
 
+	if (j->quarantine_data) {
+		qtn_proc_t qp;
+
+		if (job_assumes(j, qp = qtn_proc_alloc())) {
+			if (job_assumes(j, qtn_proc_init_with_data(qp, j->quarantine_data, j->quarantine_data_sz) == 0)) {
+				job_assumes(j, qtn_proc_apply_to_self(qp) == 0);
+			}
+		}
+	}
+
+	if (j->seatbelt_profile) {
+		char *seatbelt_err_buf = NULL;
+
+		if (!job_assumes(j, sandbox_init(j->seatbelt_profile, j->seatbelt_flags, &seatbelt_err_buf) != -1)) {
+			if (seatbelt_err_buf) {
+				job_log(j, LOG_ERR, "Sandbox failed to init: %s", seatbelt_err_buf);
+			}
+			goto out_bad;
+		}
+	}
+
 	if (j->prog) {
 		errno = posix_spawn(&junk_pid, j->inetcompat ? file2exec : j->prog, NULL, &spattr, (char *const*)argv, environ);
 		job_log_error(j, LOG_ERR, "posix_spawn(\"%s\", ...)", j->prog);
@@ -2382,6 +2394,7 @@
 		job_log_error(j, LOG_ERR, "posix_spawnp(\"%s\", ...)", argv[0]);
 	}
 
+out_bad:
 	_exit(EXIT_FAILURE);
 }
 
@@ -3231,6 +3244,25 @@
 }
 
 void
+seatbelt_setup_flags(launch_data_t obj, const char *key, void *context)
+{
+	job_t j = context;
+
+	if (launch_data_get_type(obj) != LAUNCH_DATA_BOOL) {
+		job_log(j, LOG_WARNING, "Sandbox flag value must be boolean: %s", key);
+		return;
+	}
+
+	if (launch_data_get_bool(obj) == false) {
+		return;
+	}
+
+	if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOX_NAMED) == 0) {
+		j->seatbelt_flags |= SANDBOX_NAMED;
+	}
+}
+
+void
 limititem_setup(launch_data_t obj, const char *key, void *context)
 {
 	job_t j = context;
@@ -5320,8 +5352,6 @@
 
 	kr = _vproc_grab_subset(target_subset, &reqport, &rcvright, &out_obj_array, &l2l_ports, &l2l_port_cnt);
 
-	job_log(j, LOG_NOTICE, "@@@@@ kr == 0x%x", kr);
-
 	if (!job_assumes(j, kr == 0)) {
 		goto out;
 	}
@@ -5343,11 +5373,11 @@
 
 		job_assumes(j, obj_at_idx = launch_data_array_get_index(out_obj_array, l2l_i));
 		job_assumes(j, tmp = launch_data_dict_lookup(obj_at_idx, TAKE_SUBSET_PID));
-		job_assumes(j, target_pid = launch_data_get_integer(tmp));
+		target_pid = launch_data_get_integer(tmp);
 		job_assumes(j, tmp = launch_data_dict_lookup(obj_at_idx, TAKE_SUBSET_PERPID));
-		job_assumes(j, serv_perpid = launch_data_get_bool(tmp));
+		serv_perpid = launch_data_get_bool(tmp);
 		job_assumes(j, tmp = launch_data_dict_lookup(obj_at_idx, TAKE_SUBSET_NAME));
-		job_assumes(j, serv_name = launch_data_get_string(tmp));
+		serv_name = launch_data_get_string(tmp);
 
 		j_for_service = jobmgr_find_by_pid(jmr, target_pid, true);
 
@@ -5647,19 +5677,12 @@
 }
 
 kern_return_t
-job_mig_spawn(job_t j, _internal_string_t charbuf, mach_msg_type_number_t charbuf_cnt,
-		uint32_t argc, uint32_t envc, uint64_t flags, uint16_t mig_umask,
-		binpref_t bin_pref, uint32_t binpref_cnt, pid_t *child_pid, mach_port_t *obsvr_port)
+job_mig_spawn(job_t j, vm_offset_t indata, mach_msg_type_number_t indataCnt, pid_t *child_pid, mach_port_t *obsvr_port)
 {
+	launch_data_t input_obj = NULL;
+	size_t data_offset = 0;
+	struct ldcred ldc;
 	job_t jr;
-	size_t offset = 0;
-	char *tmpp;
-	const char **argv = NULL, **env = NULL;
-	const char *label = NULL;
-	const char *path = NULL;
-	const char *workingdir = NULL;
-	size_t argv_i = 0, env_i = 0;
-	struct ldcred ldc;
 
 	runtime_get_caller_creds(&ldc);
 
@@ -5672,38 +5695,15 @@
 		return VPROC_ERR_TRY_PER_USER;
 	}
 
-	argv = alloca((argc + 1) * sizeof(char *));
-	memset(argv, 0, (argc + 1) * sizeof(char *));
-
-	if (envc > 0) {
-		env = alloca((envc + 1) * sizeof(char *));
-		memset(env, 0, (envc + 1) * sizeof(char *));
+	if (indataCnt == 0) {
+		return 1;
 	}
 
-	while (offset < charbuf_cnt) {
-		tmpp = charbuf + offset;
-		offset += strlen(tmpp) + 1;
-		if (!label) {
-			label = tmpp;
-		} else if (argc > 0) {
-			argv[argv_i] = tmpp;
-			argv_i++;
-			argc--;
-		} else if (envc > 0) {
-			env[env_i] = tmpp;
-			env_i++;
-			envc--;
-		} else if (flags & SPAWN_HAS_PATH) {
-			path = tmpp;
-			flags &= ~SPAWN_HAS_PATH;
-		} else if (flags & SPAWN_HAS_WDIR) {
-			workingdir = tmpp;
-			flags &= ~SPAWN_HAS_WDIR;
-		}
+	if (!job_assumes(j, (input_obj = launch_data_unpack((void *)indata, indataCnt, NULL, 0, &data_offset, NULL)) != NULL)) {
+		return 1;
 	}
 
-	jr = job_new_spawn(j, label, path, workingdir, argv, env, flags & SPAWN_HAS_UMASK ? &mig_umask : NULL,
-			flags & SPAWN_WANTS_WAIT4DEBUGGER);
+	jr = job_import2(input_obj);
 
 	if (jr == NULL) switch (errno) {
 	case EEXIST:
@@ -5712,9 +5712,17 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	memcpy(jr->j_binpref, bin_pref, sizeof(jr->j_binpref));
-	jr->j_binpref_cnt = binpref_cnt;
+	job_reparent_hack(jr, NULL);
 
+	if (getpid() == 1) {
+		jr->mach_uid = ldc.uid;
+	}
+
+	jr->unload_at_exit = true;
+	jr->wait4pipe_eof = true;
+	jr->stall_before_exec = jr->wait4debugger;
+	jr->wait4debugger = false;
+
 	jr = job_dispatch(jr, true);
 
 	if (!job_assumes(j, jr != NULL)) {
@@ -5726,12 +5734,12 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	job_log(j, LOG_INFO, "Spawned with flags:%s", flags & SPAWN_WANTS_WAIT4DEBUGGER ? " stopped": "");
+	job_log(j, LOG_INFO, "Spawned");
 
 	*child_pid = job_get_pid(jr);
 	*obsvr_port = jr->j_port;
 
-	mig_deallocate((vm_address_t)charbuf, charbuf_cnt);
+	mig_deallocate(indata, indataCnt);
 
 	return BOOTSTRAP_SUCCESS;
 }

Modified: trunk/launchd/src/launchd_mig_types.defs
===================================================================
--- trunk/launchd/src/launchd_mig_types.defs	2007-05-24 20:54:19 UTC (rev 23263)
+++ trunk/launchd/src/launchd_mig_types.defs	2007-05-25 20:44:01 UTC (rev 23264)
@@ -30,13 +30,10 @@
 type vproc_gsk_t		= integer_t;
 type logmsg_t			= c_string[*:2048];
 type cmd_t			= c_string[512];
-type cmd_array_t		= ^array [] of cmd_t;
 type name_t			= c_string[128];
 type name_array_t		= ^array [] of name_t;
-type _internal_string_t		= ^array [] of char;
 type bootstrap_status_t		= integer_t;
 type bootstrap_status_array_t	= ^array [] of bootstrap_status_t;
-type binpref_t			= array [8] of integer_t;
 
 type job_t = mach_port_t
         intran: job_t job_mig_intran(mach_port_t) 

Modified: trunk/launchd/src/liblaunch_private.h
===================================================================
--- trunk/launchd/src/liblaunch_private.h	2007-05-24 20:54:19 UTC (rev 23263)
+++ trunk/launchd/src/liblaunch_private.h	2007-05-25 20:44:01 UTC (rev 23264)
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <launch.h>
 #include <unistd.h>
+#include <quarantine.h>
 
 #pragma GCC visibility push(default)
 
@@ -45,9 +46,15 @@
 #define LAUNCH_KEY_BATCHCONTROL		"BatchControl"
 #define LAUNCH_KEY_BATCHQUERY		"BatchQuery"
 
+#define LAUNCH_JOBKEY_QUARANTINEDATA	"QuarantineData"
+#define LAUNCH_JOBKEY_SANDBOXPROFILE	"SandboxProfile"
+#define LAUNCH_JOBKEY_SANDBOXFLAGS	"SandboxFlags"
+#define LAUNCH_JOBKEY_SANDBOX_NAMED	"Named"
+
 #define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL	"EnterKernelDebuggerBeforeKill"
 #define LAUNCH_JOBKEY_PERJOBMACHSERVICES	"PerJobMachServices"
 #define LAUNCH_JOBKEY_SERVICEIPC		"ServiceIPC"
+#define LAUNCH_JOBKEY_BINARYORDERPREFERENCE	"BinaryOrderPreference"
 
 #define LAUNCH_JOBKEY_MACH_KUNCSERVER	"kUNCServer"
 #define LAUNCH_JOBKEY_MACH_EXCEPTIONSERVER	"ExceptionServer"
@@ -106,9 +113,12 @@
  	mach_port_t *		spawn_observer_port;
  	const cpu_type_t *	spawn_binpref;
 	size_t			spawn_binpref_cnt;
+	const qtn_proc_t	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, 1)
+#define spawn_via_launchd(a, b, c) _spawn_via_launchd(a, b, c, 2)
 pid_t _spawn_via_launchd(
 		const char *label,
 		const char *const *argv,

Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c	2007-05-24 20:54:19 UTC (rev 23263)
+++ trunk/launchd/src/libvproc.c	2007-05-25 20:44:01 UTC (rev 23264)
@@ -172,75 +172,115 @@
 pid_t
 _spawn_via_launchd(const char *label, const char *const *argv, const struct spawn_via_launchd_attr *spawn_attrs, int struct_version)
 {
-	kern_return_t kr;
+	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;
-	size_t len, buf_len = strlen(label) + 1;
-	char *buf = strdup(label);
-	uint64_t flags = 0;
-	uint32_t argc = 0;
-	uint32_t envc = 0;
-	binpref_t bin_pref;
-	size_t binpref_cnt = 0, binpref_max = sizeof(bin_pref) / sizeof(bin_pref[0]);
+	kern_return_t kr = 1;
+	void *buf = NULL;
 	pid_t p = -1;
-	mode_t u_mask = CMASK;
-	mach_port_t obsvr_port = MACH_PORT_NULL;
 
-	memset(&bin_pref, 0, sizeof(bin_pref));
+	if ((in_obj = launch_data_alloc(LAUNCH_DATA_DICTIONARY)) == NULL) {
+		goto out;
+	}
 
-	for (tmpp = argv; *tmpp; tmpp++) {
-		argc++;
-		len = strlen(*tmpp) + 1;
-		buf = reallocf(buf, buf_len + len);
-		strcpy(buf + buf_len, *tmpp);
-		buf_len += len;
+	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 2:
+		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);
+			}
+		}
+
+		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) {
-			if (spawn_attrs->spawn_binpref_cnt < binpref_max) {
-				binpref_max = spawn_attrs->spawn_binpref_cnt;
+			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);
 			}
-
-			for (; binpref_cnt < binpref_max; binpref_cnt++) {
-				bin_pref[binpref_cnt] = spawn_attrs->spawn_binpref[binpref_cnt];
-			}
+			launch_data_dict_insert(in_obj, tmp_array, LAUNCH_JOBKEY_BINARYORDERPREFERENCE);
 		}
-
+		/* fall through */
 	case 0:
 		if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_STOPPED) {
-			flags |= SPAWN_WANTS_WAIT4DEBUGGER;
+			tmp = launch_data_new_bool(true);
+			launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_WAITFORDEBUGGER);
 		}
 
 		if (spawn_attrs->spawn_env) {
+			launch_data_t tmp_dict = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
+
 			for (tmpp = spawn_attrs->spawn_env; *tmpp; tmpp++) {
-				envc++;
-				len = strlen(*tmpp) + 1;
-				buf = reallocf(buf, buf_len + len);
-				strcpy(buf + buf_len, *tmpp);
-				buf_len += len;
+				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) {
-			flags |= SPAWN_HAS_PATH;
-			len = strlen(spawn_attrs->spawn_path) + 1;
-			buf = reallocf(buf, buf_len + len);
-			strcpy(buf + buf_len, spawn_attrs->spawn_path);
-			buf_len += len;
+			tmp = launch_data_new_string(spawn_attrs->spawn_path);
+			launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_PROGRAM);
 		}
 
 		if (spawn_attrs->spawn_chdir) {
-			flags |= SPAWN_HAS_WDIR;
-			len = strlen(spawn_attrs->spawn_chdir) + 1;
-			buf = reallocf(buf, buf_len + len);
-			strcpy(buf + buf_len, spawn_attrs->spawn_chdir);
-			buf_len += len;
+			tmp = launch_data_new_string(spawn_attrs->spawn_chdir);
+			launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_WORKINGDIRECTORY);
 		}
 
 		if (spawn_attrs->spawn_umask) {
-			flags |= SPAWN_HAS_UMASK;
-			u_mask = *spawn_attrs->spawn_umask;
+			tmp = launch_data_new_integer(*spawn_attrs->spawn_umask);
+			launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_UMASK);
 		}
 
 		break;
@@ -248,29 +288,44 @@
 		break;
 	}
 
-	kr = vproc_mig_spawn(bootstrap_port, buf, buf_len, argc, envc, flags, u_mask, bin_pref, binpref_cnt, &p, &obsvr_port);
+	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;
+
+	kr = vproc_mig_spawn(bootstrap_port, indata, indata_cnt, &p, &obsvr_port);
+
 	if (kr == VPROC_ERR_TRY_PER_USER) {
 		mach_port_t puc;
 
 		if (vproc_mig_lookup_per_user_context(bootstrap_port, 0, &puc) == 0) {
-			kr = vproc_mig_spawn(puc, buf, buf_len, argc, envc, flags, u_mask, bin_pref, binpref_cnt, &p, &obsvr_port);
+			kr = vproc_mig_spawn(puc, indata, indata_cnt, &p, &obsvr_port);
 			mach_port_deallocate(mach_task_self(), puc);
 		}
 	}
 
-	free(buf);
+out:
+	if (in_obj) {
+		launch_data_free(in_obj);
+	}
 
-	if (kr == BOOTSTRAP_SUCCESS) {
+	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 {
 			mach_port_deallocate(mach_task_self(), obsvr_port);
 		}
 		return p;
-	}
-
-	switch (kr) {
 	case BOOTSTRAP_NOT_PRIVILEGED:
 		errno = EPERM; break;
 	case BOOTSTRAP_NO_MEMORY:
@@ -278,6 +333,7 @@
 	default:
 		errno = EINVAL; break;
 	}
+
 	return -1;
 }
 

Modified: trunk/launchd/src/libvproc_internal.h
===================================================================
--- trunk/launchd/src/libvproc_internal.h	2007-05-24 20:54:19 UTC (rev 23263)
+++ trunk/launchd/src/libvproc_internal.h	2007-05-25 20:44:01 UTC (rev 23264)
@@ -29,7 +29,6 @@
 typedef char * logmsg_t;
 typedef pid_t * pid_array_t;
 typedef mach_port_t vproc_mig_t;
-typedef integer_t binpref_t[8];
 
 #ifdef protocol_vproc_MSG_COUNT
 /* HACK */

Modified: trunk/launchd/src/protocol_job.defs
===================================================================
--- trunk/launchd/src/protocol_job.defs	2007-05-24 20:54:19 UTC (rev 23263)
+++ trunk/launchd/src/protocol_job.defs	2007-05-25 20:44:01 UTC (rev 23264)
@@ -109,13 +109,7 @@
 
 routine spawn(
 		__bs_port	: job_t;
-		__chars		: _internal_string_t;
-		__argc		: uint32_t;
-		__envc		: uint32_t;
-		__flags		: uint64_t;
-		__umask		: uint16_t;
-		__binpref	: binpref_t;
-		__binpref_cnt	: uint32_t;
+		__indata	: pointer_t;
 	out	__pid		: pid_t;
 	out	__obsvr_port	: mach_port_make_send_t);
 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20070525/6d26629f/attachment.html


More information about the launchd-changes mailing list