#include #include #include #include #include #include #include #include #include #define NOLOGINMSG "The system is shutting down.\n" #define SHUTPID "/var/run/shutdown.pid" #include "init.h" void usage(){ printf("Usage: shutdown {-h,-r.-c} [-t time] [-m message]\n"); exit(EXIT_FAILURE); } void sigint(int n){ unlink(SHUTPID); unlink(_PATH_NOLOGIN); exit(EXIT_SUCCESS); } int main(int argc,char * argv[]){ int sock; struct sockaddr_un name; int c; int doreboot=0,dohalt=0,docancel=0; int delay=0; int newlevel; int fd; struct initcmd cmd; time_t now; pid_t pid; if(getuid() != 0){ fprintf(stderr,"%s: Must be root.\n",argv[0]); exit(EXIT_FAILURE); } time(&now); while((c = getopt(argc,argv,"hrct:")) != -1){ switch(c){ case 'r': doreboot = 1; break; case 'h': dohalt = 1; break; case 'c': docancel = 1; break; case 't': if(strchr(optarg,':')){ int h,m; struct tm *lt; if(sscanf(optarg,"%d:%2d",&h,&m) != 2) usage(); if(h > 23 || m > 59) usage(); lt = localtime(&now); delay = ((60*h + m) - (60*lt->tm_hour + lt->tm_min))*60; if(delay < 0) delay += 60*60*24; } else { char *p; delay = strtol(optarg,&p,0)*60; if(p==optarg || delay < 0) usage(); } break; default: usage(); break; } } if(dohalt + doreboot + docancel != 1) usage(); if(!docancel && (fd = open(SHUTPID,O_RDONLY)) >= 0){ close(fd); fprintf(stderr,"Shutdown already running.\n"); exit(EXIT_FAILURE); } if(dohalt){ newlevel = HALTRL; } else if(doreboot) { newlevel = REBOOTRL; } else { if( (fd = open(SHUTPID,O_RDONLY)) < 0){ fprintf(stderr,"Shutdown not running.\n"); exit(EXIT_FAILURE); } if(read(fd,&pid,sizeof(pid)) != sizeof(pid)){ perror("read"); exit(EXIT_FAILURE); } close(fd); kill(pid,SIGINT); exit(EXIT_SUCCESS); } fd = open(_PATH_NOLOGIN,O_CREAT|O_WRONLY,0644); if(fd >= 0){ write(fd,NOLOGINMSG,strlen(NOLOGINMSG)); close(fd); } if(delay > 0){ pid = fork(); if(pid == -1){ perror("fork"); exit(EXIT_FAILURE); } if(pid > 0){ if( (fd = open(SHUTPID,O_CREAT|O_WRONLY,0644)) < 0){ perror("open"); exit(EXIT_FAILURE); } if(write(fd,&pid,sizeof(pid)) != sizeof(pid)){ perror("write"); exit(EXIT_FAILURE); } close(fd); exit(EXIT_SUCCESS); } signal(SIGINT,sigint); while(delay) delay = sleep(delay); } else { signal(SIGINT,SIG_IGN); pid = getpid(); if( (fd = open(SHUTPID,O_CREAT|O_WRONLY,0644)) >= 0){ write(fd,&pid,sizeof(pid)); close(fd); } } cmd.command = NEWLEVEL; cmd.data = newlevel; sock = socket(PF_LOCAL,SOCK_DGRAM,0); if(sock < 0){ perror("socket"); exit(EXIT_FAILURE); } name.sun_family = AF_LOCAL; strncpy(name.sun_path,SOCK_PATH,sizeof(name.sun_path)); if(connect(sock,(struct sockaddr*)&name,SUN_LEN(&name))<0){ perror("connect"); exit(EXIT_FAILURE); } if(write(sock,&cmd,sizeof(cmd)) < sizeof(cmd) ){ perror("write"); exit(EXIT_FAILURE); } close(sock); signal(SIGTERM,sigint); for(;;) sleep(1<<30); return(EXIT_SUCCESS); }