const std = @import("std"); const opts = @import("opts"); const log = std.log.scoped(.mzteriver); pub const std_options = std.Options{ .log_level = switch (@import("builtin").mode) { .Debug => .debug, else => .info, }, }; pub fn main() !void { var dbg_gpa = if (@import("builtin").mode == .Debug) std.heap.GeneralPurposeAllocator(.{}){} else {}; defer if (@TypeOf(dbg_gpa) != void) { _ = dbg_gpa.deinit(); }; const alloc = if (@TypeOf(dbg_gpa) == void) std.heap.c_allocator else dbg_gpa.allocator(); if (std.mem.endsWith(u8, std.mem.span(std.os.argv[0]), "init") or (std.os.argv.len >= 2 and std.mem.orderZ(u8, std.os.argv[1], "init") == .eq)) { log.info("running in init mode", .{}); try @import("init.zig").init(alloc); } else { log.info("running in launch mode", .{}); const logfd = logf: { const logf_path = try std.fmt.allocPrintZ( alloc, "/tmp/mzteriver-{}-{}.log", .{ std.os.linux.getuid(), std.os.linux.getpid() }, ); defer alloc.free(logf_path); log.info("river log file: {s}", .{logf_path}); break :logf try std.os.openatZ( std.os.AT.FDCWD, logf_path.ptr, // no CLOEXEC .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true, }, 0o644, ); }; { errdefer std.os.close(logfd); // redirect river's STDERR and STDOUT to log file try std.os.dup2(logfd, std.os.STDOUT_FILENO); try std.os.dup2(logfd, std.os.STDERR_FILENO); } std.os.close(logfd); var env = std.BoundedArray(?[*:0]const u8, 0xff).init(0) catch unreachable; const envp: [*:null]?[*:0]const u8 = env: { try env.appendSlice(std.os.environ); try env.append("XKB_DEFAULT_LAYOUT=de"); try env.append("QT_QPA_PLATFORM=wayland"); try env.append("XDG_CURRENT_DESKTOP=river"); if (opts.nvidia) { try env.append("WLR_NO_HARDWARE_CURSORS=1"); } // manually add sentinel try env.append(null); break :env @ptrCast(env.slice().ptr); }; return std.os.execvpeZ("river", &[_:null]?[*:0]const u8{"river"}, envp); } }