diff --git a/.gitignore b/.gitignore index 7572804..c06cb35 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ initrd* vmlinuz-linux vmlinuz* debian* +start.sh diff --git a/src/core/mainloop.nim b/src/core/mainloop.nim index dfb6b85..8c44972 100644 --- a/src/core/mainloop.nim +++ b/src/core/mainloop.nim @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import strformat - +import os import ../util/[logging, misc] @@ -27,11 +27,13 @@ proc mainLoop*(logger: Logger) = logger.debug(&"Unblocking signals") unblockSignals(logger) logger.info("System initialization complete, going idle") - while true: - try: - logger.info(&"Working...") + logger.switchToFile() + try: + discard execShellCmd("/bin/login -f root") # TODO: Use a service + while true: sleepSeconds(30) - except: - logger.critical(&"A critical error has occurred while running, restarting the mainloop! Error -> {getCurrentExceptionMsg()}") - # We *absolutely* cannot die - mainLoop(logger) + except: + logger.critical(&"A critical error has occurred while running, restarting the mainloop in 30 seconds! Error -> {getCurrentExceptionMsg()}") + sleepSeconds(30) + # We *absolutely* cannot die + mainLoop(logger) diff --git a/src/core/services.nim b/src/core/services.nim index 9e1c60f..66a7a69 100644 --- a/src/core/services.nim +++ b/src/core/services.nim @@ -112,6 +112,7 @@ proc supervisorWorker(logger: Logger, service: Service, pid: int) = var returnCode: int var sig: int var process: Process + logger.switchToFile() while true: returnCode = posix.waitPid(cint(pid), status, WUNTRACED) if WIFEXITED(status): @@ -190,8 +191,8 @@ proc startService(logger: Logger, service: Service) = proc startServices*(logger: Logger, level: RunLevel, workers: int = 1) = ## Starts the registered services in the ## given runlevel - if workers > cpuinfo.countProcessors() - 1: - logger.warning(&"The configured number of workers ({workers}) is greater than the recommended one ({cpuinfo.countProcessors() - 1}), performance may degrade") + if workers > cpuinfo.countProcessors(): + logger.warning(&"The configured number of workers ({workers}) is greater than the recommended one ({cpuinfo.countProcessors()}), performance may degrade") var workerCount: int = 0 var status: cint var pid: int = posix.fork() diff --git a/src/main.nim b/src/main.nim index bc3e892..be3adf4 100644 --- a/src/main.nim +++ b/src/main.nim @@ -38,13 +38,15 @@ proc addStuff = addSymlink(newSymlink(dest="/dev/std/err", source="/")) # Should say link already exists and points to /proc/self/fd/2 addSymlink(newSymlink(dest="/dev/std/in", source="/does/not/exist")) # Shuld say destination does not exist addSymlink(newSymlink(dest="/dev/std/in", source="/proc/self/fd/0")) # Should say link already exists - # Adds virtual filesystems + # Adds virtual filesystems (Update: apparently the kernel already mounts this stuff!) + #[ addVFS(newFilesystem(source="proc", target="/proc", fstype="proc", mountflags=0u64, data="nosuid,noexec,nodev", dump=0u8, pass=0u8)) addVFS(newFilesystem(source="sys", target="/sys", fstype="sysfs", mountflags=0u64, data="nosuid,noexec,nodev", dump=0u8, pass=0u8)) addVFS(newFilesystem(source="run", target="/run", fstype="tmpfs", mountflags=0u64, data="mode=0755,nosuid,nodev", dump=0u8, pass=0u8)) addVFS(newFilesystem(source="dev", target="/dev", fstype="devtmpfs", mountflags=0u64, data="mode=0755,nosuid", dump=0u8, pass=0u8)) addVFS(newFilesystem(source="devpts", target="/dev/pts", fstype="devpts", mountflags=0u64, data="mode=0620,gid=5,nosuid,noexec", dump=0u8, pass=0u8)) addVFS(newFilesystem(source="shm", target="/dev/shm", fstype="tmpfs", mountflags=0u64, data="mode=1777,nosuid,nodev", dump=0u8, pass=0u8)) + ]# addDirectory(newDirectory("test", 777)) # Should create a directory addDirectory(newDirectory("/dev/disk", 123)) # Should say directory already exists addDirectory(newDirectory("/dev/test/owo", 000)) # Should say path does not exist @@ -60,9 +62,11 @@ proc addStuff = addService(newService(name="exiter", description="la mamma di licenziat", exec="/bin/true", supervised=true, restart=Always, restartDelay=5, runlevel=Boot, workDir="/", kind=Simple)) + #[ addService(newService(name="sleeper", description="la mamma di danieloz", exec="/usr/bin/sleep", supervised=true, restart=Always, restartDelay=5, runlevel=Boot, workDir="/", kind=Simple)) + ]# proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab") = @@ -94,9 +98,6 @@ proc main(logger: Logger, mountDisks: bool = true, fstab: string = "/etc/fstab") # One of the key features of an init system is reaping child # processes! reapProcess(getDefaultLogger()) - onSignal(SIGINT): - # Temporary - nimDExit(getDefaultLogger(), 131, emerg=true) addStuff() try: if mountDisks: diff --git a/src/util/logging.nim b/src/util/logging.nim index d2f1c29..f7aa121 100644 --- a/src/util/logging.nim +++ b/src/util/logging.nim @@ -39,6 +39,9 @@ type handlers*: seq[LogHandler] const defaultLevel = LogLevel.Info +const logFile = "/var/log/nimd" +var logToFile: bool = false + proc log(self: Logger, level: LogLevel = defaultLevel, message: string) # Forward declaration @@ -68,67 +71,124 @@ proc log(self: Logger, level: LogLevel = defaultLevel, message: string) = handler.code(handler, self, message) +proc logTraceStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgMagenta) + stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + stderr.flushFile() + setForegroundColor(fgDefault) + + +proc logDebugStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgCyan) + stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - DEBUG ({posix.getpid()})] {message}""") + stderr.flushFile() + setForegroundColor(fgDefault) + + +proc logInfoStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgGreen) + stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - INFO ({posix.getpid()})] {message}""") + stderr.flushFile() + setForegroundColor(fgDefault) + + +proc logWarningStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgYellow) + stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - WARNING ({posix.getpid()})] {message}""") + stderr.flushFile() + setForegroundColor(fgDefault) + + +proc logErrorStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgRed) + stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - ERROR ({posix.getpid()})] {message}""") + stderr.flushFile() + setForegroundColor(fgDefault) + + +proc logCriticalStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgRed) + stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - CRITICAL ({posix.getpid()})] {message}""") + stderr.flushFile() + setForegroundColor(fgDefault) + + +proc logFatalStderr(self: LogHandler, logger: Logger, message: string) = + setForegroundColor(fgBlack) + setBackgroundColor(bgRed) + stderr.write(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - FATAL ({posix.getpid()})]""") + setForegroundColor(fgRed) + setBackgroundColor(bgDefault) + stderr.writeline(&" {message}") + setForegroundColor(fgDefault) + stderr.flushFile() + + +proc logTraceFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + + +proc logDebugFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + + +proc logInfoFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + + +proc logWarningFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + +proc logErrorFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + + +proc logCriticalFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + + +proc logFatalFile(self: LogHandler, logger: Logger, message: string) = + StreamHandler(self).file.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") + + +proc switchToFile*(self: Logger) = + ## Switches logging to file and + ## changes the behavior of getDefaultLogger + ## accordingly + if logToFile: + return + logToFile = true + self.handlers = @[] + self.addHandler(createStreamHandler(logTraceFile, LogLevel.Trace, logFile)) + self.addHandler(createStreamHandler(logDebugFile, LogLevel.Debug, logFile)) + self.addHandler(createStreamHandler(logInfoFile, LogLevel.Info, logFile)) + self.addHandler(createStreamHandler(logWarningFile, LogLevel.Warning, logFile)) + self.addHandler(createStreamHandler(logErrorFile, LogLevel.Error, logFile)) + self.addHandler(createStreamHandler(logCriticalFile, LogLevel.Critical, logFile)) + self.addHandler(createStreamHandler(logFatalFile, LogLevel.Fatal, logFile)) + + proc getDefaultLogger*(): Logger = ## Gets a simple logger with level set ## to LogLevel.Info and one handler per ## level that writes the given message to the ## standard error with some basic info like the ## current date and time and the log level - - setStdIoUnbuffered() # Doesn't work otherwise! - - proc logTrace(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgMagenta) - stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - TRACE ({posix.getpid()})] {message}""") - stderr.flushFile() - setForegroundColor(fgDefault) - - proc logDebug(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgCyan) - stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - DEBUG ({posix.getpid()})] {message}""") - stderr.flushFile() - setForegroundColor(fgDefault) - - proc logInfo(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgGreen) - stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - INFO ({posix.getpid()})] {message}""") - stderr.flushFile() - setForegroundColor(fgDefault) - - proc logWarning(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgYellow) - stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - WARNING ({posix.getpid()})] {message}""") - stderr.flushFile() - setForegroundColor(fgDefault) - - proc logError(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgRed) - stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - ERROR ({posix.getpid()})] {message}""") - stderr.flushFile() - setForegroundColor(fgDefault) - - proc logCritical(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgRed) - stderr.writeLine(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - CRITICAL ({posix.getpid()})] {message}""") - stderr.flushFile() - setForegroundColor(fgDefault) - - proc logFatal(self: LogHandler, logger: Logger, message: string) = - setForegroundColor(fgBlack) - setBackgroundColor(bgRed) - stderr.write(&"""[{fromUnix(getTime().toUnixFloat().int).format("d/M/yyyy HH:mm:ss")} - FATAL ({posix.getpid()})]""") - setForegroundColor(fgRed) - setBackgroundColor(bgDefault) - stderr.writeline(&" {message}") - setForegroundColor(fgDefault) - stderr.flushFile() - - result = newLogger() - result.addHandler(createHandler(logTrace, LogLevel.Trace)) - result.addHandler(createHandler(logDebug, LogLevel.Debug)) - result.addHandler(createHandler(logInfo, LogLevel.Info)) - result.addHandler(createHandler(logWarning, LogLevel.Warning)) - result.addHandler(createHandler(logError, LogLevel.Error)) - result.addHandler(createHandler(logCritical, LogLevel.Critical)) - result.addHandler(createHandler(logFatal, LogLevel.Fatal)) + if not logToFile: + setStdIoUnbuffered() # Colors don't work otherwise! + result.addHandler(createHandler(logTraceStderr, LogLevel.Trace)) + result.addHandler(createHandler(logDebugStderr, LogLevel.Debug)) + result.addHandler(createHandler(logInfoStderr, LogLevel.Info)) + result.addHandler(createHandler(logWarningStderr, LogLevel.Warning)) + result.addHandler(createHandler(logErrorStderr, LogLevel.Error)) + result.addHandler(createHandler(logCriticalStderr, LogLevel.Critical)) + result.addHandler(createHandler(logFatalStderr, LogLevel.Fatal)) + else: + result.addHandler(createStreamHandler(logTraceFile, LogLevel.Trace, logFile)) + result.addHandler(createStreamHandler(logDebugFile, LogLevel.Debug, logFile)) + result.addHandler(createStreamHandler(logInfoFile, LogLevel.Info, logFile)) + result.addHandler(createStreamHandler(logWarningFile, LogLevel.Warning, logFile)) + result.addHandler(createStreamHandler(logErrorFile, LogLevel.Error, logFile)) + result.addHandler(createStreamHandler(logCriticalFile, LogLevel.Critical, logFile)) + result.addHandler(createStreamHandler(logFatalFile, LogLevel.Fatal, logFile))