"Fossies" - the Fresh Open Source Software Archive

Member "sysvinit-2.96/src/halt.c" (11 Sep 2019, 7706 Bytes) of package /linux/misc/sysvinit-2.96.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "halt.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.93_vs_2.94.

    1 /*
    2  * Halt     Stop the system running.
    3  *      It re-enables CTRL-ALT-DEL, so that a hard reboot can
    4  *      be done. If called as reboot, it will reboot the system.
    5  *
    6  *      If the system is not in runlevel 0 or 6, halt will just
    7  *      execute a "shutdown -h" to halt the system, and reboot will
    8  *      execute an "shutdown -r". This is for compatibility with
    9  *      sysvinit 2.4.
   10  *
   11  * Usage:   halt [-n] [-w] [-d] [-f] [-h] [-i] [-p]
   12  *      -n: don't sync before halting the system
   13  *      -w: only write a wtmp reboot record and exit.
   14  *      -d: don't write a wtmp record.
   15  *      -f: force halt/reboot, don't call shutdown.
   16  *      -h: put harddisks in standby mode
   17  *      -i: shut down all network interfaces.
   18  *      -p: power down the system (if possible, otherwise halt).
   19  *
   20  *      Reboot and halt are both this program. Reboot
   21  *      is just a link to halt. Invoking the program
   22  *      as poweroff implies the -p option.
   23  *
   24  * Author:  Miquel van Smoorenburg, miquels@cistron.nl
   25  *
   26  * Version: 2.86,  30-Jul-2004
   27  *
   28  *      This file is part of the sysvinit suite,
   29  *      Copyright (C) 1991-2004 Miquel van Smoorenburg.
   30  *
   31  *      This program is free software; you can redistribute it and/or modify
   32  *      it under the terms of the GNU General Public License as published by
   33  *      the Free Software Foundation; either version 2 of the License, or
   34  *      (at your option) any later version.
   35  *
   36  *      This program is distributed in the hope that it will be useful,
   37  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
   38  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39  *      GNU General Public License for more details.
   40  *
   41  *      You should have received a copy of the GNU General Public License
   42  *      along with this program; if not, write to the Free Software
   43  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   44  */
   45 
   46 #include <sys/types.h>
   47 #include <sys/stat.h>
   48 #include <sys/param.h>
   49 #include <stdlib.h>
   50 #include <utmp.h>
   51 #include <fcntl.h>
   52 #include <string.h>
   53 #include <unistd.h>
   54 #include <sys/times.h>
   55 #include <time.h>
   56 #include <signal.h>
   57 #include <stdio.h>
   58 #include <getopt.h>
   59 #include "reboot.h"
   60 #include "runlevellog.h"
   61 
   62 char *Version = "@(#)halt  2.86  31-Jul-2004 miquels@cistron.nl";
   63 char *progname;
   64 
   65 #define KERNEL_MONITOR  1 /* If halt() puts you into the kernel monitor. */
   66 #define RUNLVL_PICKY    0 /* Be picky about the runlevel */
   67 
   68 extern int ifdown(void);
   69 extern int hddown(void);
   70 extern int hdflush(void);
   71 extern void write_wtmp(char *user, char *id, int pid, int type, char *line);
   72 
   73 /*
   74  *  Send usage message.
   75  */
   76 void usage(void)
   77 {
   78     fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n",
   79         progname, strcmp(progname, "halt") ? "" : " [-p]");
   80     fprintf(stderr, "\t-n: don't sync before halting the system\n");
   81     fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n");
   82     fprintf(stderr, "\t-d: don't write a wtmp record.\n");
   83     fprintf(stderr, "\t-f: force halt/reboot, don't call shutdown.\n");
   84     fprintf(stderr, "\t-h: put harddisks in standby mode.\n");
   85     fprintf(stderr, "\t-i: shut down all network interfaces.\n");
   86     if (!strcmp(progname, "halt"))
   87         fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n");
   88     exit(1);
   89 }
   90 
   91 /*
   92  *  See if we were started directly from init.
   93  *  Get the runlevel from /var/run/utmp or the environment.
   94  *      Or the /var/run/runlevel log.
   95  */
   96 int get_runlevel(void)
   97 {
   98     struct utmp *ut;
   99     char *r;
  100         int runlevel, status;
  101 
  102 #if RUNLVL_PICKY
  103     time_t boottime;
  104 #endif
  105 
  106     /*
  107      *  First see if we were started directly from init.
  108      */
  109     if (getenv("INIT_VERSION") && (r = getenv("RUNLEVEL")) != NULL)
  110         return *r;
  111 
  112     /*
  113      *  Hmm, failed - read runlevel from /var/run/utmp..
  114      */
  115 #if RUNLVL_PICKY
  116     /*
  117      *  Get boottime from the kernel.
  118      */
  119     time(&boottime);
  120     boottime -= (times(NULL) / HZ);
  121 #endif
  122 
  123     /*
  124      *  Find runlevel in utmp.
  125      */
  126     setutent();
  127     while ((ut = getutent()) != NULL) {
  128 #if RUNLVL_PICKY
  129         /*
  130          *  Only accept value if it's from after boottime.
  131          */
  132         if (ut->ut_type == RUN_LVL && ut->ut_time > boottime)
  133             return (ut->ut_pid & 255);
  134 #else
  135         if (ut->ut_type == RUN_LVL)
  136             return (ut->ut_pid & 255);
  137 #endif
  138     }
  139     endutent();
  140 
  141         /* Did not find utmp entry, try to read from log file */
  142         status = Read_Runlevel_Log(&runlevel);
  143         if (status)
  144            return runlevel;
  145 
  146     /* This should not happen but warn the user! */
  147     fprintf(stderr, "WARNING: could not determine runlevel"
  148         " - doing soft %s\n", progname);
  149     fprintf(stderr, "  (it's better to use shutdown instead of %s"
  150         " from the command line)\n", progname);
  151 
  152     return -1;
  153 }
  154 
  155 /*
  156  *  Switch to another runlevel.
  157  */
  158 void do_shutdown(char *fl, int should_poweroff, char *tm)
  159 {
  160     char *args[9];
  161     int i = 0;
  162 
  163     args[i++] = "shutdown";
  164     args[i++] = fl;
  165         if ( (! strcmp(fl, "-h") ) && (should_poweroff) )
  166            args[i++] = "-P";
  167     if (tm) {
  168         args[i++] = "-t";
  169         args[i++] = tm;
  170     }
  171     args[i++] = "now";
  172     args[i++] = NULL;
  173 
  174     execv("/sbin/shutdown", args);
  175     execv("/etc/shutdown", args);
  176     execv("/bin/shutdown", args);
  177 
  178     perror("shutdown");
  179     exit(1);
  180 }
  181 
  182 /*
  183  *  Main program.
  184  *  Write a wtmp entry and reboot cq. halt.
  185  */
  186 int main(int argc, char **argv)
  187 {
  188     int do_reboot = 0;
  189     int do_sync = 1;
  190     int do_wtmp = 1;
  191     int do_nothing = 0;
  192     int do_hard = 0;
  193     int do_ifdown = 0;
  194     int do_hddown = 0;
  195     int do_poweroff = 0;
  196     int c;
  197     char *tm = NULL;
  198 
  199     /*
  200      *  Find out who we are
  201      */
  202     /* Remove dash passed on in argv[0] when used as login shell. */
  203     if (argv[0][0] == '-') argv[0]++;
  204     if ((progname = strrchr(argv[0], '/')) != NULL)
  205         progname++;
  206     else
  207         progname = argv[0];
  208 
  209     if (!strcmp(progname, "reboot")) do_reboot = 1;
  210     if (!strcmp(progname, "poweroff")) do_poweroff = 1;
  211 
  212     /*
  213      *  Get flags
  214      */
  215     while((c = getopt(argc, argv, ":ihdfnpwt:")) != EOF) {
  216         switch(c) {
  217             case 'n':
  218                 do_sync = 0;
  219                 do_wtmp = 0;
  220                 break;
  221             case 'w':
  222                 do_nothing = 1;
  223                 break;
  224             case 'd':
  225                 do_wtmp = 0;
  226                 break;
  227             case 'f':
  228                 do_hard = 1;
  229                 break;
  230             case 'i':
  231                 do_ifdown = 1;
  232                 break;
  233             case 'h':
  234                 do_hddown = 1;
  235                 break;
  236             case 'p':
  237                 do_poweroff = 1;
  238                 break;
  239             case 't':
  240                 tm = optarg;
  241                 break;
  242             default:
  243                 usage();
  244         }
  245      }
  246     if (argc != optind) usage();
  247 
  248     if (geteuid() != 0) {
  249         fprintf(stderr, "%s: must be superuser.\n", progname);
  250         exit(1);
  251     }
  252 
  253     if (chdir("/")) {
  254         fprintf(stderr, "%s: chdir(/): %m\n", progname);
  255         exit(1);
  256     }
  257 
  258     if (!do_hard && !do_nothing) {
  259         /*
  260          *  See if we are in runlevel 0 or 6.
  261          */
  262         c = get_runlevel();
  263         if (c != '0' && c != '6')
  264             do_shutdown(do_reboot ? "-r" : "-h", do_poweroff, tm);
  265     }
  266 
  267     /*
  268      *  Record the fact that we're going down
  269      */
  270     if (do_wtmp)
  271         write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
  272 
  273     /*
  274      *  Exit if all we wanted to do was write a wtmp record.
  275      */
  276     if (do_nothing && !do_hddown && !do_ifdown) exit(0);
  277 
  278     if (do_sync) {
  279         sync();
  280         /* Sync should be fine on its own for making sure data is written.
  281                    We probably call shutdown after this anyway to clean up.
  282                    -- Jesse
  283                 sleep(2);
  284                 */
  285     }
  286 
  287     if (do_ifdown)
  288         (void)ifdown();
  289 
  290     if (do_hddown)
  291         (void)hddown();
  292     else
  293         (void)hdflush();
  294 
  295     if (do_nothing) exit(0);
  296 
  297     if (do_reboot) {
  298         init_reboot(BMAGIC_REBOOT);
  299     } else {
  300         /*
  301          *  Turn on hard reboot, CTRL-ALT-DEL will reboot now
  302          */
  303 #ifdef BMAGIC_HARD
  304         init_reboot(BMAGIC_HARD);
  305 #endif
  306 
  307         /*
  308          *  Stop init; it is insensitive to the signals sent
  309          *  by the kernel.
  310          */
  311         kill(1, SIGTSTP);
  312 
  313         /*
  314          *  Halt or poweroff.
  315          */
  316         if (do_poweroff)
  317             init_reboot(BMAGIC_POWEROFF);
  318         /*
  319          *  Fallthrough if failed.
  320          */
  321         init_reboot(BMAGIC_HALT);
  322     }
  323 
  324     /*
  325      *  If we return, we (c)ontinued from the kernel monitor.
  326      */
  327 #ifdef BMAGIC_SOFT
  328     init_reboot(BMAGIC_SOFT);
  329 #endif
  330     kill(1, SIGCONT);
  331 
  332     exit(0);
  333 }