diff options
author | Jeremy Katz <katzj@redhat.com> | 2004-06-21 22:38:36 +0000 |
---|---|---|
committer | Jeremy Katz <katzj@redhat.com> | 2004-06-21 22:38:36 +0000 |
commit | 33bf9726e7baa89b15f400cc44802e6deb69128e (patch) | |
tree | 576e1fa853319a7d0b3c41ca10bcd5c2c66eedba /loader2 | |
parent | f8d88fcc4deb7647b4dab5672e911dab1b1d1377 (diff) | |
download | anaconda-33bf9726e7baa89b15f400cc44802e6deb69128e.tar.gz anaconda-33bf9726e7baa89b15f400cc44802e6deb69128e.tar.xz anaconda-33bf9726e7baa89b15f400cc44802e6deb69128e.zip |
add support for being able to halt or poweroff in addition to rebooting. done
in response to the init process receiving SIGUSR1 or SIGUSR2 (#116414)
Diffstat (limited to 'loader2')
-rw-r--r-- | loader2/init.c | 111 | ||||
-rw-r--r-- | loader2/shutdown.c | 7 |
2 files changed, 100 insertions, 18 deletions
diff --git a/loader2/init.c b/loader2/init.c index 675713941..d54946220 100644 --- a/loader2/init.c +++ b/loader2/init.c @@ -44,7 +44,9 @@ #include <unistd.h> #include <sys/ioctl.h> #include <sys/reboot.h> +#include <linux/vt.h> #include <termios.h> +#include <libgen.h> #include "devt.h" @@ -98,10 +100,11 @@ char * env[] = { int testing=0; void unmountFilesystems(void); void disableSwap(void); -void shutDown(int noKill, int doReboot); +void shutDown(int noKill, int doReboot, int doPowerOff); +static int getNoKill(void); struct termios ts; -int mystrstr(char *str1, char *str2) { +static int mystrstr(char *str1, char *str2) { char *p; int rc=0; @@ -127,7 +130,7 @@ static void printstr(char * string) { write(1, string, strlen(string)); } -void fatal_error(int usePerror) { +static void fatal_error(int usePerror) { /* FIXME */ #if 0 if (usePerror) @@ -437,14 +440,62 @@ int copyDirectory(char * from, char * to) { return 0; } -void sigintHandler(int signum) -{ +static void termReset(void) { + /* change to tty1 */ + ioctl(0, VT_ACTIVATE, 1); /* reset terminal */ tcsetattr(0, TCSANOW, &ts); /* Shift in, default color, move down 100 lines */ /* ^O ^[[0m ^[[100E */ printf("\017\033[0m\033[100E\n"); - shutDown(0, 1); +} + +/* reboot handler */ +void sigintHandler(int signum) { + termReset(); + shutDown(getNoKill(), 1, 0); +} + +/* halt handler */ +void sigUsr1Handler(int signum) { + termReset(); + shutDown(getNoKill(), 0, 0); +} + +/* poweroff handler */ +void sigUsr2Handler(int signum) { + termReset(); + shutDown(getNoKill(), 0, 1); +} + +static int getNoKill(void) { + int fd; + int len; + char buf[1024]; + + /* look through /proc/cmdline for special options */ + if ((fd = open("/proc/cmdline", O_RDONLY,0)) > 0) { + len = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (len > 0 && mystrstr(buf, "nokill")) + return 1; + } + return 0; +} + +static int getInitPid(void) { + int fd = 0, pid = -1; + char * buf = malloc(10); + + fd = open("/var/run/init.pid", O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Unable to find pid of init!!!\n"); + return -1; + } + read(fd, buf, 9); + close(fd); + sscanf(buf, "%d", &pid); + return pid; } int main(int argc, char **argv) { @@ -459,8 +510,26 @@ int main(int argc, char **argv) { char ** argvp = argvc; char twelve = 12; int i; - char buf[500]; - int len; + + if (!strncmp(basename(argv[0]), "poweroff", 8)) { + printf("Running poweroff...\n"); + fd = getInitPid(); + if (fd > 0) + kill(fd, SIGUSR2); + exit(0); + } else if (!strncmp(basename(argv[0]), "halt", 4)) { + printf("Running halt...\n"); + fd = getInitPid(); + if (fd > 0) + kill(fd, SIGUSR1); + exit(0); + } else if (!strncmp(basename(argv[0]), "reboot", 6)) { + printf("Running reboot...\n"); + fd = getInitPid(); + if (fd > 0) + kill(fd, SIGINT); + exit(0); + } #if !defined(__s390__) && !defined(__s390x__) testing = (getppid() != 0) && (getppid() != 1); @@ -509,13 +578,7 @@ int main(int argc, char **argv) { } } - /* look through /proc/cmdline for special options */ - if ((fd = open("/proc/cmdline", O_RDONLY,0)) > 0) { - len = read(fd, buf, sizeof(buf) - 1); - close(fd); - if (len > 0 && mystrstr(buf, "nokill")) - noKill = 1; - } + noKill = getNoKill(); #if !defined(__s390__) && !defined(__s390x__) if (ioctl (0, TIOCLINUX, &twelve) < 0) { @@ -613,6 +676,18 @@ int main(int argc, char **argv) { if (!testing) doklog("/dev/tty4"); + /* write out a pid file */ + if ((fd = open("/var/run/init.pid", O_WRONLY|O_CREAT)) > 0) { + char * buf = malloc(10); + snprintf(buf, 9, "%d", getpid()); + write(fd, buf, strlen(buf)); + close(fd); + free(buf); + } else { + printf("unable to write init.pid (%d): %s\n", errno, strerror(errno)); + sleep(2); + } + /* Go into normal init mode - keep going, and then do a orderly shutdown when: @@ -635,6 +710,10 @@ int main(int argc, char **argv) { exit(0); } + /* signal handlers for halt/poweroff */ + signal(SIGUSR1, sigUsr1Handler); + signal(SIGUSR2, sigUsr2Handler); + /* set up the ctrl+alt+delete handler to kill our pid, not pid 1 */ signal(SIGINT, sigintHandler); if ((fd = open("/proc/sys/kernel/cad_pid", O_WRONLY)) != -1) { @@ -672,7 +751,7 @@ int main(int argc, char **argv) { if (testing) exit(0); - shutDown(noKill, doReboot); + shutDown(noKill, doReboot, 0); return 0; } diff --git a/loader2/shutdown.c b/loader2/shutdown.c index 2f6456d17..848d76027 100644 --- a/loader2/shutdown.c +++ b/loader2/shutdown.c @@ -41,7 +41,7 @@ void rebootHandler(int signum) { #endif } -void shutDown(int noKill, int doReboot) { +void shutDown(int noKill, int doReboot, int doPowerOff) { sync(); sync(); if (!testing && !noKill) { @@ -71,6 +71,9 @@ void shutDown(int noKill, int doReboot) { #else reboot(RB_AUTOBOOT); #endif + } else if (doPowerOff) { + printf("powering off system\n"); + reboot(RB_POWER_OFF); } else { printf("you may safely reboot your system\n"); signal(SIGINT, rebootHandler); @@ -108,6 +111,6 @@ int main(int argc, char ** argv) { dup2(fd, 2); close(fd); - shutDown(0, doReboot); + shutDown(0, doReboot, 0); } #endif |