feat: implement montauk::service_log & add support to system services

This commit is contained in:
2026-08-28 11:56:29 +02:00
parent 0d23db8a0e
commit b1f1cfe32b
8 changed files with 117 additions and 62 deletions
+1 -1
View File
@@ -12,4 +12,4 @@
#pragma once #pragma once
#define MONTAUK_BUILD_NUMBER 150 #define MONTAUK_BUILD_NUMBER 151
+24
View File
@@ -0,0 +1,24 @@
/*
* service_log.h
* Common logging policy for MontaukOS userspace services.
*/
#pragma once
#include <montauk/syscall.h>
namespace montauk {
// Append one newline-free message to the system log. When the service was
// launched from a userspace terminal, echo the same message there as well.
inline void service_log(const char* message) {
if (message == nullptr) return;
write_log(message);
if (terminal_attached()) {
print(message);
print("\n");
}
}
}
+28 -27
View File
@@ -6,6 +6,7 @@
*/ */
#include <montauk/syscall.h> #include <montauk/syscall.h>
#include <montauk/service_log.h>
#include <montauk/string.h> #include <montauk/string.h>
#include <libc/stdio.h> #include <libc/stdio.h>
@@ -247,7 +248,7 @@ static constexpr uint32_t BROADCAST_IP = 0xFFFFFFFF;
extern "C" void _start() { extern "C" void _start() {
char msg[256]; char msg[256];
montauk::print("MontaukOS DHCP Client\n"); montauk::service_log("MontaukOS DHCP Client");
// 1. Get MAC address // 1. Get MAC address
montauk::abi::NetCfg origCfg; montauk::abi::NetCfg origCfg;
@@ -255,8 +256,8 @@ extern "C" void _start() {
char macStr[32]; char macStr[32];
format_mac(macStr, sizeof(macStr), origCfg.macAddress); format_mac(macStr, sizeof(macStr), origCfg.macAddress);
snprintf(msg, sizeof(msg), "MAC address: %s\n", macStr); snprintf(msg, sizeof(msg), "MAC address: %s", macStr);
montauk::print(msg); montauk::service_log(msg);
// 2. Set IP to 0.0.0.0 to allow broadcast send/receive // 2. Set IP to 0.0.0.0 to allow broadcast send/receive
montauk::abi::NetCfg zeroCfg; montauk::abi::NetCfg zeroCfg;
@@ -268,13 +269,13 @@ extern "C" void _start() {
// 3. Create UDP socket and bind to port 68 // 3. Create UDP socket and bind to port 68
int fd = montauk::socket(montauk::abi::SOCK_UDP); int fd = montauk::socket(montauk::abi::SOCK_UDP);
if (fd < 0) { if (fd < 0) {
montauk::print("Error: failed to create UDP socket\n"); montauk::service_log("Error: failed to create UDP socket");
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
} }
if (montauk::bind(fd, DHCP_CLIENT_PORT) < 0) { if (montauk::bind(fd, DHCP_CLIENT_PORT) < 0) {
montauk::print("Error: failed to bind to port 68\n"); montauk::service_log("Error: failed to bind to port 68");
montauk::closesocket(fd); montauk::closesocket(fd);
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
@@ -284,9 +285,9 @@ extern "C" void _start() {
DhcpPacket pkt; DhcpPacket pkt;
int pktLen = build_discover(&pkt, origCfg.macAddress); int pktLen = build_discover(&pkt, origCfg.macAddress);
montauk::print("Sending DHCPDISCOVER...\n"); montauk::service_log("Sending DHCPDISCOVER...");
if (montauk::sendto(fd, (const void*)&pkt, pktLen, BROADCAST_IP, DHCP_SERVER_PORT) < 0) { if (montauk::sendto(fd, (const void*)&pkt, pktLen, BROADCAST_IP, DHCP_SERVER_PORT) < 0) {
montauk::print("Error: failed to send DISCOVER\n"); montauk::service_log("Error: failed to send DISCOVER");
montauk::closesocket(fd); montauk::closesocket(fd);
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
@@ -298,7 +299,7 @@ extern "C" void _start() {
uint64_t startMs = montauk::get_milliseconds(); uint64_t startMs = montauk::get_milliseconds();
bool gotOffer = false; bool gotOffer = false;
montauk::print("Waiting for DHCPOFFER...\n"); montauk::service_log("Waiting for DHCPOFFER...");
while (montauk::get_milliseconds() - startMs < 10000) { while (montauk::get_milliseconds() - startMs < 10000) {
uint32_t srcIp; uint32_t srcIp;
uint16_t srcPort; uint16_t srcPort;
@@ -318,7 +319,7 @@ extern "C" void _start() {
} }
if (!gotOffer) { if (!gotOffer) {
montauk::print("Error: no DHCPOFFER received (timeout)\n"); montauk::service_log("Error: no DHCPOFFER received (timeout)");
montauk::closesocket(fd); montauk::closesocket(fd);
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
@@ -326,15 +327,15 @@ extern "C" void _start() {
char ipStr[32]; char ipStr[32];
format_ip(ipStr, sizeof(ipStr), offer.offeredIp); format_ip(ipStr, sizeof(ipStr), offer.offeredIp);
snprintf(msg, sizeof(msg), "Received OFFER: %s\n", ipStr); snprintf(msg, sizeof(msg), "Received OFFER: %s", ipStr);
montauk::print(msg); montauk::service_log(msg);
// 6. Send REQUEST // 6. Send REQUEST
pktLen = build_request(&pkt, origCfg.macAddress, offer.offeredIp, offer.serverId); pktLen = build_request(&pkt, origCfg.macAddress, offer.offeredIp, offer.serverId);
montauk::print("Sending DHCPREQUEST...\n"); montauk::service_log("Sending DHCPREQUEST...");
if (montauk::sendto(fd, (const void*)&pkt, pktLen, BROADCAST_IP, DHCP_SERVER_PORT) < 0) { if (montauk::sendto(fd, (const void*)&pkt, pktLen, BROADCAST_IP, DHCP_SERVER_PORT) < 0) {
montauk::print("Error: failed to send REQUEST\n"); montauk::service_log("Error: failed to send REQUEST");
montauk::closesocket(fd); montauk::closesocket(fd);
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
@@ -344,7 +345,7 @@ extern "C" void _start() {
bool gotAck = false; bool gotAck = false;
startMs = montauk::get_milliseconds(); startMs = montauk::get_milliseconds();
montauk::print("Waiting for DHCPACK...\n"); montauk::service_log("Waiting for DHCPACK...");
while (montauk::get_milliseconds() - startMs < 10000) { while (montauk::get_milliseconds() - startMs < 10000) {
uint32_t srcIp; uint32_t srcIp;
uint16_t srcPort; uint16_t srcPort;
@@ -357,7 +358,7 @@ extern "C" void _start() {
break; break;
} }
if (offer.valid && offer.msgType == DHCPNAK) { if (offer.valid && offer.msgType == DHCPNAK) {
montauk::print("Error: received DHCPNAK from server\n"); montauk::service_log("Error: received DHCPNAK from server");
montauk::closesocket(fd); montauk::closesocket(fd);
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
@@ -372,7 +373,7 @@ extern "C" void _start() {
montauk::closesocket(fd); montauk::closesocket(fd);
if (!gotAck) { if (!gotAck) {
montauk::print("Error: no DHCPACK received (timeout)\n"); montauk::service_log("Error: no DHCPACK received (timeout)");
montauk::set_netcfg(&origCfg); montauk::set_netcfg(&origCfg);
montauk::exit(1); montauk::exit(1);
} }
@@ -386,29 +387,29 @@ extern "C" void _start() {
montauk::set_netcfg(&newCfg); montauk::set_netcfg(&newCfg);
// 9. Print results // 9. Print results
montauk::print("\nDHCP configuration applied:\n"); montauk::service_log("DHCP configuration applied:");
format_ip(ipStr, sizeof(ipStr), offer.offeredIp); format_ip(ipStr, sizeof(ipStr), offer.offeredIp);
snprintf(msg, sizeof(msg), " IP Address: %s\n", ipStr); snprintf(msg, sizeof(msg), " IP Address: %s", ipStr);
montauk::print(msg); montauk::service_log(msg);
format_ip(ipStr, sizeof(ipStr), offer.subnetMask); format_ip(ipStr, sizeof(ipStr), offer.subnetMask);
snprintf(msg, sizeof(msg), " Subnet Mask: %s\n", ipStr); snprintf(msg, sizeof(msg), " Subnet Mask: %s", ipStr);
montauk::print(msg); montauk::service_log(msg);
format_ip(ipStr, sizeof(ipStr), offer.router); format_ip(ipStr, sizeof(ipStr), offer.router);
snprintf(msg, sizeof(msg), " Gateway: %s\n", ipStr); snprintf(msg, sizeof(msg), " Gateway: %s", ipStr);
montauk::print(msg); montauk::service_log(msg);
if (offer.dns != 0) { if (offer.dns != 0) {
format_ip(ipStr, sizeof(ipStr), offer.dns); format_ip(ipStr, sizeof(ipStr), offer.dns);
snprintf(msg, sizeof(msg), " DNS Server: %s\n", ipStr); snprintf(msg, sizeof(msg), " DNS Server: %s", ipStr);
montauk::print(msg); montauk::service_log(msg);
} }
if (offer.leaseTime != 0) { if (offer.leaseTime != 0) {
snprintf(msg, sizeof(msg), " Lease Time: %u seconds\n", offer.leaseTime); snprintf(msg, sizeof(msg), " Lease Time: %u seconds", offer.leaseTime);
montauk::print(msg); montauk::service_log(msg);
} }
montauk::exit(0); montauk::exit(0);
+16 -17
View File
@@ -7,6 +7,7 @@
*/ */
#include <montauk/syscall.h> #include <montauk/syscall.h>
#include <montauk/service_log.h>
#include <montauk/string.h> #include <montauk/string.h>
#include <libc/stdio.h> #include <libc/stdio.h>
@@ -144,10 +145,10 @@ static void log_request(const char* method, const char* path, int status, int bo
montauk::gettime(&dt); montauk::gettime(&dt);
char msg[256]; char msg[256];
snprintf(msg, sizeof(msg), "[%02d:%02d:%02d] %s %s -> %d (%d bytes)\n", snprintf(msg, sizeof(msg), "[%02d:%02d:%02d] %s %s -> %d (%d bytes)",
(int)dt.Hour, (int)dt.Minute, (int)dt.Second, (int)dt.Hour, (int)dt.Minute, (int)dt.Second,
method, path, status, bodyLen); method, path, status, bodyLen);
montauk::print(msg); montauk::service_log(msg);
} }
// ---- Page generators ---- // ---- Page generators ----
@@ -454,9 +455,9 @@ extern "C" void _start() {
uint16_t port = 80; uint16_t port = 80;
if (*arg) { if (*arg) {
if (!parse_uint16(arg, &port)) { if (!parse_uint16(arg, &port)) {
montauk::print("Invalid port: "); char message[96];
montauk::print(arg); snprintf(message, sizeof(message), "Invalid port: %s", arg);
montauk::putchar('\n'); montauk::service_log(message);
montauk::exit(1); montauk::exit(1);
} }
} }
@@ -464,32 +465,30 @@ extern "C" void _start() {
// Create server socket // Create server socket
int listenFd = montauk::socket(montauk::abi::SOCK_TCP); int listenFd = montauk::socket(montauk::abi::SOCK_TCP);
if (listenFd < 0) { if (listenFd < 0) {
montauk::print("Error: failed to create socket\n"); montauk::service_log("Error: failed to create socket");
montauk::exit(1); montauk::exit(1);
} }
// Bind // Bind
if (montauk::bind(listenFd, port) < 0) { if (montauk::bind(listenFd, port) < 0) {
montauk::print("Error: failed to bind to port "); char message[64];
char tmp[8]; snprintf(message, sizeof(message), "Error: failed to bind to port %d", (int)port);
snprintf(tmp, sizeof(tmp), "%d", (int)port); montauk::service_log(message);
montauk::print(tmp);
montauk::putchar('\n');
montauk::closesocket(listenFd); montauk::closesocket(listenFd);
montauk::exit(1); montauk::exit(1);
} }
// Listen // Listen
if (montauk::listen(listenFd) < 0) { if (montauk::listen(listenFd) < 0) {
montauk::print("Error: failed to listen\n"); montauk::service_log("Error: failed to listen");
montauk::closesocket(listenFd); montauk::closesocket(listenFd);
montauk::exit(1); montauk::exit(1);
} }
char msg[128]; char msg[128];
snprintf(msg, sizeof(msg), "MontaukOS httpd listening on port %d\n", (int)port); snprintf(msg, sizeof(msg), "MontaukOS httpd listening on port %d", (int)port);
montauk::print(msg); montauk::service_log(msg);
montauk::print("Press Ctrl+Q between requests to stop.\n\n"); montauk::service_log("Press Ctrl+Q between requests to stop.");
bool running = true; bool running = true;
while (running) { while (running) {
@@ -507,7 +506,7 @@ extern "C" void _start() {
// Accept next client (blocks until a connection arrives) // Accept next client (blocks until a connection arrives)
int clientFd = montauk::accept(listenFd); int clientFd = montauk::accept(listenFd);
if (clientFd < 0) { if (clientFd < 0) {
montauk::print("Warning: accept failed\n"); montauk::service_log("Warning: accept failed");
montauk::yield(); montauk::yield();
continue; continue;
} }
@@ -525,7 +524,7 @@ extern "C" void _start() {
} }
} }
montauk::print("\nShutting down httpd...\n"); montauk::service_log("Shutting down httpd...");
montauk::closesocket(listenFd); montauk::closesocket(listenFd);
montauk::exit(0); montauk::exit(0);
} }
+5 -3
View File
@@ -6,8 +6,10 @@
#include <montauk/config.h> #include <montauk/config.h>
#include <montauk/ntp.h> #include <montauk/ntp.h>
#include <montauk/service_log.h>
#include <montauk/string.h> #include <montauk/string.h>
#include <montauk/syscall.h> #include <montauk/syscall.h>
#include <libc/stdio.h>
static constexpr uint64_t RETRY_INTERVAL_MS = static constexpr uint64_t RETRY_INTERVAL_MS =
montauk::ntp::MIN_QUERY_INTERVAL_MS; montauk::ntp::MIN_QUERY_INTERVAL_MS;
@@ -15,9 +17,9 @@ static constexpr uint64_t SYNC_INTERVAL_MS = 60ULL * 60ULL * 1000ULL;
static constexpr uint64_t CONFIG_POLL_MS = 5000; static constexpr uint64_t CONFIG_POLL_MS = 5000;
static void log(const char* message) { static void log(const char* message) {
montauk::print("ntp: "); char line[256];
montauk::print(message); snprintf(line, sizeof(line), "ntp: %s", message);
montauk::print("\n"); montauk::service_log(line);
} }
static bool load_settings(char* server, int server_cap) { static bool load_settings(char* server, int server_cap) {
+7 -3
View File
@@ -5,6 +5,7 @@
*/ */
#include <montauk/syscall.h> #include <montauk/syscall.h>
#include <montauk/service_log.h>
#include <print/print.hpp> #include <print/print.hpp>
#include "test_page_jpeg.hpp" #include "test_page_jpeg.hpp"
@@ -64,12 +65,15 @@ static void write_daemon_state(const char* phase, const char* subject = nullptr,
} }
static void log_msg(const char* fmt, ...) { static void log_msg(const char* fmt, ...) {
char body[768];
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
printf("[printd] "); vsnprintf(body, sizeof(body), fmt, ap);
vprintf(fmt, ap);
printf("\n");
va_end(ap); va_end(ap);
char line[800];
snprintf(line, sizeof(line), "[printd] %s", body);
montauk::service_log(line);
} }
static void set_job_state(JobMeta* job, const char* state, const char* message) { static void set_job_state(JobMeta* job, const char* state, const char* message) {
+12 -11
View File
@@ -5,6 +5,7 @@
#include "crypto.hpp" #include "crypto.hpp"
#include <montauk/service_log.h>
#include <montauk/ssh.h> #include <montauk/ssh.h>
#include <libc/stdio.h> #include <libc/stdio.h>
@@ -1287,17 +1288,17 @@ static void handle(int fd) {
connection.set_timeout(PREAUTH_TIMEOUT_MS); connection.set_timeout(PREAUTH_TIMEOUT_MS);
if (!version(connection)) { if (!version(connection)) {
montauk::print("sshd: client version exchange failed\n"); montauk::service_log("sshd: client version exchange failed");
} else if (!kex(connection)) { } else if (!kex(connection)) {
char message[64]; char message[64];
snprintf(message, sizeof(message), snprintf(message, sizeof(message),
"sshd: key exchange failed (%d)\n", kex_error); "sshd: key exchange failed (%d)", kex_error);
montauk::print(message); montauk::service_log(message);
} else if (!auth(connection, user)) { } else if (!auth(connection, user)) {
char message[64]; char message[64];
snprintf(message, sizeof(message), snprintf(message, sizeof(message),
"sshd: authentication failed (%d)\n", kex_error); "sshd: authentication failed (%d)", kex_error);
montauk::print(message); montauk::service_log(message);
} else { } else {
/* An authenticated session is allowed to sit idle. */ /* An authenticated session is allowed to sit idle. */
connection.clear_timeout(); connection.clear_timeout();
@@ -1309,14 +1310,14 @@ static void handle(int fd) {
extern "C" void _start() { extern "C" void _start() {
if (!rng.init()) { if (!rng.init()) {
montauk::print("sshd: secure random initialization failed\n"); montauk::service_log("sshd: secure random initialization failed");
montauk::exit(1); montauk::exit(1);
} }
if (!hostkey.load()) { if (!hostkey.load()) {
montauk::print("sshd: generating local RSA host key...\n"); montauk::service_log("sshd: generating local RSA host key...");
if (!hostkey.generate(rng)) { if (!hostkey.generate(rng)) {
montauk::print("sshd: host key generation failed\n"); montauk::service_log("sshd: host key generation failed");
montauk::exit(1); montauk::exit(1);
} }
} }
@@ -1329,13 +1330,13 @@ extern "C" void _start() {
int listener = montauk::socket(montauk::abi::SOCK_TCP); int listener = montauk::socket(montauk::abi::SOCK_TCP);
if (listener < 0 || montauk::bind(listener, (uint16_t)port) < 0 || if (listener < 0 || montauk::bind(listener, (uint16_t)port) < 0 ||
montauk::listen(listener) < 0) { montauk::listen(listener) < 0) {
montauk::print("sshd: could not listen\n"); montauk::service_log("sshd: could not listen");
montauk::exit(1); montauk::exit(1);
} }
char message[80]; char message[80];
snprintf(message, sizeof(message), "sshd: listening on port %d\n", port); snprintf(message, sizeof(message), "sshd: listening on port %d", port);
montauk::print(message); montauk::service_log(message);
for (;;) { for (;;) {
int fd = montauk::accept(listener); int fd = montauk::accept(listener);
@@ -0,0 +1,24 @@
/*
* service_log.h
* Common logging policy for MontaukOS userspace services.
*/
#pragma once
#include <montauk/syscall.h>
namespace montauk {
// Append one newline-free message to the system log. When the service was
// launched from a userspace terminal, echo the same message there as well.
inline void service_log(const char* message) {
if (message == nullptr) return;
write_log(message);
if (terminal_attached()) {
print(message);
print("\n");
}
}
}