aboutsummaryrefslogtreecommitdiff
path: root/rc.lib
blob: c224523b5e70ac3c246172e01da1bc1cf94a6118 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# -*- mode: sh -*-
# rc.lib -- common functions for rc.boot and rc.shutdown
# shellcheck disable=1090,2034

export PATH=$PATH:/usr/local/bin:/usr/bin

# logger is provided by 3 packages on the core repository (sbase,
# busybox, util-linux). However, it is optional. Since logger
# outputs to stderr, we cannot silence stderr to not display error
# messages in the rare case where it isn't available on the system.
logger=$(command -v logger) || logger=:

log() {
    # A function to log all output to syslog (if it is available)
    # and to kernel messages. This way the logs are readable after
    # reboot.
    #
    # The usability of this also depends on how early you start
    # syslogd and how late you stop it. I will be modifying this
    # to enable a way (or multiple ways) of storing boot/shutdown
    # logs in a persistent manner.
    #
    # Right now, you could possibly start a syslogd from the early
    # boot hooks which will be run right after filesystems are
    # mounted.
    #
    # If no arguments for the logger are specified, it will read
    # standard input for the log. This means you can pipe the output
    # of a command to this function. Those will be logged as well.
    [ "$1" ] && printf 'init: %s\n' "$@" >/dev/kmsg 2>/dev/null
    "$logger" -t init "${@:--s}"
}


out() {
    printf '%b%s \033[39m%s\033[m\n' "${3:-"\033[1;36m"}" "${2:-->}" "$1"
    log "$1"
}

err() { out "$1" "!>" "\033[1;31m" ;}

device_helper() {
    # We devices based on user preference, and what's available
    # on the system.
    #
    # Get the device daemon to be used, if we don't have a daemon
    # available on the system, do not continue any further.
    [ "$devd" ] || {
        devd=$(command -v udevd) || devd=$(command -v mdev) ||
        return 0
    }

    case "$1" in
        settle) case "${devd##*/}" in
                    udevd)
                        udevd -d
                        udevadm trigger -c add -t subsystems
                        udevadm trigger -c add -t devices
                        udevadm settle
                        ;;
                    mdev)
                        mdev -s
                        mdev -df & mdev_pid=$!
                        ;;
                esac
                ;;
        exit) case "${devd##*/}" in
                  udevd)
                      udevadm control --exit
                      ;;
                  mdev)
                      [ "$mdev_pid" ] && kill "$mdev_pid"
                      command -v mdev > /proc/sys/kernel/hotplug
                      ;;
              esac
    esac
}

link() {
    ln -sf "$1" "$2"
    printf '%s ==> %s\n' "$2" "$1"
}

mounted() {
    [ -e "$1" ] &&
    [ -f /proc/mounts ] &&
    while read -r _ mnt _; do
        case "$mnt" in "$1") return 0; esac
    done < /proc/mounts

    return 1
}

mnt() {
    mounted "$4" && set -- "remount,$1" "$2" "$3" "$4"
    mount -o "$1" -t "$2" "$3" "$4"
}

parse_cmdline() {
    # This is a primitive way of parsing kernel command line
    # options. Before now, carbs-init ignored these options
    # set by the user. More will be added as needed. Init scripts
    # don't need to handle most of the command line options
    # as the kernel deals with most of them, but not things
    # such as mount options.
    [ -r /proc/cmdline ] || {
        err "Kernel command line options cannot be parsed"
        shell
    }

    # We want to read words instead of lines here.
    # shellcheck disable=2013
    while read -r cmdline; do
        for arg in $cmdline; do
            case "$arg" in
                *=*) export "$arg" ;;
                *)   export "$arg=1" ;;
            esac
        done
    done < /proc/cmdline
}

random() {
    seed=/var/random.seed
    case "$1" in
        load)
            out "Seeding random..."
            [ -f "$seed" ] || {
                out "Generating entropy, this might take a while..."
                dd count=1 bs=512 if=/dev/random of="$seed" 2>/dev/null
            }
            cat "$seed" > /dev/urandom
            ;;
        save)
            mkdir -p "${seed%/*}"
            out "Saving random seed..."
            dd count=1 bs=512 if=/dev/urandom of="$seed" 2>/dev/null
            ;;
    esac
}

run_hook() {
    out "Running '$1' hooks..."
    for hook in "/etc/init/"*".$1" "/usr/lib/init/hooks/"*".$1"; do
        [ -f "$hook" ] || continue
        out "Running '$hook'..."
        . "$hook"
    done
}

shell() {
    err "Dropping to shell, type 'exit' to continue the boot process."
    sh -l
}