From 479a8c2d36a28aaac12bf349ea09999655b90353 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 26 Feb 2014 21:49:12 -0500
Subject: [PATCH 016/220] Make "exit" take a return code.

This adds "exit" with a return code.  With this patch, any "exit"
command /may/ include a return code, and on platforms that support
returning with an exit status, we will do so.  By default we return the
same exit status we did before this patch.

Signed-off-by: Peter Jones <pjones@redhat.com>
---
 grub-core/commands/minicmd.c         | 20 ++++++++++++++++----
 grub-core/kern/efi/efi.c             |  9 +++++++--
 grub-core/kern/emu/main.c            |  2 +-
 grub-core/kern/emu/misc.c            |  5 +++--
 grub-core/kern/i386/coreboot/init.c  |  2 +-
 grub-core/kern/i386/qemu/init.c      |  2 +-
 grub-core/kern/ieee1275/init.c       |  2 +-
 grub-core/kern/mips/arc/init.c       |  2 +-
 grub-core/kern/mips/loongson/init.c  |  2 +-
 grub-core/kern/mips/qemu_mips/init.c |  2 +-
 grub-core/kern/misc.c                | 11 ++++++++++-
 grub-core/kern/uboot/init.c          |  6 +++---
 grub-core/kern/xen/init.c            |  2 +-
 include/grub/misc.h                  |  2 +-
 14 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index 6bbce31..6d66b7c 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -179,12 +179,24 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
 }
 
 /* exit */
-static grub_err_t __attribute__ ((noreturn))
+static grub_err_t
 grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
-		    int argc __attribute__ ((unused)),
-		    char *argv[] __attribute__ ((unused)))
+		    int argc, char *argv[])
 {
-  grub_exit ();
+  int retval = -1;
+  unsigned long n;
+
+  if (argc < 0 || argc > 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+
+  if (argc == 1)
+    {
+      n = grub_strtoul (argv[0], 0, 10);
+      if (n != ~0UL)
+	retval = n;
+    }
+
+  grub_exit (retval);
   /* Not reached.  */
 }
 
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 6e1ceb9..370ce03 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -164,11 +164,16 @@ grub_reboot (void)
 }
 
 void
-grub_exit (void)
+grub_exit (int retval)
 {
+  int rc = GRUB_EFI_LOAD_ERROR;
+
+  if (retval == 0)
+    rc = GRUB_EFI_SUCCESS;
+
   grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
   efi_call_4 (grub_efi_system_table->boot_services->exit,
-              grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
+              grub_efi_image_handle, rc, 0, 0);
   for (;;) ;
 }
 
diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
index 425bb96..55ea5a1 100644
--- a/grub-core/kern/emu/main.c
+++ b/grub-core/kern/emu/main.c
@@ -67,7 +67,7 @@ grub_reboot (void)
 }
 
 void
-grub_exit (void)
+grub_exit (int retval __attribute__((unused)))
 {
   grub_reboot ();
 }
diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
index 65db79b..19cd007 100644
--- a/grub-core/kern/emu/misc.c
+++ b/grub-core/kern/emu/misc.c
@@ -139,9 +139,10 @@ xasprintf (const char *fmt, ...)
 
 #if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL)
 void
-grub_exit (void)
+__attribute__ ((noreturn))
+grub_exit (int rc)
 {
-  exit (1);
+  exit (rc < 0 ? 1 : rc);
 }
 #endif
 
diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c
index 3314f02..36f9134 100644
--- a/grub-core/kern/i386/coreboot/init.c
+++ b/grub-core/kern/i386/coreboot/init.c
@@ -41,7 +41,7 @@ extern grub_uint8_t _end[];
 extern grub_uint8_t _edata[];
 
 void  __attribute__ ((noreturn))
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   /* We can't use grub_fatal() in this function.  This would create an infinite
      loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit().  */
diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c
index 271b6fb..9fafe98 100644
--- a/grub-core/kern/i386/qemu/init.c
+++ b/grub-core/kern/i386/qemu/init.c
@@ -42,7 +42,7 @@ extern grub_uint8_t _end[];
 extern grub_uint8_t _edata[];
 
 void  __attribute__ ((noreturn))
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   /* We can't use grub_fatal() in this function.  This would create an infinite
      loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit().  */
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index d483e35..e71d158 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -71,7 +71,7 @@ grub_addr_t grub_ieee1275_original_stack;
 #endif
 
 void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   grub_ieee1275_exit ();
 }
diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
index 3834a14..86b3a25 100644
--- a/grub-core/kern/mips/arc/init.c
+++ b/grub-core/kern/mips/arc/init.c
@@ -276,7 +276,7 @@ grub_halt (void)
 }
 
 void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   GRUB_ARC_FIRMWARE_VECTOR->exit ();
 
diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c
index 7b96531..dff598c 100644
--- a/grub-core/kern/mips/loongson/init.c
+++ b/grub-core/kern/mips/loongson/init.c
@@ -304,7 +304,7 @@ grub_halt (void)
 }
 
 void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   grub_halt ();
 }
diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c
index be88b77..8b6c55f 100644
--- a/grub-core/kern/mips/qemu_mips/init.c
+++ b/grub-core/kern/mips/qemu_mips/init.c
@@ -75,7 +75,7 @@ grub_machine_fini (int flags __attribute__ ((unused)))
 }
 
 void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   grub_halt ();
 }
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 3b633d5..cd63a8c 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -1095,9 +1095,18 @@ grub_abort (void)
       grub_getkey ();
     }
 
-  grub_exit ();
+  grub_exit (1);
 }
 
+#if defined (__clang__) && !defined (GRUB_UTIL)
+/* clang emits references to abort().  */
+void __attribute__ ((noreturn))
+abort (void)
+{
+  grub_abort ();
+}
+#endif
+
 void
 grub_fatal (const char *fmt, ...)
 {
diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c
index 3e33864..be2a5be 100644
--- a/grub-core/kern/uboot/init.c
+++ b/grub-core/kern/uboot/init.c
@@ -39,9 +39,9 @@ extern grub_size_t grub_total_module_size;
 static unsigned long timer_start;
 
 void
-grub_exit (void)
+grub_exit (int rc)
 {
-  grub_uboot_return (0);
+  grub_uboot_return (rc < 0 ? 1 : rc);
 }
 
 static grub_uint64_t
@@ -78,7 +78,7 @@ grub_machine_init (void)
   if (!ver)
     {
       /* Don't even have a console to log errors to... */
-      grub_exit ();
+      grub_exit (-1);
     }
   else if (ver > API_SIG_VERSION)
     {
diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c
index 782ca72..708b060 100644
--- a/grub-core/kern/xen/init.c
+++ b/grub-core/kern/xen/init.c
@@ -584,7 +584,7 @@ grub_machine_init (void)
 }
 
 void
-grub_exit (void)
+grub_exit (int rc __attribute__((unused)))
 {
   struct sched_shutdown arg;
 
diff --git a/include/grub/misc.h b/include/grub/misc.h
index ee48eb7..f9135b6 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -334,7 +334,7 @@ int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
 char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
      __attribute__ ((format (GNU_PRINTF, 1, 2))) WARN_UNUSED_RESULT;
 char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) WARN_UNUSED_RESULT;
-void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
+void EXPORT_FUNC(grub_exit) (int rc) __attribute__ ((noreturn));
 grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
 					  grub_uint64_t d,
 					  grub_uint64_t *r);
-- 
1.8.3.1

