2019-12-22 07:12:39 +03:00
|
|
|
# "System" helpers.
|
|
|
|
module System
|
|
|
|
class CommandError < StandardError
|
|
|
|
end
|
|
|
|
class CommandNotFound < CommandError
|
|
|
|
end
|
2019-12-23 06:32:34 +03:00
|
|
|
class MountError < StandardError
|
|
|
|
end
|
2019-12-22 07:12:39 +03:00
|
|
|
|
2019-12-24 09:46:57 +03:00
|
|
|
def self.prettify_command(*args)
|
2019-12-24 08:54:30 +03:00
|
|
|
args = args.dup
|
|
|
|
# Removes the environment hash, if present.
|
|
|
|
args.shift if args.first.is_a?(Hash)
|
2019-12-24 09:46:57 +03:00
|
|
|
if args.length == 1
|
|
|
|
args.first
|
|
|
|
else
|
|
|
|
args.shelljoin
|
|
|
|
end
|
2019-12-24 08:54:30 +03:00
|
|
|
end
|
|
|
|
|
2019-12-22 07:12:39 +03:00
|
|
|
# Runs and pretty-prints a command. Parameters and shelling-out have the same
|
|
|
|
# meaning as with +Kernel#spawn+; one parameter is shelling-out, multiple is
|
|
|
|
# direct +exec+.
|
|
|
|
#
|
|
|
|
# @param args [Array<String>] Command and parameters
|
|
|
|
# @raise [System::CommandNotFound] on exit status 127, commonly used for command not found.
|
|
|
|
# @raise [System::CommandError] on any other exit status.
|
|
|
|
def self.run(*args)
|
2019-12-24 09:46:57 +03:00
|
|
|
pretty_command = prettify_command(*args)
|
|
|
|
$logger.debug(" $ #{pretty_command}")
|
2019-12-22 07:12:39 +03:00
|
|
|
unless system(*args)
|
|
|
|
raise CommandError.new("Could not execute `#{pretty_command}`, status nil") if $?.nil?
|
|
|
|
status = $?.exitstatus
|
|
|
|
if status == 127
|
|
|
|
raise CommandNotFound.new("Command not found... `#{pretty_command}` (#{status})")
|
|
|
|
else
|
|
|
|
raise CommandError.new("Command failed... `#{pretty_command}` (#{status})")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-24 08:54:30 +03:00
|
|
|
# Execs and pretty-prints a command.
|
|
|
|
def self.exec(*args)
|
2019-12-24 09:46:57 +03:00
|
|
|
$logger.debug(" $ #{prettify_command(*args)}")
|
2019-12-24 08:54:30 +03:00
|
|
|
Kernel.exec(*args)
|
|
|
|
end
|
|
|
|
|
2019-12-25 08:01:25 +03:00
|
|
|
# Thin wrapper over +Kernel#exec+, but with printing.
|
|
|
|
def self.spawn(*args)
|
|
|
|
$logger.debug(" $ #{prettify_command(*args)} &")
|
|
|
|
Kernel.spawn(*args)
|
|
|
|
end
|
|
|
|
|
2019-12-24 08:54:30 +03:00
|
|
|
# Discovers the location of given program name.
|
|
|
|
def self.which(program_name)
|
|
|
|
ENV["PATH"].split(":").each do |path|
|
|
|
|
full = File.join(path, program_name)
|
|
|
|
return full if File.stat(full).executable? && !File.directory?(full)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-01-21 00:37:57 +03:00
|
|
|
def self.write(file, contents)
|
|
|
|
$logger.debug("echo #{contents.to_json} > #{file}")
|
|
|
|
File.write(file, contents)
|
|
|
|
end
|
|
|
|
|
2019-12-22 07:12:39 +03:00
|
|
|
# Mounts a filesystem of type +type+ on +dest+.
|
|
|
|
#
|
|
|
|
# The +source+ parameter is optional, though kept first to keep a coherent
|
|
|
|
# order compared to the actual +mount+ command.
|
|
|
|
#
|
|
|
|
# @overload mount(source, dest, type:)
|
|
|
|
# @param source [String] (Optional) mount source, defaults to type
|
|
|
|
# @param dest [String] Destination path to mount to
|
|
|
|
# @param type [String] Type of the mount (+-t+).
|
2019-12-24 01:42:36 +03:00
|
|
|
# @param options [Array<String>] Mount options (+-o+).
|
2019-12-22 07:12:39 +03:00
|
|
|
# @overload mount(dest, type:)
|
|
|
|
# @param dest [String] Destination path to mount to
|
|
|
|
# @param type [String] Type of the mount (+-t+).
|
2019-12-24 01:42:36 +03:00
|
|
|
# @param options [Array<String>] Mount options (+-o+).
|
|
|
|
def self.mount(source, dest = nil, type: nil, options: nil)
|
2019-12-22 07:12:39 +03:00
|
|
|
# Fill-in the "reversed" optional parameters.
|
|
|
|
unless dest
|
|
|
|
dest = source
|
|
|
|
source = type
|
|
|
|
end
|
2019-12-23 06:32:34 +03:00
|
|
|
|
|
|
|
if source.nil? and type.nil?
|
|
|
|
raise MountError.new("Cannot mount when missing both source and type.")
|
|
|
|
end
|
|
|
|
|
|
|
|
args = []
|
|
|
|
if type
|
|
|
|
args << "-t"
|
|
|
|
args << type
|
|
|
|
end
|
2019-12-24 01:42:36 +03:00
|
|
|
if options
|
|
|
|
args << "-o"
|
|
|
|
args << options.join(",")
|
|
|
|
end
|
2019-12-23 06:32:34 +03:00
|
|
|
args << source
|
|
|
|
args << dest
|
|
|
|
|
|
|
|
run("mount", *args)
|
2019-12-22 07:12:39 +03:00
|
|
|
end
|
2019-12-24 05:53:48 +03:00
|
|
|
|
|
|
|
def self.failure(code, message="(No details given)", color: "000000")
|
2019-12-24 09:48:24 +03:00
|
|
|
begin
|
2019-12-24 05:53:48 +03:00
|
|
|
System.run("ply-image", "--clear=0x#{color}", "/sad-phone.png")
|
2019-12-24 09:48:24 +03:00
|
|
|
rescue CommandError
|
|
|
|
end
|
2019-12-24 05:53:48 +03:00
|
|
|
$logger.fatal("#{code}: #{message}")
|
2019-12-24 22:17:03 +03:00
|
|
|
sleep(Configuration["boot"]["fail"]["delay"])
|
|
|
|
hard_reboot if Configuration["boot"]["fail"]["reboot"]
|
2019-12-24 05:53:48 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.hard_reboot()
|
2020-01-21 00:40:11 +03:00
|
|
|
System.write("/proc/sysrq-trigger", "b\n")
|
2019-12-24 05:53:48 +03:00
|
|
|
end
|
2019-12-22 07:12:39 +03:00
|
|
|
end
|