=== modified file 'init/job.c'
--- init/job.c	2010-12-14 15:32:41 +0000
+++ init/job.c	2011-01-05 15:06:04 +0000
@@ -141,6 +141,8 @@
 	job->trace_forks = 0;
 	job->trace_state = TRACE_NONE;
 
+	job->utmp_id = NULL;
+
 	nih_hash_add (class->instances, &job->entry);
 
 	NIH_LIST_FOREACH (control_conns, iter) {

=== modified file 'init/job.h'
--- init/job.h	2009-07-03 16:38:02 +0000
+++ init/job.h	2011-01-05 15:06:04 +0000
@@ -150,6 +150,8 @@
 
 	int             trace_forks;
 	TraceState      trace_state;
+
+	char           *utmp_id;
 } Job;
 
 

=== modified file 'init/job_process.c'
--- init/job_process.c	2011-01-05 15:03:02 +0000
+++ init/job_process.c	2011-01-05 15:06:04 +0000
@@ -247,6 +247,11 @@
 	NIH_MUST (environ_set (&env, NULL, &envc, TRUE,
 			       "UPSTART_INSTANCE=%s", job->name));
 
+	/* If job->utmp_id is set store this to environment UPSTART_UTMP_ID */
+	if (job->utmp_id)
+		NIH_SHOULD (environ_set (&env, NULL, &envc, TRUE,
+			     "UPSTART_UTMP_ID=%s", job->utmp_id));
+
 	/* If we're about to spawn the main job and we expect it to become
 	 * a daemon or fork before we can move out of spawned, we need to
 	 * set a trace on it.
@@ -366,6 +371,9 @@
 	int       i, fds[2];
 	char      filename[PATH_MAX];
 	FILE     *fd;
+	struct utmpx   utmp;
+	struct timeval tv;
+	const char *utmp_id;
 
 	nih_assert (class != NULL);
 
@@ -558,6 +566,20 @@
 		}
 	}
 
+	/* Write utmp INIT_PROCESS entry */
+	if ((utmp_id = environ_get(env, "UPSTART_UTMP_ID"))) {
+		memset(&utmp, 0, sizeof(struct utmpx));
+		strncpy(utmp.ut_id, utmp_id, sizeof(utmp.ut_id));
+		utmp.ut_pid = getpid();
+		utmp.ut_type = INIT_PROCESS;
+		gettimeofday(&tv, NULL);
+		utmp.ut_tv.tv_sec = tv.tv_sec;
+		utmp.ut_tv.tv_usec = tv.tv_usec;
+		setutxent();
+		pututxline(&utmp);
+		endutxent();
+	}
+
 	/* Execute the process, if we escape from here it failed */
 	if (execvp (argv[0], argv) < 0) {
 		nih_error_raise_system ();
@@ -1176,6 +1198,11 @@
 			memset(utmptr->ut_user, 0, UT_NAMESIZE);
 			memset(utmptr->ut_host, 0, UT_HOSTSIZE);
 			utmptr->ut_time = 0;
+
+			/* Set class utmp_id for next spawn */
+			if (! job->utmp_id)
+				job->utmp_id = nih_strdup (job->class, utmptr->ut_id);
+
 			/* Update existing utmp file. */
 			pututxline(utmptr);
 

=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c	2011-01-05 15:02:01 +0000
+++ init/tests/test_job_process.c	2011-01-05 15:06:04 +0000
@@ -4514,6 +4514,7 @@
 	char            utmpname[PATH_MAX];
 	struct utmpx    utmp, *utmptr;
 	struct timeval  tv;
+	pid_t           pid;
 
 	TEST_FUNCTION ("job_process_handler");
 	program_name = "test";
@@ -4735,6 +4736,94 @@
 
 		nih_free (job);
 	}
+
+	/* Test if is set correct INIT_PROCESS for respawning process with
+	 * already existing DEAD_PROCESS utmp entry */
+	TEST_FEATURE ("with respawn process");
+	nih_free (class);
+	class = job_class_new (NULL, "test");
+	nih_hash_add (job_classes, &class->entry);
+	class->process[PROCESS_MAIN] = process_new (class);
+	class->process[PROCESS_MAIN]->command = "echo";
+	class->respawn = TRUE;
+
+	TEST_ALLOC_SAFE {
+		job = job_new (class, "");
+
+		blocked = blocked_new (job, BLOCKED_EVENT, event);
+		event_block (event);
+		nih_list_add (&job->blocking, &blocked->entry);
+	}
+
+	job->goal = JOB_START;
+	job->state = JOB_RUNNING;
+	job->pid[PROCESS_MAIN] = 2;
+
+	TEST_FREE_TAG (blocked);
+
+	job->blocker = NULL;
+	event->failed = FALSE;
+
+	job->failed = FALSE;
+	job->failed_process = -1;
+	job->exit_status = 0;
+
+	output = fopen (utmpname, "w");
+	fclose (output);
+
+	/* set utmp file */
+	utmpxname(utmpname);
+
+	/* set up utmp entries */
+	memset (&utmp, 0, sizeof utmp);
+
+	gettimeofday(&tv, NULL);
+
+	strcpy(utmp.ut_id, "1");
+	utmp.ut_type = USER_PROCESS;
+	utmp.ut_pid = 1;
+	utmp.ut_tv.tv_sec = tv.tv_sec;
+	utmp.ut_tv.tv_usec = tv.tv_usec;
+
+	setutxent();
+	pututxline(&utmp);
+
+	strcpy(utmp.ut_id, "2");
+	utmp.ut_type = USER_PROCESS;
+	utmp.ut_pid = 2;
+	pututxline(&utmp);
+
+	strcpy(utmp.ut_id, "3");
+	utmp.ut_type = USER_PROCESS;
+	utmp.ut_pid = 3;
+	pututxline(&utmp);
+
+	endutxent();
+
+	job_process_handler (NULL, 2, NIH_CHILD_EXITED, 0);
+
+	TEST_EQ_STR(job->utmp_id, "2");
+
+	job_process_run (job, PROCESS_MAIN);
+	TEST_NE (job->pid[PROCESS_MAIN], 0);
+	pid = job->pid[PROCESS_MAIN];
+
+	waitpid (job->pid[PROCESS_MAIN], NULL, 0);
+
+	setutxent();
+
+	utmptr = getutxent();
+	TEST_NE_P(utmptr, NULL);
+	TEST_EQ(utmptr->ut_pid, 1);
+	TEST_EQ(utmptr->ut_type, USER_PROCESS);
+
+	utmptr = getutxent();
+	TEST_NE_P(utmptr, NULL);
+	TEST_EQ(utmptr->ut_pid, pid);
+	TEST_EQ(utmptr->ut_type, INIT_PROCESS);
+
+	nih_free (job);
+	nih_free (class);
 }
 
 
