halt.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Poweroff reboot and halt, oh my.
  4. *
  5. * Copyright 2006 by Rob Landley <rob@landley.net>
  6. *
  7. * Licensed under GPL version 2, see file LICENSE in this tarball for details.
  8. */
  9. #include "libbb.h"
  10. #include <sys/reboot.h>
  11. #if ENABLE_FEATURE_WTMP
  12. #include <sys/utsname.h>
  13. #include <utmp.h>
  14. static void write_wtmp(void)
  15. {
  16. struct utmp utmp;
  17. struct utsname uts;
  18. if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
  19. close(creat(bb_path_wtmp_file, 0664));
  20. }
  21. memset(&utmp, 0, sizeof(utmp));
  22. utmp.ut_tv.tv_sec = time(NULL);
  23. safe_strncpy(utmp.ut_user, "shutdown", UT_NAMESIZE);
  24. utmp.ut_type = RUN_LVL;
  25. safe_strncpy(utmp.ut_id, "~~", sizeof(utmp.ut_id));
  26. safe_strncpy(utmp.ut_line, "~~", UT_LINESIZE);
  27. if (uname(&uts) == 0)
  28. safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host));
  29. updwtmp(bb_path_wtmp_file, &utmp);
  30. }
  31. #else
  32. #define write_wtmp() ((void)0)
  33. #endif
  34. #ifndef RB_HALT_SYSTEM
  35. #define RB_HALT_SYSTEM RB_HALT
  36. #endif
  37. #ifndef RB_POWER_OFF
  38. #define RB_POWER_OFF RB_POWERDOWN
  39. #endif
  40. int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  41. int halt_main(int argc UNUSED_PARAM, char **argv)
  42. {
  43. static const int magic[] = {
  44. RB_HALT_SYSTEM,
  45. RB_POWER_OFF,
  46. RB_AUTOBOOT
  47. };
  48. static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };
  49. int delay = 0;
  50. int which, flags, rc;
  51. /* Figure out which applet we're running */
  52. for (which = 0; "hpr"[which] != applet_name[0]; which++)
  53. continue;
  54. /* Parse and handle arguments */
  55. opt_complementary = "d+"; /* -d N */
  56. /* We support -w even if !ENABLE_FEATURE_WTMP, in order
  57. * to not break scripts */
  58. flags = getopt32(argv, "d:nfw", &delay);
  59. sleep(delay);
  60. write_wtmp();
  61. if (flags & 8) /* -w */
  62. return EXIT_SUCCESS;
  63. if (!(flags & 2)) /* no -n */
  64. sync();
  65. /* Perform action. */
  66. rc = 1;
  67. if (!(flags & 4)) { /* no -f */
  68. //TODO: I tend to think that signalling linuxrc is wrong
  69. // pity original author didn't comment on it...
  70. if (ENABLE_FEATURE_INITRD) {
  71. pid_t *pidlist = find_pid_by_name("linuxrc");
  72. if (pidlist[0] > 0)
  73. rc = kill(pidlist[0], signals[which]);
  74. if (ENABLE_FEATURE_CLEAN_UP)
  75. free(pidlist);
  76. }
  77. if (rc)
  78. rc = kill(1, signals[which]);
  79. } else
  80. rc = reboot(magic[which]);
  81. if (rc)
  82. bb_error_msg("no");
  83. return rc;
  84. }