diff --git a/ChangeLog b/ChangeLog
index 7af85b7..64ec795 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-24  Petr Lautrbach <plautrba@redhat.com>
+
+	* init/job_class.c, init/job_class.h, init/parse_job.c: Add new
+	'usage' stanza. 
+	* init/man/init.5: Document 'usage' stanza in init (5)
+	* init/tests/test_parse_job.c: Check 'usage' stanza
+
 2011-08-11  Scott James Remnant  <keybuk@google.com>
 
 	* init/job_process.c (job_process_spawn): Can't return on
diff --git a/init/job_class.c b/init/job_class.c
index 4b6d6be..6bcd031 100644
--- a/init/job_class.c
+++ b/init/job_class.c
@@ -219,6 +219,8 @@ job_class_new (const void *parent,
 	class->deleted = FALSE;
 	class->debug   = FALSE;
 
+	class->usage = NULL;
+
 	return class;
 
 error:
@@ -556,12 +558,18 @@ job_class_get_instance (JobClass        *class,
 	name = environ_expand (NULL, class->instance, instance_env);
 	if (! name) {
 		NihError *error;
+		char *error_message;
 
 		error = nih_error_get ();
 		if (error->number != ENOMEM) {
 			error = nih_error_steal ();
+			error_message = nih_strdup(NULL, error->message);
+			if (class->usage) {
+				nih_strcat_sprintf(&error_message, NULL, "\n%s: %s", _("usage"), class->usage);
+			}
 			nih_dbus_error_raise (DBUS_ERROR_INVALID_ARGS,
-					      error->message);
+					      error_message);
+			nih_free (error_message);
 			nih_free (error);
 		}
 
@@ -755,12 +763,18 @@ job_class_start (JobClass        *class,
 	name = environ_expand (NULL, class->instance, start_env);
 	if (! name) {
 		NihError *error;
+		char *error_message;
 
 		error = nih_error_get ();
 		if (error->number != ENOMEM) {
 			error = nih_error_steal ();
+			error_message = nih_strdup(NULL, error->message);
+			if (class->usage) {
+				nih_strcat_sprintf(&error_message, NULL, "\n%s: %s", _("usage"), class->usage);
+			}
 			nih_dbus_error_raise (DBUS_ERROR_INVALID_ARGS,
-					      error->message);
+					      error_message);
+			nih_free (error_message);
 			nih_free (error);
 		}
 
diff --git a/init/job_class.h b/init/job_class.h
index f621a60..dac4e55 100644
--- a/init/job_class.h
+++ b/init/job_class.h
@@ -157,6 +157,7 @@ typedef enum console_type {
  * @chroot: root directory of process (implies @chdir if not set),
  * @chdir: working directory of process,
  * @deleted: whether job should be deleted when finished.
+ * @usage: usage message text if initctl fails
  *
  * This structure holds the configuration of a known task or service that
  * should be tracked by the init daemon; as tasks and services are
@@ -209,6 +210,8 @@ typedef struct job_class {
 
 	int             deleted;
 	int             debug;
+
+	char           *usage;
 } JobClass;
 
 
diff --git a/init/man/init.5 b/init/man/init.5
index 60c89fe..1e1c23a 100644
--- a/init/man/init.5
+++ b/init/man/init.5
@@ -560,6 +560,18 @@ to resolve a class of events, such as those emitted by
 .BR upstart-udev-bridge (8) "" .
 
 .\"
+.TP
+.B usage \fIUSAGE\fR
+This stanza contains usage message which is displayed after one command of
+.BR start (8),
+.BR stop (8),
+.BR status (8)
+fails. 
+
+.nf
+usage "serial DEV=<device> [SPEED=<speed>]"
+.fi
+.\"
 .SS Process environment
 Many common adjustments to the process environment, such as resource
 limits, may be configured directly in the job rather than having to handle
diff --git a/init/parse_job.c b/init/parse_job.c
index 2321789..ffd4dcd 100644
--- a/init/parse_job.c
+++ b/init/parse_job.c
@@ -217,6 +217,10 @@ static int stanza_manual      (JobClass *class, NihConfigStanza *stanza,
 			       const char *file, size_t len,
 			       size_t *pos, size_t *lineno)
 	__attribute__ ((warn_unused_result));
+static int stanza_usage       (JobClass *class, NihConfigStanza *stanza,
+			       const char *file, size_t len,
+			       size_t *pos, size_t *lineno)
+	__attribute__ ((warn_unused_result));
 
 
 /**
@@ -255,6 +259,7 @@ static NihConfigStanza stanzas[] = {
 	{ "chdir",       (NihConfigHandler)stanza_chdir       },
 	{ "debug",       (NihConfigHandler)stanza_debug       },
 	{ "manual",      (NihConfigHandler)stanza_manual      },
+	{ "usage",       (NihConfigHandler)stanza_usage       },
 
 	NIH_CONFIG_LAST
 };
@@ -2538,3 +2543,40 @@ stanza_chdir (JobClass        *class,
 
 	return nih_config_skip_comment (file, len, pos, lineno);
 }
+
+/**
+ * stanza_usage:
+ * @class: job class being parsed,
+ * @stanza: stanza found,
+ * @file: file or string to parse,
+ * @len: length of @file,
+ * @pos: offset within @file,
+ * @lineno: line number.
+ *
+ * Parse a usage stanza from @file, extracting a single argument
+ * containing a usage message.
+ *
+ * Returns: zero on success, negative value on error.
+ **/
+static int
+stanza_usage (JobClass        *class,
+	      NihConfigStanza *stanza,
+	      const char      *file,
+	      size_t           len,
+	      size_t          *pos,
+	      size_t          *lineno)
+{
+	nih_assert (class != NULL);
+	nih_assert (stanza != NULL);
+	nih_assert (file != NULL);
+	nih_assert (pos != NULL);
+
+	if (class->usage)
+		nih_unref (class->usage, class);
+
+	class->usage = nih_config_next_arg (class, file, len, pos, lineno);
+	if (! class->usage)
+		return -1;
+
+	return nih_config_skip_comment (file, len, pos, lineno);
+}
diff --git a/init/tests/test_parse_job.c b/init/tests/test_parse_job.c
index d76fc8e..b0a039f 100644
--- a/init/tests/test_parse_job.c
+++ b/init/tests/test_parse_job.c
@@ -7933,6 +7933,122 @@ test_stanza_chdir (void)
 	nih_free (err);
 }
 
+void
+test_stanza_usage (void)
+{
+	JobClass*job;
+	NihError *err;
+	size_t    pos, lineno;
+	char      buf[1024];
+
+	TEST_FUNCTION ("stanza_usage");
+
+	/* Check that a usage stanza with an argument results in it
+	 * being stored in the job.
+	 */
+	TEST_FEATURE ("with single argument");
+	strcpy (buf, "usage \"stanza usage test message\"\n");
+
+	TEST_ALLOC_FAIL {
+		pos = 0;
+		lineno = 1;
+		job = parse_job (NULL, NULL, NULL, "test", buf, strlen (buf),
+				 &pos, &lineno);
+
+		if (test_alloc_failed) {
+			TEST_EQ_P (job, NULL);
+
+			err = nih_error_get ();
+			TEST_EQ (err->number, ENOMEM);
+			nih_free (err);
+
+			continue;
+		}
+
+		TEST_EQ (pos, strlen (buf));
+		TEST_EQ (lineno, 2);
+
+		TEST_ALLOC_SIZE (job, sizeof (JobClass));
+
+		TEST_ALLOC_PARENT (job->usage, job);
+		TEST_EQ_STR (job->usage, "stanza usage test message");
+
+		nih_free (job);
+	}
+
+
+	/* Check that the last of multiple usage stanzas is used.
+	 */
+	TEST_FEATURE ("with multiple stanzas");
+	strcpy (buf, "usage \"stanza usage original\"\n");
+	strcat (buf, "usage \"stanza usage test message\"\n");
+
+	TEST_ALLOC_FAIL {
+		pos = 0;
+		lineno = 1;
+		job = parse_job (NULL, NULL, NULL, "test", buf, strlen (buf),
+				 &pos, &lineno);
+
+		if (test_alloc_failed) {
+			TEST_EQ_P (job, NULL);
+
+			err = nih_error_get ();
+			TEST_EQ (err->number, ENOMEM);
+			nih_free (err);
+
+			continue;
+		}
+
+		TEST_EQ (pos, strlen (buf));
+		TEST_EQ (lineno, 3);
+
+		TEST_ALLOC_SIZE (job, sizeof (JobClass));
+
+		TEST_ALLOC_PARENT (job->usage, job);
+		TEST_EQ_STR (job->usage, "stanza usage test message");
+
+		nih_free (job);
+	}
+
+
+	/* Check that a usage stanza without an argument results in
+	 * a syntax error.
+	 */
+	TEST_FEATURE ("with missing argument");
+	strcpy (buf, "usage\n");
+
+	pos = 0;
+	lineno = 1;
+	job = parse_job (NULL, NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+
+	TEST_EQ_P (job, NULL);
+
+	err = nih_error_get ();
+	TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN);
+	TEST_EQ (pos, 5);
+	TEST_EQ (lineno, 1);
+	nih_free (err);
+
+
+	/* Check that a usage stanza with an extra second argument
+	 * results in a syntax error.
+	 */
+	TEST_FEATURE ("with extra arguments");
+	strcpy (buf, "usage stanza usage test message\n");
+
+	pos = 0;
+	lineno = 1;
+	job = parse_job (NULL, NULL, NULL, "test", buf, strlen (buf), &pos, &lineno);
+
+	TEST_EQ_P (job, NULL);
+
+	err = nih_error_get ();
+	TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN);
+	TEST_EQ (pos, 13);
+	TEST_EQ (lineno, 1);
+	nih_free (err);
+}
+
 int
 main (int   argc,
       char *argv[])
@@ -7979,6 +8095,7 @@ main (int   argc,
 	test_stanza_limit ();
 	test_stanza_chroot ();
 	test_stanza_chdir ();
+	test_stanza_usage ();
 
 	return 0;
 }