github.com/andrewsun2898/u-root@v6.0.1-0.20200616011413-4b2895c1b815+incompatible/cmds/core/init/init.go (about)

     1  // Copyright 2012-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // init is u-root's standard userspace init process.
     6  //
     7  // init is intended to be the first process run by the kernel when it boots up.
     8  // init does some basic initialization (mount file systems, turn on loopback)
     9  // and then tries to execute, in order, /inito, a uinit (either in /bin, /bbin,
    10  // or /ubin), and then a shell (/bin/defaultsh and /bin/sh).
    11  package main
    12  
    13  import (
    14  	"flag"
    15  	"fmt"
    16  	"io/ioutil"
    17  	"log"
    18  	"os/exec"
    19  	"syscall"
    20  
    21  	"github.com/u-root/u-root/pkg/cmdline"
    22  	"github.com/u-root/u-root/pkg/libinit"
    23  	"github.com/u-root/u-root/pkg/uflag"
    24  	"github.com/u-root/u-root/pkg/ulog"
    25  )
    26  
    27  var (
    28  	verbose  = flag.Bool("v", false, "print all build commands")
    29  	test     = flag.Bool("test", false, "Test mode: don't try to set control tty")
    30  	debug    = func(string, ...interface{}) {}
    31  	osInitGo = func() {}
    32  )
    33  
    34  func main() {
    35  	flag.Parse()
    36  
    37  	log.Printf("Welcome to u-root!")
    38  	fmt.Println(`                              _`)
    39  	fmt.Println(`   _   _      _ __ ___   ___ | |_`)
    40  	fmt.Println(`  | | | |____| '__/ _ \ / _ \| __|`)
    41  	fmt.Println(`  | |_| |____| | | (_) | (_) | |_`)
    42  	fmt.Println(`   \__,_|    |_|  \___/ \___/ \__|`)
    43  	fmt.Println()
    44  
    45  	log.SetPrefix("init: ")
    46  
    47  	if *verbose {
    48  		debug = log.Printf
    49  	}
    50  
    51  	// Before entering an interactive shell, decrease the loglevel because
    52  	// spamming non-critical logs onto the shell frustrates users. The logs
    53  	// are still accessible through dmesg.
    54  	if !*verbose {
    55  		// Only messages more severe than "notice" are printed.
    56  		if err := ulog.KernelLog.SetConsoleLogLevel(ulog.KLogNotice); err != nil {
    57  			log.Printf("Could not set log level: %v", err)
    58  		}
    59  	}
    60  
    61  	libinit.SetEnv()
    62  	libinit.CreateRootfs()
    63  	libinit.NetInit()
    64  
    65  	// Potentially exec systemd if we have been asked to.
    66  	osInitGo()
    67  
    68  	// Start background build.
    69  	if isBgBuildEnabled() {
    70  		go startBgBuild()
    71  	}
    72  
    73  	// Turn off job control when test mode is on.
    74  	ctty := libinit.WithTTYControl(!*test)
    75  
    76  	// Allows passing args to uinit via kernel parameters, for example:
    77  	//
    78  	// uroot.uinitargs="-v --foobar"
    79  	//
    80  	// We also allow passing args to uinit via a flags file in
    81  	// /etc/uinit.flags.
    82  	args := cmdline.GetUinitArgs()
    83  	if contents, err := ioutil.ReadFile("/etc/uinit.flags"); err == nil {
    84  		args = append(args, uflag.FileToArgv(string(contents))...)
    85  	}
    86  	uinitArgs := libinit.WithArguments(args...)
    87  
    88  	cmdList := []*exec.Cmd{
    89  		// inito is (optionally) created by the u-root command when the
    90  		// u-root initramfs is merged with an existing initramfs that
    91  		// has a /init. The name inito means "original /init" There may
    92  		// be an inito if we are building on an existing initramfs. All
    93  		// initos need their own pid space.
    94  		libinit.Command("/inito", libinit.WithCloneFlags(syscall.CLONE_NEWPID), ctty),
    95  
    96  		libinit.Command("/bbin/uinit", ctty, uinitArgs),
    97  		libinit.Command("/bin/uinit", ctty, uinitArgs),
    98  		libinit.Command("/buildbin/uinit", ctty, uinitArgs),
    99  
   100  		libinit.Command("/bin/defaultsh", ctty),
   101  		libinit.Command("/bin/sh", ctty),
   102  	}
   103  
   104  	cmdCount := libinit.RunCommands(debug, cmdList...)
   105  	if cmdCount == 0 {
   106  		log.Printf("No suitable executable found in %v", cmdList)
   107  	}
   108  
   109  	// We need to reap all children before exiting.
   110  	log.Printf("Waiting for orphaned children")
   111  	libinit.WaitOrphans()
   112  	log.Printf("All commands exited")
   113  	log.Printf("Syncing filesystems")
   114  	syscall.Sync()
   115  	log.Printf("Exiting...")
   116  }