mirror of
https://github.com/fairyglade/ly.git
synced 2025-12-21 11:44:55 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
170e523823 | ||
|
|
f983c6b19b | ||
|
|
d12850889c | ||
|
|
42393f46d1 |
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -58,8 +58,8 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Relevant logs
|
label: Relevant logs
|
||||||
description: |
|
description: |
|
||||||
Please copy and paste (or attach) any relevant logs, error messages or any other output. This will be automatically formatted into code, so no need for backticks. Screenshots are accepted if they make life easier for you.
|
Please copy and paste any relevant logs, error messages or any other output. This will be automatically formatted into code, so no need for backticks. Screenshots are accepted if they make life easier for you.
|
||||||
Moreover, it is almost always a good idea to include your session log and your general log files (found at ~/ly-session.log and /var/log/ly.log respectively by default) as it usually contains relevant information about the problem.
|
If you're using the latest code on master (for v1.1.0), including your session log (found at /var/log/ly-session.log unless modified) is a good idea. (But make sure it's relevant!)
|
||||||
render: shell
|
render: shell
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: moreinfo
|
id: moreinfo
|
||||||
|
|||||||
BIN
.github/screenshot.png
vendored
BIN
.github/screenshot.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 43 KiB |
125
build.zig
125
build.zig
@@ -8,11 +8,9 @@ const InitSystem = enum {
|
|||||||
runit,
|
runit,
|
||||||
s6,
|
s6,
|
||||||
dinit,
|
dinit,
|
||||||
sysvinit,
|
|
||||||
freebsd,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const min_zig_string = "0.15.0";
|
const min_zig_string = "0.14.0";
|
||||||
const current_zig = builtin.zig_version;
|
const current_zig = builtin.zig_version;
|
||||||
|
|
||||||
// Implementing zig version detection through compile time
|
// Implementing zig version detection through compile time
|
||||||
@@ -23,7 +21,7 @@ comptime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ly_version = std.SemanticVersion{ .major = 1, .minor = 2, .patch = 0 };
|
const ly_version = std.SemanticVersion{ .major = 1, .minor = 1, .patch = 1 };
|
||||||
|
|
||||||
var dest_directory: []const u8 = undefined;
|
var dest_directory: []const u8 = undefined;
|
||||||
var config_directory: []const u8 = undefined;
|
var config_directory: []const u8 = undefined;
|
||||||
@@ -43,7 +41,6 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const version_str = try getVersionStr(b, "ly", ly_version);
|
const version_str = try getVersionStr(b, "ly", ly_version);
|
||||||
const enable_x11_support = b.option(bool, "enable_x11_support", "Enable X11 support (default is on)") orelse true;
|
const enable_x11_support = b.option(bool, "enable_x11_support", "Enable X11 support (default is on)") orelse true;
|
||||||
const default_tty = b.option(u8, "default_tty", "Set the TTY (default is 2)") orelse 2;
|
const default_tty = b.option(u8, "default_tty", "Set the TTY (default is 2)") orelse 2;
|
||||||
const fallback_tty = b.option(u8, "fallback_tty", "Set the fallback TTY (default is 2). This value gets embedded into the binary") orelse 2;
|
|
||||||
|
|
||||||
default_tty_str = try std.fmt.allocPrint(b.allocator, "{d}", .{default_tty});
|
default_tty_str = try std.fmt.allocPrint(b.allocator, "{d}", .{default_tty});
|
||||||
|
|
||||||
@@ -51,7 +48,6 @@ pub fn build(b: *std.Build) !void {
|
|||||||
build_options.addOption([]const u8, "prefix_directory", prefix_directory);
|
build_options.addOption([]const u8, "prefix_directory", prefix_directory);
|
||||||
build_options.addOption([]const u8, "version", version_str);
|
build_options.addOption([]const u8, "version", version_str);
|
||||||
build_options.addOption(u8, "tty", default_tty);
|
build_options.addOption(u8, "tty", default_tty);
|
||||||
build_options.addOption(u8, "fallback_tty", fallback_tty);
|
|
||||||
build_options.addOption(bool, "enable_x11_support", enable_x11_support);
|
build_options.addOption(bool, "enable_x11_support", enable_x11_support);
|
||||||
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
@@ -59,13 +55,9 @@ pub fn build(b: *std.Build) !void {
|
|||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "ly",
|
.name = "ly",
|
||||||
.root_module = b.createModule(.{
|
.root_source_file = b.path("src/main.zig"),
|
||||||
.root_source_file = b.path("src/main.zig"),
|
.target = target,
|
||||||
.target = target,
|
.optimize = optimize,
|
||||||
.optimize = optimize,
|
|
||||||
}),
|
|
||||||
// Here until the native backend matures in terms of performance
|
|
||||||
.use_llvm = true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const zigini = b.dependency("zigini", .{ .target = target, .optimize = optimize });
|
const zigini = b.dependency("zigini", .{ .target = target, .optimize = optimize });
|
||||||
@@ -76,17 +68,13 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const clap = b.dependency("clap", .{ .target = target, .optimize = optimize });
|
const clap = b.dependency("clap", .{ .target = target, .optimize = optimize });
|
||||||
exe.root_module.addImport("clap", clap.module("clap"));
|
exe.root_module.addImport("clap", clap.module("clap"));
|
||||||
|
|
||||||
const termbox_dep = b.dependency("termbox2", .{
|
exe.addIncludePath(b.path("include"));
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
|
|
||||||
exe.linkSystemLibrary("pam");
|
exe.linkSystemLibrary("pam");
|
||||||
if (enable_x11_support) exe.linkSystemLibrary("xcb");
|
if (enable_x11_support) exe.linkSystemLibrary("xcb");
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
|
|
||||||
const translate_c = b.addTranslateC(.{
|
const translate_c = b.addTranslateC(.{
|
||||||
.root_source_file = termbox_dep.path("termbox2.h"),
|
.root_source_file = b.path("include/termbox2.h"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
@@ -134,10 +122,6 @@ pub fn Installer(install_config: bool) type {
|
|||||||
try patch_map.put("$PREFIX_DIRECTORY", prefix_directory);
|
try patch_map.put("$PREFIX_DIRECTORY", prefix_directory);
|
||||||
try patch_map.put("$EXECUTABLE_NAME", executable_name);
|
try patch_map.put("$EXECUTABLE_NAME", executable_name);
|
||||||
|
|
||||||
// The "-a" argument doesn't exist on FreeBSD, so we use "-p"
|
|
||||||
// instead to shutdown the system.
|
|
||||||
try patch_map.put("$PLATFORM_SHUTDOWN_ARG", if (init_system == .freebsd) "-p" else "-a");
|
|
||||||
|
|
||||||
try install_ly(allocator, patch_map, install_config);
|
try install_ly(allocator, patch_map, install_config);
|
||||||
try install_service(allocator, patch_map);
|
try install_service(allocator, patch_map);
|
||||||
}
|
}
|
||||||
@@ -151,12 +135,6 @@ fn install_ly(allocator: std.mem.Allocator, patch_map: PatchMap, install_config:
|
|||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_config_directory});
|
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_config_directory});
|
||||||
};
|
};
|
||||||
|
|
||||||
const ly_custom_sessions_directory = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/ly/custom-sessions" });
|
|
||||||
|
|
||||||
std.fs.cwd().makePath(ly_custom_sessions_directory) catch {
|
|
||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_custom_sessions_directory});
|
|
||||||
};
|
|
||||||
|
|
||||||
const ly_lang_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/ly/lang" });
|
const ly_lang_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/ly/lang" });
|
||||||
std.fs.cwd().makePath(ly_lang_path) catch {
|
std.fs.cwd().makePath(ly_lang_path) catch {
|
||||||
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_lang_path});
|
std.debug.print("warn: {s} already exists as a directory.\n", .{ly_lang_path});
|
||||||
@@ -185,51 +163,30 @@ fn install_ly(allocator: std.mem.Allocator, patch_map: PatchMap, install_config:
|
|||||||
try installText(patched_config, config_dir, ly_config_directory, "config.ini", .{});
|
try installText(patched_config, config_dir, ly_config_directory, "config.ini", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const patched_example_config = try patchFile(allocator, "res/config.ini", patch_map);
|
|
||||||
try installText(patched_example_config, config_dir, ly_config_directory, "config.ini.example", .{});
|
|
||||||
|
|
||||||
const patched_setup = try patchFile(allocator, "res/setup.sh", patch_map);
|
const patched_setup = try patchFile(allocator, "res/setup.sh", patch_map);
|
||||||
try installText(patched_setup, config_dir, ly_config_directory, "setup.sh", .{ .mode = 0o755 });
|
try installText(patched_setup, config_dir, ly_config_directory, "setup.sh", .{ .mode = 0o755 });
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
var custom_sessions_dir = std.fs.cwd().openDir(ly_custom_sessions_directory, .{}) catch unreachable;
|
|
||||||
defer custom_sessions_dir.close();
|
|
||||||
|
|
||||||
const patched_readme = try patchFile(allocator, "res/custom-sessions/README", patch_map);
|
|
||||||
try installText(patched_readme, custom_sessions_dir, ly_custom_sessions_directory, "README", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var lang_dir = std.fs.cwd().openDir(ly_lang_path, .{}) catch unreachable;
|
var lang_dir = std.fs.cwd().openDir(ly_lang_path, .{}) catch unreachable;
|
||||||
defer lang_dir.close();
|
defer lang_dir.close();
|
||||||
|
|
||||||
const languages = [_][]const u8{
|
try installFile("res/lang/cat.ini", lang_dir, ly_lang_path, "cat.ini", .{});
|
||||||
"ar.ini",
|
try installFile("res/lang/cs.ini", lang_dir, ly_lang_path, "cs.ini", .{});
|
||||||
"cat.ini",
|
try installFile("res/lang/de.ini", lang_dir, ly_lang_path, "de.ini", .{});
|
||||||
"cs.ini",
|
try installFile("res/lang/en.ini", lang_dir, ly_lang_path, "en.ini", .{});
|
||||||
"de.ini",
|
try installFile("res/lang/es.ini", lang_dir, ly_lang_path, "es.ini", .{});
|
||||||
"en.ini",
|
try installFile("res/lang/fr.ini", lang_dir, ly_lang_path, "fr.ini", .{});
|
||||||
"es.ini",
|
try installFile("res/lang/it.ini", lang_dir, ly_lang_path, "it.ini", .{});
|
||||||
"fr.ini",
|
try installFile("res/lang/pl.ini", lang_dir, ly_lang_path, "pl.ini", .{});
|
||||||
"it.ini",
|
try installFile("res/lang/pt.ini", lang_dir, ly_lang_path, "pt.ini", .{});
|
||||||
"ja_JP.ini",
|
try installFile("res/lang/pt_BR.ini", lang_dir, ly_lang_path, "pt_BR.ini", .{});
|
||||||
"lv.ini",
|
try installFile("res/lang/ro.ini", lang_dir, ly_lang_path, "ro.ini", .{});
|
||||||
"pl.ini",
|
try installFile("res/lang/ru.ini", lang_dir, ly_lang_path, "ru.ini", .{});
|
||||||
"pt.ini",
|
try installFile("res/lang/sr.ini", lang_dir, ly_lang_path, "sr.ini", .{});
|
||||||
"pt_BR.ini",
|
try installFile("res/lang/sv.ini", lang_dir, ly_lang_path, "sv.ini", .{});
|
||||||
"ro.ini",
|
try installFile("res/lang/tr.ini", lang_dir, ly_lang_path, "tr.ini", .{});
|
||||||
"ru.ini",
|
try installFile("res/lang/uk.ini", lang_dir, ly_lang_path, "uk.ini", .{});
|
||||||
"sr.ini",
|
|
||||||
"sv.ini",
|
|
||||||
"tr.ini",
|
|
||||||
"uk.ini",
|
|
||||||
"zh_CN.ini",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline for (languages) |language| {
|
|
||||||
try installFile("res/lang/" ++ language, lang_dir, ly_lang_path, language, .{});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -243,7 +200,7 @@ fn install_ly(allocator: std.mem.Allocator, patch_map: PatchMap, install_config:
|
|||||||
var pam_dir = std.fs.cwd().openDir(pam_path, .{}) catch unreachable;
|
var pam_dir = std.fs.cwd().openDir(pam_path, .{}) catch unreachable;
|
||||||
defer pam_dir.close();
|
defer pam_dir.close();
|
||||||
|
|
||||||
try installFile(if (init_system == .freebsd) "res/pam.d/ly-freebsd" else "res/pam.d/ly-linux", pam_dir, pam_path, "ly", .{ .override_mode = 0o644 });
|
try installFile("res/pam.d/ly", pam_dir, pam_path, "ly", .{ .override_mode = 0o644 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,23 +271,6 @@ fn install_service(allocator: std.mem.Allocator, patch_map: PatchMap) !void {
|
|||||||
const patched_service = try patchFile(allocator, "res/ly-dinit", patch_map);
|
const patched_service = try patchFile(allocator, "res/ly-dinit", patch_map);
|
||||||
try installText(patched_service, service_dir, service_path, "ly", .{});
|
try installText(patched_service, service_dir, service_path, "ly", .{});
|
||||||
},
|
},
|
||||||
.sysvinit => {
|
|
||||||
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/init.d" });
|
|
||||||
std.fs.cwd().makePath(service_path) catch {};
|
|
||||||
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
|
||||||
defer service_dir.close();
|
|
||||||
|
|
||||||
const patched_service = try patchFile(allocator, "res/ly-sysvinit", patch_map);
|
|
||||||
try installText(patched_service, service_dir, service_path, "ly", .{ .mode = 0o755 });
|
|
||||||
},
|
|
||||||
.freebsd => {
|
|
||||||
const exe_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, prefix_directory, "/bin" });
|
|
||||||
var executable_dir = std.fs.cwd().openDir(exe_path, .{}) catch unreachable;
|
|
||||||
defer executable_dir.close();
|
|
||||||
|
|
||||||
const patched_wrapper = try patchFile(allocator, "res/ly-freebsd-wrapper", patch_map);
|
|
||||||
try installText(patched_wrapper, executable_dir, exe_path, "ly_wrapper", .{ .mode = 0o755 });
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,8 +302,6 @@ pub fn Uninstaller(uninstall_config: bool) type {
|
|||||||
try deleteFile(allocator, config_directory, "/s6/adminsv/default/contents.d/ly-srv", "s6 admin service not found");
|
try deleteFile(allocator, config_directory, "/s6/adminsv/default/contents.d/ly-srv", "s6 admin service not found");
|
||||||
},
|
},
|
||||||
.dinit => try deleteFile(allocator, config_directory, "/dinit.d/ly", "dinit service not found"),
|
.dinit => try deleteFile(allocator, config_directory, "/dinit.d/ly", "dinit service not found"),
|
||||||
.sysvinit => try deleteFile(allocator, config_directory, "/init.d/ly", "sysvinit service not found"),
|
|
||||||
.freebsd => try deleteFile(allocator, prefix_directory, "/bin/ly_wrapper", "freebsd wrapper not found"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -404,7 +342,7 @@ fn getVersionStr(b: *std.Build, name: []const u8, version: std.SemanticVersion)
|
|||||||
|
|
||||||
const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
|
const ancestor_ver = try std.SemanticVersion.parse(tagged_ancestor);
|
||||||
if (version.order(ancestor_ver) != .gt) {
|
if (version.order(ancestor_ver) != .gt) {
|
||||||
std.debug.print("{s} version '{f}' must be greater than tagged ancestor '{f}'\n", .{ name, version, ancestor_ver });
|
std.debug.print("{s} version '{}' must be greater than tagged ancestor '{}'\n", .{ name, version, ancestor_ver });
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,11 +377,8 @@ fn patchFile(allocator: std.mem.Allocator, source_file: []const u8, patch_map: P
|
|||||||
var file = try std.fs.cwd().openFile(source_file, .{});
|
var file = try std.fs.cwd().openFile(source_file, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
const stat = try file.stat();
|
const reader = file.reader();
|
||||||
|
var text = try reader.readAllAlloc(allocator, std.math.maxInt(u16));
|
||||||
var buffer: [4096]u8 = undefined;
|
|
||||||
var reader = file.reader(&buffer);
|
|
||||||
var text = try reader.interface.readAlloc(allocator, stat.size);
|
|
||||||
|
|
||||||
var iterator = patch_map.iterator();
|
var iterator = patch_map.iterator();
|
||||||
while (iterator.next()) |kv| {
|
while (iterator.next()) |kv| {
|
||||||
@@ -465,10 +400,8 @@ fn installText(
|
|||||||
var file = try destination_directory.createFile(destination_file, options);
|
var file = try destination_directory.createFile(destination_file, options);
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var buffer: [1024]u8 = undefined;
|
const writer = file.writer();
|
||||||
var writer = file.writer(&buffer);
|
try writer.writeAll(text);
|
||||||
try writer.interface.writeAll(text);
|
|
||||||
try writer.interface.flush();
|
|
||||||
|
|
||||||
std.debug.print("info: installed {s}/{s}\n", .{ destination_directory_path, destination_file });
|
std.debug.print("info: installed {s}/{s}\n", .{ destination_directory_path, destination_file });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
.{
|
.{
|
||||||
.name = .ly,
|
.name = .ly,
|
||||||
.version = "1.2.0",
|
.version = "1.1.1",
|
||||||
.fingerprint = 0xa148ffcc5dc2cb59,
|
.fingerprint = 0xa148ffcc5dc2cb59,
|
||||||
.minimum_zig_version = "0.15.0",
|
.minimum_zig_version = "0.14.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.clap = .{
|
.clap = .{
|
||||||
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.11.0.tar.gz",
|
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.10.0.tar.gz",
|
||||||
.hash = "clap-0.11.0-oBajB-HnAQDPCKYzwF7rO3qDFwRcD39Q0DALlTSz5H7e",
|
.hash = "clap-0.10.0-oBajB434AQBDh-Ei3YtoKIRxZacVPF1iSwp3IX_ZB8f0",
|
||||||
},
|
},
|
||||||
.zigini = .{
|
.zigini = .{
|
||||||
.url = "https://github.com/AnErrupTion/zigini/archive/96ca1d9f1a7ec741f07ceb104dae2b3a7bdfd48a.tar.gz",
|
.url = "https://github.com/Kawaii-Ash/zigini/archive/2ed3d417f17fab5b0ee8cad8a63c6d62d7ac1042.tar.gz",
|
||||||
.hash = "zigini-0.3.2-BSkB7WJJAADybd5DGd9MLCp6ikGGUq9wicxsjv0HF1Qc",
|
.hash = "zigini-0.3.1-BSkB7XJGAAB2E-sKyzhTaQCBlYBL8yqzE4E_jmSY99sC",
|
||||||
},
|
|
||||||
.termbox2 = .{
|
|
||||||
.url = "git+https://github.com/AnErrupTion/termbox2?ref=master#290ac6b8225aacfd16851224682b851b65fcb918",
|
|
||||||
.hash = "N-V-__8AAGcUBQAa5vov1Yi_9AXEffFQ1e2KsXaK4dgygRKq",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.paths = .{""},
|
.paths = .{""},
|
||||||
|
|||||||
4321
include/termbox2.h
Normal file
4321
include/termbox2.h
Normal file
File diff suppressed because it is too large
Load Diff
334
readme.md
334
readme.md
@@ -1,19 +1,14 @@
|
|||||||
# The Ly display manager
|
# Ly - a TUI display manager
|
||||||
|
|
||||||
|
## Development is now continuing on [Codeberg](https://codeberg.org/AnErrupTion/ly), with the [GitHub](https://github.com/fairyglade/ly) repository becoming a mirror. Issues & pull requests on GitHub will be ignored from now on.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD,
|
Ly is a lightweight TUI (ncurses-like) display manager for Linux and BSD.
|
||||||
designed with portability in mind (e.g. it does not require systemd to run).
|
|
||||||
|
|
||||||
Join us on Matrix over at [#ly:envs.net](https://matrix.to/#/#ly:envs.net)!
|
|
||||||
|
|
||||||
**Note**: Development happens on [Codeberg](https://codeberg.org/fairyglade/ly)
|
|
||||||
with a mirror on [GitHub](https://github.com/fairyglade/ly).
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- Compile-time:
|
- Compile-time:
|
||||||
- zig 0.15.x
|
- zig 0.14.0
|
||||||
- libc
|
- libc
|
||||||
- pam
|
- pam
|
||||||
- xcb (optional, required by default; needed for X11 support)
|
- xcb (optional, required by default; needed for X11 support)
|
||||||
@@ -24,263 +19,256 @@ with a mirror on [GitHub](https://github.com/fairyglade/ly).
|
|||||||
- brightnessctl
|
- brightnessctl
|
||||||
|
|
||||||
### Debian
|
### Debian
|
||||||
|
|
||||||
```
|
```
|
||||||
# apt install build-essential libpam0g-dev libxcb-xkb-dev xauth xserver-xorg brightnessctl
|
# apt install build-essential libpam0g-dev libxcb-xkb-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Fedora
|
### Fedora
|
||||||
|
|
||||||
**Warning**: You may encounter issues with SELinux on Fedora.
|
**Warning**: You may encounter issues with SELinux on Fedora.
|
||||||
It is recommended to add a rule for Ly as it currently does not ship one.
|
It is recommended to add a rule for Ly as it currently does not ship one.
|
||||||
|
|
||||||
```
|
```
|
||||||
# dnf install kernel-devel pam-devel libxcb-devel zig xorg-x11-xauth xorg-x11-server brightnessctl
|
# dnf install kernel-devel pam-devel libxcb-devel zig
|
||||||
```
|
```
|
||||||
|
|
||||||
### FreeBSD
|
|
||||||
|
|
||||||
```
|
|
||||||
# pkg install ca_root_nss libxcb git xorg xauth
|
|
||||||
```
|
|
||||||
|
|
||||||
## Packaging status
|
|
||||||
|
|
||||||
[](https://repology.org/project/ly/versions)
|
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
The following desktop environments were tested with success:
|
||||||
|
|
||||||
Ly has been tested with a wide variety of desktop environments and window
|
[Wayland Environments](#supported-wayland-environments)
|
||||||
managers, all of which you can find in the sections below:
|
|
||||||
|
|
||||||
[Wayland environments](#supported-wayland-environments)
|
[X11 Environments](#supported-x11-environments)
|
||||||
|
|
||||||
[X11 environments](#supported-x11-environments)
|
Ly should work with any X desktop environment, and provides
|
||||||
|
basic wayland support (sway works very well, for example).
|
||||||
|
|
||||||
## Manually building
|
## systemd?
|
||||||
|
Unlike what you may have heard, Ly does not require `systemd`,
|
||||||
The procedure for manually building Ly is pretty standard:
|
and was even specifically designed not to depend on `logind`.
|
||||||
|
You should be able to make it work easily with a better init,
|
||||||
|
changing the source code won't be necessary :)
|
||||||
|
|
||||||
|
## Cloning and Compiling
|
||||||
|
Clone the repository
|
||||||
|
```
|
||||||
|
$ git clone https://codeberg.org/AnErrupTion/ly
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the directory to ly
|
||||||
```
|
```
|
||||||
$ git clone https://codeberg.org/fairyglade/ly.git
|
|
||||||
$ cd ly
|
$ cd ly
|
||||||
|
```
|
||||||
|
|
||||||
|
Compile
|
||||||
|
```
|
||||||
$ zig build
|
$ zig build
|
||||||
```
|
```
|
||||||
|
|
||||||
After building, you can (optionally) test Ly in a terminal emulator, although
|
Test in the configured tty (tty2 by default)
|
||||||
authentication will **not** work:
|
or a terminal emulator (but authentication won't work)
|
||||||
|
|
||||||
```
|
```
|
||||||
$ zig build run
|
$ zig build run
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: While you can also run Ly in a terminal emulator as root, it is
|
**Important**: Running Ly in a terminal emulator as root is *not* recommended. If you
|
||||||
**not** recommended either. If you want to properly test Ly, please enable its
|
want to properly test Ly, please enable its service (as described below) and reboot
|
||||||
service (as described below) and reboot your machine.
|
your machine.
|
||||||
|
|
||||||
The following sections show how to install Ly for a particular init system.
|
|
||||||
Because the procedure is very similar for all of them, the commands will only
|
|
||||||
be detailed for the first section (which is about systemd).
|
|
||||||
|
|
||||||
**Note**: All following sections will assume you are using LightDM for
|
|
||||||
convenience sake.
|
|
||||||
|
|
||||||
### systemd
|
|
||||||
|
|
||||||
Now, you can install Ly on your system:
|
|
||||||
|
|
||||||
|
Install Ly for systemd-based systems (the default)
|
||||||
```
|
```
|
||||||
# zig build installexe -Dinit_system=systemd
|
# zig build installexe
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: The `init_system` parameter is optional and defaults to `systemd`.
|
Instead of DISPLAY_MANAGER you need to add your DM:
|
||||||
|
- gdm.service
|
||||||
Note that you also need to disable your current display manager. For example,
|
- sddm.service
|
||||||
if LightDM is the current display manager, you can execute the following
|
- lightdm.service
|
||||||
command:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# systemctl disable lightdm.service
|
# systemctl disable DISPLAY_MANAGER
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, similarly to the previous command, you need to enable the Ly service:
|
Enable the service
|
||||||
|
|
||||||
```
|
```
|
||||||
# systemctl enable ly.service
|
# systemctl enable ly.service
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Because Ly runs in a TTY, you **must** disable the TTY service
|
If you need to switch between ttys after Ly's start you also have to
|
||||||
that Ly will run on, otherwise bad things will happen. For example, to disable `getty` spawning on TTY 2 (the default TTY on which Ly spawns), you need to
|
disable getty on Ly's tty to prevent "login" from spawning on top of it
|
||||||
execute the following command:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# systemctl disable getty@tty2.service
|
# systemctl disable getty@tty2.service
|
||||||
```
|
```
|
||||||
|
|
||||||
You can change the TTY Ly will run on by editing the `tty` option in the
|
|
||||||
configuration file **and** change which TTY is used in the corresponding
|
|
||||||
service file..
|
|
||||||
|
|
||||||
### OpenRC
|
### OpenRC
|
||||||
|
**NOTE 1**: On Gentoo, Ly will disable the `display-manager-init` service in order to run.
|
||||||
|
|
||||||
|
Clone, compile and test.
|
||||||
|
|
||||||
|
Install Ly and the provided OpenRC service
|
||||||
```
|
```
|
||||||
# zig build installexe -Dinit_system=openrc
|
# zig build installexe -Dinit_system=openrc
|
||||||
# rc-update del lightdm
|
```
|
||||||
|
|
||||||
|
Enable the service
|
||||||
|
```
|
||||||
# rc-update add ly
|
# rc-update add ly
|
||||||
|
```
|
||||||
|
|
||||||
|
You can edit which tty Ly will start on by editing the `tty` option in the configuration file.
|
||||||
|
|
||||||
|
If you choose a tty that already has a login/getty running (has a basic login prompt),
|
||||||
|
then you have to disable getty, so it doesn't respawn on top of ly
|
||||||
|
```
|
||||||
# rc-update del agetty.tty2
|
# rc-update del agetty.tty2
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: On Gentoo specifically, you also **must** comment out the appropriate
|
**NOTE 2**: To avoid a console spawning on top on Ly, comment out the appropriate line from /etc/inittab (default is 2).
|
||||||
line for the TTY in /etc/inittab.
|
|
||||||
|
|
||||||
### runit
|
### runit
|
||||||
|
|
||||||
```
|
```
|
||||||
# zig build installexe -Dinit_system=runit
|
# zig build installexe -Dinit_system=runit
|
||||||
# rm /var/service/lightdm
|
|
||||||
# ln -s /etc/sv/ly /var/service/
|
# ln -s /etc/sv/ly /var/service/
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, ly will run on tty2. To change the tty it must be set in `/etc/ly/config.ini`
|
||||||
|
|
||||||
|
You should as well disable your existing display manager service if needed, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
# rm /var/service/lxdm
|
||||||
|
```
|
||||||
|
|
||||||
|
The agetty service for the tty console where you are running ly should be disabled.
|
||||||
|
For instance, if you are running ly on tty2 (that's the default, check your `/etc/ly/config.ini`)
|
||||||
|
you should disable the agetty-tty2 service like this:
|
||||||
|
|
||||||
|
```
|
||||||
# rm /var/service/agetty-tty2
|
# rm /var/service/agetty-tty2
|
||||||
```
|
```
|
||||||
|
|
||||||
### s6
|
### s6
|
||||||
|
|
||||||
```
|
```
|
||||||
# zig build installexe -Dinit_system=s6
|
# zig build installexe -Dinit_system=s6
|
||||||
# s6-rc -d change lightdm
|
```
|
||||||
|
|
||||||
|
Then, edit `/etc/s6/config/ttyX.conf` and set `SPAWN="no"`, where X is the TTY ID (e.g. `2`).
|
||||||
|
|
||||||
|
Finally, enable the service:
|
||||||
|
|
||||||
|
```
|
||||||
# s6-service add default ly-srv
|
# s6-service add default ly-srv
|
||||||
# s6-db-reload
|
# s6-db-reload
|
||||||
# s6-rc -u change ly-srv
|
# s6-rc -u change ly-srv
|
||||||
```
|
```
|
||||||
|
|
||||||
To disable TTY 2, edit `/etc/s6/config/tty2.conf` and set `SPAWN="no"`.
|
|
||||||
|
|
||||||
### dinit
|
### dinit
|
||||||
|
|
||||||
```
|
```
|
||||||
# zig build installexe -Dinit_system=dinit
|
# zig build installexe -Dinit_system=dinit
|
||||||
# dinitctl disable lightdm
|
|
||||||
# dinitctl enable ly
|
# dinitctl enable ly
|
||||||
```
|
```
|
||||||
|
|
||||||
To disable TTY 2, go to `/etc/dinit.d/config/console.conf` and modify
|
In addition to the steps above, you will also have to keep a TTY free within `/etc/dinit.d/config/console.conf`.
|
||||||
`ACTIVE_CONSOLES`.
|
|
||||||
|
|
||||||
### sysvinit
|
To do that, change `ACTIVE_CONSOLES` so that the tty that ly should use in `/etc/ly/config.ini` is free.
|
||||||
|
|
||||||
```
|
|
||||||
# zig build installexe -Dinit_system=sysvinit
|
|
||||||
# update-rc.d lightdm disable
|
|
||||||
# update-rc.d ly defaults
|
|
||||||
```
|
|
||||||
|
|
||||||
To disable TTY 2, go to `/etc/inittab` and comment out the line containing `tty2`.
|
|
||||||
|
|
||||||
### FreeBSD
|
|
||||||
|
|
||||||
```
|
|
||||||
# zig build installexe -Dprefix_directory=/usr/local -Dconfig_directory=/usr/local/etc -Dinit_system=freebsd
|
|
||||||
# sysrc lightdm_enable="NO"
|
|
||||||
```
|
|
||||||
|
|
||||||
To enable Ly, add the following entry to `/etc/gettytab`:
|
|
||||||
|
|
||||||
```
|
|
||||||
Ly:\
|
|
||||||
:lo=/usr/local/bin/ly_wrapper:\
|
|
||||||
:al=root:
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, modify the command field of the `ttyv1` terminal entry in `/etc/ttys`
|
|
||||||
(TTYs in FreeBSD start at 0):
|
|
||||||
|
|
||||||
```
|
|
||||||
ttyv1 "/usr/libexec/getty Ly" xterm on secure
|
|
||||||
```
|
|
||||||
|
|
||||||
### Updating
|
### Updating
|
||||||
|
You can also install Ly without overrding the current configuration file. That's called
|
||||||
You can also install Ly without overrding the current configuration file. This
|
*updating*. To update, simply run:
|
||||||
is called **updating**. To update, simply run:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# zig build installnoconf
|
# zig build installnoconf
|
||||||
```
|
```
|
||||||
|
|
||||||
You can, of course, still select the init system of your choice when using this
|
You can, of course, still select the init system of your choice when using this command.
|
||||||
command.
|
|
||||||
|
## Arch Linux Installation
|
||||||
|
You can install ly from the [`[extra]` repos](https://archlinux.org/packages/extra/x86_64/ly/):
|
||||||
|
```
|
||||||
|
# pacman -S ly
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gentoo Installation
|
||||||
|
You can install ly from the GURU repository:
|
||||||
|
|
||||||
|
Note: If the package is masked, you may need to unmask it using ~amd64 keyword:
|
||||||
|
```bash
|
||||||
|
# echo 'x11-misc/ly ~amd64' >> /etc/portage/package.accept_keywords
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Enable the GURU repository:
|
||||||
|
```bash
|
||||||
|
# eselect repository enable guru
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Sync the GURU repository:
|
||||||
|
```bash
|
||||||
|
# emaint sync -r guru
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install ly from source:
|
||||||
|
```bash
|
||||||
|
# emerge --ask x11-misc/ly
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
You can find all the configuration in `/etc/ly/config.ini`.
|
||||||
You can find all the configuration in `/etc/ly/config.ini`. The file is fully
|
The file is commented, and includes the default values.
|
||||||
commented, and includes the default values.
|
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
|
Use the up and down arrow keys to change the current field, and the
|
||||||
|
left and right arrow keys to change the target desktop environment
|
||||||
|
while on the desktop field (above the login field).
|
||||||
|
|
||||||
Use the Up/Down arrow keys to change the current field, and the Left/Right
|
## .xinitrc
|
||||||
arrow keys to scroll through the different fields (whether it be the info line,
|
If your .xinitrc doesn't work make sure it is executable and includes a shebang.
|
||||||
the desktop environment, or the username). The info line is where messages and
|
This file is supposed to be a shell script! Quoting from xinit's man page:
|
||||||
errors are displayed.
|
|
||||||
|
|
||||||
## A note on .xinitrc
|
> If no specific client program is given on the command line, xinit will look for a file in the user's home directory called .xinitrc to run as a shell script to start up client programs.
|
||||||
|
|
||||||
If your `.xinitrc` file doesn't work ,make sure it is executable and includes a
|
|
||||||
shebang. This file is supposed to be a shell script! Quoting from `xinit`'s man
|
|
||||||
page:
|
|
||||||
|
|
||||||
> If no specific client program is given on the command line, xinit will look
|
|
||||||
> for a file in the user's home directory called .xinitrc to run as a shell
|
|
||||||
> script to start up client programs.
|
|
||||||
|
|
||||||
A typical shebang for a shell script looks like this:
|
|
||||||
|
|
||||||
|
On Arch Linux, the example .xinitrc (/etc/X11/xinit/xinitrc) starts like this:
|
||||||
```
|
```
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
|
|
||||||
- The numlock and capslock state is printed in the top-right corner.
|
- The numlock and capslock state is printed in the top-right corner.
|
||||||
- Use the F1 and F2 keys to respectively shutdown and reboot.
|
- Use the F1 and F2 keys to respectively shutdown and reboot.
|
||||||
- Take a look at your `.xsession` file if X doesn't start, as it can interfere
|
- Take a look at your .xsession if X doesn't start, as it can interfere
|
||||||
(this file is launched with X to configure the display properly).
|
(this file is launched with X to configure the display properly).
|
||||||
|
|
||||||
## Supported Wayland environments
|
## Supported Wayland Environments
|
||||||
|
- budgie
|
||||||
|
- cosmic
|
||||||
|
- deepin
|
||||||
|
- enlightenment
|
||||||
|
- gnome
|
||||||
|
- hyprland
|
||||||
|
- kde
|
||||||
|
- labwc
|
||||||
|
- niri
|
||||||
|
- pantheon
|
||||||
|
- sway
|
||||||
|
- weston
|
||||||
|
|
||||||
- budgie
|
## Supported X11 Environments
|
||||||
- cosmic
|
- awesome
|
||||||
- deepin
|
- bspwm
|
||||||
- enlightenment
|
- budgie
|
||||||
- gnome
|
- cinnamon
|
||||||
- hyprland
|
- dwm
|
||||||
- kde
|
- enlightenment
|
||||||
- labwc
|
- gnome
|
||||||
- niri
|
- kde
|
||||||
- pantheon
|
- leftwm
|
||||||
- sway
|
- lxde
|
||||||
- weston
|
- mate
|
||||||
|
- maxx
|
||||||
|
- pantheon
|
||||||
|
- qwm
|
||||||
|
- spectrwm
|
||||||
|
- windowmaker
|
||||||
|
- xfce
|
||||||
|
- xmonad
|
||||||
|
|
||||||
## Supported X11 environments
|
|
||||||
|
|
||||||
- awesome
|
## Additional Information
|
||||||
- bspwm
|
The name "Ly" is a tribute to the fairy from the game Rayman.
|
||||||
- budgie
|
Ly was tested by oxodao, who is some seriously awesome dude.
|
||||||
- cinnamon
|
|
||||||
- dwm
|
|
||||||
- enlightenment
|
|
||||||
- gnome
|
|
||||||
- kde
|
|
||||||
- leftwm
|
|
||||||
- lxde
|
|
||||||
- mate
|
|
||||||
- maxx
|
|
||||||
- pantheon
|
|
||||||
- qwm
|
|
||||||
- spectrwm
|
|
||||||
- windowmaker
|
|
||||||
- xfce
|
|
||||||
- xmonad
|
|
||||||
|
|
||||||
## A final note
|
|
||||||
|
|
||||||
The name "Ly" is a tribute to the fairy from the game Rayman. Ly was tested by
|
|
||||||
oxodao, who is some seriously awesome dude.
|
|
||||||
|
|||||||
125
res/config.ini
125
res/config.ini
@@ -1,14 +1,14 @@
|
|||||||
# Ly supports 24-bit true color with styling, which means each color is a 32-bit value.
|
# Ly supports 24-bit true color with styling, which means each color is a 32-bit value.
|
||||||
# The format is 0xSSRRGGBB, where SS is the styling, RR is red, GG is green, and BB is blue.
|
# The format is 0xSSRRGGBB, where SS is the styling, RR is red, GG is green, and BB is blue.
|
||||||
# Here are the possible styling options:
|
# Here are the possible styling options:
|
||||||
# TB_BOLD 0x01000000
|
#define TB_BOLD 0x01000000
|
||||||
# TB_UNDERLINE 0x02000000
|
#define TB_UNDERLINE 0x02000000
|
||||||
# TB_REVERSE 0x04000000
|
#define TB_REVERSE 0x04000000
|
||||||
# TB_ITALIC 0x08000000
|
#define TB_ITALIC 0x08000000
|
||||||
# TB_BLINK 0x10000000
|
#define TB_BLINK 0x10000000
|
||||||
# TB_HI_BLACK 0x20000000
|
#define TB_HI_BLACK 0x20000000
|
||||||
# TB_BRIGHT 0x40000000
|
#define TB_BRIGHT 0x40000000
|
||||||
# TB_DIM 0x80000000
|
#define TB_DIM 0x80000000
|
||||||
# Programmatically, you'd apply them using the bitwise OR operator (|), but because Ly's
|
# Programmatically, you'd apply them using the bitwise OR operator (|), but because Ly's
|
||||||
# configuration doesn't support using it, you have to manually compute the color value.
|
# configuration doesn't support using it, you have to manually compute the color value.
|
||||||
# Note that, if you want to use the default color value of the terminal, you can use the
|
# Note that, if you want to use the default color value of the terminal, you can use the
|
||||||
@@ -23,7 +23,6 @@ allow_empty_password = true
|
|||||||
# doom -> PSX DOOM fire
|
# doom -> PSX DOOM fire
|
||||||
# matrix -> CMatrix
|
# matrix -> CMatrix
|
||||||
# colormix -> Color mixing shader
|
# colormix -> Color mixing shader
|
||||||
# gameoflife -> John Conway's Game of Life
|
|
||||||
animation = none
|
animation = none
|
||||||
|
|
||||||
# Stop the animation after some time
|
# Stop the animation after some time
|
||||||
@@ -41,11 +40,6 @@ asterisk = *
|
|||||||
# The number of failed authentications before a special animation is played... ;)
|
# The number of failed authentications before a special animation is played... ;)
|
||||||
auth_fails = 10
|
auth_fails = 10
|
||||||
|
|
||||||
# Identifier for battery whose charge to display at top left
|
|
||||||
# Primary battery is usually BAT0 or BAT1
|
|
||||||
# If set to null, battery status won't be shown
|
|
||||||
battery_id = null
|
|
||||||
|
|
||||||
# Background color id
|
# Background color id
|
||||||
bg = 0x00000000
|
bg = 0x00000000
|
||||||
|
|
||||||
@@ -55,12 +49,6 @@ bg = 0x00000000
|
|||||||
# fa -> Farsi
|
# fa -> Farsi
|
||||||
bigclock = none
|
bigclock = none
|
||||||
|
|
||||||
# Set bigclock to 12-hour notation.
|
|
||||||
bigclock_12hr = false
|
|
||||||
|
|
||||||
# Set bigclock to show the seconds.
|
|
||||||
bigclock_seconds = false
|
|
||||||
|
|
||||||
# Blank main box background
|
# Blank main box background
|
||||||
# Setting to false will make it transparent
|
# Setting to false will make it transparent
|
||||||
blank_box = true
|
blank_box = true
|
||||||
@@ -72,14 +60,14 @@ border_fg = 0x00FFFFFF
|
|||||||
# If set to null, none will be shown
|
# If set to null, none will be shown
|
||||||
box_title = null
|
box_title = null
|
||||||
|
|
||||||
# Brightness decrease command
|
# Brightness increase command
|
||||||
brightness_down_cmd = $PREFIX_DIRECTORY/bin/brightnessctl -q -n s 10%-
|
brightness_down_cmd = $PREFIX_DIRECTORY/bin/brightnessctl -q s 10%-
|
||||||
|
|
||||||
# Brightness decrease key, or null to disable
|
# Brightness decrease key, or null to disable
|
||||||
brightness_down_key = F5
|
brightness_down_key = F5
|
||||||
|
|
||||||
# Brightness increase command
|
# Brightness increase command
|
||||||
brightness_up_cmd = $PREFIX_DIRECTORY/bin/brightnessctl -q -n s +10%
|
brightness_up_cmd = $PREFIX_DIRECTORY/bin/brightnessctl -q s +10%
|
||||||
|
|
||||||
# Brightness increase key, or null to disable
|
# Brightness increase key, or null to disable
|
||||||
brightness_up_key = F6
|
brightness_up_key = F6
|
||||||
@@ -94,9 +82,6 @@ clock = null
|
|||||||
# CMatrix animation foreground color id
|
# CMatrix animation foreground color id
|
||||||
cmatrix_fg = 0x0000FF00
|
cmatrix_fg = 0x0000FF00
|
||||||
|
|
||||||
# CMatrix animation character string head color id
|
|
||||||
cmatrix_head_col = 0x01FFFFFF
|
|
||||||
|
|
||||||
# CMatrix animation minimum codepoint. It uses a 16-bit integer
|
# CMatrix animation minimum codepoint. It uses a 16-bit integer
|
||||||
# For Japanese characters for example, you can use 0x3000 here
|
# For Japanese characters for example, you can use 0x3000 here
|
||||||
cmatrix_min_codepoint = 0x21
|
cmatrix_min_codepoint = 0x21
|
||||||
@@ -114,28 +99,20 @@ colormix_col2 = 0x000000FF
|
|||||||
# Color mixing animation third color id
|
# Color mixing animation third color id
|
||||||
colormix_col3 = 0x20000000
|
colormix_col3 = 0x20000000
|
||||||
|
|
||||||
# Custom sessions directory
|
# Console path
|
||||||
# You can specify multiple directories,
|
console_dev = /dev/console
|
||||||
# e.g. $CONFIG_DIRECTORY/ly/custom-sessions:$PREFIX_DIRECTORY/share/custom-sessions
|
|
||||||
custom_sessions = $CONFIG_DIRECTORY/ly/custom-sessions
|
|
||||||
|
|
||||||
# Input box active by default on startup
|
# Input box active by default on startup
|
||||||
# Available inputs: info_line, session, login, password
|
# Available inputs: info_line, session, login, password
|
||||||
default_input = login
|
default_input = login
|
||||||
|
|
||||||
# DOOM animation fire height (1 thru 9)
|
# DOOM animation top color (low intensity flames)
|
||||||
doom_fire_height = 6
|
doom_top_color = 0x00FF0000
|
||||||
|
|
||||||
# DOOM animation fire spread (0 thru 4)
|
# DOOM animation middle color (medium intensity flames)
|
||||||
doom_fire_spread = 2
|
doom_middle_color = 0x00FFFF00
|
||||||
|
|
||||||
# DOOM animation custom top color (low intensity flames)
|
# DOOM animation bottom color (high intensity flames)
|
||||||
doom_top_color = 0x009F2707
|
|
||||||
|
|
||||||
# DOOM animation custom middle color (medium intensity flames)
|
|
||||||
doom_middle_color = 0x00C78F17
|
|
||||||
|
|
||||||
# DOOM animation custom bottom color (high intensity flames)
|
|
||||||
doom_bottom_color = 0x00FFFFFF
|
doom_bottom_color = 0x00FFFFFF
|
||||||
|
|
||||||
# Error background color id
|
# Error background color id
|
||||||
@@ -148,52 +125,12 @@ error_fg = 0x01FF0000
|
|||||||
# Foreground color id
|
# Foreground color id
|
||||||
fg = 0x00FFFFFF
|
fg = 0x00FFFFFF
|
||||||
|
|
||||||
# Render true colors (if supported)
|
|
||||||
# If false, output will be in eight-color mode
|
|
||||||
# All eight-color mode color codes:
|
|
||||||
# TB_DEFAULT 0x0000
|
|
||||||
# TB_BLACK 0x0001
|
|
||||||
# TB_RED 0x0002
|
|
||||||
# TB_GREEN 0x0003
|
|
||||||
# TB_YELLOW 0x0004
|
|
||||||
# TB_BLUE 0x0005
|
|
||||||
# TB_MAGENTA 0x0006
|
|
||||||
# TB_CYAN 0x0007
|
|
||||||
# TB_WHITE 0x0008
|
|
||||||
# If full color is off, the styling options still work. The colors are
|
|
||||||
# always 32-bit values with the styling in the most significant byte.
|
|
||||||
full_color = true
|
|
||||||
|
|
||||||
# Game of Life entropy interval (0 = disabled, >0 = add entropy every N generations)
|
|
||||||
# 0 -> Pure Conway's Game of Life (will eventually stabilize)
|
|
||||||
# 10 -> Add entropy every 10 generations (recommended for continuous activity)
|
|
||||||
# 50+ -> Less frequent entropy for more natural evolution
|
|
||||||
gameoflife_entropy_interval = 10
|
|
||||||
|
|
||||||
# Game of Life animation foreground color id
|
|
||||||
gameoflife_fg = 0x0000FF00
|
|
||||||
|
|
||||||
# Game of Life frame delay (lower = faster animation, higher = slower)
|
|
||||||
# 1-3 -> Very fast animation
|
|
||||||
# 6 -> Default smooth animation speed
|
|
||||||
# 10+ -> Slower, more contemplative speed
|
|
||||||
gameoflife_frame_delay = 6
|
|
||||||
|
|
||||||
# Game of Life initial cell density (0.0 to 1.0)
|
|
||||||
# 0.1 -> Sparse, minimal activity
|
|
||||||
# 0.4 -> Balanced activity (recommended)
|
|
||||||
# 0.7+ -> Dense, chaotic patterns
|
|
||||||
gameoflife_initial_density = 0.4
|
|
||||||
|
|
||||||
# Remove main box borders
|
# Remove main box borders
|
||||||
hide_borders = false
|
hide_borders = false
|
||||||
|
|
||||||
# Remove power management command hints
|
# Remove power management command hints
|
||||||
hide_key_hints = false
|
hide_key_hints = false
|
||||||
|
|
||||||
# Remove version number from the top left corner
|
|
||||||
hide_version_string = false
|
|
||||||
|
|
||||||
# Initial text to show on the info line
|
# Initial text to show on the info line
|
||||||
# If set to null, the info line defaults to the hostname
|
# If set to null, the info line defaults to the hostname
|
||||||
initial_info_text = null
|
initial_info_text = null
|
||||||
@@ -205,25 +142,21 @@ input_len = 34
|
|||||||
# Available languages are found in $CONFIG_DIRECTORY/ly/lang/
|
# Available languages are found in $CONFIG_DIRECTORY/ly/lang/
|
||||||
lang = en
|
lang = en
|
||||||
|
|
||||||
|
# Load the saved desktop and username
|
||||||
|
load = true
|
||||||
|
|
||||||
# Command executed when logging in
|
# Command executed when logging in
|
||||||
# If null, no command will be executed
|
# If null, no command will be executed
|
||||||
# Important: the code itself must end with `exec "$@"` in order to launch the session!
|
# Important: the code itself must end with `exec "$@"` in order to launch the session!
|
||||||
# You can also set environment variables in there, they'll persist until logout
|
# You can also set environment variables in there, they'll persist until logout
|
||||||
login_cmd = null
|
login_cmd = null
|
||||||
|
|
||||||
# Path for login.defs file (used for listing all local users on the system on
|
|
||||||
# Linux)
|
|
||||||
login_defs_path = /etc/login.defs
|
|
||||||
|
|
||||||
# Command executed when logging out
|
# Command executed when logging out
|
||||||
# If null, no command will be executed
|
# If null, no command will be executed
|
||||||
# Important: the session will already be terminated when this command is executed, so
|
# Important: the session will already be terminated when this command is executed, so
|
||||||
# no need to add `exec "$@"` at the end
|
# no need to add `exec "$@"` at the end
|
||||||
logout_cmd = null
|
logout_cmd = null
|
||||||
|
|
||||||
# General log file path
|
|
||||||
ly_log = /var/log/ly.log
|
|
||||||
|
|
||||||
# Main box horizontal margin
|
# Main box horizontal margin
|
||||||
margin_box_h = 2
|
margin_box_h = 2
|
||||||
|
|
||||||
@@ -238,7 +171,7 @@ numlock = false
|
|||||||
|
|
||||||
# Default path
|
# Default path
|
||||||
# If null, ly doesn't set a path
|
# If null, ly doesn't set a path
|
||||||
path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
path = /sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
|
||||||
|
|
||||||
# Command executed when pressing restart_key
|
# Command executed when pressing restart_key
|
||||||
restart_cmd = /sbin/shutdown -r now
|
restart_cmd = /sbin/shutdown -r now
|
||||||
@@ -246,7 +179,7 @@ restart_cmd = /sbin/shutdown -r now
|
|||||||
# Specifies the key used for restart (F1-F12)
|
# Specifies the key used for restart (F1-F12)
|
||||||
restart_key = F2
|
restart_key = F2
|
||||||
|
|
||||||
# Save the current desktop and login as defaults, and load them on startup
|
# Save the current desktop and login as defaults
|
||||||
save = true
|
save = true
|
||||||
|
|
||||||
# Service name (set to ly to use the provided pam config file)
|
# Service name (set to ly to use the provided pam config file)
|
||||||
@@ -256,15 +189,14 @@ service_name = ly
|
|||||||
# This will contain stdout and stderr of Wayland sessions
|
# This will contain stdout and stderr of Wayland sessions
|
||||||
# By default it's saved in the user's home directory
|
# By default it's saved in the user's home directory
|
||||||
# Important: due to technical limitations, X11 and shell sessions aren't supported, which
|
# Important: due to technical limitations, X11 and shell sessions aren't supported, which
|
||||||
# means you won't get any logs from those sessions.
|
# means you won't get any logs from those sessions
|
||||||
# If null, no session log will be created
|
|
||||||
session_log = ly-session.log
|
session_log = ly-session.log
|
||||||
|
|
||||||
# Setup command
|
# Setup command
|
||||||
setup_cmd = $CONFIG_DIRECTORY/ly/setup.sh
|
setup_cmd = $CONFIG_DIRECTORY/ly/setup.sh
|
||||||
|
|
||||||
# Command executed when pressing shutdown_key
|
# Command executed when pressing shutdown_key
|
||||||
shutdown_cmd = /sbin/shutdown $PLATFORM_SHUTDOWN_ARG now
|
shutdown_cmd = /sbin/shutdown -a now
|
||||||
|
|
||||||
# Specifies the key used for shutdown (F1-F12)
|
# Specifies the key used for shutdown (F1-F12)
|
||||||
shutdown_key = F1
|
shutdown_key = F1
|
||||||
@@ -278,6 +210,9 @@ sleep_key = F3
|
|||||||
# Center the session name.
|
# Center the session name.
|
||||||
text_in_center = false
|
text_in_center = false
|
||||||
|
|
||||||
|
# TTY in use
|
||||||
|
tty = $DEFAULT_TTY
|
||||||
|
|
||||||
# Default vi mode
|
# Default vi mode
|
||||||
# normal -> normal mode
|
# normal -> normal mode
|
||||||
# insert -> insert mode
|
# insert -> insert mode
|
||||||
@@ -288,7 +223,7 @@ vi_mode = false
|
|||||||
|
|
||||||
# Wayland desktop environments
|
# Wayland desktop environments
|
||||||
# You can specify multiple directories,
|
# You can specify multiple directories,
|
||||||
# e.g. $PREFIX_DIRECTORY/share/wayland-sessions:$PREFIX_DIRECTORY/local/share/wayland-sessions
|
# e.g. /usr/share/wayland-sessions:/usr/local/share/wayland-sessions
|
||||||
waylandsessions = $PREFIX_DIRECTORY/share/wayland-sessions
|
waylandsessions = $PREFIX_DIRECTORY/share/wayland-sessions
|
||||||
|
|
||||||
# Xorg server command
|
# Xorg server command
|
||||||
@@ -303,5 +238,5 @@ xinitrc = ~/.xinitrc
|
|||||||
|
|
||||||
# Xorg desktop environments
|
# Xorg desktop environments
|
||||||
# You can specify multiple directories,
|
# You can specify multiple directories,
|
||||||
# e.g. $PREFIX_DIRECTORY/share/xsessions:$PREFIX_DIRECTORY/local/share/xsessions
|
# e.g. /usr/share/xsessions:/usr/local/share/xsessions
|
||||||
xsessions = $PREFIX_DIRECTORY/share/xsessions
|
xsessions = $PREFIX_DIRECTORY/share/xsessions
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
A custom session is just a desktop entry file, like for X11 and Wayland
|
|
||||||
sessions. For example:
|
|
||||||
|
|
||||||
[Desktop Entry]
|
|
||||||
Name=Fish shell
|
|
||||||
Exec=$PREFIX_DIRECTORY/bin/fish
|
|
||||||
DesktopNames=null
|
|
||||||
Terminal=true
|
|
||||||
|
|
||||||
The DesktopNames value is optional and sets the XDG_SESSION_DESKTOP and
|
|
||||||
XDG_CURRENT_DESKTOP environment variables. If equal to null or if not present,
|
|
||||||
XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP will not be set. Otherwise, the
|
|
||||||
syntax is the same as described in the Freedesktop Desktop Entry Specification.
|
|
||||||
|
|
||||||
The Terminal value specifies if standard output and standard error should be
|
|
||||||
redirected to the session log file found in Ly's configuration file. If set to
|
|
||||||
true, Ly will consider the program is going to run in a TTY, and thus will not
|
|
||||||
redirect standard output & error. It is optional and defaults to false.
|
|
||||||
|
|
||||||
Finally, do note that, if the Terminal value is set to true, the
|
|
||||||
XDG_SESSION_TYPE environment variable will be set to "tty". Otherwise, it will
|
|
||||||
be set to "unspecified" (without quotes), which is behavior that at least
|
|
||||||
systemd recognizes (see pam_systemd's man page).
|
|
||||||
@@ -2,21 +2,17 @@ authenticating = جاري المصادقة...
|
|||||||
brightness_down = خفض السطوع
|
brightness_down = خفض السطوع
|
||||||
brightness_up = رفع السطوع
|
brightness_up = رفع السطوع
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = فشل في تخصيص الذاكرة
|
err_alloc = فشل في تخصيص الذاكرة
|
||||||
err_bounds = out-of-bounds index
|
err_bounds = out-of-bounds index
|
||||||
err_brightness_change = فشل في تغيير سطوع الشاشة
|
err_brightness_change = فشل في تغيير سطوع الشاشة
|
||||||
err_chdir = فشل في فتح مجلد المنزل
|
err_chdir = فشل في فتح مجلد المنزل
|
||||||
|
|
||||||
err_config = فشل في تفسير ملف الإعدادات
|
err_config = فشل في تفسير ملف الإعدادات
|
||||||
|
err_console_dev = فشل في الوصول إلى جهاز وحدة التحكم
|
||||||
err_dgn_oob = رسالة سجل (Log)
|
err_dgn_oob = رسالة سجل (Log)
|
||||||
err_domain = اسم نطاق غير صالح
|
err_domain = اسم نطاق غير صالح
|
||||||
err_empty_password = لا يُسمح بكلمة مرور فارغة
|
err_empty_password = لا يُسمح بكلمة مرور فارغة
|
||||||
err_envlist = فشل في جلب قائمة المتغيرات البيئية
|
err_envlist = فشل في جلب قائمة المتغيرات البيئية
|
||||||
|
|
||||||
err_hostname = فشل في جلب اسم المضيف (Hostname)
|
err_hostname = فشل في جلب اسم المضيف (Hostname)
|
||||||
|
|
||||||
|
|
||||||
err_mlock = فشل في تأمين ذاكرة كلمة المرور (mlock)
|
err_mlock = فشل في تأمين ذاكرة كلمة المرور (mlock)
|
||||||
err_null = مؤشر فارغ (Null pointer)
|
err_null = مؤشر فارغ (Null pointer)
|
||||||
err_numlock = فشل في ضبط Num Lock
|
err_numlock = فشل في ضبط Num Lock
|
||||||
@@ -42,10 +38,8 @@ err_perm_group = فشل في تخفيض صلاحيات المجموعة (Group p
|
|||||||
err_perm_user = فشل في تخفيض صلاحيات المستخدم (User permissions)
|
err_perm_user = فشل في تخفيض صلاحيات المستخدم (User permissions)
|
||||||
err_pwnam = فشل في جلب معلومات المستخدم
|
err_pwnam = فشل في جلب معلومات المستخدم
|
||||||
err_sleep = فشل في تنفيذ أمر sleep
|
err_sleep = فشل في تنفيذ أمر sleep
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = فشل في نقل تحكم الطرفية (TTY)
|
err_tty_ctrl = فشل في نقل تحكم الطرفية (TTY)
|
||||||
|
err_unknown = حدث خطأ غير معروف
|
||||||
err_user_gid = فشل في تعيين معرّف المجموعة (GID) للمستخدم
|
err_user_gid = فشل في تعيين معرّف المجموعة (GID) للمستخدم
|
||||||
err_user_init = فشل في تهيئة بيانات المستخدم
|
err_user_init = فشل في تهيئة بيانات المستخدم
|
||||||
err_user_uid = فشل في تعيين معرّف المستخدم (UID)
|
err_user_uid = فشل في تعيين معرّف المستخدم (UID)
|
||||||
|
|||||||
@@ -2,21 +2,17 @@ authenticating = autenticant...
|
|||||||
brightness_down = abaixar brillantor
|
brightness_down = abaixar brillantor
|
||||||
brightness_up = apujar brillantor
|
brightness_up = apujar brillantor
|
||||||
capslock = Bloq Majús
|
capslock = Bloq Majús
|
||||||
|
|
||||||
err_alloc = assignació de memòria fallida
|
err_alloc = assignació de memòria fallida
|
||||||
err_bounds = índex fora de límits
|
err_bounds = índex fora de límits
|
||||||
err_brightness_change = error en canviar la brillantor
|
err_brightness_change = error en canviar la brillantor
|
||||||
err_chdir = error en obrir la carpeta home
|
err_chdir = error en obrir la carpeta home
|
||||||
|
|
||||||
|
err_console_dev = error en accedir a la consola
|
||||||
err_dgn_oob = missatge de registre
|
err_dgn_oob = missatge de registre
|
||||||
err_domain = domini invàlid
|
err_domain = domini invàlid
|
||||||
|
|
||||||
err_envlist = error en obtenir l'envlist
|
err_envlist = error en obtenir l'envlist
|
||||||
|
|
||||||
err_hostname = error en obtenir el nom de l'amfitrió
|
err_hostname = error en obtenir el nom de l'amfitrió
|
||||||
|
|
||||||
|
|
||||||
err_mlock = error en bloquejar la memòria de clau
|
err_mlock = error en bloquejar la memòria de clau
|
||||||
err_null = punter nul
|
err_null = punter nul
|
||||||
err_numlock = error en establir el Bloq num
|
err_numlock = error en establir el Bloq num
|
||||||
@@ -43,9 +39,7 @@ err_perm_user = error en degradar els permisos de l'usuari
|
|||||||
err_pwnam = error en obtenir la informació de l'usuari
|
err_pwnam = error en obtenir la informació de l'usuari
|
||||||
|
|
||||||
|
|
||||||
|
err_unknown = ha ocorregut un error desconegut
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = error en establir el GID de l'usuari
|
err_user_gid = error en establir el GID de l'usuari
|
||||||
err_user_init = error en inicialitzar usuari
|
err_user_init = error en inicialitzar usuari
|
||||||
err_user_uid = error en establir l'UID de l'usuari
|
err_user_uid = error en establir l'UID de l'usuari
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = alokace paměti selhala
|
err_alloc = alokace paměti selhala
|
||||||
err_bounds = index je mimo hranice pole
|
err_bounds = index je mimo hranice pole
|
||||||
|
|
||||||
err_chdir = nelze otevřít domovský adresář
|
err_chdir = nelze otevřít domovský adresář
|
||||||
|
|
||||||
|
err_console_dev = chyba při přístupu do konzole
|
||||||
err_dgn_oob = zpráva protokolu
|
err_dgn_oob = zpráva protokolu
|
||||||
err_domain = neplatná doména
|
err_domain = neplatná doména
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = nelze získat název hostitele
|
err_hostname = nelze získat název hostitele
|
||||||
|
|
||||||
|
|
||||||
err_mlock = uzamčení paměti hesel selhalo
|
err_mlock = uzamčení paměti hesel selhalo
|
||||||
err_null = nulový ukazatel
|
err_null = nulový ukazatel
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = nelze získat informace o uživateli
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = nastavení GID uživatele selhalo
|
err_user_gid = nastavení GID uživatele selhalo
|
||||||
err_user_init = inicializace uživatele selhala
|
err_user_init = inicializace uživatele selhala
|
||||||
err_user_uid = nastavení UID uživateli selhalo
|
err_user_uid = nastavení UID uživateli selhalo
|
||||||
|
|||||||
@@ -1,70 +1,64 @@
|
|||||||
authenticating = authentifizieren...
|
|
||||||
brightness_down = Helligkeit-
|
|
||||||
brightness_up = Helligkeit+
|
|
||||||
capslock = Feststelltaste
|
capslock = Feststelltaste
|
||||||
|
|
||||||
err_alloc = Speicherzuweisung fehlgeschlagen
|
err_alloc = Speicherzuweisung fehlgeschlagen
|
||||||
err_bounds = Index ausserhalb des Bereichs
|
err_bounds = Listenindex ist außerhalb des Bereichs
|
||||||
err_brightness_change = Helligkeitsänderung fehlgeschlagen
|
|
||||||
err_chdir = Fehler beim Oeffnen des Home-Ordners
|
|
||||||
|
|
||||||
err_config = Fehler beim Verarbeiten der Konfigurationsdatei
|
err_chdir = Fehler beim oeffnen des home-ordners
|
||||||
err_dgn_oob = Diagnose-Nachricht
|
|
||||||
err_domain = Ungueltige Domain
|
|
||||||
err_empty_password = Leeres Passwort nicht zugelassen
|
|
||||||
err_envlist = Fehler beim Abrufen der Umgebungs-Variablen
|
|
||||||
|
|
||||||
err_hostname = Abrufen des Hostnames fehlgeschlagen
|
err_console_dev = Zugriff auf die Konsole fehlgeschlagen
|
||||||
|
err_dgn_oob = Protokoll Nachricht
|
||||||
|
err_domain = Unzulaessige domain
|
||||||
|
|
||||||
|
|
||||||
err_mlock = Sperren des Passwortspeichers fehlgeschlagen
|
err_hostname = Holen des Hostnames fehlgeschlagen
|
||||||
err_null = Null Pointer
|
err_mlock = Abschließen des Passwortspeichers fehlgeschlagen
|
||||||
err_numlock = Numlock konnte nicht aktiviert werden
|
err_null = Null Zeiger
|
||||||
err_pam = PAM-Transaktion fehlgeschlagen
|
|
||||||
err_pam_abort = PAM-Transaktion abgebrochen
|
err_pam = pam Transaktion fehlgeschlagen
|
||||||
|
err_pam_abort = pam Transaktion abgebrochen
|
||||||
err_pam_acct_expired = Benutzerkonto abgelaufen
|
err_pam_acct_expired = Benutzerkonto abgelaufen
|
||||||
err_pam_auth = Authentifizierungsfehler
|
err_pam_auth = Authentifizierungs Fehler
|
||||||
err_pam_authinfo_unavail = Abrufen der Benutzerinformationen fehlgeschlagen
|
err_pam_authinfo_unavail = holen der Benutzerinformationen fehlgeschlagen
|
||||||
err_pam_authok_reqd = Passwort abgelaufen
|
err_pam_authok_reqd = Schluessel abgelaufen
|
||||||
err_pam_buf = Speicherpufferfehler
|
err_pam_buf = Speicherpufferfehler
|
||||||
err_pam_cred_err = Fehler beim Setzen der Anmeldedaten
|
err_pam_cred_err = Fehler beim setzen der Anmeldedaten
|
||||||
err_pam_cred_expired = Anmeldedaten abgelaufen
|
err_pam_cred_expired = Anmeldedaten abgelaufen
|
||||||
err_pam_cred_insufficient = Anmeldedaten unzureichend
|
err_pam_cred_insufficient = Anmeldedaten unzureichend
|
||||||
err_pam_cred_unavail = Fehler beim Abrufen der Anmeldedaten
|
err_pam_cred_unavail = Fehler beim holen der Anmeldedaten
|
||||||
err_pam_maxtries = Maximale Versuchsanzahl erreicht
|
err_pam_maxtries = Maximale Versuche erreicht
|
||||||
err_pam_perm_denied = Zugriff verweigert
|
err_pam_perm_denied = Zugriff Verweigert
|
||||||
err_pam_session = Sitzungsfehler
|
err_pam_session = Sitzungsfehler
|
||||||
err_pam_sys = Systemfehler
|
err_pam_sys = Systemfehler
|
||||||
err_pam_user_unknown = Unbekannter Nutzer
|
err_pam_user_unknown = Unbekannter Nutzer
|
||||||
err_path = Fehler beim Setzen des Pfades
|
err_path = Fehler beim setzen des Pfades
|
||||||
err_perm_dir = Ordnerwechsel fehlgeschlagen
|
err_perm_dir = Fehler beim wechseln des Ordners
|
||||||
err_perm_group = Fehler beim Heruntersetzen der Gruppenberechtigungen
|
err_perm_group = Fehler beim heruntersetzen der Gruppen Berechtigungen
|
||||||
err_perm_user = Fehler beim Heruntersetzen der Nutzerberechtigungen
|
err_perm_user = Fehler beim heruntersetzen der Nutzer Berechtigungen
|
||||||
err_pwnam = Abrufen der Benutzerinformationen fehlgeschlagen
|
err_pwnam = Holen der Benutzerinformationen fehlgeschlagen
|
||||||
err_sleep = Sleep-Befehl fehlgeschlagen
|
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = Fehler bei der TTY-Uebergabe
|
|
||||||
|
|
||||||
err_user_gid = Fehler beim Setzen der Gruppen-ID
|
err_user_gid = Fehler beim setzen der Gruppen Id des Nutzers
|
||||||
err_user_init = Nutzer-Initialisierung fehlgeschlagen
|
err_user_init = Initialisierung des Nutzers fehlgeschlagen
|
||||||
err_user_uid = Setzen der Benutzer-ID fehlgeschlagen
|
err_user_uid = Setzen der Benutzer Id fehlgeschlagen
|
||||||
err_xauth = Xauth-Befehl fehlgeschlagen
|
|
||||||
err_xcb_conn = xcb-Verbindung fehlgeschlagen
|
|
||||||
err_xsessions_dir = Fehler beim Finden des Sitzungsordners
|
err_xsessions_dir = Fehler beim finden des Sitzungsordners
|
||||||
err_xsessions_open = Fehler beim Oeffnen des Sitzungsordners
|
err_xsessions_open = Fehler beim öffnen des Sitzungsordners
|
||||||
insert = Einfügen
|
|
||||||
login = Nutzer
|
login = Anmelden
|
||||||
logout = Abmelden
|
logout = Abgemeldet
|
||||||
no_x11_support = X11-Support bei Kompilierung deaktiviert
|
|
||||||
normal = Normal
|
|
||||||
numlock = Numlock
|
numlock = Numtaste
|
||||||
other = Andere
|
|
||||||
password = Passwort
|
password = Passwort
|
||||||
restart = Neustarten
|
restart = Neustarten
|
||||||
shell = Shell
|
shell = shell
|
||||||
shutdown = Herunterfahren
|
shutdown = Herunterfahren
|
||||||
sleep = Sleep
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
x11 = X11
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -2,21 +2,17 @@ authenticating = authenticating...
|
|||||||
brightness_down = decrease brightness
|
brightness_down = decrease brightness
|
||||||
brightness_up = increase brightness
|
brightness_up = increase brightness
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
custom = custom
|
|
||||||
err_alloc = failed memory allocation
|
err_alloc = failed memory allocation
|
||||||
err_bounds = out-of-bounds index
|
err_bounds = out-of-bounds index
|
||||||
err_brightness_change = failed to change brightness
|
err_brightness_change = failed to change brightness
|
||||||
err_chdir = failed to open home folder
|
err_chdir = failed to open home folder
|
||||||
err_clock_too_long = clock string too long
|
|
||||||
err_config = unable to parse config file
|
err_config = unable to parse config file
|
||||||
|
err_console_dev = failed to access console
|
||||||
err_dgn_oob = log message
|
err_dgn_oob = log message
|
||||||
err_domain = invalid domain
|
err_domain = invalid domain
|
||||||
err_empty_password = empty password not allowed
|
err_empty_password = empty password not allowed
|
||||||
err_envlist = failed to get envlist
|
err_envlist = failed to get envlist
|
||||||
err_get_active_tty = failed to get active tty
|
|
||||||
err_hostname = failed to get hostname
|
err_hostname = failed to get hostname
|
||||||
err_lock_state = failed to get lock state
|
|
||||||
err_log = failed to open log file
|
|
||||||
err_mlock = failed to lock password memory
|
err_mlock = failed to lock password memory
|
||||||
err_null = null pointer
|
err_null = null pointer
|
||||||
err_numlock = failed to set numlock
|
err_numlock = failed to set numlock
|
||||||
@@ -42,10 +38,8 @@ err_perm_group = failed to downgrade group permissions
|
|||||||
err_perm_user = failed to downgrade user permissions
|
err_perm_user = failed to downgrade user permissions
|
||||||
err_pwnam = failed to get user info
|
err_pwnam = failed to get user info
|
||||||
err_sleep = failed to execute sleep command
|
err_sleep = failed to execute sleep command
|
||||||
err_battery = failed to load battery status
|
|
||||||
err_switch_tty = failed to switch tty
|
|
||||||
err_tty_ctrl = tty control transfer failed
|
err_tty_ctrl = tty control transfer failed
|
||||||
err_no_users = no users found
|
err_unknown = an unknown error occurred
|
||||||
err_user_gid = failed to set user GID
|
err_user_gid = failed to set user GID
|
||||||
err_user_init = failed to initialize user
|
err_user_init = failed to initialize user
|
||||||
err_user_uid = failed to set user UID
|
err_user_uid = failed to set user UID
|
||||||
|
|||||||
@@ -2,21 +2,17 @@ authenticating = autenticando...
|
|||||||
brightness_down = bajar brillo
|
brightness_down = bajar brillo
|
||||||
brightness_up = subir brillo
|
brightness_up = subir brillo
|
||||||
capslock = Bloq Mayús
|
capslock = Bloq Mayús
|
||||||
|
|
||||||
err_alloc = asignación de memoria fallida
|
err_alloc = asignación de memoria fallida
|
||||||
err_bounds = índice fuera de límites
|
err_bounds = índice fuera de límites
|
||||||
|
|
||||||
err_chdir = error al abrir la carpeta home
|
err_chdir = error al abrir la carpeta home
|
||||||
|
|
||||||
|
err_console_dev = error al acceder a la consola
|
||||||
err_dgn_oob = mensaje de registro
|
err_dgn_oob = mensaje de registro
|
||||||
err_domain = dominio inválido
|
err_domain = dominio inválido
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = error al obtener el nombre de host
|
err_hostname = error al obtener el nombre de host
|
||||||
|
|
||||||
|
|
||||||
err_mlock = error al bloquear la contraseña de memoria
|
err_mlock = error al bloquear la contraseña de memoria
|
||||||
err_null = puntero nulo
|
err_null = puntero nulo
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = error al obtener la información del usuario
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = error al establecer el GID del usuario
|
err_user_gid = error al establecer el GID del usuario
|
||||||
err_user_init = error al inicializar usuario
|
err_user_init = error al inicializar usuario
|
||||||
err_user_uid = error al establecer el UID del usuario
|
err_user_uid = error al establecer el UID del usuario
|
||||||
|
|||||||
@@ -2,21 +2,17 @@ authenticating = authentification...
|
|||||||
brightness_down = diminuer la luminosité
|
brightness_down = diminuer la luminosité
|
||||||
brightness_up = augmenter la luminosité
|
brightness_up = augmenter la luminosité
|
||||||
capslock = verr.maj
|
capslock = verr.maj
|
||||||
custom = customisé
|
|
||||||
err_alloc = échec d'allocation mémoire
|
err_alloc = échec d'allocation mémoire
|
||||||
err_bounds = indice hors-limite
|
err_bounds = indice hors-limite
|
||||||
err_brightness_change = échec du changement de luminosité
|
err_brightness_change = échec du changement de luminosité
|
||||||
err_chdir = échec de l'ouverture du répertoire home
|
err_chdir = échec de l'ouverture du répertoire home
|
||||||
err_clock_too_long = chaîne de formattage de l'horloge trop longue
|
|
||||||
err_config = échec de lecture du fichier de configuration
|
err_config = échec de lecture du fichier de configuration
|
||||||
|
err_console_dev = échec d'accès à la console
|
||||||
err_dgn_oob = message
|
err_dgn_oob = message
|
||||||
err_domain = domaine invalide
|
err_domain = domaine invalide
|
||||||
err_empty_password = mot de passe vide non autorisé
|
err_empty_password = mot de passe vide non autorisé
|
||||||
err_envlist = échec de lecture de la liste d'environnement
|
err_envlist = échec de lecture de la liste d'environnement
|
||||||
err_get_active_tty = échec de lecture du terminal actif
|
|
||||||
err_hostname = échec de lecture du nom d'hôte
|
err_hostname = échec de lecture du nom d'hôte
|
||||||
err_lock_state = échec de lecture de l'état de verrouillage
|
|
||||||
err_log = échec de l'ouverture du fichier de journal
|
|
||||||
err_mlock = échec du verrouillage mémoire
|
err_mlock = échec du verrouillage mémoire
|
||||||
err_null = pointeur null
|
err_null = pointeur null
|
||||||
err_numlock = échec de modification du verr.num
|
err_numlock = échec de modification du verr.num
|
||||||
@@ -42,10 +38,8 @@ err_perm_group = échec du déclassement des permissions de groupe
|
|||||||
err_perm_user = échec du déclassement des permissions utilisateur
|
err_perm_user = échec du déclassement des permissions utilisateur
|
||||||
err_pwnam = échec de lecture des infos utilisateur
|
err_pwnam = échec de lecture des infos utilisateur
|
||||||
err_sleep = échec de l'exécution de la commande de veille
|
err_sleep = échec de l'exécution de la commande de veille
|
||||||
err_battery = échec de lecture de l'état de la batterie
|
|
||||||
err_switch_tty = échec du changement de terminal
|
|
||||||
err_tty_ctrl = échec du transfert de contrôle du terminal
|
err_tty_ctrl = échec du transfert de contrôle du terminal
|
||||||
err_no_users = aucun utilisateur trouvé
|
err_unknown = une erreur inconnue est survenue
|
||||||
err_user_gid = échec de modification du GID
|
err_user_gid = échec de modification du GID
|
||||||
err_user_init = échec d'initialisation de l'utilisateur
|
err_user_init = échec d'initialisation de l'utilisateur
|
||||||
err_user_uid = échec de modification du UID
|
err_user_uid = échec de modification du UID
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = impossibile allocare memoria
|
err_alloc = impossibile allocare memoria
|
||||||
err_bounds = indice fuori limite
|
err_bounds = indice fuori limite
|
||||||
|
|
||||||
err_chdir = impossibile aprire home directory
|
err_chdir = impossibile aprire home directory
|
||||||
|
|
||||||
|
err_console_dev = impossibile aprire console
|
||||||
err_dgn_oob = messaggio log
|
err_dgn_oob = messaggio log
|
||||||
err_domain = dominio non valido
|
err_domain = dominio non valido
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = impossibile ottenere hostname
|
err_hostname = impossibile ottenere hostname
|
||||||
|
|
||||||
|
|
||||||
err_mlock = impossibile ottenere lock per la password in memoria
|
err_mlock = impossibile ottenere lock per la password in memoria
|
||||||
err_null = puntatore nullo
|
err_null = puntatore nullo
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = impossibile ottenere dati utente
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = impossibile impostare GID utente
|
err_user_gid = impossibile impostare GID utente
|
||||||
err_user_init = impossibile inizializzare utente
|
err_user_init = impossibile inizializzare utente
|
||||||
err_user_uid = impossible impostare UID utente
|
err_user_uid = impossible impostare UID utente
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
authenticating = 認証中...
|
|
||||||
brightness_down = 明るさを下げる
|
|
||||||
brightness_up = 明るさを上げる
|
|
||||||
capslock = CapsLock
|
|
||||||
|
|
||||||
err_alloc = メモリ割り当て失敗
|
|
||||||
err_bounds = 境界外インデックス
|
|
||||||
err_brightness_change = 明るさの変更に失敗しました
|
|
||||||
err_chdir = ホームフォルダを開けませんでした
|
|
||||||
|
|
||||||
err_config = 設定ファイルを解析できません
|
|
||||||
err_dgn_oob = ログメッセージ
|
|
||||||
err_domain = 無効なドメイン
|
|
||||||
err_empty_password = 空のパスワードは許可されていません
|
|
||||||
err_envlist = 環境変数リストの取得に失敗しました
|
|
||||||
|
|
||||||
err_hostname = ホスト名の取得に失敗しました
|
|
||||||
|
|
||||||
|
|
||||||
err_mlock = パスワードメモリのロックに失敗しました
|
|
||||||
err_null = ヌルポインタ
|
|
||||||
err_numlock = NumLockの設定に失敗しました
|
|
||||||
err_pam = PAMトランザクション失敗
|
|
||||||
err_pam_abort = PAMトランザクションが中断されました
|
|
||||||
err_pam_acct_expired = アカウントの有効期限が切れています
|
|
||||||
err_pam_auth = 認証エラー
|
|
||||||
err_pam_authinfo_unavail = ユーザー情報の取得に失敗しました
|
|
||||||
err_pam_authok_reqd = トークンの有効期限が切れています
|
|
||||||
err_pam_buf = メモリバッファエラー
|
|
||||||
err_pam_cred_err = 認証情報の設定に失敗しました
|
|
||||||
err_pam_cred_expired = 認証情報の有効期限が切れています
|
|
||||||
err_pam_cred_insufficient = 認証情報が不十分です
|
|
||||||
err_pam_cred_unavail = 認証情報の取得に失敗しました
|
|
||||||
err_pam_maxtries = 最大試行回数に到達しました
|
|
||||||
err_pam_perm_denied = アクセスが拒否されました
|
|
||||||
err_pam_session = セッションエラー
|
|
||||||
err_pam_sys = システムエラー
|
|
||||||
err_pam_user_unknown = 不明なユーザー
|
|
||||||
err_path = パスの設定に失敗しました
|
|
||||||
err_perm_dir = カレントディレクトリの変更に失敗しました
|
|
||||||
err_perm_group = グループ権限のダウングレードに失敗しました
|
|
||||||
err_perm_user = ユーザー権限のダウングレードに失敗しました
|
|
||||||
err_pwnam = ユーザー情報の取得に失敗しました
|
|
||||||
err_sleep = スリープコマンドの実行に失敗しました
|
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = TTY制御の転送に失敗しました
|
|
||||||
|
|
||||||
err_user_gid = ユーザーGIDの設定に失敗しました
|
|
||||||
err_user_init = ユーザーの初期化に失敗しました
|
|
||||||
err_user_uid = ユーザーUIDの設定に失敗しました
|
|
||||||
err_xauth = xauthコマンドの実行に失敗しました
|
|
||||||
err_xcb_conn = XCB接続に失敗しました
|
|
||||||
err_xsessions_dir = セッションフォルダが見つかりませんでした
|
|
||||||
err_xsessions_open = セッションフォルダを開けませんでした
|
|
||||||
insert = 挿入
|
|
||||||
login = ログイン
|
|
||||||
logout = ログアウト済み
|
|
||||||
no_x11_support = X11サポートはコンパイル時に無効化されています
|
|
||||||
normal = 通常
|
|
||||||
numlock = NumLock
|
|
||||||
other = その他
|
|
||||||
password = パスワード
|
|
||||||
restart = 再起動
|
|
||||||
shell = シェル
|
|
||||||
shutdown = シャットダウン
|
|
||||||
sleep = スリープ
|
|
||||||
wayland = Wayland
|
|
||||||
x11 = X11
|
|
||||||
xinitrc = xinitrc
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
authenticating = autentificējas...
|
|
||||||
brightness_down = samazināt spilgtumu
|
|
||||||
brightness_up = palielināt spilgtumu
|
|
||||||
capslock = caps lock
|
|
||||||
custom = pielāgots
|
|
||||||
err_alloc = neizdevās atmiņas piešķiršana
|
|
||||||
err_bounds = indekss ārpus robežām
|
|
||||||
err_brightness_change = neizdevās mainīt spilgtumu
|
|
||||||
err_chdir = neizdevās atvērt mājas mapi
|
|
||||||
err_clock_too_long = pulksteņa virkne pārāk gara
|
|
||||||
err_config = neizdevās parsēt konfigurācijas failu
|
|
||||||
err_dgn_oob = žurnāla ziņojums
|
|
||||||
err_domain = nederīgs domēns
|
|
||||||
err_empty_password = tukša parole nav atļauta
|
|
||||||
err_envlist = neizdevās iegūt vides mainīgo sarakstu
|
|
||||||
err_get_active_tty = neizdevās iegūt aktīvo tty
|
|
||||||
err_hostname = neizdevās iegūt hostname
|
|
||||||
err_lock_state = neizdevās iegūt bloķēšanas stāvokli
|
|
||||||
err_log = neizdevās atvērt žurnāla failu
|
|
||||||
err_mlock = neizdevās bloķēt paroles atmiņu
|
|
||||||
err_null = null rādītājs
|
|
||||||
err_numlock = neizdevās iestatīt numlock
|
|
||||||
err_pam = pam transakcija neizdevās
|
|
||||||
err_pam_abort = pam transakcija pārtraukta
|
|
||||||
err_pam_acct_expired = konts novecojis
|
|
||||||
err_pam_auth = autentifikācijas kļūda
|
|
||||||
err_pam_authinfo_unavail = neizdevās iegūt lietotāja informāciju
|
|
||||||
err_pam_authok_reqd = žetons beidzies
|
|
||||||
err_pam_buf = atmiņas bufera kļūda
|
|
||||||
err_pam_cred_err = neizdevās iestatīt akreditācijas datus
|
|
||||||
err_pam_cred_expired = akreditācijas dati novecojuši
|
|
||||||
err_pam_cred_insufficient = nepietiekami akreditācijas dati
|
|
||||||
err_pam_cred_unavail = neizdevās iegūt akreditācijas datus
|
|
||||||
err_pam_maxtries = sasniegts maksimālais mēģinājumu skaits
|
|
||||||
err_pam_perm_denied = piekļuve liegta
|
|
||||||
err_pam_session = sesijas kļūda
|
|
||||||
err_pam_sys = sistēmas kļūda
|
|
||||||
err_pam_user_unknown = nezināms lietotājs
|
|
||||||
err_path = neizdevās iestatīt ceļu
|
|
||||||
err_perm_dir = neizdevās mainīt pašreizējo mapi
|
|
||||||
err_perm_group = neizdevās pazemināt grupas atļaujas
|
|
||||||
err_perm_user = neizdevās pazemināt lietotāja atļaujas
|
|
||||||
err_pwnam = neizdevās iegūt lietotāja informāciju
|
|
||||||
err_sleep = neizdevās izpildīt miega komandu
|
|
||||||
err_battery = neizdevās ielādēt akumulatora stāvokli
|
|
||||||
err_switch_tty = neizdevās pārslēgt tty
|
|
||||||
err_tty_ctrl = tty vadības nodošana neizdevās
|
|
||||||
err_no_users = lietotāji nav atrasti
|
|
||||||
err_user_gid = neizdevās iestatīt lietotāja GID
|
|
||||||
err_user_init = neizdevās inicializēt lietotāju
|
|
||||||
err_user_uid = neizdevās iestatīt lietotāja UID
|
|
||||||
err_xauth = xauth komanda neizdevās
|
|
||||||
err_xcb_conn = xcb savienojums neizdevās
|
|
||||||
err_xsessions_dir = neizdevās atrast sesiju mapi
|
|
||||||
err_xsessions_open = neizdevās atvērt sesiju mapi
|
|
||||||
insert = ievietot
|
|
||||||
login = lietotājs
|
|
||||||
logout = iziet
|
|
||||||
no_x11_support = x11 atbalsts atspējots kompilācijas laikā
|
|
||||||
normal = parastais
|
|
||||||
numlock = numlock
|
|
||||||
other = cits
|
|
||||||
password = parole
|
|
||||||
restart = restartēt
|
|
||||||
shell = terminālis
|
|
||||||
shutdown = izslēgt
|
|
||||||
sleep = snauda
|
|
||||||
wayland = wayland
|
|
||||||
x11 = x11
|
|
||||||
xinitrc = xinitrc
|
|
||||||
|
|
||||||
@@ -2,21 +2,17 @@ authenticating = uwierzytelnianie...
|
|||||||
brightness_down = zmniejsz jasność
|
brightness_down = zmniejsz jasność
|
||||||
brightness_up = zwiększ jasność
|
brightness_up = zwiększ jasność
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = nieudana alokacja pamięci
|
err_alloc = nieudana alokacja pamięci
|
||||||
err_bounds = indeks poza zakresem
|
err_bounds = indeks poza zakresem
|
||||||
err_brightness_change = nie udało się zmienić jasności
|
err_brightness_change = nie udało się zmienić jasności
|
||||||
err_chdir = nie udało się otworzyć folderu domowego
|
err_chdir = nie udało się otworzyć folderu domowego
|
||||||
|
|
||||||
err_config = nie można przetworzyć pliku konfiguracyjnego
|
err_config = nie można przetworzyć pliku konfiguracyjnego
|
||||||
|
err_console_dev = nie udało się uzyskać dostępu do konsoli
|
||||||
err_dgn_oob = wiadomość loga
|
err_dgn_oob = wiadomość loga
|
||||||
err_domain = niepoprawna domena
|
err_domain = niepoprawna domena
|
||||||
err_empty_password = puste hasło jest niedozwolone
|
err_empty_password = puste hasło jest niedozwolone
|
||||||
err_envlist = nie udało się pobrać listy zmiennych środowiskowych
|
err_envlist = nie udało się pobrać listy zmiennych środowiskowych
|
||||||
|
|
||||||
err_hostname = nie udało się uzyskać nazwy hosta
|
err_hostname = nie udało się uzyskać nazwy hosta
|
||||||
|
|
||||||
|
|
||||||
err_mlock = nie udało się zablokować pamięci haseł
|
err_mlock = nie udało się zablokować pamięci haseł
|
||||||
err_null = pusty wskaźnik
|
err_null = pusty wskaźnik
|
||||||
err_numlock = nie udało się ustawić numlock
|
err_numlock = nie udało się ustawić numlock
|
||||||
@@ -42,10 +38,8 @@ err_perm_group = nie udało się obniżyć uprawnień grupy
|
|||||||
err_perm_user = nie udało się obniżyć uprawnień użytkownika
|
err_perm_user = nie udało się obniżyć uprawnień użytkownika
|
||||||
err_pwnam = nie udało się uzyskać informacji o użytkowniku
|
err_pwnam = nie udało się uzyskać informacji o użytkowniku
|
||||||
err_sleep = nie udało się wykonać polecenia sleep
|
err_sleep = nie udało się wykonać polecenia sleep
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = nie udało się przekazać kontroli tty
|
err_tty_ctrl = nie udało się przekazać kontroli tty
|
||||||
|
err_unknown = wystąpił nieznany błąd
|
||||||
err_user_gid = nie udało się ustawić GID użytkownika
|
err_user_gid = nie udało się ustawić GID użytkownika
|
||||||
err_user_init = nie udało się zainicjalizować użytkownika
|
err_user_init = nie udało się zainicjalizować użytkownika
|
||||||
err_user_uid = nie udało się ustawić UID użytkownika
|
err_user_uid = nie udało się ustawić UID użytkownika
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = erro na atribuição de memória
|
err_alloc = erro na atribuição de memória
|
||||||
err_bounds = índice fora de limites
|
err_bounds = índice fora de limites
|
||||||
|
|
||||||
err_chdir = erro ao abrir a pasta home
|
err_chdir = erro ao abrir a pasta home
|
||||||
|
|
||||||
|
err_console_dev = erro ao aceder à consola
|
||||||
err_dgn_oob = mensagem de registo
|
err_dgn_oob = mensagem de registo
|
||||||
err_domain = domínio inválido
|
err_domain = domínio inválido
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = erro ao obter o nome do host
|
err_hostname = erro ao obter o nome do host
|
||||||
|
|
||||||
|
|
||||||
err_mlock = erro de bloqueio de memória
|
err_mlock = erro de bloqueio de memória
|
||||||
err_null = ponteiro nulo
|
err_null = ponteiro nulo
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = erro ao obter informação do utilizador
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = erro ao definir o GID do utilizador
|
err_user_gid = erro ao definir o GID do utilizador
|
||||||
err_user_init = erro ao iniciar o utilizador
|
err_user_init = erro ao iniciar o utilizador
|
||||||
err_user_uid = erro ao definir o UID do utilizador
|
err_user_uid = erro ao definir o UID do utilizador
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = caixa alta
|
capslock = caixa alta
|
||||||
|
|
||||||
err_alloc = alocação de memória malsucedida
|
err_alloc = alocação de memória malsucedida
|
||||||
err_bounds = índice fora de limites
|
err_bounds = índice fora de limites
|
||||||
|
|
||||||
err_chdir = não foi possível abrir o diretório home
|
err_chdir = não foi possível abrir o diretório home
|
||||||
|
|
||||||
|
err_console_dev = não foi possível acessar o console
|
||||||
err_dgn_oob = mensagem de log
|
err_dgn_oob = mensagem de log
|
||||||
err_domain = domínio inválido
|
err_domain = domínio inválido
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = não foi possível obter o nome do host
|
err_hostname = não foi possível obter o nome do host
|
||||||
|
|
||||||
|
|
||||||
err_mlock = bloqueio da memória de senha malsucedido
|
err_mlock = bloqueio da memória de senha malsucedido
|
||||||
err_null = ponteiro nulo
|
err_null = ponteiro nulo
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = não foi possível obter informações do usuário
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = não foi possível definir o GID do usuário
|
err_user_gid = não foi possível definir o GID do usuário
|
||||||
err_user_init = não foi possível iniciar o usuário
|
err_user_init = não foi possível iniciar o usuário
|
||||||
err_user_uid = não foi possível definir o UID do usuário
|
err_user_uid = não foi possível definir o UID do usuário
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ capslock = capslock
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
err_console_dev = nu s-a putut accesa consola
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -52,8 +48,6 @@ err_perm_user = nu s-a putut face downgrade permisiunilor de utilizator
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
login = utilizator
|
login = utilizator
|
||||||
logout = opreşte sesiunea
|
logout = opreşte sesiunea
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,18 @@
|
|||||||
authenticating = аутентификация...
|
|
||||||
brightness_down = уменьшить яркость
|
|
||||||
brightness_up = увеличить яркость
|
|
||||||
capslock = capslock
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
capslock = capslock
|
||||||
err_alloc = не удалось выделить память
|
err_alloc = не удалось выделить память
|
||||||
err_bounds = за пределами индекса
|
err_bounds = за пределами индекса
|
||||||
err_brightness_change = не удалось изменить яркость
|
|
||||||
err_chdir = не удалось открыть домашнюю папку
|
err_chdir = не удалось открыть домашнюю папку
|
||||||
|
|
||||||
err_config = не удалось разобрать файл конфигурации
|
err_console_dev = не удалось получить доступ к консоли
|
||||||
err_dgn_oob = отладочное сообщение (log)
|
err_dgn_oob = отладочное сообщение (log)
|
||||||
err_domain = неверный домен
|
err_domain = неверный домен
|
||||||
err_empty_password = пустой пароль не допустим
|
|
||||||
err_envlist = не удалось получить список переменных среды
|
|
||||||
|
|
||||||
err_hostname = не удалось получить имя хоста
|
err_hostname = не удалось получить имя хоста
|
||||||
|
|
||||||
|
|
||||||
err_mlock = сбой блокировки памяти
|
err_mlock = сбой блокировки памяти
|
||||||
err_null = нулевой указатель
|
err_null = нулевой указатель
|
||||||
|
|
||||||
@@ -41,30 +37,28 @@ err_perm_dir = не удалось изменить текущий катало
|
|||||||
err_perm_group = не удалось понизить права доступа группы
|
err_perm_group = не удалось понизить права доступа группы
|
||||||
err_perm_user = не удалось понизить права доступа пользователя
|
err_perm_user = не удалось понизить права доступа пользователя
|
||||||
err_pwnam = не удалось получить информацию о пользователе
|
err_pwnam = не удалось получить информацию о пользователе
|
||||||
err_sleep = не удалось выполнить команду sleep
|
|
||||||
|
|
||||||
err_switch_tty = не удалось переключить tty
|
|
||||||
err_tty_ctrl = передача управления tty не удалась
|
|
||||||
err_no_users = пользователи не найдены
|
|
||||||
err_user_gid = не удалось установить GID пользователя
|
err_user_gid = не удалось установить GID пользователя
|
||||||
err_user_init = не удалось инициализировать пользователя
|
err_user_init = не удалось инициализировать пользователя
|
||||||
err_user_uid = не удалось установить UID пользователя
|
err_user_uid = не удалось установить UID пользователя
|
||||||
err_xauth = команда xauth не выполнена
|
|
||||||
err_xcb_conn = ошибка подключения xcb
|
|
||||||
err_xsessions_dir = не удалось найти сессионную папку
|
err_xsessions_dir = не удалось найти сессионную папку
|
||||||
err_xsessions_open = не удалось открыть сессионную папку
|
err_xsessions_open = не удалось открыть сессионную папку
|
||||||
|
|
||||||
login = логин
|
login = логин
|
||||||
logout = вышел из системы
|
logout = logged out
|
||||||
no_x11_support = поддержка x11 отключена во время компиляции
|
|
||||||
|
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
other = прочие
|
|
||||||
password = пароль
|
password = пароль
|
||||||
restart = перезагрузить
|
restart = перезагрузить
|
||||||
shell = оболочка
|
shell = shell
|
||||||
shutdown = выключить
|
shutdown = выключить
|
||||||
sleep = сон
|
|
||||||
wayland = wayland
|
wayland = wayland
|
||||||
x11 = x11
|
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = neuspijesna alokacija memorije
|
err_alloc = neuspijesna alokacija memorije
|
||||||
err_bounds = izvan granica indeksa
|
err_bounds = izvan granica indeksa
|
||||||
|
|
||||||
err_chdir = neuspijesno otvaranje home foldera
|
err_chdir = neuspijesno otvaranje home foldera
|
||||||
|
|
||||||
|
err_console_dev = neuspijesno pristupanje konzoli
|
||||||
err_dgn_oob = log poruka
|
err_dgn_oob = log poruka
|
||||||
err_domain = nevazeci domen
|
err_domain = nevazeci domen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = neuspijesno trazenje hostname-a
|
err_hostname = neuspijesno trazenje hostname-a
|
||||||
|
|
||||||
|
|
||||||
err_mlock = neuspijesno zakljucavanje memorije lozinke
|
err_mlock = neuspijesno zakljucavanje memorije lozinke
|
||||||
err_null = null pokazivac
|
err_null = null pokazivac
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = neuspijesno skupljanje informacija o korisniku
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = neuspijesno postavljanje korisničkog GID-a
|
err_user_gid = neuspijesno postavljanje korisničkog GID-a
|
||||||
err_user_init = neuspijensa inicijalizacija korisnika
|
err_user_init = neuspijensa inicijalizacija korisnika
|
||||||
err_user_uid = neuspijesno postavljanje UID-a korisnika
|
err_user_uid = neuspijesno postavljanje UID-a korisnika
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = misslyckad minnesallokering
|
err_alloc = misslyckad minnesallokering
|
||||||
err_bounds = utanför banan index
|
err_bounds = utanför banan index
|
||||||
|
|
||||||
err_chdir = misslyckades att öppna hemkatalog
|
err_chdir = misslyckades att öppna hemkatalog
|
||||||
|
|
||||||
|
err_console_dev = misslyckades att komma åt konsol
|
||||||
err_dgn_oob = loggmeddelande
|
err_dgn_oob = loggmeddelande
|
||||||
err_domain = okänd domän
|
err_domain = okänd domän
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = misslyckades att hämta värdnamn
|
err_hostname = misslyckades att hämta värdnamn
|
||||||
|
|
||||||
|
|
||||||
err_mlock = misslyckades att låsa lösenordsminne
|
err_mlock = misslyckades att låsa lösenordsminne
|
||||||
err_null = nullpekare
|
err_null = nullpekare
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = misslyckades att hämta användarinfo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = misslyckades att ställa in användar-GID
|
err_user_gid = misslyckades att ställa in användar-GID
|
||||||
err_user_init = misslyckades att initialisera användaren
|
err_user_init = misslyckades att initialisera användaren
|
||||||
err_user_uid = misslyckades att ställa in användar-UID
|
err_user_uid = misslyckades att ställa in användar-UID
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = basarisiz bellek ayirma
|
err_alloc = basarisiz bellek ayirma
|
||||||
err_bounds = sinirlarin disinda dizin
|
err_bounds = sinirlarin disinda dizin
|
||||||
|
|
||||||
err_chdir = ev klasoru acilamadi
|
err_chdir = ev klasoru acilamadi
|
||||||
|
|
||||||
|
err_console_dev = konsola erisilemedi
|
||||||
err_dgn_oob = log mesaji
|
err_dgn_oob = log mesaji
|
||||||
err_domain = gecersiz etki alani
|
err_domain = gecersiz etki alani
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = ana bilgisayar adi alinamadi
|
err_hostname = ana bilgisayar adi alinamadi
|
||||||
|
|
||||||
|
|
||||||
err_mlock = parola bellegi kilitlenemedi
|
err_mlock = parola bellegi kilitlenemedi
|
||||||
err_null = bos isaretci hatasi
|
err_null = bos isaretci hatasi
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = kullanici bilgileri alinamadi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = kullanici icin GID ayarlanamadi
|
err_user_gid = kullanici icin GID ayarlanamadi
|
||||||
err_user_init = kullanici oturumu baslatilamadi
|
err_user_init = kullanici oturumu baslatilamadi
|
||||||
err_user_uid = kullanici icin UID ayarlanamadi
|
err_user_uid = kullanici icin UID ayarlanamadi
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = невдале виділення пам'яті
|
err_alloc = невдале виділення пам'яті
|
||||||
err_bounds = поза межами індексу
|
err_bounds = поза межами індексу
|
||||||
|
|
||||||
err_chdir = не вдалося відкрити домашній каталог
|
err_chdir = не вдалося відкрити домашній каталог
|
||||||
|
|
||||||
|
err_console_dev = невдалий доступ до консолі
|
||||||
err_dgn_oob = повідомлення журналу (log)
|
err_dgn_oob = повідомлення журналу (log)
|
||||||
err_domain = недійсний домен
|
err_domain = недійсний домен
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = не вдалося отримати ім'я хосту
|
err_hostname = не вдалося отримати ім'я хосту
|
||||||
|
|
||||||
|
|
||||||
err_mlock = збій блокування пам'яті
|
err_mlock = збій блокування пам'яті
|
||||||
err_null = нульовий вказівник
|
err_null = нульовий вказівник
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = не вдалося отримати дані користувача
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = не вдалося змінити GID користувача
|
err_user_gid = не вдалося змінити GID користувача
|
||||||
err_user_init = не вдалося ініціалізувати користувача
|
err_user_init = не вдалося ініціалізувати користувача
|
||||||
err_user_uid = не вдалося змінити UID користувача
|
err_user_uid = не вдалося змінити UID користувача
|
||||||
|
|||||||
@@ -2,21 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
capslock = 大写锁定
|
capslock = 大写锁定
|
||||||
|
|
||||||
err_alloc = 内存分配失败
|
err_alloc = 内存分配失败
|
||||||
err_bounds = 索引越界
|
err_bounds = 索引越界
|
||||||
|
|
||||||
err_chdir = 无法打开home文件夹
|
err_chdir = 无法打开home文件夹
|
||||||
|
|
||||||
|
err_console_dev = 无法访问控制台
|
||||||
err_dgn_oob = 日志消息
|
err_dgn_oob = 日志消息
|
||||||
err_domain = 无效的域
|
err_domain = 无效的域
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = 获取主机名失败
|
err_hostname = 获取主机名失败
|
||||||
|
|
||||||
|
|
||||||
err_mlock = 锁定密码存储器失败
|
err_mlock = 锁定密码存储器失败
|
||||||
err_null = 空指针
|
err_null = 空指针
|
||||||
|
|
||||||
@@ -44,8 +40,6 @@ err_pwnam = 获取用户信息失败
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = 设置用户GID失败
|
err_user_gid = 设置用户GID失败
|
||||||
err_user_init = 初始化用户失败
|
err_user_init = 初始化用户失败
|
||||||
err_user_uid = 设置用户UID失败
|
err_user_uid = 设置用户UID失败
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
type = process
|
type = process
|
||||||
restart = true
|
restart = true
|
||||||
smooth-recovery = true
|
smooth-recovery = true
|
||||||
command = $PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME
|
command = $PREFIX_DIRECTORY/bin/$EXE_NAME
|
||||||
depends-on = login.target
|
depends-on = loginready
|
||||||
termsignal = HUP
|
termsignal = HUP
|
||||||
# ly needs access to the console while login.target already occupies it
|
# ly needs access to the console while loginready already occupies it
|
||||||
options = shares-console
|
options = shares-console
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# On FreeBSD, even if we override the default login program, getty will still
|
|
||||||
# try to append "login -fp root" as arguments to Ly, which is not supported.
|
|
||||||
# To avoid this, we use a wrapper script that ignores these arguments before
|
|
||||||
# actually executing Ly.
|
|
||||||
exec $PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME
|
|
||||||
@@ -19,8 +19,12 @@ then
|
|||||||
commandUL="/sbin/agetty"
|
commandUL="/sbin/agetty"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
## Get the tty from the conf file
|
||||||
|
CONFTTY=$(cat $CONFIG_DIRECTORY/ly/config.ini | sed -n 's/^tty.*=[^1-9]*// p')
|
||||||
|
|
||||||
## The execution vars
|
## The execution vars
|
||||||
TTY="tty$DEFAULT_TTY"
|
# If CONFTTY is empty then default to $DEFAULT_TTY
|
||||||
|
TTY="tty${CONFTTY:-$DEFAULT_TTY}"
|
||||||
TERM=linux
|
TERM=linux
|
||||||
BAUD=38400
|
BAUD=38400
|
||||||
# If we don't have getty then we should have agetty
|
# If we don't have getty then we should have agetty
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ fi
|
|||||||
|
|
||||||
BAUD_RATE=38400
|
BAUD_RATE=38400
|
||||||
TERM_NAME=linux
|
TERM_NAME=linux
|
||||||
TTY=tty$DEFAULT_TTY
|
|
||||||
|
auxtty=$(/bin/cat $CONFIG_DIRECTORY/ly/config.ini 2>/dev/null 1| /bin/sed -n 's/\(^[[:space:]]*tty[[:space:]]*=[[:space:]]*\)\([[:digit:]][[:digit:]]*\)\(.*\)/\2/p')
|
||||||
|
TTY=tty${auxtty:-$DEFAULT_TTY}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/execlineb -P
|
#!/bin/execlineb -P
|
||||||
exec agetty -L -8 -n -l $PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME tty$DEFAULT_TTY 115200
|
exec agetty -L -8 -n -l $PREFIX_DIRECTORY/bin/$EXE_NAME tty$DEFAULT_TTY 115200
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
### BEGIN INIT INFO
|
|
||||||
# Provides: ly
|
|
||||||
# Required-Start: $remote_fs $syslog
|
|
||||||
# Required-Stop: $remote_fs $syslog
|
|
||||||
# Default-Start: 2 3 4 5
|
|
||||||
# Default-Stop: 0 1 6
|
|
||||||
# Short-Description: Ly display manager
|
|
||||||
# Description: Starts and stops the Ly display manager
|
|
||||||
### END INIT INFO
|
|
||||||
#
|
|
||||||
# Author: AnErrupTion <anerruption@disroot.org>
|
|
||||||
#
|
|
||||||
|
|
||||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
|
||||||
DAEMON=/usr/bin/ly
|
|
||||||
TTY=/dev/tty$DEFAULT_TTY
|
|
||||||
PIDFILE=/var/run/ly.pid
|
|
||||||
NAME=ly
|
|
||||||
DESC="Ly display manager"
|
|
||||||
|
|
||||||
. /lib/lsb/init-functions
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
log_daemon_msg "Starting $DESC on $TTY..."
|
|
||||||
if [ -f "$PIDFILE" ]; then
|
|
||||||
log_progress_msg "$DESC is already running"
|
|
||||||
log_end_msg 0
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure TTY exists
|
|
||||||
[ -c "$TTY" ] || {
|
|
||||||
log_failure_msg "$TTY does not exist"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
start-stop-daemon --start --background --make-pidfile --pidfile $PIDFILE \
|
|
||||||
--chdir / --exec /bin/sh -- -c "exec setsid sh -c 'exec <$TTY >$TTY 2>&1 $DAEMON'"
|
|
||||||
log_end_msg $?
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
log_daemon_msg "Stopping $DESC..."
|
|
||||||
start-stop-daemon --stop --pidfile $PIDFILE --retry 5
|
|
||||||
RETVAL=$?
|
|
||||||
[ $RETVAL -eq 0 ] && rm -f "$PIDFILE"
|
|
||||||
log_end_msg $RETVAL
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
echo "Restarting $DESC..."
|
|
||||||
$0 stop
|
|
||||||
sleep 1
|
|
||||||
$0 start
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
status_of_proc -p $PIDFILE $DAEMON $NAME && exit 0 || exit $?
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: /etc/init.d/$NAME {start|stop|restart|status}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#%PAM-1.0
|
|
||||||
|
|
||||||
# OpenPAM (used in FreeBSD) doesn't support prepending "-" for ignoring missing
|
|
||||||
# modules.
|
|
||||||
auth include login
|
|
||||||
account include login
|
|
||||||
password include login
|
|
||||||
session include login
|
|
||||||
@@ -6,18 +6,16 @@ const Ini = ini.Ini;
|
|||||||
|
|
||||||
pub const DesktopEntry = struct {
|
pub const DesktopEntry = struct {
|
||||||
Exec: []const u8 = "",
|
Exec: []const u8 = "",
|
||||||
Name: []const u8 = "",
|
Name: [:0]const u8 = "",
|
||||||
DesktopNames: ?[]u8 = null,
|
DesktopNames: ?[:0]u8 = null,
|
||||||
Terminal: ?bool = null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
|
pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
|
||||||
|
|
||||||
entry_ini: ?Ini(Entry) = null,
|
entry_ini: ?Ini(Entry) = null,
|
||||||
name: []const u8 = "",
|
name: [:0]const u8 = "",
|
||||||
xdg_session_desktop: ?[]const u8 = null,
|
xdg_session_desktop: ?[:0]const u8 = null,
|
||||||
xdg_desktop_names: ?[]const u8 = null,
|
xdg_desktop_names: ?[:0]const u8 = null,
|
||||||
cmd: ?[]const u8 = null,
|
cmd: []const u8 = "",
|
||||||
specifier: []const u8 = "",
|
specifier: []const u8 = "",
|
||||||
display_server: DisplayServer = .wayland,
|
display_server: DisplayServer = .wayland,
|
||||||
is_terminal: bool = false,
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const LogFile = @This();
|
|
||||||
|
|
||||||
path: []const u8,
|
|
||||||
could_open_log_file: bool = undefined,
|
|
||||||
file: std.fs.File = undefined,
|
|
||||||
buffer: []u8,
|
|
||||||
file_writer: std.fs.File.Writer = undefined,
|
|
||||||
|
|
||||||
pub fn init(path: []const u8, buffer: []u8) !LogFile {
|
|
||||||
var log_file = LogFile{ .path = path, .buffer = buffer };
|
|
||||||
log_file.could_open_log_file = try openLogFile(path, &log_file);
|
|
||||||
return log_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reinit(self: *LogFile) !void {
|
|
||||||
self.could_open_log_file = try openLogFile(self.path, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *LogFile) void {
|
|
||||||
self.file_writer.interface.flush() catch {};
|
|
||||||
self.file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn openLogFile(path: []const u8, log_file: *LogFile) !bool {
|
|
||||||
var could_open_log_file = true;
|
|
||||||
open_log_file: {
|
|
||||||
log_file.file = std.fs.cwd().openFile(path, .{ .mode = .write_only }) catch std.fs.cwd().createFile(path, .{ .mode = 0o666 }) catch {
|
|
||||||
// If we could neither open an existing log file nor create a new
|
|
||||||
// one, abort.
|
|
||||||
could_open_log_file = false;
|
|
||||||
break :open_log_file;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!could_open_log_file) {
|
|
||||||
log_file.file = try std.fs.openFileAbsolute("/dev/null", .{ .mode = .write_only });
|
|
||||||
}
|
|
||||||
|
|
||||||
var log_file_writer = log_file.file.writer(log_file.buffer);
|
|
||||||
|
|
||||||
// Seek to the end of the log file
|
|
||||||
if (could_open_log_file) {
|
|
||||||
const stat = try log_file.file.stat();
|
|
||||||
try log_file_writer.seekTo(stat.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_file.file_writer = log_file_writer;
|
|
||||||
return could_open_log_file;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
// We set both values to 0 by default so that, in case they aren't present in
|
|
||||||
// the login.defs for some reason, then only the root username will be shown
|
|
||||||
uid_min: std.posix.uid_t = 0,
|
|
||||||
uid_max: std.posix.uid_t = 0,
|
|
||||||
@@ -7,27 +7,26 @@ const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
|||||||
const Doom = @This();
|
const Doom = @This();
|
||||||
|
|
||||||
pub const STEPS = 12;
|
pub const STEPS = 12;
|
||||||
pub const HEIGHT_MAX = 9;
|
|
||||||
pub const SPREAD_MAX = 4;
|
|
||||||
|
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
terminal_buffer: *TerminalBuffer,
|
terminal_buffer: *TerminalBuffer,
|
||||||
buffer: []u8,
|
buffer: []u8,
|
||||||
height: u8,
|
|
||||||
spread: u8,
|
|
||||||
fire: [STEPS + 1]Cell,
|
fire: [STEPS + 1]Cell,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u32, middle_color: u32, bottom_color: u32, fire_height: u8, fire_spread: u8) !Doom {
|
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u32, middle_color: u32, bottom_color: u32) !Doom {
|
||||||
const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height);
|
const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height);
|
||||||
initBuffer(buffer, terminal_buffer.width);
|
initBuffer(buffer, terminal_buffer.width);
|
||||||
|
|
||||||
const levels =
|
return .{
|
||||||
[_]Cell{
|
.allocator = allocator,
|
||||||
Cell.init(' ', terminal_buffer.bg, terminal_buffer.bg),
|
.terminal_buffer = terminal_buffer,
|
||||||
Cell.init(0x2591, top_color, terminal_buffer.bg),
|
.buffer = buffer,
|
||||||
Cell.init(0x2592, top_color, terminal_buffer.bg),
|
.fire = [_]Cell{
|
||||||
Cell.init(0x2593, top_color, terminal_buffer.bg),
|
Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT),
|
||||||
Cell.init(0x2588, top_color, terminal_buffer.bg),
|
Cell.init(0x2591, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2592, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2593, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
|
Cell.init(0x2588, top_color, TerminalBuffer.Color.DEFAULT),
|
||||||
Cell.init(0x2591, middle_color, top_color),
|
Cell.init(0x2591, middle_color, top_color),
|
||||||
Cell.init(0x2592, middle_color, top_color),
|
Cell.init(0x2592, middle_color, top_color),
|
||||||
Cell.init(0x2593, middle_color, top_color),
|
Cell.init(0x2593, middle_color, top_color),
|
||||||
@@ -36,15 +35,7 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u
|
|||||||
Cell.init(0x2592, bottom_color, middle_color),
|
Cell.init(0x2592, bottom_color, middle_color),
|
||||||
Cell.init(0x2593, bottom_color, middle_color),
|
Cell.init(0x2593, bottom_color, middle_color),
|
||||||
Cell.init(0x2588, bottom_color, middle_color),
|
Cell.init(0x2588, bottom_color, middle_color),
|
||||||
};
|
},
|
||||||
|
|
||||||
return .{
|
|
||||||
.allocator = allocator,
|
|
||||||
.terminal_buffer = terminal_buffer,
|
|
||||||
.buffer = buffer,
|
|
||||||
.height = @min(HEIGHT_MAX, fire_height),
|
|
||||||
.spread = @min(SPREAD_MAX, fire_spread),
|
|
||||||
.fire = levels,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,35 +57,20 @@ fn draw(self: *Doom) void {
|
|||||||
for (0..self.terminal_buffer.width) |x| {
|
for (0..self.terminal_buffer.width) |x| {
|
||||||
// We start from 1 so that we always have the topmost line when spreading fire
|
// We start from 1 so that we always have the topmost line when spreading fire
|
||||||
for (1..self.terminal_buffer.height) |y| {
|
for (1..self.terminal_buffer.height) |y| {
|
||||||
// Get index of current cell in fire level buffer
|
// Get current cell
|
||||||
const from = y * self.terminal_buffer.width + x;
|
const from = y * self.terminal_buffer.width + x;
|
||||||
|
const cell_index = self.buffer[from];
|
||||||
|
|
||||||
// Generate random data for fire propagation
|
// Spread fire
|
||||||
const rand_loss = self.terminal_buffer.random.intRangeAtMost(u8, 0, HEIGHT_MAX);
|
const propagate = self.terminal_buffer.random.int(u1);
|
||||||
const rand_spread = self.terminal_buffer.random.intRangeAtMost(u8, 0, self.spread * 2);
|
const to = from - self.terminal_buffer.width; // Get the line above
|
||||||
|
|
||||||
// Select semi-random target cell
|
self.buffer[to] = if (cell_index > 0) cell_index - propagate else cell_index;
|
||||||
const to = from -| self.terminal_buffer.width + self.spread -| rand_spread;
|
|
||||||
const to_x = to % self.terminal_buffer.width;
|
|
||||||
const to_y = to / self.terminal_buffer.width;
|
|
||||||
|
|
||||||
// Get fire level of current cell
|
// Put the cell
|
||||||
const level_buf_from = self.buffer[from];
|
const cell = self.fire[cell_index];
|
||||||
|
cell.put(x, y);
|
||||||
// Choose new fire level and store in level buffer
|
|
||||||
const level_buf_to = level_buf_from -| @intFromBool(rand_loss >= self.height);
|
|
||||||
self.buffer[to] = level_buf_to;
|
|
||||||
|
|
||||||
// Send known fire levels to terminal buffer
|
|
||||||
const from_cell = self.fire[level_buf_from];
|
|
||||||
const to_cell = self.fire[level_buf_to];
|
|
||||||
from_cell.put(x, y);
|
|
||||||
to_cell.put(to_x, to_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw bottom line (fire source)
|
|
||||||
const src_cell = self.fire[STEPS];
|
|
||||||
src_cell.put(x, self.terminal_buffer.height - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const Animation = @import("../tui/Animation.zig");
|
|
||||||
const Cell = @import("../tui/Cell.zig");
|
|
||||||
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const GameOfLife = @This();
|
|
||||||
|
|
||||||
// Visual styles - using block characters like other animations
|
|
||||||
const ALIVE_CHAR: u21 = 0x2588; // Full block █
|
|
||||||
const DEAD_CHAR: u21 = ' ';
|
|
||||||
const NEIGHBOR_DIRS = [_][2]i8{
|
|
||||||
.{ -1, -1 }, .{ -1, 0 }, .{ -1, 1 },
|
|
||||||
.{ 0, -1 }, .{ 0, 1 }, .{ 1, -1 },
|
|
||||||
.{ 1, 0 }, .{ 1, 1 },
|
|
||||||
};
|
|
||||||
|
|
||||||
allocator: Allocator,
|
|
||||||
terminal_buffer: *TerminalBuffer,
|
|
||||||
current_grid: []bool,
|
|
||||||
next_grid: []bool,
|
|
||||||
frame_counter: usize,
|
|
||||||
generation: u64,
|
|
||||||
fg_color: u32,
|
|
||||||
entropy_interval: usize,
|
|
||||||
frame_delay: usize,
|
|
||||||
initial_density: f32,
|
|
||||||
dead_cell: Cell,
|
|
||||||
width: usize,
|
|
||||||
height: usize,
|
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg_color: u32, entropy_interval: usize, frame_delay: usize, initial_density: f32) !GameOfLife {
|
|
||||||
const width = terminal_buffer.width;
|
|
||||||
const height = terminal_buffer.height;
|
|
||||||
const grid_size = width * height;
|
|
||||||
|
|
||||||
const current_grid = try allocator.alloc(bool, grid_size);
|
|
||||||
const next_grid = try allocator.alloc(bool, grid_size);
|
|
||||||
|
|
||||||
var game = GameOfLife{
|
|
||||||
.allocator = allocator,
|
|
||||||
.terminal_buffer = terminal_buffer,
|
|
||||||
.current_grid = current_grid,
|
|
||||||
.next_grid = next_grid,
|
|
||||||
.frame_counter = 0,
|
|
||||||
.generation = 0,
|
|
||||||
.fg_color = fg_color,
|
|
||||||
.entropy_interval = entropy_interval,
|
|
||||||
.frame_delay = frame_delay,
|
|
||||||
.initial_density = initial_density,
|
|
||||||
.dead_cell = .{ .ch = DEAD_CHAR, .fg = @intCast(TerminalBuffer.Color.DEFAULT), .bg = terminal_buffer.bg },
|
|
||||||
.width = width,
|
|
||||||
.height = height,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize grid
|
|
||||||
game.initializeGrid();
|
|
||||||
|
|
||||||
return game;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn animation(self: *GameOfLife) Animation {
|
|
||||||
return Animation.init(self, deinit, realloc, draw);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deinit(self: *GameOfLife) void {
|
|
||||||
self.allocator.free(self.current_grid);
|
|
||||||
self.allocator.free(self.next_grid);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn realloc(self: *GameOfLife) anyerror!void {
|
|
||||||
const new_width = self.terminal_buffer.width;
|
|
||||||
const new_height = self.terminal_buffer.height;
|
|
||||||
const new_size = new_width * new_height;
|
|
||||||
|
|
||||||
const current_grid = try self.allocator.realloc(self.current_grid, new_size);
|
|
||||||
const next_grid = try self.allocator.realloc(self.next_grid, new_size);
|
|
||||||
|
|
||||||
self.current_grid = current_grid;
|
|
||||||
self.next_grid = next_grid;
|
|
||||||
self.width = new_width;
|
|
||||||
self.height = new_height;
|
|
||||||
|
|
||||||
self.initializeGrid();
|
|
||||||
self.generation = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw(self: *GameOfLife) void {
|
|
||||||
// Update game state at controlled frame rate
|
|
||||||
self.frame_counter += 1;
|
|
||||||
if (self.frame_counter >= self.frame_delay) {
|
|
||||||
self.frame_counter = 0;
|
|
||||||
self.updateGeneration();
|
|
||||||
self.generation += 1;
|
|
||||||
|
|
||||||
// Add entropy based on configuration (0 = disabled, >0 = interval)
|
|
||||||
if (self.entropy_interval > 0 and self.generation % self.entropy_interval == 0) {
|
|
||||||
self.addEntropy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render with the configured color
|
|
||||||
const alive_cell = Cell{ .ch = ALIVE_CHAR, .fg = self.fg_color, .bg = self.terminal_buffer.bg };
|
|
||||||
|
|
||||||
for (0..self.height) |y| {
|
|
||||||
const row_offset = y * self.width;
|
|
||||||
for (0..self.width) |x| {
|
|
||||||
const cell = if (self.current_grid[row_offset + x]) alive_cell else self.dead_cell;
|
|
||||||
cell.put(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn updateGeneration(self: *GameOfLife) void {
|
|
||||||
// Conway's Game of Life rules with optimized neighbor counting
|
|
||||||
for (0..self.height) |y| {
|
|
||||||
const row_offset = y * self.width;
|
|
||||||
for (0..self.width) |x| {
|
|
||||||
const index = row_offset + x;
|
|
||||||
const neighbors = self.countNeighborsOptimized(x, y);
|
|
||||||
const is_alive = self.current_grid[index];
|
|
||||||
|
|
||||||
// Optimized rule application
|
|
||||||
self.next_grid[index] = switch (neighbors) {
|
|
||||||
2 => is_alive,
|
|
||||||
3 => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Efficient grid swap
|
|
||||||
std.mem.swap([]bool, &self.current_grid, &self.next_grid);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn countNeighborsOptimized(self: *GameOfLife, x: usize, y: usize) u8 {
|
|
||||||
var count: u8 = 0;
|
|
||||||
|
|
||||||
for (NEIGHBOR_DIRS) |dir| {
|
|
||||||
const neighbor_x = @as(i32, @intCast(x)) + dir[0];
|
|
||||||
const neighbor_y = @as(i32, @intCast(y)) + dir[1];
|
|
||||||
const width_i32: i32 = @intCast(self.width);
|
|
||||||
const height_i32: i32 = @intCast(self.height);
|
|
||||||
|
|
||||||
// Toroidal wrapping with modular arithmetic
|
|
||||||
const wx: usize = @intCast(@mod(neighbor_x + width_i32, width_i32));
|
|
||||||
const wy: usize = @intCast(@mod(neighbor_y + height_i32, height_i32));
|
|
||||||
|
|
||||||
if (self.current_grid[wy * self.width + wx]) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn initializeGrid(self: *GameOfLife) void {
|
|
||||||
const total_cells = self.width * self.height;
|
|
||||||
|
|
||||||
// Clear grid
|
|
||||||
@memset(self.current_grid, false);
|
|
||||||
@memset(self.next_grid, false);
|
|
||||||
|
|
||||||
// Random initialization with configurable density
|
|
||||||
for (0..total_cells) |i| {
|
|
||||||
self.current_grid[i] = self.terminal_buffer.random.float(f32) < self.initial_density;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn addEntropy(self: *GameOfLife) void {
|
|
||||||
// Add fewer random cells but in clusters for more interesting patterns
|
|
||||||
const clusters = 2;
|
|
||||||
for (0..clusters) |_| {
|
|
||||||
const cx = self.terminal_buffer.random.intRangeAtMost(usize, 1, self.width - 2);
|
|
||||||
const cy = self.terminal_buffer.random.intRangeAtMost(usize, 1, self.height - 2);
|
|
||||||
|
|
||||||
// Small cluster around center point
|
|
||||||
for (0..3) |dy| {
|
|
||||||
for (0..3) |dx| {
|
|
||||||
if (self.terminal_buffer.random.float(f32) < 0.4) {
|
|
||||||
const x = (cx + dx) % self.width;
|
|
||||||
const y = (cy + dy) % self.height;
|
|
||||||
self.current_grid[y * self.width + x] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,6 +11,8 @@ pub const FRAME_DELAY: usize = 8;
|
|||||||
// Characters change mid-scroll
|
// Characters change mid-scroll
|
||||||
pub const MID_SCROLL_CHANGE = true;
|
pub const MID_SCROLL_CHANGE = true;
|
||||||
|
|
||||||
|
const DOT_HEAD_COLOR: u32 = @intCast(TerminalBuffer.Color.WHITE | TerminalBuffer.Styling.BOLD);
|
||||||
|
|
||||||
const Matrix = @This();
|
const Matrix = @This();
|
||||||
|
|
||||||
pub const Dot = struct {
|
pub const Dot = struct {
|
||||||
@@ -31,12 +33,11 @@ lines: []Line,
|
|||||||
frame: usize,
|
frame: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
fg: u32,
|
fg: u32,
|
||||||
head_col: u32,
|
|
||||||
min_codepoint: u16,
|
min_codepoint: u16,
|
||||||
max_codepoint: u16,
|
max_codepoint: u16,
|
||||||
default_cell: Cell,
|
default_cell: Cell,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg: u32, head_col: u32, min_codepoint: u16, max_codepoint: u16) !Matrix {
|
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg: u32, min_codepoint: u16, max_codepoint: u16) !Matrix {
|
||||||
const dots = try allocator.alloc(Dot, terminal_buffer.width * (terminal_buffer.height + 1));
|
const dots = try allocator.alloc(Dot, terminal_buffer.width * (terminal_buffer.height + 1));
|
||||||
const lines = try allocator.alloc(Line, terminal_buffer.width);
|
const lines = try allocator.alloc(Line, terminal_buffer.width);
|
||||||
|
|
||||||
@@ -50,7 +51,6 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fg: u32, hea
|
|||||||
.frame = 3,
|
.frame = 3,
|
||||||
.count = 0,
|
.count = 0,
|
||||||
.fg = fg,
|
.fg = fg,
|
||||||
.head_col = head_col,
|
|
||||||
.min_codepoint = min_codepoint,
|
.min_codepoint = min_codepoint,
|
||||||
.max_codepoint = max_codepoint - min_codepoint,
|
.max_codepoint = max_codepoint - min_codepoint,
|
||||||
.default_cell = .{ .ch = ' ', .fg = fg, .bg = terminal_buffer.bg },
|
.default_cell = .{ .ch = ' ', .fg = fg, .bg = terminal_buffer.bg },
|
||||||
@@ -157,13 +157,11 @@ fn draw(self: *Matrix) void {
|
|||||||
const dot = self.dots[buf_width * y + x];
|
const dot = self.dots[buf_width * y + x];
|
||||||
const cell = if (dot.value == null or dot.value == ' ') self.default_cell else Cell{
|
const cell = if (dot.value == null or dot.value == ' ') self.default_cell else Cell{
|
||||||
.ch = @intCast(dot.value.?),
|
.ch = @intCast(dot.value.?),
|
||||||
.fg = if (dot.is_head) self.head_col else self.fg,
|
.fg = if (dot.is_head) DOT_HEAD_COLOR else self.fg,
|
||||||
.bg = self.terminal_buffer.bg,
|
.bg = self.terminal_buffer.bg,
|
||||||
};
|
};
|
||||||
|
|
||||||
cell.put(x, y - 1);
|
cell.put(x, y - 1);
|
||||||
// Fill background in between columns
|
|
||||||
self.default_cell.put(x + 1, y - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
352
src/auth.zig
352
src/auth.zig
@@ -5,8 +5,8 @@ const enums = @import("enums.zig");
|
|||||||
const Environment = @import("Environment.zig");
|
const Environment = @import("Environment.zig");
|
||||||
const interop = @import("interop.zig");
|
const interop = @import("interop.zig");
|
||||||
const SharedError = @import("SharedError.zig");
|
const SharedError = @import("SharedError.zig");
|
||||||
const LogFile = @import("LogFile.zig");
|
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
const Md5 = std.crypto.hash.Md5;
|
const Md5 = std.crypto.hash.Md5;
|
||||||
const utmp = interop.utmp;
|
const utmp = interop.utmp;
|
||||||
const Utmp = utmp.utmpx;
|
const Utmp = utmp.utmpx;
|
||||||
@@ -14,8 +14,8 @@ const Utmp = utmp.utmpx;
|
|||||||
pub const AuthOptions = struct {
|
pub const AuthOptions = struct {
|
||||||
tty: u8,
|
tty: u8,
|
||||||
service_name: [:0]const u8,
|
service_name: [:0]const u8,
|
||||||
path: ?[]const u8,
|
path: ?[:0]const u8,
|
||||||
session_log: ?[]const u8,
|
session_log: []const u8,
|
||||||
xauth_cmd: []const u8,
|
xauth_cmd: []const u8,
|
||||||
setup_cmd: []const u8,
|
setup_cmd: []const u8,
|
||||||
login_cmd: ?[]const u8,
|
login_cmd: ?[]const u8,
|
||||||
@@ -24,33 +24,28 @@ pub const AuthOptions = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var xorg_pid: std.posix.pid_t = 0;
|
var xorg_pid: std.posix.pid_t = 0;
|
||||||
pub fn xorgSignalHandler(i: c_int) callconv(.c) void {
|
pub fn xorgSignalHandler(i: c_int) callconv(.C) void {
|
||||||
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
|
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
var child_pid: std.posix.pid_t = 0;
|
var child_pid: std.posix.pid_t = 0;
|
||||||
pub fn sessionSignalHandler(i: c_int) callconv(.c) void {
|
pub fn sessionSignalHandler(i: c_int) callconv(.C) void {
|
||||||
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn authenticate(allocator: std.mem.Allocator, log_file: *LogFile, options: AuthOptions, current_environment: Environment, login: []const u8, password: []const u8) !void {
|
pub fn authenticate(options: AuthOptions, current_environment: Environment, login: [:0]const u8, password: [:0]const u8) !void {
|
||||||
var tty_buffer: [3]u8 = undefined;
|
var tty_buffer: [3]u8 = undefined;
|
||||||
const tty_str = try std.fmt.bufPrint(&tty_buffer, "{d}", .{options.tty});
|
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{options.tty});
|
||||||
|
|
||||||
var pam_tty_buffer: [6]u8 = undefined;
|
var pam_tty_buffer: [6]u8 = undefined;
|
||||||
const pam_tty_str = try std.fmt.bufPrintZ(&pam_tty_buffer, "tty{d}", .{options.tty});
|
const pam_tty_str = try std.fmt.bufPrintZ(&pam_tty_buffer, "tty{d}", .{options.tty});
|
||||||
|
|
||||||
// Set the XDG environment variables
|
// Set the XDG environment variables
|
||||||
try setXdgEnv(allocator, tty_str, current_environment);
|
setXdgSessionEnv(current_environment.display_server);
|
||||||
|
try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names);
|
||||||
|
|
||||||
// Open the PAM session
|
// Open the PAM session
|
||||||
const login_z = try allocator.dupeZ(u8, login);
|
var credentials = [_:null]?[*:0]const u8{ login, password };
|
||||||
defer allocator.free(login_z);
|
|
||||||
|
|
||||||
const password_z = try allocator.dupeZ(u8, password);
|
|
||||||
defer allocator.free(password_z);
|
|
||||||
|
|
||||||
var credentials = [_:null]?[*:0]const u8{ login_z, password_z };
|
|
||||||
|
|
||||||
const conv = interop.pam.pam_conv{
|
const conv = interop.pam.pam_conv{
|
||||||
.conv = loginConv,
|
.conv = loginConv,
|
||||||
@@ -58,68 +53,53 @@ pub fn authenticate(allocator: std.mem.Allocator, log_file: *LogFile, options: A
|
|||||||
};
|
};
|
||||||
var handle: ?*interop.pam.pam_handle = undefined;
|
var handle: ?*interop.pam.pam_handle = undefined;
|
||||||
|
|
||||||
var log_writer = &log_file.file_writer.interface;
|
|
||||||
|
|
||||||
try log_writer.writeAll("[pam] starting session\n");
|
|
||||||
var status = interop.pam.pam_start(options.service_name, null, &conv, &handle);
|
var status = interop.pam.pam_start(options.service_name, null, &conv, &handle);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer _ = interop.pam.pam_end(handle, status);
|
defer _ = interop.pam.pam_end(handle, status);
|
||||||
|
|
||||||
// Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module
|
// Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module
|
||||||
try log_writer.writeAll("[pam] setting tty\n");
|
|
||||||
status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr);
|
status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
// Do the PAM routine
|
// Do the PAM routine
|
||||||
try log_writer.writeAll("[pam] authenticating\n");
|
|
||||||
status = interop.pam.pam_authenticate(handle, 0);
|
status = interop.pam.pam_authenticate(handle, 0);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
try log_writer.writeAll("[pam] validating account\n");
|
|
||||||
status = interop.pam.pam_acct_mgmt(handle, 0);
|
status = interop.pam.pam_acct_mgmt(handle, 0);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
|
|
||||||
try log_writer.writeAll("[pam] setting credentials\n");
|
|
||||||
status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED);
|
status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED);
|
defer status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED);
|
||||||
|
|
||||||
try log_writer.writeAll("[pam] opening session\n");
|
|
||||||
status = interop.pam.pam_open_session(handle, 0);
|
status = interop.pam.pam_open_session(handle, 0);
|
||||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||||
defer status = interop.pam.pam_close_session(handle, 0);
|
defer status = interop.pam.pam_close_session(handle, 0);
|
||||||
|
|
||||||
var user_entry: interop.UsernameEntry = undefined;
|
var pwd: *interop.pwd.passwd = undefined;
|
||||||
{
|
{
|
||||||
defer interop.closePasswordDatabase();
|
defer interop.pwd.endpwent();
|
||||||
|
|
||||||
// Get password structure from username
|
// Get password structure from username
|
||||||
user_entry = interop.getUsernameEntry(login_z) orelse return error.GetPasswordNameFailed;
|
pwd = interop.pwd.getpwnam(login) orelse return error.GetPasswordNameFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set user shell if it hasn't already been set
|
// Set user shell if it hasn't already been set
|
||||||
if (user_entry.shell == null) interop.setUserShell(&user_entry);
|
if (pwd.pw_shell == null) {
|
||||||
|
interop.unistd.setusershell();
|
||||||
|
pwd.pw_shell = interop.unistd.getusershell();
|
||||||
|
interop.unistd.endusershell();
|
||||||
|
}
|
||||||
|
|
||||||
var shared_err = try SharedError.init();
|
var shared_err = try SharedError.init();
|
||||||
defer shared_err.deinit();
|
defer shared_err.deinit();
|
||||||
|
|
||||||
log_file.deinit();
|
|
||||||
|
|
||||||
child_pid = try std.posix.fork();
|
child_pid = try std.posix.fork();
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
try log_file.reinit();
|
startSession(options, tty_str, pwd, handle, current_environment) catch |e| {
|
||||||
log_writer = &log_file.file_writer.interface;
|
|
||||||
|
|
||||||
try log_writer.writeAll("starting session\n");
|
|
||||||
|
|
||||||
startSession(log_file, allocator, options, tty_str, user_entry, handle, current_environment) catch |e| {
|
|
||||||
shared_err.writeError(e);
|
shared_err.writeError(e);
|
||||||
|
|
||||||
log_file.deinit();
|
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
log_file.deinit();
|
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,113 +108,123 @@ pub fn authenticate(allocator: std.mem.Allocator, log_file: *LogFile, options: A
|
|||||||
{
|
{
|
||||||
// If an error occurs here, we can send SIGTERM to the session
|
// If an error occurs here, we can send SIGTERM to the session
|
||||||
errdefer cleanup: {
|
errdefer cleanup: {
|
||||||
std.posix.kill(child_pid, std.posix.SIG.TERM) catch break :cleanup;
|
_ = std.posix.kill(child_pid, std.posix.SIG.TERM) catch break :cleanup;
|
||||||
_ = std.posix.waitpid(child_pid, 0);
|
_ = std.posix.waitpid(child_pid, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we receive SIGTERM, forward it to child_pid
|
// If we receive SIGTERM, forward it to child_pid
|
||||||
const act = std.posix.Sigaction{
|
const act = std.posix.Sigaction{
|
||||||
.handler = .{ .handler = &sessionSignalHandler },
|
.handler = .{ .handler = &sessionSignalHandler },
|
||||||
.mask = std.posix.sigemptyset(),
|
.mask = std.posix.empty_sigset,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
||||||
|
|
||||||
try addUtmpEntry(&entry, user_entry.username.?, child_pid);
|
try addUtmpEntry(&entry, pwd.pw_name.?, child_pid);
|
||||||
}
|
}
|
||||||
// Wait for the session to stop
|
// Wait for the session to stop
|
||||||
_ = std.posix.waitpid(child_pid, 0);
|
_ = std.posix.waitpid(child_pid, 0);
|
||||||
|
|
||||||
try log_file.reinit();
|
|
||||||
|
|
||||||
removeUtmpEntry(&entry);
|
removeUtmpEntry(&entry);
|
||||||
|
|
||||||
if (shared_err.readError()) |err| return err;
|
if (shared_err.readError()) |err| return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startSession(
|
fn startSession(
|
||||||
log_file: *LogFile,
|
|
||||||
allocator: std.mem.Allocator,
|
|
||||||
options: AuthOptions,
|
options: AuthOptions,
|
||||||
tty_str: []u8,
|
tty_str: [:0]u8,
|
||||||
user_entry: interop.UsernameEntry,
|
pwd: *interop.pwd.passwd,
|
||||||
handle: ?*interop.pam.pam_handle,
|
handle: ?*interop.pam.pam_handle,
|
||||||
current_environment: Environment,
|
current_environment: Environment,
|
||||||
) !void {
|
) !void {
|
||||||
// Set the user's GID & PID
|
if (builtin.os.tag == .freebsd) {
|
||||||
try interop.setUserContext(allocator, user_entry);
|
// FreeBSD has initgroups() in unistd
|
||||||
|
const status = interop.unistd.initgroups(pwd.pw_name, pwd.pw_gid);
|
||||||
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
|
|
||||||
|
// FreeBSD sets the GID and UID with setusercontext()
|
||||||
|
const result = interop.pwd.setusercontext(null, pwd, pwd.pw_uid, interop.pwd.LOGIN_SETALL);
|
||||||
|
if (result != 0) return error.SetUserUidFailed;
|
||||||
|
} else {
|
||||||
|
const status = interop.grp.initgroups(pwd.pw_name, pwd.pw_gid);
|
||||||
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
|
|
||||||
|
std.posix.setgid(pwd.pw_gid) catch return error.SetUserGidFailed;
|
||||||
|
std.posix.setuid(pwd.pw_uid) catch return error.SetUserUidFailed;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the environment
|
// Set up the environment
|
||||||
try initEnv(allocator, user_entry, options.path);
|
try initEnv(pwd, options.path);
|
||||||
|
|
||||||
// Reset the XDG environment variables
|
// Reset the XDG environment variables
|
||||||
try setXdgEnv(allocator, tty_str, current_environment);
|
setXdgSessionEnv(current_environment.display_server);
|
||||||
|
try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names);
|
||||||
|
|
||||||
// Set the PAM variables
|
// Set the PAM variables
|
||||||
const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle);
|
const pam_env_vars: ?[*:null]?[*:0]u8 = interop.pam.pam_getenvlist(handle);
|
||||||
if (pam_env_vars == null) return error.GetEnvListFailed;
|
if (pam_env_vars == null) return error.GetEnvListFailed;
|
||||||
|
|
||||||
const env_list = std.mem.span(pam_env_vars.?);
|
const env_list = std.mem.span(pam_env_vars.?);
|
||||||
for (env_list) |env_var| try interop.putEnvironmentVariable(env_var);
|
for (env_list) |env_var| _ = interop.stdlib.putenv(env_var);
|
||||||
|
|
||||||
// Change to the user's home directory
|
// Change to the user's home directory
|
||||||
std.posix.chdir(user_entry.home.?) catch return error.ChangeDirectoryFailed;
|
std.posix.chdirZ(pwd.pw_dir.?) catch return error.ChangeDirectoryFailed;
|
||||||
|
|
||||||
// Signal to the session process to give up control on the TTY
|
// Signal to the session process to give up control on the TTY
|
||||||
std.posix.kill(options.session_pid, std.posix.SIG.CHLD) catch return error.TtyControlTransferFailed;
|
_ = std.posix.kill(options.session_pid, std.posix.SIG.CHLD) catch return error.TtyControlTransferFailed;
|
||||||
|
|
||||||
// Execute what the user requested
|
// Execute what the user requested
|
||||||
switch (current_environment.display_server) {
|
switch (current_environment.display_server) {
|
||||||
.wayland, .shell, .custom => try executeCmd(log_file, allocator, user_entry.shell.?, options, current_environment.is_terminal, current_environment.cmd),
|
.wayland => try executeWaylandCmd(pwd.pw_shell.?, options, current_environment.cmd),
|
||||||
|
.shell => try executeShellCmd(pwd.pw_shell.?, options),
|
||||||
.xinitrc, .x11 => if (build_options.enable_x11_support) {
|
.xinitrc, .x11 => if (build_options.enable_x11_support) {
|
||||||
var vt_buf: [5]u8 = undefined;
|
var vt_buf: [5]u8 = undefined;
|
||||||
const vt = try std.fmt.bufPrint(&vt_buf, "vt{d}", .{options.tty});
|
const vt = try std.fmt.bufPrint(&vt_buf, "vt{d}", .{options.tty});
|
||||||
try executeX11Cmd(log_file, allocator, user_entry.shell.?, user_entry.home.?, options, current_environment.cmd orelse "", vt);
|
try executeX11Cmd(pwd.pw_shell.?, pwd.pw_dir.?, options, current_environment.cmd, vt);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initEnv(allocator: std.mem.Allocator, entry: interop.UsernameEntry, path_env: ?[]const u8) !void {
|
fn initEnv(pwd: *interop.pwd.passwd, path_env: ?[:0]const u8) !void {
|
||||||
if (entry.home) |home| {
|
_ = interop.stdlib.setenv("HOME", pwd.pw_dir, 1);
|
||||||
try interop.setEnvironmentVariable(allocator, "HOME", home, true);
|
_ = interop.stdlib.setenv("PWD", pwd.pw_dir, 1);
|
||||||
try interop.setEnvironmentVariable(allocator, "PWD", home, true);
|
_ = interop.stdlib.setenv("SHELL", pwd.pw_shell, 1);
|
||||||
} else return error.NoHomeDirectory;
|
_ = interop.stdlib.setenv("USER", pwd.pw_name, 1);
|
||||||
|
_ = interop.stdlib.setenv("LOGNAME", pwd.pw_name, 1);
|
||||||
try interop.setEnvironmentVariable(allocator, "SHELL", entry.shell.?, true);
|
|
||||||
try interop.setEnvironmentVariable(allocator, "USER", entry.username.?, true);
|
|
||||||
try interop.setEnvironmentVariable(allocator, "LOGNAME", entry.username.?, true);
|
|
||||||
|
|
||||||
if (path_env) |path| {
|
if (path_env) |path| {
|
||||||
interop.setEnvironmentVariable(allocator, "PATH", path, true) catch return error.SetPathFailed;
|
const status = interop.stdlib.setenv("PATH", path, 1);
|
||||||
|
if (status != 0) return error.SetPathFailed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setXdgEnv(allocator: std.mem.Allocator, tty_str: []u8, environment: Environment) !void {
|
fn setXdgSessionEnv(display_server: enums.DisplayServer) void {
|
||||||
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_TYPE", switch (environment.display_server) {
|
_ = interop.stdlib.setenv("XDG_SESSION_TYPE", switch (display_server) {
|
||||||
.wayland => "wayland",
|
.wayland => "wayland",
|
||||||
.shell => "tty",
|
.shell => "tty",
|
||||||
.xinitrc, .x11 => "x11",
|
.xinitrc, .x11 => "x11",
|
||||||
.custom => if (environment.is_terminal) "tty" else "unspecified",
|
}, 0);
|
||||||
}, false);
|
}
|
||||||
|
|
||||||
|
fn setXdgEnv(tty_str: [:0]u8, maybe_desktop_name: ?[:0]const u8, maybe_xdg_desktop_names: ?[:0]const u8) !void {
|
||||||
// The "/run/user/%d" directory is not available on FreeBSD. It is much
|
// The "/run/user/%d" directory is not available on FreeBSD. It is much
|
||||||
// better to stick to the defaults and let applications using
|
// better to stick to the defaults and let applications using
|
||||||
// XDG_RUNTIME_DIR to fall back to directories inside user's home
|
// XDG_RUNTIME_DIR to fall back to directories inside user's home
|
||||||
// directory.
|
// directory.
|
||||||
if (builtin.os.tag != .freebsd) {
|
if (builtin.os.tag != .freebsd) {
|
||||||
const uid = std.posix.getuid();
|
const uid = interop.unistd.getuid();
|
||||||
var uid_buffer: [32]u8 = undefined; // No UID can be larger than this
|
var uid_buffer: [10 + @sizeOf(u32) + 1]u8 = undefined;
|
||||||
const uid_str = try std.fmt.bufPrint(&uid_buffer, "/run/user/{d}", .{uid});
|
const uid_str = try std.fmt.bufPrintZ(&uid_buffer, "/run/user/{d}", .{uid});
|
||||||
|
|
||||||
try interop.setEnvironmentVariable(allocator, "XDG_RUNTIME_DIR", uid_str, false);
|
_ = interop.stdlib.setenv("XDG_RUNTIME_DIR", uid_str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (environment.xdg_desktop_names) |xdg_desktop_names| try interop.setEnvironmentVariable(allocator, "XDG_CURRENT_DESKTOP", xdg_desktop_names, false);
|
if (maybe_xdg_desktop_names) |xdg_desktop_names| _ = interop.stdlib.setenv("XDG_CURRENT_DESKTOP", xdg_desktop_names, 0);
|
||||||
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_CLASS", "user", false);
|
_ = interop.stdlib.setenv("XDG_SESSION_CLASS", "user", 0);
|
||||||
try interop.setEnvironmentVariable(allocator, "XDG_SESSION_ID", "1", false);
|
_ = interop.stdlib.setenv("XDG_SESSION_ID", "1", 0);
|
||||||
if (environment.xdg_session_desktop) |desktop_name| try interop.setEnvironmentVariable(allocator, "XDG_SESSION_DESKTOP", desktop_name, false);
|
if (maybe_desktop_name) |desktop_name| _ = interop.stdlib.setenv("XDG_SESSION_DESKTOP", desktop_name, 0);
|
||||||
try interop.setEnvironmentVariable(allocator, "XDG_SEAT", "seat0", false);
|
_ = interop.stdlib.setenv("XDG_SEAT", "seat0", 0);
|
||||||
try interop.setEnvironmentVariable(allocator, "XDG_VTNR", tty_str, false);
|
_ = interop.stdlib.setenv("XDG_VTNR", tty_str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loginConv(
|
fn loginConv(
|
||||||
@@ -242,7 +232,7 @@ fn loginConv(
|
|||||||
msg: ?[*]?*const interop.pam.pam_message,
|
msg: ?[*]?*const interop.pam.pam_message,
|
||||||
resp: ?*?[*]interop.pam.pam_response,
|
resp: ?*?[*]interop.pam.pam_response,
|
||||||
appdata_ptr: ?*anyopaque,
|
appdata_ptr: ?*anyopaque,
|
||||||
) callconv(.c) c_int {
|
) callconv(.C) c_int {
|
||||||
const message_count: u32 = @intCast(num_msg);
|
const message_count: u32 = @intCast(num_msg);
|
||||||
const messages = msg.?;
|
const messages = msg.?;
|
||||||
|
|
||||||
@@ -286,8 +276,8 @@ fn loginConv(
|
|||||||
if (status != interop.pam.PAM_SUCCESS) {
|
if (status != interop.pam.PAM_SUCCESS) {
|
||||||
// Memory is freed by pam otherwise
|
// Memory is freed by pam otherwise
|
||||||
allocator.free(response);
|
allocator.free(response);
|
||||||
if (username) |str| allocator.free(str);
|
if (username != null) allocator.free(username.?);
|
||||||
if (password) |str| allocator.free(str);
|
if (password != null) allocator.free(password.?);
|
||||||
} else {
|
} else {
|
||||||
resp.?.* = response.ptr;
|
resp.?.* = response.ptr;
|
||||||
}
|
}
|
||||||
@@ -311,50 +301,46 @@ fn getXPid(display_num: u8) !i32 {
|
|||||||
const file = try std.fs.openFileAbsolute(file_name, .{});
|
const file = try std.fs.openFileAbsolute(file_name, .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var file_buffer: [32]u8 = undefined;
|
var file_buf: [20]u8 = undefined;
|
||||||
var file_reader = file.reader(&file_buffer);
|
var fbs = std.io.fixedBufferStream(&file_buf);
|
||||||
var reader = &file_reader.interface;
|
|
||||||
|
|
||||||
var buffer: [20]u8 = undefined;
|
_ = try file.reader().streamUntilDelimiter(fbs.writer(), '\n', 20);
|
||||||
var writer = std.Io.Writer.fixed(&buffer);
|
const line = fbs.getWritten();
|
||||||
|
|
||||||
const written = try reader.streamDelimiter(&writer, '\n');
|
return std.fmt.parseInt(i32, std.mem.trim(u8, line, " "), 10);
|
||||||
return std.fmt.parseInt(i32, std.mem.trim(u8, buffer[0..written], " "), 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createXauthFile(pwd: []const u8, buffer: []u8) ![]const u8 {
|
fn createXauthFile(pwd: [:0]const u8) ![:0]const u8 {
|
||||||
var xauth_buf: [100]u8 = undefined;
|
var xauth_buf: [100]u8 = undefined;
|
||||||
var xauth_dir: []const u8 = undefined;
|
var xauth_dir: [:0]const u8 = undefined;
|
||||||
const xdg_rt_dir = std.posix.getenv("XDG_RUNTIME_DIR");
|
const xdg_rt_dir = std.posix.getenv("XDG_RUNTIME_DIR");
|
||||||
var xauth_file: []const u8 = "lyxauth";
|
var xauth_file: []const u8 = "lyxauth";
|
||||||
|
|
||||||
if (xdg_rt_dir == null) no_rt_dir: {
|
if (xdg_rt_dir == null) {
|
||||||
const xdg_cfg_home = std.posix.getenv("XDG_CONFIG_HOME");
|
const xdg_cfg_home = std.posix.getenv("XDG_CONFIG_HOME");
|
||||||
if (xdg_cfg_home == null) no_cfg_home: {
|
var sb: std.c.Stat = undefined;
|
||||||
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/.config", .{pwd});
|
if (xdg_cfg_home == null) {
|
||||||
|
xauth_dir = try std.fmt.bufPrintZ(&xauth_buf, "{s}/.config", .{pwd});
|
||||||
var dir = std.fs.cwd().openDir(xauth_dir, .{}) catch {
|
_ = std.c.stat(xauth_dir, &sb);
|
||||||
// xauth_dir isn't a directory
|
const mode = sb.mode & std.posix.S.IFMT;
|
||||||
|
if (mode == std.posix.S.IFDIR) {
|
||||||
|
xauth_dir = try std.fmt.bufPrintZ(&xauth_buf, "{s}/ly", .{xauth_dir});
|
||||||
|
} else {
|
||||||
xauth_dir = pwd;
|
xauth_dir = pwd;
|
||||||
xauth_file = ".lyxauth";
|
xauth_file = ".lyxauth";
|
||||||
break :no_cfg_home;
|
}
|
||||||
};
|
|
||||||
dir.close();
|
|
||||||
|
|
||||||
// xauth_dir is a directory, use it to store Xauthority
|
|
||||||
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/ly", .{xauth_dir});
|
|
||||||
} else {
|
} else {
|
||||||
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/ly", .{xdg_cfg_home.?});
|
xauth_dir = try std.fmt.bufPrintZ(&xauth_buf, "{s}/ly", .{xdg_cfg_home.?});
|
||||||
}
|
}
|
||||||
|
|
||||||
const file = std.fs.cwd().openFile(xauth_dir, .{}) catch break :no_rt_dir;
|
_ = std.c.stat(xauth_dir, &sb);
|
||||||
file.close();
|
const mode = sb.mode & std.posix.S.IFMT;
|
||||||
|
if (mode != std.posix.S.IFDIR) {
|
||||||
// xauth_dir is a file, create the parent directory
|
std.posix.mkdir(xauth_dir, 777) catch {
|
||||||
std.posix.mkdir(xauth_dir, 777) catch {
|
xauth_dir = pwd;
|
||||||
xauth_dir = pwd;
|
xauth_file = ".lyxauth";
|
||||||
xauth_file = ".lyxauth";
|
};
|
||||||
};
|
}
|
||||||
} else {
|
} else {
|
||||||
xauth_dir = xdg_rt_dir.?;
|
xauth_dir = xdg_rt_dir.?;
|
||||||
}
|
}
|
||||||
@@ -364,8 +350,9 @@ fn createXauthFile(pwd: []const u8, buffer: []u8) ![]const u8 {
|
|||||||
while (xauth_dir[i] == '/') i -= 1;
|
while (xauth_dir[i] == '/') i -= 1;
|
||||||
const trimmed_xauth_dir = xauth_dir[0 .. i + 1];
|
const trimmed_xauth_dir = xauth_dir[0 .. i + 1];
|
||||||
|
|
||||||
const xauthority: []u8 = try std.fmt.bufPrint(buffer, "{s}/{s}", .{ trimmed_xauth_dir, xauth_file });
|
var buf: [256]u8 = undefined;
|
||||||
const file = try std.fs.createFileAbsolute(xauthority, .{});
|
const xauthority: [:0]u8 = try std.fmt.bufPrintZ(&buf, "{s}/{s}", .{ trimmed_xauth_dir, xauth_file });
|
||||||
|
const file = try std.fs.createFileAbsoluteZ(xauthority, .{});
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return xauthority;
|
return xauthority;
|
||||||
@@ -381,10 +368,13 @@ fn mcookie() [Md5.digest_length * 2]u8 {
|
|||||||
return std.fmt.bytesToHex(&out, .lower);
|
return std.fmt.bytesToHex(&out, .lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xauth(log_file: *LogFile, allocator: std.mem.Allocator, display_name: []u8, shell: [*:0]const u8, home: []const u8, xauth_buffer: []u8, options: AuthOptions) !void {
|
fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, options: AuthOptions) !void {
|
||||||
const xauthority = try createXauthFile(home, xauth_buffer);
|
var pwd_buf: [100]u8 = undefined;
|
||||||
try interop.setEnvironmentVariable(allocator, "XAUTHORITY", xauthority, true);
|
const pwd = try std.fmt.bufPrintZ(&pwd_buf, "{s}", .{pw_dir});
|
||||||
try interop.setEnvironmentVariable(allocator, "DISPLAY", display_name, true);
|
|
||||||
|
const xauthority = try createXauthFile(pwd);
|
||||||
|
_ = interop.stdlib.setenv("XAUTHORITY", xauthority, 1);
|
||||||
|
_ = interop.stdlib.setenv("DISPLAY", display_name, 1);
|
||||||
|
|
||||||
const magic_cookie = mcookie();
|
const magic_cookie = mcookie();
|
||||||
|
|
||||||
@@ -392,42 +382,46 @@ fn xauth(log_file: *LogFile, allocator: std.mem.Allocator, display_name: []u8, s
|
|||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . {s}", .{ options.xauth_cmd, display_name, magic_cookie }) catch std.process.exit(1);
|
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . {s}", .{ options.xauth_cmd, display_name, magic_cookie }) catch std.process.exit(1);
|
||||||
|
|
||||||
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = std.posix.waitpid(pid, 0);
|
const status = std.posix.waitpid(pid, 0);
|
||||||
if (status.status != 0) {
|
if (status.status != 0) return error.XauthFailed;
|
||||||
try log_file.file_writer.interface.print("xauth command failed with status {d}\n", .{status.status});
|
|
||||||
return error.XauthFailed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executeX11Cmd(log_file: *LogFile, allocator: std.mem.Allocator, shell: []const u8, home: []const u8, options: AuthOptions, desktop_cmd: []const u8, vt: []const u8) !void {
|
fn executeShellCmd(shell: [*:0]const u8, options: AuthOptions) !void {
|
||||||
var log_writer = &log_file.file_writer.interface;
|
// We don't want to redirect stdout and stderr in a shell session
|
||||||
var xauth_buffer: [256]u8 = undefined;
|
|
||||||
|
|
||||||
try log_writer.writeAll("[x11] getting free display\n");
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", shell });
|
||||||
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
|
return std.posix.execveZ(shell, &args, std.c.environ);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn executeWaylandCmd(shell: [*:0]const u8, options: AuthOptions, desktop_cmd: []const u8) !void {
|
||||||
|
const log_file = try redirectStandardStreams(options.session_log, true);
|
||||||
|
defer log_file.close();
|
||||||
|
|
||||||
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
|
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", desktop_cmd });
|
||||||
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
|
return std.posix.execveZ(shell, &args, std.c.environ);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, options: AuthOptions, desktop_cmd: []const u8, vt: []const u8) !void {
|
||||||
const display_num = try getFreeDisplay();
|
const display_num = try getFreeDisplay();
|
||||||
var buf: [4]u8 = undefined;
|
var buf: [5]u8 = undefined;
|
||||||
const display_name = try std.fmt.bufPrint(&buf, ":{d}", .{display_num});
|
const display_name = try std.fmt.bufPrintZ(&buf, ":{d}", .{display_num});
|
||||||
|
try xauth(display_name, shell, pw_dir, options);
|
||||||
|
|
||||||
const shell_z = try allocator.dupeZ(u8, shell);
|
|
||||||
defer allocator.free(shell_z);
|
|
||||||
|
|
||||||
try log_writer.writeAll("[x11] creating xauth file\n");
|
|
||||||
try xauth(log_file, allocator, display_name, shell_z, home, &xauth_buffer, options);
|
|
||||||
|
|
||||||
try log_writer.writeAll("[x11] starting x server\n");
|
|
||||||
const pid = try std.posix.fork();
|
const pid = try std.posix.fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.x_cmd, display_name, vt }) catch std.process.exit(1);
|
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.x_cmd, display_name, vt }) catch std.process.exit(1);
|
||||||
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
const args = [_:null]?[*:0]const u8{ shell_z, "-c", cmd_str };
|
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||||
std.posix.execveZ(shell_z, &args, std.c.environ) catch {};
|
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,24 +437,21 @@ fn executeX11Cmd(log_file: *LogFile, allocator: std.mem.Allocator, shell: []cons
|
|||||||
|
|
||||||
// X Server detaches from the process.
|
// X Server detaches from the process.
|
||||||
// PID can be fetched from /tmp/X{d}.lock
|
// PID can be fetched from /tmp/X{d}.lock
|
||||||
try log_writer.writeAll("[x11] getting x server pid\n");
|
|
||||||
const x_pid = try getXPid(display_num);
|
const x_pid = try getXPid(display_num);
|
||||||
|
|
||||||
try log_writer.writeAll("[x11] launching environment\n");
|
|
||||||
xorg_pid = try std.posix.fork();
|
xorg_pid = try std.posix.fork();
|
||||||
if (xorg_pid == 0) {
|
if (xorg_pid == 0) {
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
var cmd_buffer: [1024]u8 = undefined;
|
||||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", desktop_cmd }) catch std.process.exit(1);
|
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", desktop_cmd }) catch std.process.exit(1);
|
||||||
|
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||||
const args = [_:null]?[*:0]const u8{ shell_z, "-c", cmd_str };
|
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||||
std.posix.execveZ(shell_z, &args, std.c.environ) catch {};
|
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we receive SIGTERM, clean up by killing the xorg_pid process
|
// If we receive SIGTERM, clean up by killing the xorg_pid process
|
||||||
const act = std.posix.Sigaction{
|
const act = std.posix.Sigaction{
|
||||||
.handler = .{ .handler = &xorgSignalHandler },
|
.handler = .{ .handler = &xorgSignalHandler },
|
||||||
.mask = std.posix.sigemptyset(),
|
.mask = std.posix.empty_sigset,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
||||||
@@ -468,44 +459,15 @@ fn executeX11Cmd(log_file: *LogFile, allocator: std.mem.Allocator, shell: []cons
|
|||||||
_ = std.posix.waitpid(xorg_pid, 0);
|
_ = std.posix.waitpid(xorg_pid, 0);
|
||||||
interop.xcb.xcb_disconnect(xcb);
|
interop.xcb.xcb_disconnect(xcb);
|
||||||
|
|
||||||
// TODO: Find a more robust way to ensure that X has been terminated (pidfds?)
|
std.posix.kill(x_pid, 0) catch return;
|
||||||
std.posix.kill(x_pid, std.posix.SIG.TERM) catch {};
|
std.posix.kill(x_pid, std.posix.SIG.KILL) catch {};
|
||||||
std.Thread.sleep(std.time.ns_per_s * 1); // Wait 1 second before sending SIGKILL
|
|
||||||
std.posix.kill(x_pid, std.posix.SIG.KILL) catch return;
|
|
||||||
|
|
||||||
_ = std.posix.waitpid(x_pid, 0);
|
var status: c_int = 0;
|
||||||
|
_ = std.c.waitpid(x_pid, &status, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn executeCmd(global_log_file: *LogFile, allocator: std.mem.Allocator, shell: []const u8, options: AuthOptions, is_terminal: bool, exec_cmd: ?[]const u8) !void {
|
fn redirectStandardStreams(session_log: []const u8, create: bool) !std.fs.File {
|
||||||
var maybe_log_file: ?std.fs.File = null;
|
const log_file = if (create) (try std.fs.cwd().createFile(session_log, .{ .mode = 0o666 })) else (try std.fs.cwd().openFile(session_log, .{ .mode = .read_write }));
|
||||||
if (!is_terminal) {
|
|
||||||
// For custom desktop entries, the "Terminal" value here determines if
|
|
||||||
// we redirect standard output & error or not. That is, we redirect only
|
|
||||||
// if it's equal to false (so if it's not running in a TTY).
|
|
||||||
if (options.session_log) |log_path| {
|
|
||||||
maybe_log_file = try redirectStandardStreams(global_log_file, log_path, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer if (maybe_log_file) |log_file| log_file.close();
|
|
||||||
|
|
||||||
const shell_z = try allocator.dupeZ(u8, shell);
|
|
||||||
defer allocator.free(shell_z);
|
|
||||||
|
|
||||||
var cmd_buffer: [1024]u8 = undefined;
|
|
||||||
const cmd_str = try std.fmt.bufPrintZ(&cmd_buffer, "{s} {s} {s}", .{ options.setup_cmd, options.login_cmd orelse "", exec_cmd orelse shell });
|
|
||||||
|
|
||||||
const args = [_:null]?[*:0]const u8{ shell_z, "-c", cmd_str };
|
|
||||||
return std.posix.execveZ(shell_z, &args, std.c.environ);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn redirectStandardStreams(global_log_file: *LogFile, session_log: []const u8, create: bool) !std.fs.File {
|
|
||||||
const log_file = if (create) (std.fs.cwd().createFile(session_log, .{ .mode = 0o666 }) catch |err| {
|
|
||||||
try global_log_file.file_writer.interface.print("failed to create new session log file: {s}\n", .{@errorName(err)});
|
|
||||||
return err;
|
|
||||||
}) else (std.fs.cwd().openFile(session_log, .{ .mode = .read_write }) catch |err| {
|
|
||||||
try global_log_file.file_writer.interface.print("failed to open existing session log file: {s}\n", .{@errorName(err)});
|
|
||||||
return err;
|
|
||||||
});
|
|
||||||
|
|
||||||
try std.posix.dup2(std.posix.STDOUT_FILENO, std.posix.STDERR_FILENO);
|
try std.posix.dup2(std.posix.STDOUT_FILENO, std.posix.STDERR_FILENO);
|
||||||
try std.posix.dup2(log_file.handle, std.posix.STDOUT_FILENO);
|
try std.posix.dup2(log_file.handle, std.posix.STDOUT_FILENO);
|
||||||
@@ -513,21 +475,18 @@ fn redirectStandardStreams(global_log_file: *LogFile, session_log: []const u8, c
|
|||||||
return log_file;
|
return log_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addUtmpEntry(entry: *Utmp, username: []const u8, pid: c_int) !void {
|
fn addUtmpEntry(entry: *Utmp, username: [*:0]const u8, pid: c_int) !void {
|
||||||
entry.ut_type = utmp.USER_PROCESS;
|
entry.ut_type = utmp.USER_PROCESS;
|
||||||
entry.ut_pid = pid;
|
entry.ut_pid = pid;
|
||||||
|
|
||||||
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
var buf: [4096]u8 = undefined;
|
||||||
const tty_path = try std.os.getFdPath(std.posix.STDIN_FILENO, &buf);
|
const ttyname = try std.os.getFdPath(std.posix.STDIN_FILENO, &buf);
|
||||||
|
|
||||||
// Get the TTY name (i.e. without the /dev/ prefix)
|
|
||||||
var ttyname_buf: [@sizeOf(@TypeOf(entry.ut_line))]u8 = undefined;
|
var ttyname_buf: [@sizeOf(@TypeOf(entry.ut_line))]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrintZ(&ttyname_buf, "{s}", .{tty_path["/dev/".len..]});
|
_ = try std.fmt.bufPrintZ(&ttyname_buf, "{s}", .{ttyname["/dev/".len..]});
|
||||||
|
|
||||||
entry.ut_line = ttyname_buf;
|
entry.ut_line = ttyname_buf;
|
||||||
// Get the TTY ID (i.e. without the tty prefix) and truncate it to the size
|
entry.ut_id = ttyname_buf["tty".len..7].*;
|
||||||
// of ut_id if necessary
|
|
||||||
entry.ut_id = ttyname_buf["tty".len..(@sizeOf(@TypeOf(entry.ut_id)) + "tty".len)].*;
|
|
||||||
|
|
||||||
var username_buf: [@sizeOf(@TypeOf(entry.ut_user))]u8 = undefined;
|
var username_buf: [@sizeOf(@TypeOf(entry.ut_user))]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrintZ(&username_buf, "{s}", .{username});
|
_ = try std.fmt.bufPrintZ(&username_buf, "{s}", .{username});
|
||||||
@@ -538,17 +497,14 @@ fn addUtmpEntry(entry: *Utmp, username: []const u8, pid: c_int) !void {
|
|||||||
host[0] = 0;
|
host[0] = 0;
|
||||||
entry.ut_host = host;
|
entry.ut_host = host;
|
||||||
|
|
||||||
const time = try interop.getTimeOfDay();
|
var tv: interop.system_time.timeval = undefined;
|
||||||
|
_ = interop.system_time.gettimeofday(&tv, null);
|
||||||
|
|
||||||
entry.ut_tv = .{
|
entry.ut_tv = .{
|
||||||
.tv_sec = @intCast(time.seconds),
|
.tv_sec = @intCast(tv.tv_sec),
|
||||||
.tv_usec = @intCast(time.microseconds),
|
.tv_usec = @intCast(tv.tv_usec),
|
||||||
};
|
};
|
||||||
|
entry.ut_addr_v6[0] = 0;
|
||||||
// FreeBSD doesn't have this field
|
|
||||||
if (builtin.os.tag == .linux) {
|
|
||||||
entry.ut_addr_v6[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
utmp.setutxent();
|
utmp.setutxent();
|
||||||
_ = utmp.pututxline(entry);
|
_ = utmp.pututxline(entry);
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ pub const WIDTH = Lang.WIDTH;
|
|||||||
pub const HEIGHT = Lang.HEIGHT;
|
pub const HEIGHT = Lang.HEIGHT;
|
||||||
pub const SIZE = Lang.SIZE;
|
pub const SIZE = Lang.SIZE;
|
||||||
|
|
||||||
pub fn clockCell(animate: bool, char: u8, fg: u32, bg: u32, bigclock: Bigclock) ![SIZE]Cell {
|
pub fn clockCell(animate: bool, char: u8, fg: u32, bg: u32, bigclock: Bigclock) [SIZE]Cell {
|
||||||
var cells: [SIZE]Cell = undefined;
|
var cells: [SIZE]Cell = undefined;
|
||||||
|
|
||||||
const time = try interop.getTimeOfDay();
|
var tv: interop.system_time.timeval = undefined;
|
||||||
const clock_chars = toBigNumber(if (animate and char == ':' and @divTrunc(time.microseconds, 500000) != 0) ' ' else char, bigclock);
|
_ = interop.system_time.gettimeofday(&tv, null);
|
||||||
|
|
||||||
|
const clock_chars = toBigNumber(if (animate and char == ':' and @divTrunc(tv.tv_usec, 500000) != 0) ' ' else char, bigclock);
|
||||||
for (0..cells.len) |i| cells[i] = Cell.init(clock_chars[i], fg, bg);
|
for (0..cells.len) |i| cells[i] = Cell.init(clock_chars[i], fg, bg);
|
||||||
|
|
||||||
return cells;
|
return cells;
|
||||||
@@ -49,9 +51,6 @@ fn toBigNumber(char: u8, bigclock: Bigclock) [SIZE]u21 {
|
|||||||
'7' => locale_chars.SEVEN,
|
'7' => locale_chars.SEVEN,
|
||||||
'8' => locale_chars.EIGHT,
|
'8' => locale_chars.EIGHT,
|
||||||
'9' => locale_chars.NINE,
|
'9' => locale_chars.NINE,
|
||||||
'p', 'P' => locale_chars.P,
|
|
||||||
'a', 'A' => locale_chars.A,
|
|
||||||
'm', 'M' => locale_chars.M,
|
|
||||||
':' => locale_chars.S,
|
':' => locale_chars.S,
|
||||||
else => locale_chars.E,
|
else => locale_chars.E,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
const interop = @import("../interop.zig");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub const WIDTH = 5;
|
pub const WIDTH = 5;
|
||||||
pub const HEIGHT = 5;
|
pub const HEIGHT = 5;
|
||||||
pub const SIZE = WIDTH * HEIGHT;
|
pub const SIZE = WIDTH * HEIGHT;
|
||||||
|
|
||||||
pub const X: u32 = if (interop.supportsUnicode()) 0x2593 else '#';
|
pub const X: u32 = if (builtin.os.tag == .linux or builtin.os.tag.isBSD()) 0x2593 else '#';
|
||||||
pub const O: u32 = 0;
|
pub const O: u32 = 0;
|
||||||
|
|
||||||
// zig fmt: off
|
|
||||||
pub const LocaleChars = struct {
|
pub const LocaleChars = struct {
|
||||||
ZERO: [SIZE]u21,
|
ZERO: [SIZE]u21,
|
||||||
ONE: [SIZE]u21,
|
ONE: [SIZE]u21,
|
||||||
@@ -21,8 +20,4 @@ pub const LocaleChars = struct {
|
|||||||
NINE: [SIZE]u21,
|
NINE: [SIZE]u21,
|
||||||
S: [SIZE]u21,
|
S: [SIZE]u21,
|
||||||
E: [SIZE]u21,
|
E: [SIZE]u21,
|
||||||
P: [SIZE]u21,
|
};
|
||||||
A: [SIZE]u21,
|
|
||||||
M: [SIZE]u21,
|
|
||||||
};
|
|
||||||
// zig fmt: on
|
|
||||||
@@ -90,26 +90,5 @@ pub const locale_chars = LocaleChars{
|
|||||||
O,O,O,O,O,
|
O,O,O,O,O,
|
||||||
O,O,O,O,O,
|
O,O,O,O,O,
|
||||||
},
|
},
|
||||||
.P = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,O,O,
|
|
||||||
X,X,O,O,O,
|
|
||||||
},
|
|
||||||
.A = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
X,X,O,X,X,
|
|
||||||
},
|
|
||||||
.M = [_]u21{
|
|
||||||
X,X,X,X,X,
|
|
||||||
X,O,X,O,X,
|
|
||||||
X,O,X,O,X,
|
|
||||||
X,O,O,O,X,
|
|
||||||
X,O,O,O,X,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
@@ -76,27 +76,6 @@ pub const locale_chars = LocaleChars{
|
|||||||
O,O,O,X,O,
|
O,O,O,X,O,
|
||||||
O,O,O,X,O,
|
O,O,O,X,O,
|
||||||
},
|
},
|
||||||
.P = [_]u21{
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
},
|
|
||||||
.A = [_]u21{
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
},
|
|
||||||
.M = [_]u21{
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
O,O,O,O,O,
|
|
||||||
},
|
|
||||||
.S = [_]u21{
|
.S = [_]u21{
|
||||||
O,O,O,O,O,
|
O,O,O,O,O,
|
||||||
O,O,X,O,O,
|
O,O,X,O,O,
|
||||||
@@ -112,4 +91,4 @@ pub const locale_chars = LocaleChars{
|
|||||||
O,O,O,O,O,
|
O,O,O,O,O,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
@@ -11,68 +11,56 @@ animation: Animation = .none,
|
|||||||
animation_timeout_sec: u12 = 0,
|
animation_timeout_sec: u12 = 0,
|
||||||
asterisk: ?u32 = '*',
|
asterisk: ?u32 = '*',
|
||||||
auth_fails: u64 = 10,
|
auth_fails: u64 = 10,
|
||||||
battery_id: ?[]const u8 = null,
|
|
||||||
bg: u32 = 0x00000000,
|
bg: u32 = 0x00000000,
|
||||||
bigclock: Bigclock = .none,
|
bigclock: Bigclock = .none,
|
||||||
bigclock_12hr: bool = false,
|
|
||||||
bigclock_seconds: bool = false,
|
|
||||||
blank_box: bool = true,
|
blank_box: bool = true,
|
||||||
border_fg: u32 = 0x00FFFFFF,
|
border_fg: u32 = 0x00FFFFFF,
|
||||||
box_title: ?[]const u8 = null,
|
box_title: ?[]const u8 = null,
|
||||||
brightness_down_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/brightnessctl -q -n s 10%-",
|
brightness_down_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/brightnessctl -q s 10%-",
|
||||||
brightness_down_key: ?[]const u8 = "F5",
|
brightness_down_key: ?[]const u8 = "F5",
|
||||||
brightness_up_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/brightnessctl -q -n s +10%",
|
brightness_up_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/brightnessctl -q s +10%",
|
||||||
brightness_up_key: ?[]const u8 = "F6",
|
brightness_up_key: ?[]const u8 = "F6",
|
||||||
clear_password: bool = false,
|
clear_password: bool = false,
|
||||||
clock: ?[:0]const u8 = null,
|
clock: ?[:0]const u8 = null,
|
||||||
cmatrix_fg: u32 = 0x0000FF00,
|
cmatrix_fg: u32 = 0x0000FF00,
|
||||||
cmatrix_head_col: u32 = 0x01FFFFFF,
|
|
||||||
cmatrix_min_codepoint: u16 = 0x21,
|
cmatrix_min_codepoint: u16 = 0x21,
|
||||||
cmatrix_max_codepoint: u16 = 0x7B,
|
cmatrix_max_codepoint: u16 = 0x7B,
|
||||||
colormix_col1: u32 = 0x00FF0000,
|
colormix_col1: u32 = 0x00FF0000,
|
||||||
colormix_col2: u32 = 0x000000FF,
|
colormix_col2: u32 = 0x000000FF,
|
||||||
colormix_col3: u32 = 0x20000000,
|
colormix_col3: u32 = 0x20000000,
|
||||||
custom_sessions: []const u8 = build_options.config_directory ++ "/ly/custom-sessions",
|
console_dev: []const u8 = "/dev/console",
|
||||||
default_input: Input = .login,
|
default_input: Input = .login,
|
||||||
doom_fire_height: u8 = 6,
|
|
||||||
doom_fire_spread: u8 = 2,
|
|
||||||
doom_top_color: u32 = 0x00FF0000,
|
doom_top_color: u32 = 0x00FF0000,
|
||||||
doom_middle_color: u32 = 0x00FFFF00,
|
doom_middle_color: u32 = 0x00FFFF00,
|
||||||
doom_bottom_color: u32 = 0x00FFFFFF,
|
doom_bottom_color: u32 = 0x00FFFFFF,
|
||||||
error_bg: u32 = 0x00000000,
|
error_bg: u32 = 0x00000000,
|
||||||
error_fg: u32 = 0x01FF0000,
|
error_fg: u32 = 0x01FF0000,
|
||||||
fg: u32 = 0x00FFFFFF,
|
fg: u32 = 0x00FFFFFF,
|
||||||
full_color: bool = true,
|
|
||||||
gameoflife_fg: u32 = 0x0000FF00,
|
|
||||||
gameoflife_entropy_interval: usize = 10,
|
|
||||||
gameoflife_frame_delay: usize = 6,
|
|
||||||
gameoflife_initial_density: f32 = 0.4,
|
|
||||||
hide_borders: bool = false,
|
hide_borders: bool = false,
|
||||||
hide_key_hints: bool = false,
|
hide_key_hints: bool = false,
|
||||||
hide_version_string: bool = false,
|
|
||||||
initial_info_text: ?[]const u8 = null,
|
initial_info_text: ?[]const u8 = null,
|
||||||
input_len: u8 = 34,
|
input_len: u8 = 34,
|
||||||
lang: []const u8 = "en",
|
lang: []const u8 = "en",
|
||||||
|
load: bool = true,
|
||||||
login_cmd: ?[]const u8 = null,
|
login_cmd: ?[]const u8 = null,
|
||||||
login_defs_path: []const u8 = "/etc/login.defs",
|
|
||||||
logout_cmd: ?[]const u8 = null,
|
logout_cmd: ?[]const u8 = null,
|
||||||
ly_log: []const u8 = "/var/log/ly.log",
|
|
||||||
margin_box_h: u8 = 2,
|
margin_box_h: u8 = 2,
|
||||||
margin_box_v: u8 = 1,
|
margin_box_v: u8 = 1,
|
||||||
min_refresh_delta: u16 = 5,
|
min_refresh_delta: u16 = 5,
|
||||||
numlock: bool = false,
|
numlock: bool = false,
|
||||||
path: ?[]const u8 = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
path: ?[:0]const u8 = "/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
|
||||||
restart_cmd: []const u8 = "/sbin/shutdown -r now",
|
restart_cmd: []const u8 = "/sbin/shutdown -r now",
|
||||||
restart_key: []const u8 = "F2",
|
restart_key: []const u8 = "F2",
|
||||||
save: bool = true,
|
save: bool = true,
|
||||||
service_name: [:0]const u8 = "ly",
|
service_name: [:0]const u8 = "ly",
|
||||||
session_log: ?[]const u8 = "ly-session.log",
|
session_log: []const u8 = "ly-session.log",
|
||||||
setup_cmd: []const u8 = build_options.config_directory ++ "/ly/setup.sh",
|
setup_cmd: []const u8 = build_options.config_directory ++ "/ly/setup.sh",
|
||||||
shutdown_cmd: []const u8 = "/sbin/shutdown -a now",
|
shutdown_cmd: []const u8 = "/sbin/shutdown -a now",
|
||||||
shutdown_key: []const u8 = "F1",
|
shutdown_key: []const u8 = "F1",
|
||||||
sleep_cmd: ?[]const u8 = null,
|
sleep_cmd: ?[]const u8 = null,
|
||||||
sleep_key: []const u8 = "F3",
|
sleep_key: []const u8 = "F3",
|
||||||
text_in_center: bool = false,
|
text_in_center: bool = false,
|
||||||
|
tty: u8 = build_options.tty,
|
||||||
vi_default_mode: ViMode = .normal,
|
vi_default_mode: ViMode = .normal,
|
||||||
vi_mode: bool = false,
|
vi_mode: bool = false,
|
||||||
waylandsessions: []const u8 = build_options.prefix_directory ++ "/share/wayland-sessions",
|
waylandsessions: []const u8 = build_options.prefix_directory ++ "/share/wayland-sessions",
|
||||||
|
|||||||
@@ -7,21 +7,17 @@ authenticating: []const u8 = "authenticating...",
|
|||||||
brightness_down: []const u8 = "decrease brightness",
|
brightness_down: []const u8 = "decrease brightness",
|
||||||
brightness_up: []const u8 = "increase brightness",
|
brightness_up: []const u8 = "increase brightness",
|
||||||
capslock: []const u8 = "capslock",
|
capslock: []const u8 = "capslock",
|
||||||
custom: []const u8 = "custom",
|
|
||||||
err_alloc: []const u8 = "failed memory allocation",
|
err_alloc: []const u8 = "failed memory allocation",
|
||||||
err_bounds: []const u8 = "out-of-bounds index",
|
err_bounds: []const u8 = "out-of-bounds index",
|
||||||
err_brightness_change: []const u8 = "failed to change brightness",
|
err_brightness_change: []const u8 = "failed to change brightness",
|
||||||
err_chdir: []const u8 = "failed to open home folder",
|
err_chdir: []const u8 = "failed to open home folder",
|
||||||
err_clock_too_long: []const u8 = "clock string too long",
|
|
||||||
err_config: []const u8 = "unable to parse config file",
|
err_config: []const u8 = "unable to parse config file",
|
||||||
|
err_console_dev: []const u8 = "failed to access console",
|
||||||
err_dgn_oob: []const u8 = "log message",
|
err_dgn_oob: []const u8 = "log message",
|
||||||
err_domain: []const u8 = "invalid domain",
|
err_domain: []const u8 = "invalid domain",
|
||||||
err_empty_password: []const u8 = "empty password not allowed",
|
err_empty_password: []const u8 = "empty password not allowed",
|
||||||
err_envlist: []const u8 = "failed to get envlist",
|
err_envlist: []const u8 = "failed to get envlist",
|
||||||
err_get_active_tty: []const u8 = "failed to get active tty",
|
|
||||||
err_hostname: []const u8 = "failed to get hostname",
|
err_hostname: []const u8 = "failed to get hostname",
|
||||||
err_lock_state: []const u8 = "failed to get lock state",
|
|
||||||
err_log: []const u8 = "failed to open log file",
|
|
||||||
err_mlock: []const u8 = "failed to lock password memory",
|
err_mlock: []const u8 = "failed to lock password memory",
|
||||||
err_null: []const u8 = "null pointer",
|
err_null: []const u8 = "null pointer",
|
||||||
err_numlock: []const u8 = "failed to set numlock",
|
err_numlock: []const u8 = "failed to set numlock",
|
||||||
@@ -47,10 +43,8 @@ err_perm_group: []const u8 = "failed to downgrade group permissions",
|
|||||||
err_perm_user: []const u8 = "failed to downgrade user permissions",
|
err_perm_user: []const u8 = "failed to downgrade user permissions",
|
||||||
err_pwnam: []const u8 = "failed to get user info",
|
err_pwnam: []const u8 = "failed to get user info",
|
||||||
err_sleep: []const u8 = "failed to execute sleep command",
|
err_sleep: []const u8 = "failed to execute sleep command",
|
||||||
err_battery: []const u8 = "failed to load battery status",
|
|
||||||
err_switch_tty: []const u8 = "failed to switch tty",
|
|
||||||
err_tty_ctrl: []const u8 = "tty control transfer failed",
|
err_tty_ctrl: []const u8 = "tty control transfer failed",
|
||||||
err_no_users: []const u8 = "no users found",
|
err_unknown: []const u8 = "an unknown error occurred",
|
||||||
err_user_gid: []const u8 = "failed to set user GID",
|
err_user_gid: []const u8 = "failed to set user GID",
|
||||||
err_user_init: []const u8 = "failed to initialize user",
|
err_user_init: []const u8 = "failed to initialize user",
|
||||||
err_user_uid: []const u8 = "failed to set user UID",
|
err_user_uid: []const u8 = "failed to set user UID",
|
||||||
@@ -59,13 +53,13 @@ err_xcb_conn: []const u8 = "xcb connection failed",
|
|||||||
err_xsessions_dir: []const u8 = "failed to find sessions folder",
|
err_xsessions_dir: []const u8 = "failed to find sessions folder",
|
||||||
err_xsessions_open: []const u8 = "failed to open sessions folder",
|
err_xsessions_open: []const u8 = "failed to open sessions folder",
|
||||||
insert: []const u8 = "insert",
|
insert: []const u8 = "insert",
|
||||||
login: []const u8 = "login",
|
login: []const u8 = "login:",
|
||||||
logout: []const u8 = "logged out",
|
logout: []const u8 = "logged out",
|
||||||
no_x11_support: []const u8 = "x11 support disabled at compile-time",
|
no_x11_support: []const u8 = "x11 support disabled at compile-time",
|
||||||
normal: []const u8 = "normal",
|
normal: []const u8 = "normal",
|
||||||
numlock: []const u8 = "numlock",
|
numlock: []const u8 = "numlock",
|
||||||
other: []const u8 = "other",
|
other: []const u8 = "other",
|
||||||
password: []const u8 = "password",
|
password: []const u8 = "password:",
|
||||||
restart: []const u8 = "reboot",
|
restart: []const u8 = "reboot",
|
||||||
shell: [:0]const u8 = "shell",
|
shell: [:0]const u8 = "shell",
|
||||||
shutdown: []const u8 = "shutdown",
|
shutdown: []const u8 = "shutdown",
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const SavedUsers = @This();
|
|
||||||
|
|
||||||
const User = struct {
|
|
||||||
username: []const u8,
|
|
||||||
session_index: usize,
|
|
||||||
};
|
|
||||||
|
|
||||||
user_list: std.ArrayList(User),
|
|
||||||
last_username_index: ?usize,
|
|
||||||
|
|
||||||
pub fn init() SavedUsers {
|
|
||||||
return .{
|
|
||||||
.user_list = .empty,
|
|
||||||
.last_username_index = null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *SavedUsers, allocator: std.mem.Allocator) void {
|
|
||||||
self.user_list.deinit(allocator);
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,9 @@
|
|||||||
// The migrator ensures compatibility with older configuration files
|
// The migrator ensures compatibility with <=0.6.0 configuration files
|
||||||
// Properties removed or changed since 0.6.0
|
|
||||||
// Color codes interpreted differently since 1.1.0
|
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ini = @import("zigini");
|
const ini = @import("zigini");
|
||||||
const Config = @import("Config.zig");
|
const Save = @import("Save.zig");
|
||||||
const OldSave = @import("OldSave.zig");
|
const enums = @import("../enums.zig");
|
||||||
const SavedUsers = @import("SavedUsers.zig");
|
|
||||||
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
|
||||||
|
|
||||||
const Color = TerminalBuffer.Color;
|
|
||||||
const Styling = TerminalBuffer.Styling;
|
|
||||||
|
|
||||||
const color_properties = [_][]const u8{
|
const color_properties = [_][]const u8{
|
||||||
"bg",
|
"bg",
|
||||||
@@ -23,10 +16,6 @@ const color_properties = [_][]const u8{
|
|||||||
"error_fg",
|
"error_fg",
|
||||||
"fg",
|
"fg",
|
||||||
};
|
};
|
||||||
|
|
||||||
var set_color_properties =
|
|
||||||
[_]bool{ false, false, false, false, false, false, false, false, false };
|
|
||||||
|
|
||||||
const removed_properties = [_][]const u8{
|
const removed_properties = [_][]const u8{
|
||||||
"wayland_specifier",
|
"wayland_specifier",
|
||||||
"max_desktop_len",
|
"max_desktop_len",
|
||||||
@@ -37,22 +26,22 @@ const removed_properties = [_][]const u8{
|
|||||||
"term_restore_cursor_cmd",
|
"term_restore_cursor_cmd",
|
||||||
"x_cmd_setup",
|
"x_cmd_setup",
|
||||||
"wayland_cmd",
|
"wayland_cmd",
|
||||||
"console_dev",
|
|
||||||
"load",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var temporary_allocator = std.heap.page_allocator;
|
var temporary_allocator = std.heap.page_allocator;
|
||||||
|
var buffer = std.mem.zeroes([10 * color_properties.len]u8);
|
||||||
pub var auto_eight_colors: bool = true;
|
|
||||||
|
|
||||||
pub var maybe_animate: ?bool = null;
|
pub var maybe_animate: ?bool = null;
|
||||||
pub var maybe_save_file: ?[]const u8 = null;
|
pub var maybe_save_file: ?[]const u8 = null;
|
||||||
|
|
||||||
|
pub var mapped_config_fields = false;
|
||||||
|
|
||||||
pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniField {
|
pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniField {
|
||||||
if (std.mem.eql(u8, field.key, "animate")) {
|
if (std.mem.eql(u8, field.key, "animate")) {
|
||||||
// The option doesn't exist anymore, but we save its value for "animation"
|
// The option doesn't exist anymore, but we save its value for "animation"
|
||||||
maybe_animate = std.mem.eql(u8, field.value, "true");
|
maybe_animate = std.mem.eql(u8, field.value, "true");
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,29 +57,19 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
|||||||
else => "none",
|
else => "none",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
return mapped_field;
|
return mapped_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline for (color_properties, &set_color_properties) |property, *status| {
|
inline for (color_properties) |property| {
|
||||||
if (std.mem.eql(u8, field.key, property)) {
|
if (std.mem.eql(u8, field.key, property)) {
|
||||||
// Color has been set; it won't be overwritten if we default to eight-color output
|
|
||||||
status.* = true;
|
|
||||||
|
|
||||||
// These options now uses a 32-bit RGB value instead of an arbitrary 16-bit integer
|
// These options now uses a 32-bit RGB value instead of an arbitrary 16-bit integer
|
||||||
// If they're all using eight-color codes, we start in eight-color mode
|
const color = std.fmt.parseInt(u16, field.value, 0) catch return field;
|
||||||
const color = std.fmt.parseInt(u16, field.value, 0) catch {
|
var mapped_field = field;
|
||||||
auto_eight_colors = false;
|
|
||||||
return field;
|
|
||||||
};
|
|
||||||
|
|
||||||
const color_no_styling = color & 0x00FF;
|
mapped_field.value = mapColor(color) catch return field;
|
||||||
const styling_only = color & 0xFF00;
|
mapped_config_fields = true;
|
||||||
|
return mapped_field;
|
||||||
// If color is "greater" than TB_WHITE, or the styling is "greater" than TB_DIM,
|
|
||||||
// we have an invalid color, so do not use eight-color mode
|
|
||||||
if (color_no_styling > 0x0008 or styling_only > 0x8000) auto_eight_colors = false;
|
|
||||||
|
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +78,7 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
|||||||
var mapped_field = field;
|
var mapped_field = field;
|
||||||
mapped_field.key = "clear_password";
|
mapped_field.key = "clear_password";
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
return mapped_field;
|
return mapped_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +94,7 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
|||||||
else => "login",
|
else => "login",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
return mapped_field;
|
return mapped_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,12 +102,14 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
|||||||
// The option doesn't exist anymore, but we save its value for migration later on
|
// The option doesn't exist anymore, but we save its value for migration later on
|
||||||
maybe_save_file = temporary_allocator.dupe(u8, field.value) catch return null;
|
maybe_save_file = temporary_allocator.dupe(u8, field.value) catch return null;
|
||||||
|
|
||||||
|
mapped_config_fields = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline for (removed_properties) |property| {
|
inline for (removed_properties) |property| {
|
||||||
if (std.mem.eql(u8, field.key, property)) {
|
if (std.mem.eql(u8, field.key, property)) {
|
||||||
// The options don't exist anymore
|
// The options don't exist anymore
|
||||||
|
mapped_config_fields = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,57 +121,28 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
|||||||
|
|
||||||
if (std.mem.eql(u8, field.value, "true")) {
|
if (std.mem.eql(u8, field.value, "true")) {
|
||||||
mapped_field.value = "en";
|
mapped_field.value = "en";
|
||||||
|
mapped_config_fields = true;
|
||||||
} else if (std.mem.eql(u8, field.value, "false")) {
|
} else if (std.mem.eql(u8, field.value, "false")) {
|
||||||
mapped_field.value = "none";
|
mapped_field.value = "none";
|
||||||
|
mapped_config_fields = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapped_field;
|
return mapped_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, field.key, "full_color")) {
|
|
||||||
// If color mode is defined, definitely don't set it automatically
|
|
||||||
auto_eight_colors = false;
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
|
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the stuff we only handle after reading the config.
|
// This is the stuff we only handle after reading the config.
|
||||||
// For example, the "animate" field could come after "animation"
|
// For example, the "animate" field could come after "animation"
|
||||||
pub fn lateConfigFieldHandler(config: *Config) void {
|
pub fn lateConfigFieldHandler(animation: *enums.Animation) void {
|
||||||
if (maybe_animate) |animate| {
|
if (maybe_animate) |animate| {
|
||||||
if (!animate) config.*.animation = .none;
|
if (!animate) animation.* = .none;
|
||||||
}
|
|
||||||
|
|
||||||
if (auto_eight_colors) {
|
|
||||||
// Valid config file predates true-color mode
|
|
||||||
// Will use eight-color output instead
|
|
||||||
config.full_color = false;
|
|
||||||
|
|
||||||
// We cannot rely on Config defaults when in eight-color mode,
|
|
||||||
// because they will appear as undesired colors.
|
|
||||||
// Instead set color properties to matching eight-color codes
|
|
||||||
config.doom_top_color = Color.ECOL_RED;
|
|
||||||
config.doom_middle_color = Color.ECOL_YELLOW;
|
|
||||||
config.doom_bottom_color = Color.ECOL_WHITE;
|
|
||||||
config.cmatrix_head_col = Styling.BOLD | Color.ECOL_WHITE;
|
|
||||||
|
|
||||||
// These may be in the config, so only change those which were not set
|
|
||||||
if (!set_color_properties[0]) config.bg = Color.DEFAULT;
|
|
||||||
if (!set_color_properties[1]) config.border_fg = Color.ECOL_WHITE;
|
|
||||||
if (!set_color_properties[2]) config.cmatrix_fg = Color.ECOL_GREEN;
|
|
||||||
if (!set_color_properties[3]) config.colormix_col1 = Color.ECOL_RED;
|
|
||||||
if (!set_color_properties[4]) config.colormix_col2 = Color.ECOL_BLUE;
|
|
||||||
if (!set_color_properties[5]) config.colormix_col3 = Color.ECOL_BLACK;
|
|
||||||
if (!set_color_properties[6]) config.error_bg = Color.DEFAULT;
|
|
||||||
if (!set_color_properties[7]) config.error_fg = Styling.BOLD | Color.ECOL_RED;
|
|
||||||
if (!set_color_properties[8]) config.fg = Color.ECOL_WHITE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tryMigrateFirstSaveFile(user_buf: *[32]u8) OldSave {
|
pub fn tryMigrateSaveFile(user_buf: *[32]u8) Save {
|
||||||
var save = OldSave{};
|
var save = Save{};
|
||||||
|
|
||||||
if (maybe_save_file) |path| {
|
if (maybe_save_file) |path| {
|
||||||
defer temporary_allocator.free(path);
|
defer temporary_allocator.free(path);
|
||||||
@@ -196,21 +150,21 @@ pub fn tryMigrateFirstSaveFile(user_buf: *[32]u8) OldSave {
|
|||||||
var file = std.fs.openFileAbsolute(path, .{}) catch return save;
|
var file = std.fs.openFileAbsolute(path, .{}) catch return save;
|
||||||
defer file.close();
|
defer file.close();
|
||||||
|
|
||||||
var file_buffer: [64]u8 = undefined;
|
const reader = file.reader();
|
||||||
var file_reader = file.reader(&file_buffer);
|
|
||||||
var reader = &file_reader.interface;
|
|
||||||
|
|
||||||
var user_writer = std.Io.Writer.fixed(user_buf);
|
var user_fbs = std.io.fixedBufferStream(user_buf);
|
||||||
var written = reader.streamDelimiter(&user_writer, '\n') catch return save;
|
reader.streamUntilDelimiter(user_fbs.writer(), '\n', user_buf.len) catch return save;
|
||||||
if (written > 0) save.user = user_buf[0..written];
|
const user = user_fbs.getWritten();
|
||||||
|
if (user.len > 0) save.user = user;
|
||||||
|
|
||||||
var session_buf: [20]u8 = undefined;
|
var session_buf: [20]u8 = undefined;
|
||||||
var session_writer = std.Io.Writer.fixed(&session_buf);
|
var session_fbs = std.io.fixedBufferStream(&session_buf);
|
||||||
written = reader.streamDelimiter(&session_writer, '\n') catch return save;
|
reader.streamUntilDelimiter(session_fbs.writer(), '\n', session_buf.len) catch return save;
|
||||||
|
|
||||||
|
const session_index_str = session_fbs.getWritten();
|
||||||
var session_index: ?usize = null;
|
var session_index: ?usize = null;
|
||||||
if (written > 0) {
|
if (session_index_str.len > 0) {
|
||||||
session_index = std.fmt.parseUnsigned(usize, session_buf[0..written], 10) catch return save;
|
session_index = std.fmt.parseUnsigned(usize, session_index_str, 10) catch return save;
|
||||||
}
|
}
|
||||||
save.session_index = session_index;
|
save.session_index = session_index;
|
||||||
}
|
}
|
||||||
@@ -218,28 +172,32 @@ pub fn tryMigrateFirstSaveFile(user_buf: *[32]u8) OldSave {
|
|||||||
return save;
|
return save;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tryMigrateIniSaveFile(allocator: std.mem.Allocator, save_ini: *ini.Ini(OldSave), path: []const u8, saved_users: *SavedUsers, usernames: [][]const u8) !bool {
|
fn mapColor(color: u16) ![]const u8 {
|
||||||
var old_save_file_exists = true;
|
const color_no_styling = color & 0x00FF;
|
||||||
|
const styling_only = color & 0xFF00;
|
||||||
|
|
||||||
var user_buf: [32]u8 = undefined;
|
// If color is "greater" than TB_WHITE, or the styling is "greater" than TB_DIM,
|
||||||
const save = save_ini.readFileToStruct(path, .{
|
// we have an invalid color, so return an error
|
||||||
.fieldHandler = null,
|
if (color_no_styling > 0x0008 or styling_only > 0x8000) return error.InvalidColor;
|
||||||
.comment_characters = "#",
|
|
||||||
}) catch no_save_file: {
|
var new_color: u32 = switch (color_no_styling) {
|
||||||
old_save_file_exists = false;
|
0x0000 => 0x00000000, // Default
|
||||||
break :no_save_file tryMigrateFirstSaveFile(&user_buf);
|
0x0001 => 0x20000000, // "Hi-black" styling
|
||||||
|
0x0002 => 0x00FF0000, // Red
|
||||||
|
0x0003 => 0x0000FF00, // Green
|
||||||
|
0x0004 => 0x00FFFF00, // Yellow
|
||||||
|
0x0005 => 0x000000FF, // Blue
|
||||||
|
0x0006 => 0x00FF00FF, // Magenta
|
||||||
|
0x0007 => 0x0000FFFF, // Cyan
|
||||||
|
0x0008 => 0x00FFFFFF, // White
|
||||||
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!old_save_file_exists) return false;
|
// Only applying styling if color isn't black and styling isn't also black
|
||||||
|
if (!(new_color == 0x20000000 and styling_only == 0x20000000)) {
|
||||||
// Add all other users to the list
|
// Shift styling by 16 to the left to apply it to the new 32-bit color
|
||||||
for (usernames, 0..) |username, i| {
|
new_color |= @as(u32, @intCast(styling_only)) << 16;
|
||||||
if (save.user) |user| {
|
|
||||||
if (std.mem.eql(u8, user, username)) saved_users.last_username_index = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
try saved_users.user_list.append(allocator, .{ .username = username, .session_index = save.session_index orelse 0 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return try std.fmt.bufPrint(&buffer, "0x{X}", .{new_color});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ pub const Animation = enum {
|
|||||||
doom,
|
doom,
|
||||||
matrix,
|
matrix,
|
||||||
colormix,
|
colormix,
|
||||||
gameoflife,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DisplayServer = enum {
|
pub const DisplayServer = enum {
|
||||||
@@ -11,7 +10,6 @@ pub const DisplayServer = enum {
|
|||||||
shell,
|
shell,
|
||||||
xinitrc,
|
xinitrc,
|
||||||
x11,
|
x11,
|
||||||
custom,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Input = enum {
|
pub const Input = enum {
|
||||||
|
|||||||
387
src/interop.zig
387
src/interop.zig
@@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const UidRange = @import("UidRange.zig");
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
pub const termbox = @import("termbox2");
|
pub const termbox = @import("termbox2");
|
||||||
|
|
||||||
@@ -17,372 +17,95 @@ pub const xcb = @cImport({
|
|||||||
@cInclude("xcb/xcb.h");
|
@cInclude("xcb/xcb.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
const pwd = @cImport({
|
pub const unistd = @cImport({
|
||||||
@cInclude("pwd.h");
|
|
||||||
// We include a FreeBSD-specific header here since login_cap.h references
|
|
||||||
// the passwd struct directly, so we can't import it separately
|
|
||||||
if (builtin.os.tag == .freebsd) {
|
|
||||||
@cInclude("sys/types.h");
|
|
||||||
@cInclude("login_cap.h");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const stdlib = @cImport({
|
|
||||||
@cInclude("stdlib.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
const unistd = @cImport({
|
|
||||||
@cInclude("unistd.h");
|
@cInclude("unistd.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
const grp = @cImport({
|
pub const time = @cImport({
|
||||||
@cInclude("grp.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
const system_time = @cImport({
|
|
||||||
@cInclude("sys/time.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
const time = @cImport({
|
|
||||||
@cInclude("time.h");
|
@cInclude("time.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const TimeOfDay = struct {
|
pub const system_time = @cImport({
|
||||||
seconds: i64,
|
@cInclude("sys/time.h");
|
||||||
microseconds: i64,
|
});
|
||||||
};
|
|
||||||
|
|
||||||
pub const UsernameEntry = struct {
|
pub const stdlib = @cImport({
|
||||||
username: ?[]const u8,
|
@cInclude("stdlib.h");
|
||||||
uid: std.posix.uid_t,
|
});
|
||||||
gid: std.posix.gid_t,
|
|
||||||
home: ?[]const u8,
|
|
||||||
shell: ?[]const u8,
|
|
||||||
passwd_struct: [*c]pwd.passwd,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Contains the platform-specific code
|
pub const pwd = @cImport({
|
||||||
fn PlatformStruct() type {
|
@cInclude("pwd.h");
|
||||||
return switch (builtin.os.tag) {
|
// We include a FreeBSD-specific header here since login_cap.h references
|
||||||
.linux => struct {
|
// the passwd struct directly, so we can't import it separately'
|
||||||
pub const kd = @cImport({
|
if (builtin.os.tag == .freebsd) @cInclude("login_cap.h");
|
||||||
@cInclude("sys/kd.h");
|
});
|
||||||
});
|
|
||||||
|
|
||||||
pub const vt = @cImport({
|
pub const grp = @cImport({
|
||||||
@cInclude("sys/vt.h");
|
@cInclude("grp.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const LedState = c_char;
|
// BSD-specific headers
|
||||||
pub const get_led_state = kd.KDGKBLED;
|
pub const kbio = @cImport({
|
||||||
pub const set_led_state = kd.KDSKBLED;
|
@cInclude("sys/kbio.h");
|
||||||
pub const numlock_led = kd.K_NUMLOCK;
|
});
|
||||||
pub const capslock_led = kd.K_CAPSLOCK;
|
|
||||||
pub const vt_activate = vt.VT_ACTIVATE;
|
|
||||||
pub const vt_waitactive = vt.VT_WAITACTIVE;
|
|
||||||
|
|
||||||
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
// Linux-specific headers
|
||||||
const status = grp.initgroups(username, @intCast(entry.gid));
|
pub const kd = @cImport({
|
||||||
if (status != 0) return error.GroupInitializationFailed;
|
@cInclude("sys/kd.h");
|
||||||
|
});
|
||||||
|
|
||||||
std.posix.setgid(@intCast(entry.gid)) catch return error.SetUserGidFailed;
|
pub const vt = @cImport({
|
||||||
std.posix.setuid(@intCast(entry.uid)) catch return error.SetUserUidFailed;
|
@cInclude("sys/vt.h");
|
||||||
}
|
});
|
||||||
|
|
||||||
// Procedure:
|
// Used for getting & setting the lock state
|
||||||
// 1. Open /proc/self/stat to retrieve the tty_nr field
|
const LedState = if (builtin.os.tag.isBSD()) c_int else c_char;
|
||||||
// 2. Parse the tty_nr field to extract the major and minor device
|
const get_led_state = if (builtin.os.tag.isBSD()) kbio.KDGETLED else kd.KDGKBLED;
|
||||||
// numbers
|
const set_led_state = if (builtin.os.tag.isBSD()) kbio.KDSETLED else kd.KDSKBLED;
|
||||||
// 3. Then, read every /sys/class/tty/[dir]/dev, where [dir] is
|
const numlock_led = if (builtin.os.tag.isBSD()) kbio.LED_NUM else kd.K_NUMLOCK;
|
||||||
// every sub-directory
|
const capslock_led = if (builtin.os.tag.isBSD()) kbio.LED_CAP else kd.K_CAPSLOCK;
|
||||||
// 4. Finally, compare the major and minor device numbers with the
|
|
||||||
// extracted values. If they correspond, parse [dir] to get the
|
|
||||||
// TTY ID
|
|
||||||
pub fn getActiveTtyImpl(allocator: std.mem.Allocator) !u8 {
|
|
||||||
var file_buffer: [256]u8 = undefined;
|
|
||||||
var tty_major: u16 = undefined;
|
|
||||||
var tty_minor: u16 = undefined;
|
|
||||||
|
|
||||||
{
|
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) ![]u8 {
|
||||||
var file = try std.fs.openFileAbsolute("/proc/self/stat", .{});
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
var reader = file.reader(&file_buffer);
|
|
||||||
var buffer: [1024]u8 = undefined;
|
|
||||||
const read = try readBuffer(&reader.interface, &buffer);
|
|
||||||
|
|
||||||
var iterator = std.mem.splitScalar(u8, buffer[0..read], ' ');
|
|
||||||
var fields: [52][]const u8 = undefined;
|
|
||||||
var index: usize = 0;
|
|
||||||
|
|
||||||
while (iterator.next()) |field| {
|
|
||||||
fields[index] = field;
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tty_nr = try std.fmt.parseInt(u16, fields[6], 10);
|
|
||||||
tty_major = tty_nr / 256;
|
|
||||||
tty_minor = tty_nr % 256;
|
|
||||||
}
|
|
||||||
|
|
||||||
var directory = try std.fs.openDirAbsolute("/sys/class/tty", .{ .iterate = true });
|
|
||||||
defer directory.close();
|
|
||||||
|
|
||||||
var iterator = directory.iterate();
|
|
||||||
while (try iterator.next()) |entry| {
|
|
||||||
const path = try std.fmt.allocPrint(allocator, "/sys/class/tty/{s}/dev", .{entry.name});
|
|
||||||
defer allocator.free(path);
|
|
||||||
|
|
||||||
var file = try std.fs.openFileAbsolute(path, .{});
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
var reader = file.reader(&file_buffer);
|
|
||||||
var buffer: [16]u8 = undefined;
|
|
||||||
const read = try readBuffer(&reader.interface, &buffer);
|
|
||||||
|
|
||||||
var device_iterator = std.mem.splitScalar(u8, buffer[0..(read - 1)], ':');
|
|
||||||
const device_major_str = device_iterator.next() orelse continue;
|
|
||||||
const device_minor_str = device_iterator.next() orelse continue;
|
|
||||||
|
|
||||||
const device_major = try std.fmt.parseInt(u8, device_major_str, 10);
|
|
||||||
const device_minor = try std.fmt.parseInt(u8, device_minor_str, 10);
|
|
||||||
|
|
||||||
if (device_major == tty_major and device_minor == tty_minor) {
|
|
||||||
const tty_id_str = entry.name["tty".len..];
|
|
||||||
return try std.fmt.parseInt(u8, tty_id_str, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.NoTtyFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is very bad parsing, but we only need to get 2 values..
|
|
||||||
// and the format of the file seems to be standard? So this should
|
|
||||||
// be fine...
|
|
||||||
pub fn getUserIdRange(allocator: std.mem.Allocator, file_path: []const u8) !UidRange {
|
|
||||||
const login_defs_file = try std.fs.cwd().openFile(file_path, .{});
|
|
||||||
defer login_defs_file.close();
|
|
||||||
|
|
||||||
const login_defs_buffer = try login_defs_file.readToEndAlloc(allocator, std.math.maxInt(u16));
|
|
||||||
defer allocator.free(login_defs_buffer);
|
|
||||||
|
|
||||||
var iterator = std.mem.splitScalar(u8, login_defs_buffer, '\n');
|
|
||||||
var uid_range = UidRange{};
|
|
||||||
|
|
||||||
while (iterator.next()) |line| {
|
|
||||||
const trimmed_line = std.mem.trim(u8, line, " \n\r\t");
|
|
||||||
|
|
||||||
if (std.mem.startsWith(u8, trimmed_line, "UID_MIN")) {
|
|
||||||
uid_range.uid_min = try parseValue(std.posix.uid_t, "UID_MIN", trimmed_line);
|
|
||||||
} else if (std.mem.startsWith(u8, trimmed_line, "UID_MAX")) {
|
|
||||||
uid_range.uid_max = try parseValue(std.posix.uid_t, "UID_MAX", trimmed_line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return uid_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parseValue(comptime T: type, name: []const u8, buffer: []const u8) !T {
|
|
||||||
var iterator = std.mem.splitAny(u8, buffer, " \t");
|
|
||||||
var maybe_value: ?T = null;
|
|
||||||
|
|
||||||
while (iterator.next()) |slice| {
|
|
||||||
// Skip the slice if it's empty (whitespace) or is the name of the
|
|
||||||
// property (e.g. UID_MIN or UID_MAX)
|
|
||||||
if (slice.len == 0 or std.mem.eql(u8, slice, name)) continue;
|
|
||||||
maybe_value = std.fmt.parseInt(T, slice, 10) catch continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return maybe_value orelse error.ValueNotFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readBuffer(reader: *std.Io.Reader, buffer: []u8) !usize {
|
|
||||||
var bytes_read: usize = 0;
|
|
||||||
var byte: u8 = try reader.takeByte();
|
|
||||||
|
|
||||||
while (byte != 0 and bytes_read < buffer.len) {
|
|
||||||
buffer[bytes_read] = byte;
|
|
||||||
bytes_read += 1;
|
|
||||||
byte = reader.takeByte() catch break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes_read;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.freebsd => struct {
|
|
||||||
pub const kbio = @cImport({
|
|
||||||
@cInclude("sys/kbio.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
pub const consio = @cImport({
|
|
||||||
@cInclude("sys/consio.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
pub const LedState = c_int;
|
|
||||||
pub const get_led_state = kbio.KDGETLED;
|
|
||||||
pub const set_led_state = kbio.KDSETLED;
|
|
||||||
pub const numlock_led = kbio.LED_NUM;
|
|
||||||
pub const capslock_led = kbio.LED_CAP;
|
|
||||||
pub const vt_activate = consio.VT_ACTIVATE;
|
|
||||||
pub const vt_waitactive = consio.VT_WAITACTIVE;
|
|
||||||
|
|
||||||
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
|
||||||
// FreeBSD has initgroups() in unistd
|
|
||||||
const status = unistd.initgroups(username, @intCast(entry.gid));
|
|
||||||
if (status != 0) return error.GroupInitializationFailed;
|
|
||||||
|
|
||||||
// FreeBSD sets the GID and UID with setusercontext()
|
|
||||||
const result = pwd.setusercontext(null, entry.passwd_struct, @intCast(entry.uid), pwd.LOGIN_SETALL);
|
|
||||||
if (result != 0) return error.SetUserUidFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getActiveTtyImpl(_: std.mem.Allocator) !u8 {
|
|
||||||
return error.FeatureUnimplemented;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getUserIdRange(_: std.mem.Allocator, _: []const u8) !UidRange {
|
|
||||||
return .{
|
|
||||||
// Hardcoded default values chosen from
|
|
||||||
// /usr/src/usr.sbin/pw/pw_conf.c
|
|
||||||
.uid_min = 1000,
|
|
||||||
.uid_max = 32000,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => @compileError("Unsupported target: " ++ builtin.os.tag),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const platform_struct = PlatformStruct();
|
|
||||||
|
|
||||||
pub fn supportsUnicode() bool {
|
|
||||||
return builtin.os.tag == .linux or builtin.os.tag == .freebsd;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) []u8 {
|
|
||||||
const timer = std.time.timestamp();
|
const timer = std.time.timestamp();
|
||||||
const tm_info = time.localtime(&timer);
|
const tm_info = time.localtime(&timer);
|
||||||
|
|
||||||
const len = time.strftime(buf, buf.len, format, tm_info);
|
const len = time.strftime(buf, buf.len, format, tm_info);
|
||||||
|
if (len < 0) return error.CannotGetFormattedTime;
|
||||||
|
|
||||||
return buf[0..len];
|
return buf[0..len];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTimeOfDay() !TimeOfDay {
|
pub fn switchTty(console_dev: []const u8, tty: u8) !void {
|
||||||
var tv: system_time.timeval = undefined;
|
const fd = try std.posix.open(console_dev, .{ .ACCMODE = .WRONLY }, 0);
|
||||||
const status = system_time.gettimeofday(&tv, null);
|
defer std.posix.close(fd);
|
||||||
|
|
||||||
if (status != 0) return error.FailedToGetTimeOfDay;
|
_ = std.c.ioctl(fd, vt.VT_ACTIVATE, tty);
|
||||||
|
_ = std.c.ioctl(fd, vt.VT_WAITACTIVE, tty);
|
||||||
return .{
|
|
||||||
.seconds = @intCast(tv.tv_sec),
|
|
||||||
.microseconds = @intCast(tv.tv_usec),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getActiveTty(allocator: std.mem.Allocator) !u8 {
|
pub fn getLockState(console_dev: []const u8) !struct {
|
||||||
return platform_struct.getActiveTtyImpl(allocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn switchTty(tty: u8) !void {
|
|
||||||
var status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.vt_activate, tty);
|
|
||||||
if (status != 0) return error.FailedToActivateTty;
|
|
||||||
|
|
||||||
status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.vt_waitactive, tty);
|
|
||||||
if (status != 0) return error.FailedToWaitForActiveTty;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getLockState() !struct {
|
|
||||||
numlock: bool,
|
numlock: bool,
|
||||||
capslock: bool,
|
capslock: bool,
|
||||||
} {
|
} {
|
||||||
var led: platform_struct.LedState = undefined;
|
const fd = try std.posix.open(console_dev, .{ .ACCMODE = .RDONLY }, 0);
|
||||||
const status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.get_led_state, &led);
|
defer std.posix.close(fd);
|
||||||
if (status != 0) return error.FailedToGetLockState;
|
|
||||||
|
var led: LedState = undefined;
|
||||||
|
_ = std.c.ioctl(fd, get_led_state, &led);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.numlock = (led & platform_struct.numlock_led) != 0,
|
.numlock = (led & numlock_led) != 0,
|
||||||
.capslock = (led & platform_struct.capslock_led) != 0,
|
.capslock = (led & capslock_led) != 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setNumlock(val: bool) !void {
|
pub fn setNumlock(val: bool) !void {
|
||||||
var led: platform_struct.LedState = undefined;
|
var led: LedState = undefined;
|
||||||
var status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.get_led_state, &led);
|
_ = std.c.ioctl(0, get_led_state, &led);
|
||||||
if (status != 0) return error.FailedToGetNumlock;
|
|
||||||
|
|
||||||
const numlock = (led & platform_struct.numlock_led) != 0;
|
const numlock = (led & numlock_led) != 0;
|
||||||
if (numlock != val) {
|
if (numlock != val) {
|
||||||
status = std.c.ioctl(std.posix.STDIN_FILENO, platform_struct.set_led_state, led ^ platform_struct.numlock_led);
|
const status = std.c.ioctl(std.posix.STDIN_FILENO, set_led_state, led ^ numlock_led);
|
||||||
if (status != 0) return error.FailedToSetNumlock;
|
if (status != 0) return error.FailedToSetNumlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setUserContext(allocator: std.mem.Allocator, entry: UsernameEntry) !void {
|
|
||||||
const username_z = try allocator.dupeZ(u8, entry.username.?);
|
|
||||||
defer allocator.free(username_z);
|
|
||||||
|
|
||||||
return platform_struct.setUserContextImpl(username_z.ptr, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setUserShell(entry: *UsernameEntry) void {
|
|
||||||
unistd.setusershell();
|
|
||||||
|
|
||||||
const shell = unistd.getusershell();
|
|
||||||
entry.shell = std.mem.span(shell);
|
|
||||||
|
|
||||||
unistd.endusershell();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setEnvironmentVariable(allocator: std.mem.Allocator, name: []const u8, value: []const u8, replace: bool) !void {
|
|
||||||
const name_z = try allocator.dupeZ(u8, name);
|
|
||||||
defer allocator.free(name_z);
|
|
||||||
|
|
||||||
const value_z = try allocator.dupeZ(u8, value);
|
|
||||||
defer allocator.free(value_z);
|
|
||||||
|
|
||||||
const status = stdlib.setenv(name_z.ptr, value_z.ptr, @intFromBool(replace));
|
|
||||||
if (status != 0) return error.SetEnvironmentVariableFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn putEnvironmentVariable(name_and_value: [*c]u8) !void {
|
|
||||||
const status = stdlib.putenv(name_and_value);
|
|
||||||
if (status != 0) return error.PutEnvironmentVariableFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getNextUsernameEntry() ?UsernameEntry {
|
|
||||||
const entry = pwd.getpwent();
|
|
||||||
if (entry == null) return null;
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.username = if (entry.*.pw_name) |name| std.mem.span(name) else null,
|
|
||||||
.uid = @intCast(entry.*.pw_uid),
|
|
||||||
.gid = @intCast(entry.*.pw_gid),
|
|
||||||
.home = if (entry.*.pw_dir) |dir| std.mem.span(dir) else null,
|
|
||||||
.shell = if (entry.*.pw_shell) |shell| std.mem.span(shell) else null,
|
|
||||||
.passwd_struct = entry,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getUsernameEntry(username: [:0]const u8) ?UsernameEntry {
|
|
||||||
const entry = pwd.getpwnam(username);
|
|
||||||
if (entry == null) return null;
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.username = if (entry.*.pw_name) |name| std.mem.span(name) else null,
|
|
||||||
.uid = @intCast(entry.*.pw_uid),
|
|
||||||
.gid = @intCast(entry.*.pw_gid),
|
|
||||||
.home = if (entry.*.pw_dir) |dir| std.mem.span(dir) else null,
|
|
||||||
.shell = if (entry.*.pw_shell) |shell| std.mem.span(shell) else null,
|
|
||||||
.passwd_struct = entry,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn closePasswordDatabase() void {
|
|
||||||
pwd.endpwent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is very bad parsing, but we only need to get 2 values... and the format
|
|
||||||
// of the file doesn't seem to be standard? So this should be fine...
|
|
||||||
pub fn getUserIdRange(allocator: std.mem.Allocator, file_path: []const u8) !UidRange {
|
|
||||||
return platform_struct.getUserIdRange(allocator, file_path);
|
|
||||||
}
|
|
||||||
|
|||||||
840
src/main.zig
840
src/main.zig
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const interop = @import("../interop.zig");
|
const interop = @import("../interop.zig");
|
||||||
const Cell = @import("Cell.zig");
|
const Cell = @import("Cell.zig");
|
||||||
|
|
||||||
@@ -30,22 +31,14 @@ pub const Styling = struct {
|
|||||||
|
|
||||||
pub const Color = struct {
|
pub const Color = struct {
|
||||||
pub const DEFAULT = 0x00000000;
|
pub const DEFAULT = 0x00000000;
|
||||||
pub const TRUE_BLACK = Styling.HI_BLACK;
|
pub const BLACK = Styling.HI_BLACK;
|
||||||
pub const TRUE_RED = 0x00FF0000;
|
pub const RED = 0x00FF0000;
|
||||||
pub const TRUE_GREEN = 0x0000FF00;
|
pub const GREEN = 0x0000FF00;
|
||||||
pub const TRUE_YELLOW = 0x00FFFF00;
|
pub const YELLOW = 0x00FFFF00;
|
||||||
pub const TRUE_BLUE = 0x000000FF;
|
pub const BLUE = 0x000000FF;
|
||||||
pub const TRUE_MAGENTA = 0x00FF00FF;
|
pub const MAGENTA = 0x00FF00FF;
|
||||||
pub const TRUE_CYAN = 0x0000FFFF;
|
pub const CYAN = 0x0000FFFF;
|
||||||
pub const TRUE_WHITE = 0x00FFFFFF;
|
pub const WHITE = 0x00FFFFFF;
|
||||||
pub const ECOL_BLACK = 1;
|
|
||||||
pub const ECOL_RED = 2;
|
|
||||||
pub const ECOL_GREEN = 3;
|
|
||||||
pub const ECOL_YELLOW = 4;
|
|
||||||
pub const ECOL_BLUE = 5;
|
|
||||||
pub const ECOL_MAGENTA = 6;
|
|
||||||
pub const ECOL_CYAN = 7;
|
|
||||||
pub const ECOL_WHITE = 8;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
random: Random,
|
random: Random,
|
||||||
@@ -81,7 +74,7 @@ pub fn init(options: InitOptions, labels_max_length: usize, random: Random) Term
|
|||||||
.fg = options.fg,
|
.fg = options.fg,
|
||||||
.bg = options.bg,
|
.bg = options.bg,
|
||||||
.border_fg = options.border_fg,
|
.border_fg = options.border_fg,
|
||||||
.box_chars = if (interop.supportsUnicode()) .{
|
.box_chars = if (builtin.os.tag == .linux or builtin.os.tag.isBSD()) .{
|
||||||
.left_up = 0x250C,
|
.left_up = 0x250C,
|
||||||
.left_down = 0x2514,
|
.left_down = 0x2514,
|
||||||
.right_up = 0x2510,
|
.right_up = 0x2510,
|
||||||
@@ -117,28 +110,24 @@ pub fn cascade(self: TerminalBuffer) bool {
|
|||||||
|
|
||||||
while (y > 0) : (y -= 1) {
|
while (y > 0) : (y -= 1) {
|
||||||
for (0..self.width) |x| {
|
for (0..self.width) |x| {
|
||||||
var cell: ?*termbox.tb_cell = undefined;
|
var cell: termbox.tb_cell = undefined;
|
||||||
var cell_under: ?*termbox.tb_cell = undefined;
|
var cell_under: termbox.tb_cell = undefined;
|
||||||
|
|
||||||
_ = termbox.tb_get_cell(@intCast(x), @intCast(y - 1), 1, &cell);
|
_ = termbox.tb_get_cell(@intCast(x), @intCast(y - 1), 1, &cell);
|
||||||
_ = termbox.tb_get_cell(@intCast(x), @intCast(y), 1, &cell_under);
|
_ = termbox.tb_get_cell(@intCast(x), @intCast(y), 1, &cell_under);
|
||||||
|
|
||||||
// This shouldn't happen under normal circumstances, but because
|
const char: u8 = @truncate(cell.ch);
|
||||||
// this is a *secret* animation, there's no need to care that much
|
|
||||||
if (cell == null or cell_under == null) continue;
|
|
||||||
|
|
||||||
const char: u8 = @truncate(cell.?.ch);
|
|
||||||
if (std.ascii.isWhitespace(char)) continue;
|
if (std.ascii.isWhitespace(char)) continue;
|
||||||
|
|
||||||
const char_under: u8 = @truncate(cell_under.?.ch);
|
const char_under: u8 = @truncate(cell_under.ch);
|
||||||
if (!std.ascii.isWhitespace(char_under)) continue;
|
if (!std.ascii.isWhitespace(char_under)) continue;
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
if ((self.random.int(u16) % 10) > 7) continue;
|
if ((self.random.int(u16) % 10) > 7) continue;
|
||||||
|
|
||||||
_ = termbox.tb_set_cell(@intCast(x), @intCast(y), cell.?.ch, cell.?.fg, cell.?.bg);
|
_ = termbox.tb_set_cell(@intCast(x), @intCast(y), cell.ch, cell.fg, cell.bg);
|
||||||
_ = termbox.tb_set_cell(@intCast(x), @intCast(y - 1), ' ', cell_under.?.fg, cell_under.?.bg);
|
_ = termbox.tb_set_cell(@intCast(x), @intCast(y - 1), ' ', cell_under.fg, cell_under.bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,9 +207,9 @@ pub fn drawColorLabel(text: []const u8, x: usize, y: usize, fg: u32, bg: u32) vo
|
|||||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||||
var utf8 = utf8view.iterator();
|
var utf8 = utf8view.iterator();
|
||||||
|
|
||||||
var i: c_int = @intCast(x);
|
var i = x;
|
||||||
while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) {
|
while (utf8.nextCodepoint()) |codepoint| : (i += 1) {
|
||||||
_ = termbox.tb_set_cell(i, yc, codepoint, fg, bg);
|
_ = termbox.tb_set_cell(@intCast(i), yc, codepoint, fg, bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,10 +218,10 @@ pub fn drawConfinedLabel(self: TerminalBuffer, text: []const u8, x: usize, y: us
|
|||||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||||
var utf8 = utf8view.iterator();
|
var utf8 = utf8view.iterator();
|
||||||
|
|
||||||
var i: c_int = @intCast(x);
|
var i: usize = 0;
|
||||||
while (utf8.nextCodepoint()) |codepoint| : (i += termbox.tb_wcwidth(codepoint)) {
|
while (utf8.nextCodepoint()) |codepoint| : (i += 1) {
|
||||||
if (i - @as(c_int, @intCast(x)) >= max_length) break;
|
if (i >= max_length) break;
|
||||||
_ = termbox.tb_set_cell(i, yc, codepoint, self.fg, self.bg);
|
_ = termbox.tb_set_cell(@intCast(i + x), yc, codepoint, self.fg, self.bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,8 +235,7 @@ pub fn drawCharMultiple(self: TerminalBuffer, char: u32, x: usize, y: usize, len
|
|||||||
pub fn strWidth(str: []const u8) !u8 {
|
pub fn strWidth(str: []const u8) !u8 {
|
||||||
const utf8view = try std.unicode.Utf8View.init(str);
|
const utf8view = try std.unicode.Utf8View.init(str);
|
||||||
var utf8 = utf8view.iterator();
|
var utf8 = utf8view.iterator();
|
||||||
var i: c_int = 0;
|
var i: u8 = 0;
|
||||||
while (utf8.nextCodepoint()) |codepoint| i += termbox.tb_wcwidth(codepoint);
|
while (utf8.nextCodepoint()) |_| i += 1;
|
||||||
|
return i;
|
||||||
return @intCast(i);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const generic = @import("generic.zig");
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const MessageLabel = generic.CyclableLabel(Message, Message);
|
const MessageLabel = generic.CyclableLabel(Message);
|
||||||
|
|
||||||
const InfoLine = @This();
|
const InfoLine = @This();
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ label: MessageLabel,
|
|||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer) InfoLine {
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer) InfoLine {
|
||||||
return .{
|
return .{
|
||||||
.label = MessageLabel.init(allocator, buffer, drawItem, null, null),
|
.label = MessageLabel.init(allocator, buffer, drawItem),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +1,46 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
const enums = @import("../../enums.zig");
|
const enums = @import("../../enums.zig");
|
||||||
|
const ini = @import("zigini");
|
||||||
const Environment = @import("../../Environment.zig");
|
const Environment = @import("../../Environment.zig");
|
||||||
const generic = @import("generic.zig");
|
const generic = @import("generic.zig");
|
||||||
const UserList = @import("UserList.zig");
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const DisplayServer = enums.DisplayServer;
|
const DisplayServer = enums.DisplayServer;
|
||||||
|
const Ini = ini.Ini;
|
||||||
const Env = struct {
|
const EnvironmentLabel = generic.CyclableLabel(Environment);
|
||||||
environment: Environment,
|
|
||||||
index: usize,
|
|
||||||
};
|
|
||||||
const EnvironmentLabel = generic.CyclableLabel(Env, *UserList);
|
|
||||||
|
|
||||||
const Session = @This();
|
const Session = @This();
|
||||||
|
|
||||||
label: EnvironmentLabel,
|
label: EnvironmentLabel,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, user_list: *UserList) Session {
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer) Session {
|
||||||
return .{
|
return .{
|
||||||
.label = EnvironmentLabel.init(allocator, buffer, drawItem, sessionChanged, user_list),
|
.label = EnvironmentLabel.init(allocator, buffer, drawItem),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Session) void {
|
pub fn deinit(self: *Session) void {
|
||||||
for (self.label.list.items) |*env| {
|
for (self.label.list.items) |*environment| {
|
||||||
if (env.environment.entry_ini) |*entry_ini| entry_ini.deinit();
|
if (environment.entry_ini) |*entry_ini| entry_ini.deinit();
|
||||||
|
if (environment.xdg_session_desktop) |session_desktop| self.label.allocator.free(session_desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.label.deinit();
|
self.label.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addEnvironment(self: *Session, environment: Environment) !void {
|
pub fn addEnvironment(self: *Session, environment: Environment) !void {
|
||||||
try self.label.addItem(.{ .environment = environment, .index = self.label.list.items.len });
|
try self.label.addItem(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sessionChanged(env: Env, maybe_user_list: ?*UserList) void {
|
fn drawItem(label: *EnvironmentLabel, environment: Environment, x: usize, y: usize) bool {
|
||||||
if (maybe_user_list) |user_list| {
|
const length = @min(environment.name.len, label.visible_length - 3);
|
||||||
user_list.label.list.items[user_list.label.current].session_index.* = env.index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn drawItem(label: *EnvironmentLabel, env: Env, x: usize, y: usize) bool {
|
|
||||||
const length = @min(env.environment.name.len, label.visible_length - 3);
|
|
||||||
if (length == 0) return false;
|
if (length == 0) return false;
|
||||||
|
|
||||||
const nx = if (label.text_in_center) (label.x + (label.visible_length - env.environment.name.len) / 2) else (label.x + 2);
|
const nx = if (label.text_in_center) (label.x + (label.visible_length - environment.name.len) / 2) else (label.x + 2);
|
||||||
label.first_char_x = nx + env.environment.name.len;
|
label.first_char_x = nx + environment.name.len;
|
||||||
|
|
||||||
label.buffer.drawLabel(env.environment.specifier, x, y);
|
label.buffer.drawLabel(environment.specifier, x, y);
|
||||||
label.buffer.drawLabel(env.environment.name, nx, label.y);
|
label.buffer.drawLabel(environment.name, nx, label.y);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
|
||||||
const generic = @import("generic.zig");
|
|
||||||
const Session = @import("Session.zig");
|
|
||||||
const SavedUsers = @import("../../config/SavedUsers.zig");
|
|
||||||
|
|
||||||
const StringList = std.ArrayListUnmanaged([]const u8);
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
pub const User = struct {
|
|
||||||
name: []const u8,
|
|
||||||
session_index: *usize,
|
|
||||||
allocated_index: bool,
|
|
||||||
};
|
|
||||||
const UserLabel = generic.CyclableLabel(User, *Session);
|
|
||||||
|
|
||||||
const UserList = @This();
|
|
||||||
|
|
||||||
label: UserLabel,
|
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, usernames: StringList, saved_users: *SavedUsers, session: *Session) !UserList {
|
|
||||||
var userList = UserList{
|
|
||||||
.label = UserLabel.init(allocator, buffer, drawItem, usernameChanged, session),
|
|
||||||
};
|
|
||||||
|
|
||||||
for (usernames.items) |username| {
|
|
||||||
if (username.len == 0) continue;
|
|
||||||
|
|
||||||
var maybe_session_index: ?*usize = null;
|
|
||||||
for (saved_users.user_list.items) |*saved_user| {
|
|
||||||
if (std.mem.eql(u8, username, saved_user.username)) {
|
|
||||||
maybe_session_index = &saved_user.session_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var allocated_index = false;
|
|
||||||
if (maybe_session_index == null) {
|
|
||||||
maybe_session_index = try allocator.create(usize);
|
|
||||||
maybe_session_index.?.* = 0;
|
|
||||||
allocated_index = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try userList.label.addItem(.{
|
|
||||||
.name = username,
|
|
||||||
.session_index = maybe_session_index.?,
|
|
||||||
.allocated_index = allocated_index,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return userList;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *UserList) void {
|
|
||||||
for (self.label.list.items) |user| {
|
|
||||||
if (user.allocated_index) {
|
|
||||||
self.label.allocator.destroy(user.session_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.label.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getCurrentUsername(self: UserList) []const u8 {
|
|
||||||
return self.label.list.items[self.label.current].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn usernameChanged(user: User, maybe_session: ?*Session) void {
|
|
||||||
if (maybe_session) |session| {
|
|
||||||
session.label.current = user.session_index.*;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn drawItem(label: *UserLabel, user: User, _: usize, _: usize) bool {
|
|
||||||
const length = @min(user.name.len, label.visible_length - 3);
|
|
||||||
if (length == 0) return false;
|
|
||||||
|
|
||||||
const x = if (label.text_in_center) (label.x + (label.visible_length - user.name.len) / 2) else (label.x + 2);
|
|
||||||
label.first_char_x = x + user.name.len;
|
|
||||||
|
|
||||||
label.buffer.drawLabel(user.name, x, label.y);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,11 @@ const std = @import("std");
|
|||||||
const interop = @import("../../interop.zig");
|
const interop = @import("../../interop.zig");
|
||||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||||
|
|
||||||
pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) type {
|
pub fn CyclableLabel(comptime ItemType: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ItemList = std.ArrayListUnmanaged(ItemType);
|
const ItemList = std.ArrayListUnmanaged(ItemType);
|
||||||
const DrawItemFn = *const fn (*Self, ItemType, usize, usize) bool;
|
const DrawItemFn = *const fn (*Self, ItemType, usize, usize) bool;
|
||||||
const ChangeItemFn = *const fn (ItemType, ?ChangeItemType) void;
|
|
||||||
|
|
||||||
const termbox = interop.termbox;
|
const termbox = interop.termbox;
|
||||||
|
|
||||||
@@ -23,10 +22,8 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
|||||||
first_char_x: usize,
|
first_char_x: usize,
|
||||||
text_in_center: bool,
|
text_in_center: bool,
|
||||||
draw_item_fn: DrawItemFn,
|
draw_item_fn: DrawItemFn,
|
||||||
change_item_fn: ?ChangeItemFn,
|
|
||||||
change_item_arg: ?ChangeItemType,
|
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, draw_item_fn: DrawItemFn, change_item_fn: ?ChangeItemFn, change_item_arg: ?ChangeItemType) Self {
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, draw_item_fn: DrawItemFn) Self {
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.buffer = buffer,
|
.buffer = buffer,
|
||||||
@@ -38,8 +35,6 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
|||||||
.first_char_x = 0,
|
.first_char_x = 0,
|
||||||
.text_in_center = false,
|
.text_in_center = false,
|
||||||
.draw_item_fn = draw_item_fn,
|
.draw_item_fn = draw_item_fn,
|
||||||
.change_item_fn = change_item_fn,
|
|
||||||
.change_item_arg = change_item_arg,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,19 +94,21 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn goLeft(self: *Self) void {
|
fn goLeft(self: *Self) void {
|
||||||
self.current = if (self.current == 0) self.list.items.len - 1 else self.current - 1;
|
if (self.current == 0) {
|
||||||
|
self.current = self.list.items.len - 1;
|
||||||
if (self.change_item_fn) |change_item_fn| {
|
return;
|
||||||
@call(.auto, change_item_fn, .{ self.list.items[self.current], self.change_item_arg });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.current -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn goRight(self: *Self) void {
|
fn goRight(self: *Self) void {
|
||||||
self.current = if (self.current == self.list.items.len - 1) 0 else self.current + 1;
|
if (self.current == self.list.items.len - 1) {
|
||||||
|
self.current = 0;
|
||||||
if (self.change_item_fn) |change_item_fn| {
|
return;
|
||||||
@call(.auto, change_item_fn, .{ self.list.items[self.current], self.change_item_arg });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.current += 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user