mirror of
https://github.com/fairyglade/ly.git
synced 2025-12-21 03:34:54 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0692885c5 | ||
|
|
b6d3aa0e1c | ||
|
|
e6966a628c | ||
|
|
cab3f1bfb5 | ||
|
|
a9ff0a6d07 | ||
|
|
92beb24c80 | ||
|
|
7e18d906c4 | ||
|
|
3bfdc75a70 | ||
|
|
6cce221cbf | ||
|
|
1c99574f73 | ||
|
|
b249dba092 | ||
|
|
3365b33d6d | ||
|
|
6cb53b6e38 | ||
|
|
d82fa82a87 | ||
|
|
c2b3d794e8 | ||
|
|
e29bda3250 | ||
|
|
4df2382698 | ||
|
|
3dfb86fe69 | ||
|
|
f9a001b160 | ||
|
|
5235ca47c5 | ||
|
|
a94abf2e69 | ||
|
|
fe354a4809 | ||
|
|
8c964d9ce5 | ||
|
|
392ea6ea63 | ||
|
|
10854e643a | ||
|
|
1980b2e479 | ||
|
|
816be7449f | ||
|
|
f0758d812e | ||
|
|
3c0c84d067 | ||
|
|
cc07c4870a | ||
|
|
68ec85f412 | ||
|
|
1537addd67 | ||
|
|
2da3648179 | ||
|
|
0cf752f3b8 | ||
|
|
15c78c838a | ||
|
|
4a486bd876 | ||
|
|
38173d8557 | ||
|
|
95d1d9378c | ||
|
|
6f62106fcc | ||
|
|
4171e29995 | ||
|
|
80c27224e9 | ||
|
|
106f157a2c | ||
|
|
ec16ad5dfc | ||
|
|
5f22173b91 | ||
|
|
4bc405f239 |
11
.github/ISSUE_TEMPLATE/bug.yml
vendored
11
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -11,11 +11,15 @@ body:
|
|||||||
options:
|
options:
|
||||||
- label: I have looked for any other duplicate issues
|
- label: I have looked for any other duplicate issues
|
||||||
required: true
|
required: true
|
||||||
|
- label: I have reproduced the issue on a fresh install of my OS & Ly with default settings, except ones I will mention
|
||||||
|
required: true
|
||||||
|
- label: I have confirmed this issue also occurs on the latest development version
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: version
|
id: version
|
||||||
attributes:
|
attributes:
|
||||||
label: Ly version
|
label: Ly version
|
||||||
description: The output of `ly --version`. Please note that only Ly v1.1.0 and above are supported.
|
description: The output of `ly --version`. Please note that only Ly v1.2.0 and above are supported.
|
||||||
placeholder: 1.1.0-dev.12+2b0301c
|
placeholder: 1.1.0-dev.12+2b0301c
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
@@ -58,8 +62,9 @@ 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 (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. The log files (located as specified by `/etc/ly/config.ini`) usually contain relevant information about the problem:
|
||||||
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.
|
- The session log is located at `~/.local/state/ly-session.log` by default.
|
||||||
|
- The system log is located at `/var/log/ly.log` by default.
|
||||||
render: shell
|
render: shell
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: moreinfo
|
id: moreinfo
|
||||||
|
|||||||
11
.github/pull_request_template.md
vendored
Normal file
11
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
## What are the changes about?
|
||||||
|
|
||||||
|
_Replace this with a brief description of your changes_
|
||||||
|
|
||||||
|
## What existing issue does this resolve?
|
||||||
|
|
||||||
|
_Replace this with a reference to an existing issue, or N/A if there is none_
|
||||||
|
|
||||||
|
## Pre-requisites
|
||||||
|
|
||||||
|
- [ ] I have tested & confirmed the changes work locally
|
||||||
BIN
.github/screenshot.png
vendored
BIN
.github/screenshot.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 34 KiB |
21
build.zig
21
build.zig
@@ -23,7 +23,7 @@ comptime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ly_version = std.SemanticVersion{ .major = 1, .minor = 2, .patch = 0 };
|
const ly_version = std.SemanticVersion{ .major = 1, .minor = 3, .patch = 0 };
|
||||||
|
|
||||||
var dest_directory: []const u8 = undefined;
|
var dest_directory: []const u8 = undefined;
|
||||||
var config_directory: []const u8 = undefined;
|
var config_directory: []const u8 = undefined;
|
||||||
@@ -44,6 +44,8 @@ pub fn build(b: *std.Build) !void {
|
|||||||
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;
|
const fallback_tty = b.option(u8, "fallback_tty", "Set the fallback TTY (default is 2). This value gets embedded into the binary") orelse 2;
|
||||||
|
const fallback_uid_min = b.option(std.posix.uid_t, "fallback_uid_min", "Set the fallback minimum UID (default is 1000). This value gets embedded into the binary") orelse 1000;
|
||||||
|
const fallback_uid_max = b.option(std.posix.uid_t, "fallback_uid_max", "Set the fallback maximum UID (default is 60000). This value gets embedded into the binary") orelse 60000;
|
||||||
|
|
||||||
default_tty_str = try std.fmt.allocPrint(b.allocator, "{d}", .{default_tty});
|
default_tty_str = try std.fmt.allocPrint(b.allocator, "{d}", .{default_tty});
|
||||||
|
|
||||||
@@ -52,6 +54,8 @@ pub fn build(b: *std.Build) !void {
|
|||||||
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(u8, "fallback_tty", fallback_tty);
|
||||||
|
build_options.addOption(std.posix.uid_t, "fallback_uid_min", fallback_uid_min);
|
||||||
|
build_options.addOption(std.posix.uid_t, "fallback_uid_max", fallback_uid_max);
|
||||||
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(.{});
|
||||||
@@ -244,6 +248,7 @@ fn install_ly(allocator: std.mem.Allocator, patch_map: PatchMap, install_config:
|
|||||||
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(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(if (init_system == .freebsd) "res/pam.d/ly-freebsd-autologin" else "res/pam.d/ly-linux-autologin", pam_dir, pam_path, "ly-autologin", .{ .override_mode = 0o644 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,8 +260,8 @@ fn install_service(allocator: std.mem.Allocator, patch_map: PatchMap) !void {
|
|||||||
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
var service_dir = std.fs.cwd().openDir(service_path, .{}) catch unreachable;
|
||||||
defer service_dir.close();
|
defer service_dir.close();
|
||||||
|
|
||||||
const patched_service = try patchFile(allocator, "res/ly.service", patch_map);
|
const patched_service = try patchFile(allocator, "res/ly@.service", patch_map);
|
||||||
try installText(patched_service, service_dir, service_path, "ly.service", .{ .mode = 0o644 });
|
try installText(patched_service, service_dir, service_path, "ly@.service", .{ .mode = 0o644 });
|
||||||
},
|
},
|
||||||
.openrc => {
|
.openrc => {
|
||||||
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/init.d" });
|
const service_path = try std.fs.path.join(allocator, &[_][]const u8{ dest_directory, config_directory, "/init.d" });
|
||||||
@@ -283,7 +288,13 @@ fn install_service(allocator: std.mem.Allocator, patch_map: PatchMap) !void {
|
|||||||
const patched_run = try patchFile(allocator, "res/ly-runit-service/run", patch_map);
|
const patched_run = try patchFile(allocator, "res/ly-runit-service/run", patch_map);
|
||||||
try installText(patched_run, service_dir, service_path, "run", .{ .mode = 0o755 });
|
try installText(patched_run, service_dir, service_path, "run", .{ .mode = 0o755 });
|
||||||
|
|
||||||
try std.fs.cwd().symLink("/run/runit/supervise.ly", supervise_path, .{});
|
std.fs.cwd().symLink("/run/runit/supervise.ly", supervise_path, .{}) catch |err| {
|
||||||
|
if (err == error.PathAlreadyExists) {
|
||||||
|
std.debug.print("warn: /run/runit/supervise.ly already exists as a symbolic link.\n", .{});
|
||||||
|
} else {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
};
|
||||||
std.debug.print("info: installed symlink /run/runit/supervise.ly\n", .{});
|
std.debug.print("info: installed symlink /run/runit/supervise.ly\n", .{});
|
||||||
},
|
},
|
||||||
.s6 => {
|
.s6 => {
|
||||||
@@ -354,7 +365,7 @@ pub fn Uninstaller(uninstall_config: bool) type {
|
|||||||
try deleteFile(allocator, config_directory, "/pam.d/ly", "ly pam file not found");
|
try deleteFile(allocator, config_directory, "/pam.d/ly", "ly pam file not found");
|
||||||
|
|
||||||
switch (init_system) {
|
switch (init_system) {
|
||||||
.systemd => try deleteFile(allocator, prefix_directory, "/lib/systemd/system/ly.service", "systemd service not found"),
|
.systemd => try deleteFile(allocator, prefix_directory, "/lib/systemd/system/ly@.service", "systemd service not found"),
|
||||||
.openrc => try deleteFile(allocator, config_directory, "/init.d/ly", "openrc service not found"),
|
.openrc => try deleteFile(allocator, config_directory, "/init.d/ly", "openrc service not found"),
|
||||||
.runit => try deleteTree(allocator, config_directory, "/sv/ly", "runit service not found"),
|
.runit => try deleteTree(allocator, config_directory, "/sv/ly", "runit service not found"),
|
||||||
.s6 => {
|
.s6 => {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
.{
|
.{
|
||||||
.name = .ly,
|
.name = .ly,
|
||||||
.version = "1.2.0",
|
.version = "1.3.0",
|
||||||
.fingerprint = 0xa148ffcc5dc2cb59,
|
.fingerprint = 0xa148ffcc5dc2cb59,
|
||||||
.minimum_zig_version = "0.15.0",
|
.minimum_zig_version = "0.15.0",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.clap = .{
|
.clap = .{
|
||||||
.url = "https://github.com/Hejsil/zig-clap/archive/refs/tags/0.11.0.tar.gz",
|
.url = "git+https://github.com/Hejsil/zig-clap#5289e0753cd274d65344bef1c114284c633536ea",
|
||||||
.hash = "clap-0.11.0-oBajB-HnAQDPCKYzwF7rO3qDFwRcD39Q0DALlTSz5H7e",
|
.hash = "clap-0.11.0-oBajB-HnAQDPCKYzwF7rO3qDFwRcD39Q0DALlTSz5H7e",
|
||||||
},
|
},
|
||||||
.zigini = .{
|
.zigini = .{
|
||||||
.url = "https://github.com/AnErrupTion/zigini/archive/96ca1d9f1a7ec741f07ceb104dae2b3a7bdfd48a.tar.gz",
|
.url = "git+https://github.com/AnErrupTion/zigini?ref=zig-0.15.0#9281f47702b57779e831d7618e158abb8eb4d4a2",
|
||||||
.hash = "zigini-0.3.2-BSkB7WJJAADybd5DGd9MLCp6ikGGUq9wicxsjv0HF1Qc",
|
.hash = "zigini-0.3.3-36M0FRJJAADZVq5HPm-hYKMpFFTr0OgjbEYcK2ijKZ5n",
|
||||||
},
|
},
|
||||||
.termbox2 = .{
|
.termbox2 = .{
|
||||||
.url = "git+https://github.com/AnErrupTion/termbox2?ref=master#290ac6b8225aacfd16851224682b851b65fcb918",
|
.url = "git+https://github.com/AnErrupTion/termbox2?ref=master#290ac6b8225aacfd16851224682b851b65fcb918",
|
||||||
|
|||||||
20
readme.md
20
readme.md
@@ -44,9 +44,9 @@ It is recommended to add a rule for Ly as it currently does not ship one.
|
|||||||
# pkg install ca_root_nss libxcb git xorg xauth
|
# pkg install ca_root_nss libxcb git xorg xauth
|
||||||
```
|
```
|
||||||
|
|
||||||
## Packaging status
|
## Availability
|
||||||
|
|
||||||
[](https://repology.org/project/ly/versions)
|
[](https://repology.org/project/ly-display-manager/versions)
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
@@ -57,6 +57,11 @@ managers, all of which you can find in the sections below:
|
|||||||
|
|
||||||
[X11 environments](#supported-x11-environments)
|
[X11 environments](#supported-x11-environments)
|
||||||
|
|
||||||
|
Logs are defined by `/etc/ly/config.ini`:
|
||||||
|
|
||||||
|
- The session log is located at `~/.local/state/ly-session.log` by default.
|
||||||
|
- The system log is located at `/var/log/ly.log` by default.
|
||||||
|
|
||||||
## Manually building
|
## Manually building
|
||||||
|
|
||||||
The procedure for manually building Ly is pretty standard:
|
The procedure for manually building Ly is pretty standard:
|
||||||
@@ -106,20 +111,19 @@ command:
|
|||||||
Then, similarly to the previous command, you need to enable the Ly service:
|
Then, similarly to the previous command, you need to enable the Ly service:
|
||||||
|
|
||||||
```
|
```
|
||||||
# systemctl enable ly.service
|
# systemctl enable ly@tty2.service
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Because Ly runs in a TTY, you **must** disable the TTY service
|
**Important**: Because Ly runs in a TTY, you **must** disable the TTY service
|
||||||
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
|
that Ly will run on, otherwise bad things will happen. For example, to disable `getty` spawning on TTY 2, you need to execute the following command:
|
||||||
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
|
You can change the TTY Ly will run on by editing the corresponding
|
||||||
configuration file **and** change which TTY is used in the corresponding
|
service file for your platform, or on systemd, by enabling the service on
|
||||||
service file..
|
different TTYs, as is done above.
|
||||||
|
|
||||||
### OpenRC
|
### OpenRC
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ allow_empty_password = true
|
|||||||
# matrix -> CMatrix
|
# matrix -> CMatrix
|
||||||
# colormix -> Color mixing shader
|
# colormix -> Color mixing shader
|
||||||
# gameoflife -> John Conway's Game of Life
|
# gameoflife -> John Conway's Game of Life
|
||||||
|
# dur_file -> .dur file format (https://github.com/cmang/durdraw/tree/master)
|
||||||
animation = none
|
animation = none
|
||||||
|
|
||||||
# Stop the animation after some time
|
# Stop the animation after some time
|
||||||
@@ -39,6 +40,7 @@ animation_timeout_sec = 0
|
|||||||
asterisk = *
|
asterisk = *
|
||||||
|
|
||||||
# The number of failed authentications before a special animation is played... ;)
|
# The number of failed authentications before a special animation is played... ;)
|
||||||
|
# If set to 0, the animation will never be played
|
||||||
auth_fails = 10
|
auth_fails = 10
|
||||||
|
|
||||||
# Identifier for battery whose charge to display at top left
|
# Identifier for battery whose charge to display at top left
|
||||||
@@ -46,6 +48,30 @@ auth_fails = 10
|
|||||||
# If set to null, battery status won't be shown
|
# If set to null, battery status won't be shown
|
||||||
battery_id = null
|
battery_id = null
|
||||||
|
|
||||||
|
# Automatic login configuration
|
||||||
|
# This feature allows Ly to automatically log in a user without password prompt.
|
||||||
|
# IMPORTANT: Both auto_login_user and auto_login_session must be set for this to work.
|
||||||
|
# Autologin only happens once at startup - it won't re-trigger after logout.
|
||||||
|
|
||||||
|
# PAM service name to use for automatic login
|
||||||
|
# The default service (ly-autologin) uses pam_permit to allow login without password
|
||||||
|
# The appropriate platform-specific PAM configuration (ly-autologin) will be used automatically
|
||||||
|
auto_login_service = ly-autologin
|
||||||
|
|
||||||
|
# Session name to launch automatically
|
||||||
|
# To find available session names, check the .desktop files in:
|
||||||
|
# - /usr/share/xsessions/ (for X11 sessions)
|
||||||
|
# - /usr/share/wayland-sessions/ (for Wayland sessions)
|
||||||
|
# Use the filename without .desktop extension, or the value of DesktopNames field
|
||||||
|
# Examples: "i3", "sway", "gnome", "plasma", "xfce"
|
||||||
|
# If null, automatic login is disabled
|
||||||
|
auto_login_session = null
|
||||||
|
|
||||||
|
# Username to automatically log in
|
||||||
|
# Must be a valid user on the system
|
||||||
|
# If null, automatic login is disabled
|
||||||
|
auto_login_user = null
|
||||||
|
|
||||||
# Background color id
|
# Background color id
|
||||||
bg = 0x00000000
|
bg = 0x00000000
|
||||||
|
|
||||||
@@ -138,6 +164,18 @@ doom_middle_color = 0x00C78F17
|
|||||||
# DOOM animation custom bottom color (high intensity flames)
|
# DOOM animation custom bottom color (high intensity flames)
|
||||||
doom_bottom_color = 0x00FFFFFF
|
doom_bottom_color = 0x00FFFFFF
|
||||||
|
|
||||||
|
# Dur file path
|
||||||
|
dur_file_path = $CONFIG_DIRECTORY/ly/example.dur
|
||||||
|
|
||||||
|
# Dur offset x direction
|
||||||
|
dur_x_offset = 0
|
||||||
|
|
||||||
|
# Dur offset y direction
|
||||||
|
dur_y_offset = 0
|
||||||
|
|
||||||
|
# Set margin to the edges of the DM (useful for curved monitors)
|
||||||
|
edge_margin = 0
|
||||||
|
|
||||||
# Error background color id
|
# Error background color id
|
||||||
error_bg = 0x00000000
|
error_bg = 0x00000000
|
||||||
|
|
||||||
@@ -162,6 +200,8 @@ fg = 0x00FFFFFF
|
|||||||
# TB_WHITE 0x0008
|
# TB_WHITE 0x0008
|
||||||
# If full color is off, the styling options still work. The colors are
|
# 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.
|
# always 32-bit values with the styling in the most significant byte.
|
||||||
|
# Note: If using the dur_file animation option and the dur file's color range
|
||||||
|
# is saved as 256 with this option disabled, the file will not be drawn.
|
||||||
full_color = true
|
full_color = true
|
||||||
|
|
||||||
# Game of Life entropy interval (0 = disabled, >0 = add entropy every N generations)
|
# Game of Life entropy interval (0 = disabled, >0 = add entropy every N generations)
|
||||||
@@ -185,15 +225,31 @@ gameoflife_frame_delay = 6
|
|||||||
# 0.7+ -> Dense, chaotic patterns
|
# 0.7+ -> Dense, chaotic patterns
|
||||||
gameoflife_initial_density = 0.4
|
gameoflife_initial_density = 0.4
|
||||||
|
|
||||||
|
# Command executed when pressing hibernate key (can be null)
|
||||||
|
hibernate_cmd = null
|
||||||
|
|
||||||
|
# Specifies the key used for hibernate (F1-F12)
|
||||||
|
hibernate_key = F4
|
||||||
|
|
||||||
# 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 keyboard lock states from the top right corner
|
||||||
|
hide_keyboard_locks = false
|
||||||
|
|
||||||
# Remove version number from the top left corner
|
# Remove version number from the top left corner
|
||||||
hide_version_string = false
|
hide_version_string = false
|
||||||
|
|
||||||
|
# Command executed when no input is detected for a certain time
|
||||||
|
# If null, no command will be executed
|
||||||
|
inactivity_cmd = null
|
||||||
|
|
||||||
|
# Executes a command after a certain amount of seconds
|
||||||
|
inactivity_delay = 0
|
||||||
|
|
||||||
# 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
|
||||||
@@ -258,7 +314,7 @@ service_name = ly
|
|||||||
# 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
|
# If null, no session log will be created
|
||||||
session_log = ly-session.log
|
session_log = .local/state/ly-session.log
|
||||||
|
|
||||||
# Setup command
|
# Setup command
|
||||||
setup_cmd = $CONFIG_DIRECTORY/ly/setup.sh
|
setup_cmd = $CONFIG_DIRECTORY/ly/setup.sh
|
||||||
@@ -275,6 +331,10 @@ sleep_cmd = null
|
|||||||
# Specifies the key used for sleep (F1-F12)
|
# Specifies the key used for sleep (F1-F12)
|
||||||
sleep_key = F3
|
sleep_key = F3
|
||||||
|
|
||||||
|
# Command executed when starting Ly (before the TTY is taken control of)
|
||||||
|
# If null, no command will be executed
|
||||||
|
start_cmd = null
|
||||||
|
|
||||||
# Center the session name.
|
# Center the session name.
|
||||||
text_in_center = false
|
text_in_center = false
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@ 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_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
|
||||||
@@ -44,8 +49,10 @@ err_pwnam = فشل في جلب معلومات المستخدم
|
|||||||
err_sleep = فشل في تنفيذ أمر sleep
|
err_sleep = فشل في تنفيذ أمر sleep
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = فشل في نقل تحكم الطرفية (TTY)
|
err_tty_ctrl = فشل في نقل تحكم الطرفية (TTY)
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = فشل في تعيين معرّف المجموعة (GID) للمستخدم
|
err_user_gid = فشل في تعيين معرّف المجموعة (GID) للمستخدم
|
||||||
err_user_init = فشل في تهيئة بيانات المستخدم
|
err_user_init = فشل في تهيئة بيانات المستخدم
|
||||||
err_user_uid = فشل في تعيين معرّف المستخدم (UID)
|
err_user_uid = فشل في تعيين معرّف المستخدم (UID)
|
||||||
@@ -53,6 +60,7 @@ err_xauth = فشل في تنفيذ أمر xauth
|
|||||||
err_xcb_conn = فشل في الاتصال بمكتبة XCB
|
err_xcb_conn = فشل في الاتصال بمكتبة XCB
|
||||||
err_xsessions_dir = فشل في العثور على مجلد Xsessions
|
err_xsessions_dir = فشل في العثور على مجلد Xsessions
|
||||||
err_xsessions_open = فشل في فتح مجلد Xsessions
|
err_xsessions_open = فشل في فتح مجلد Xsessions
|
||||||
|
|
||||||
insert = ادخال
|
insert = ادخال
|
||||||
login = تسجيل الدخول
|
login = تسجيل الدخول
|
||||||
logout = تم تسجيل خروجك
|
logout = تم تسجيل خروجك
|
||||||
|
|||||||
78
res/lang/bg.ini
Normal file
78
res/lang/bg.ini
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
authenticating = удостоверяване...
|
||||||
|
brightness_down = намаляване на яркостта
|
||||||
|
brightness_up = увеличаване на яркостта
|
||||||
|
capslock = caps lock
|
||||||
|
custom = персонализирано
|
||||||
|
err_alloc = неуспешно заделяне на памет
|
||||||
|
err_args = неуспешен анализ на аргументите от командния ред
|
||||||
|
err_autologin_session = сесията за автоматично влизане не е намерена
|
||||||
|
err_bounds = индексът е извън границите
|
||||||
|
err_brightness_change = неуспешна промяна на яркостта
|
||||||
|
err_chdir = неуспешно отваряне на домашната папка
|
||||||
|
err_clock_too_long = низът на часовника е твърде дълъг
|
||||||
|
err_config = неуспешен анализ на конфигурационния файл
|
||||||
|
err_crawl = неуспешно обхождане на папките със сесии
|
||||||
|
err_dgn_oob = съобщение в дневника
|
||||||
|
err_domain = невалиден домейн
|
||||||
|
err_empty_password = не е позволена празна парола
|
||||||
|
err_envlist = неуспешно получаване на списъка с променливи на средата
|
||||||
|
err_get_active_tty = неуспешно откриване на активния TTY
|
||||||
|
err_hibernate = неуспешно изпълнение на командата за хибернация
|
||||||
|
err_hostname = неуспешно получаване на името на хоста
|
||||||
|
err_inactivity = неуспешно изпълнение на командата за неактивност
|
||||||
|
err_lock_state = неуспешно получаване на състоянието на заключване
|
||||||
|
err_log = неуспешно отваряне на файла с дневника
|
||||||
|
err_mlock = неуспешно заключване на паметта за паролата
|
||||||
|
err_null = нулев указател
|
||||||
|
err_numlock = неуспешно задаване на num lock
|
||||||
|
err_pam = неуспешна транзакция
|
||||||
|
err_pam_abort = прекратена транзакция
|
||||||
|
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_start = неуспешно изпълнение на командата за стартиране
|
||||||
|
err_battery = неуспешно зареждане на състоянието на батерията
|
||||||
|
err_switch_tty = неуспешна смяна на TTY
|
||||||
|
err_tty_ctrl = неуспешно прехвърляне на контрола над TTY
|
||||||
|
err_no_users = не са намерени потребители
|
||||||
|
err_uid_range = неуспешно динамично получаване на UID обхват
|
||||||
|
err_user_gid = неуспешно задаване на потребителския GID
|
||||||
|
err_user_init = неуспешна стартиране на потребителя
|
||||||
|
err_user_uid = неуспешно задаване на потребителския UID
|
||||||
|
err_xauth = неуспешна команда xauth
|
||||||
|
err_xcb_conn = неуспешна xcb връзка
|
||||||
|
err_xsessions_dir = папката със сесии не е намерена
|
||||||
|
err_xsessions_open = неуспешно отваряне на папката със сесии
|
||||||
|
hibernate = хибернация
|
||||||
|
insert = вмъкване
|
||||||
|
login = вход
|
||||||
|
logout = излизане
|
||||||
|
no_x11_support = поддръжката на x11 е изключена при компилирането
|
||||||
|
normal = нормално
|
||||||
|
numlock = num lock
|
||||||
|
other = друго
|
||||||
|
password = парола
|
||||||
|
restart = рестартиране
|
||||||
|
shell = обвивка
|
||||||
|
shutdown = изключване
|
||||||
|
sleep = заспиване
|
||||||
|
wayland = wayland
|
||||||
|
x11 = x11
|
||||||
|
xinitrc = xinitrc
|
||||||
@@ -4,19 +4,24 @@ 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_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
|
||||||
@@ -46,6 +51,8 @@ err_pwnam = error en obtenir la informació de l'usuari
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@@ -53,6 +60,7 @@ err_xauth = error en la comanda xauth
|
|||||||
err_xcb_conn = error en la connexió xcb
|
err_xcb_conn = error en la connexió xcb
|
||||||
err_xsessions_dir = error en trobar la carpeta de sessions
|
err_xsessions_dir = error en trobar la carpeta de sessions
|
||||||
err_xsessions_open = error en obrir la carpeta de sessions
|
err_xsessions_open = error en obrir la carpeta de sessions
|
||||||
|
|
||||||
insert = inserir
|
insert = inserir
|
||||||
login = iniciar sessió
|
login = iniciar sessió
|
||||||
logout = sessió tancada
|
logout = sessió tancada
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = nastavení UID uživateli selhalo
|
|||||||
err_xsessions_dir = nepodařilo se najít složku relací
|
err_xsessions_dir = nepodařilo se najít složku relací
|
||||||
err_xsessions_open = nepodařilo se otevřít složku relací
|
err_xsessions_open = nepodařilo se otevřít složku relací
|
||||||
|
|
||||||
|
|
||||||
login = uživatel
|
login = uživatel
|
||||||
logout = odhlášen
|
logout = odhlášen
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@ brightness_up = Helligkeit+
|
|||||||
capslock = Feststelltaste
|
capslock = Feststelltaste
|
||||||
|
|
||||||
err_alloc = Speicherzuweisung fehlgeschlagen
|
err_alloc = Speicherzuweisung fehlgeschlagen
|
||||||
|
|
||||||
|
|
||||||
err_bounds = Index ausserhalb des Bereichs
|
err_bounds = Index ausserhalb des Bereichs
|
||||||
err_brightness_change = Helligkeitsänderung fehlgeschlagen
|
err_brightness_change = Helligkeitsänderung fehlgeschlagen
|
||||||
err_chdir = Fehler beim Oeffnen des Home-Ordners
|
err_chdir = Fehler beim Oeffnen des Home-Ordners
|
||||||
|
|
||||||
err_config = Fehler beim Verarbeiten der Konfigurationsdatei
|
err_config = Fehler beim Verarbeiten der Konfigurationsdatei
|
||||||
|
|
||||||
err_dgn_oob = Diagnose-Nachricht
|
err_dgn_oob = Diagnose-Nachricht
|
||||||
err_domain = Ungueltige Domain
|
err_domain = Ungueltige Domain
|
||||||
err_empty_password = Leeres Passwort nicht zugelassen
|
err_empty_password = Leeres Passwort nicht zugelassen
|
||||||
err_envlist = Fehler beim Abrufen der Umgebungs-Variablen
|
err_envlist = Fehler beim Abrufen der Umgebungs-Variablen
|
||||||
|
|
||||||
|
|
||||||
err_hostname = Abrufen des Hostnames fehlgeschlagen
|
err_hostname = Abrufen des Hostnames fehlgeschlagen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_mlock = Sperren des Passwortspeichers fehlgeschlagen
|
err_mlock = Sperren des Passwortspeichers fehlgeschlagen
|
||||||
err_null = Null Pointer
|
err_null = Null Pointer
|
||||||
err_numlock = Numlock konnte nicht aktiviert werden
|
err_numlock = Numlock konnte nicht aktiviert werden
|
||||||
@@ -44,8 +49,10 @@ err_pwnam = Abrufen der Benutzerinformationen fehlgeschlagen
|
|||||||
err_sleep = Sleep-Befehl fehlgeschlagen
|
err_sleep = Sleep-Befehl fehlgeschlagen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = Fehler bei der TTY-Uebergabe
|
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
|
||||||
err_user_init = Nutzer-Initialisierung fehlgeschlagen
|
err_user_init = Nutzer-Initialisierung fehlgeschlagen
|
||||||
err_user_uid = Setzen der Benutzer-ID fehlgeschlagen
|
err_user_uid = Setzen der Benutzer-ID fehlgeschlagen
|
||||||
@@ -53,6 +60,7 @@ err_xauth = Xauth-Befehl fehlgeschlagen
|
|||||||
err_xcb_conn = xcb-Verbindung 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 Oeffnen des Sitzungsordners
|
||||||
|
|
||||||
insert = Einfügen
|
insert = Einfügen
|
||||||
login = Nutzer
|
login = Nutzer
|
||||||
logout = Abmelden
|
logout = Abmelden
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ brightness_up = increase brightness
|
|||||||
capslock = capslock
|
capslock = capslock
|
||||||
custom = custom
|
custom = custom
|
||||||
err_alloc = failed memory allocation
|
err_alloc = failed memory allocation
|
||||||
|
err_args = unable to parse command line arguments
|
||||||
|
err_autologin_session = autologin session not found
|
||||||
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_clock_too_long = clock string too long
|
||||||
err_config = unable to parse config file
|
err_config = unable to parse config file
|
||||||
|
err_crawl = failed to crawl session directories
|
||||||
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_get_active_tty = failed to get active tty
|
||||||
|
err_hibernate = failed to execute hibernate command
|
||||||
err_hostname = failed to get hostname
|
err_hostname = failed to get hostname
|
||||||
|
err_inactivity = failed to execute inactivity command
|
||||||
err_lock_state = failed to get lock state
|
err_lock_state = failed to get lock state
|
||||||
err_log = failed to open log file
|
err_log = failed to open log file
|
||||||
err_mlock = failed to lock password memory
|
err_mlock = failed to lock password memory
|
||||||
@@ -42,10 +47,12 @@ 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_start = failed to execute start command
|
||||||
err_battery = failed to load battery status
|
err_battery = failed to load battery status
|
||||||
err_switch_tty = failed to switch tty
|
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_no_users = no users found
|
||||||
|
err_uid_range = failed to dynamically get uid range
|
||||||
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
|
||||||
@@ -53,6 +60,7 @@ err_xauth = xauth command failed
|
|||||||
err_xcb_conn = xcb connection failed
|
err_xcb_conn = xcb connection failed
|
||||||
err_xsessions_dir = failed to find sessions folder
|
err_xsessions_dir = failed to find sessions folder
|
||||||
err_xsessions_open = failed to open sessions folder
|
err_xsessions_open = failed to open sessions folder
|
||||||
|
hibernate = hibernate
|
||||||
insert = insert
|
insert = insert
|
||||||
login = login
|
login = login
|
||||||
logout = logged out
|
logout = logged out
|
||||||
|
|||||||
@@ -4,19 +4,24 @@ 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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -53,6 +60,7 @@ err_user_uid = error al establecer el UID del usuario
|
|||||||
|
|
||||||
err_xsessions_dir = error al buscar la carpeta de sesiones
|
err_xsessions_dir = error al buscar la carpeta de sesiones
|
||||||
err_xsessions_open = error al abrir la carpeta de sesiones
|
err_xsessions_open = error al abrir la carpeta de sesiones
|
||||||
|
|
||||||
insert = insertar
|
insert = insertar
|
||||||
login = usuario
|
login = usuario
|
||||||
logout = cerrar sesión
|
logout = cerrar sesión
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ brightness_up = augmenter la luminosité
|
|||||||
capslock = verr.maj
|
capslock = verr.maj
|
||||||
custom = customisé
|
custom = customisé
|
||||||
err_alloc = échec d'allocation mémoire
|
err_alloc = échec d'allocation mémoire
|
||||||
|
err_args = échec de l'analyse des arguments en lignes de commande
|
||||||
|
err_autologin_session = session de connexion automatique introuvable
|
||||||
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_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_crawl = échec de la navigation des répertoires de session
|
||||||
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_get_active_tty = échec de lecture du terminal actif
|
||||||
|
err_hibernate = échec de l'exécution de la commande de veille prolongée
|
||||||
err_hostname = échec de lecture du nom d'hôte
|
err_hostname = échec de lecture du nom d'hôte
|
||||||
|
err_inactivity = échec de l'exécution de la commande d'inactivité
|
||||||
err_lock_state = échec de lecture de l'état de verrouillage
|
err_lock_state = échec de lecture de l'état de verrouillage
|
||||||
err_log = échec de l'ouverture du fichier de journal
|
err_log = échec de l'ouverture du fichier de journal
|
||||||
err_mlock = échec du verrouillage mémoire
|
err_mlock = échec du verrouillage mémoire
|
||||||
@@ -42,10 +47,12 @@ 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_start = échec de l'exécution de la commande de démarrage
|
||||||
err_battery = échec de lecture de l'état de la batterie
|
err_battery = échec de lecture de l'état de la batterie
|
||||||
err_switch_tty = échec du changement de terminal
|
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_no_users = aucun utilisateur trouvé
|
||||||
|
err_uid_range = échec de récupération dynamique de la plage d'UID
|
||||||
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
|
||||||
@@ -53,6 +60,7 @@ err_xauth = échec de la commande xauth
|
|||||||
err_xcb_conn = échec de la connexion xcb
|
err_xcb_conn = échec de la connexion xcb
|
||||||
err_xsessions_dir = échec de la recherche du dossier de sessions
|
err_xsessions_dir = échec de la recherche du dossier de sessions
|
||||||
err_xsessions_open = échec de l'ouverture du dossier de sessions
|
err_xsessions_open = échec de l'ouverture du dossier de sessions
|
||||||
|
hibernate = veille prolongée
|
||||||
insert = insertion
|
insert = insertion
|
||||||
login = identifiant
|
login = identifiant
|
||||||
logout = déconnecté
|
logout = déconnecté
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = impossible impostare UID utente
|
|||||||
err_xsessions_dir = impossibile localizzare cartella sessioni
|
err_xsessions_dir = impossibile localizzare cartella sessioni
|
||||||
err_xsessions_open = impossibile aprire cartella sessioni
|
err_xsessions_open = impossibile aprire cartella sessioni
|
||||||
|
|
||||||
|
|
||||||
login = username
|
login = username
|
||||||
logout = scollegato
|
logout = scollegato
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@ brightness_up = 明るさを上げる
|
|||||||
capslock = CapsLock
|
capslock = CapsLock
|
||||||
|
|
||||||
err_alloc = メモリ割り当て失敗
|
err_alloc = メモリ割り当て失敗
|
||||||
|
|
||||||
|
|
||||||
err_bounds = 境界外インデックス
|
err_bounds = 境界外インデックス
|
||||||
err_brightness_change = 明るさの変更に失敗しました
|
err_brightness_change = 明るさの変更に失敗しました
|
||||||
err_chdir = ホームフォルダを開けませんでした
|
err_chdir = ホームフォルダを開けませんでした
|
||||||
|
|
||||||
err_config = 設定ファイルを解析できません
|
err_config = 設定ファイルを解析できません
|
||||||
|
|
||||||
err_dgn_oob = ログメッセージ
|
err_dgn_oob = ログメッセージ
|
||||||
err_domain = 無効なドメイン
|
err_domain = 無効なドメイン
|
||||||
err_empty_password = 空のパスワードは許可されていません
|
err_empty_password = 空のパスワードは許可されていません
|
||||||
err_envlist = 環境変数リストの取得に失敗しました
|
err_envlist = 環境変数リストの取得に失敗しました
|
||||||
|
|
||||||
|
|
||||||
err_hostname = ホスト名の取得に失敗しました
|
err_hostname = ホスト名の取得に失敗しました
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_mlock = パスワードメモリのロックに失敗しました
|
err_mlock = パスワードメモリのロックに失敗しました
|
||||||
err_null = ヌルポインタ
|
err_null = ヌルポインタ
|
||||||
err_numlock = NumLockの設定に失敗しました
|
err_numlock = NumLockの設定に失敗しました
|
||||||
@@ -44,8 +49,10 @@ err_pwnam = ユーザー情報の取得に失敗しました
|
|||||||
err_sleep = スリープコマンドの実行に失敗しました
|
err_sleep = スリープコマンドの実行に失敗しました
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_tty_ctrl = TTY制御の転送に失敗しました
|
err_tty_ctrl = TTY制御の転送に失敗しました
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = ユーザーGIDの設定に失敗しました
|
err_user_gid = ユーザーGIDの設定に失敗しました
|
||||||
err_user_init = ユーザーの初期化に失敗しました
|
err_user_init = ユーザーの初期化に失敗しました
|
||||||
err_user_uid = ユーザーUIDの設定に失敗しました
|
err_user_uid = ユーザーUIDの設定に失敗しました
|
||||||
@@ -53,6 +60,7 @@ err_xauth = xauthコマンドの実行に失敗しました
|
|||||||
err_xcb_conn = XCB接続に失敗しました
|
err_xcb_conn = XCB接続に失敗しました
|
||||||
err_xsessions_dir = セッションフォルダが見つかりませんでした
|
err_xsessions_dir = セッションフォルダが見つかりませんでした
|
||||||
err_xsessions_open = セッションフォルダを開けませんでした
|
err_xsessions_open = セッションフォルダを開けませんでした
|
||||||
|
|
||||||
insert = 挿入
|
insert = 挿入
|
||||||
login = ログイン
|
login = ログイン
|
||||||
logout = ログアウト済み
|
logout = ログアウト済み
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ brightness_up = palielināt spilgtumu
|
|||||||
capslock = caps lock
|
capslock = caps lock
|
||||||
custom = pielāgots
|
custom = pielāgots
|
||||||
err_alloc = neizdevās atmiņas piešķiršana
|
err_alloc = neizdevās atmiņas piešķiršana
|
||||||
|
|
||||||
|
|
||||||
err_bounds = indekss ārpus robežām
|
err_bounds = indekss ārpus robežām
|
||||||
err_brightness_change = neizdevās mainīt spilgtumu
|
err_brightness_change = neizdevās mainīt spilgtumu
|
||||||
err_chdir = neizdevās atvērt mājas mapi
|
err_chdir = neizdevās atvērt mājas mapi
|
||||||
err_clock_too_long = pulksteņa virkne pārāk gara
|
err_clock_too_long = pulksteņa virkne pārāk gara
|
||||||
err_config = neizdevās parsēt konfigurācijas failu
|
err_config = neizdevās parsēt konfigurācijas failu
|
||||||
|
|
||||||
err_dgn_oob = žurnāla ziņojums
|
err_dgn_oob = žurnāla ziņojums
|
||||||
err_domain = nederīgs domēns
|
err_domain = nederīgs domēns
|
||||||
err_empty_password = tukša parole nav atļauta
|
err_empty_password = tukša parole nav atļauta
|
||||||
err_envlist = neizdevās iegūt vides mainīgo sarakstu
|
err_envlist = neizdevās iegūt vides mainīgo sarakstu
|
||||||
err_get_active_tty = neizdevās iegūt aktīvo tty
|
err_get_active_tty = neizdevās iegūt aktīvo tty
|
||||||
|
|
||||||
err_hostname = neizdevās iegūt hostname
|
err_hostname = neizdevās iegūt hostname
|
||||||
|
|
||||||
err_lock_state = neizdevās iegūt bloķēšanas stāvokli
|
err_lock_state = neizdevās iegūt bloķēšanas stāvokli
|
||||||
err_log = neizdevās atvērt žurnāla failu
|
err_log = neizdevās atvērt žurnāla failu
|
||||||
err_mlock = neizdevās bloķēt paroles atmiņu
|
err_mlock = neizdevās bloķēt paroles atmiņu
|
||||||
@@ -42,10 +47,12 @@ err_perm_group = neizdevās pazemināt grupas atļaujas
|
|||||||
err_perm_user = neizdevās pazemināt lietotāja atļaujas
|
err_perm_user = neizdevās pazemināt lietotāja atļaujas
|
||||||
err_pwnam = neizdevās iegūt lietotāja informāciju
|
err_pwnam = neizdevās iegūt lietotāja informāciju
|
||||||
err_sleep = neizdevās izpildīt miega komandu
|
err_sleep = neizdevās izpildīt miega komandu
|
||||||
|
|
||||||
err_battery = neizdevās ielādēt akumulatora stāvokli
|
err_battery = neizdevās ielādēt akumulatora stāvokli
|
||||||
err_switch_tty = neizdevās pārslēgt tty
|
err_switch_tty = neizdevās pārslēgt tty
|
||||||
err_tty_ctrl = tty vadības nodošana neizdevās
|
err_tty_ctrl = tty vadības nodošana neizdevās
|
||||||
err_no_users = lietotāji nav atrasti
|
err_no_users = lietotāji nav atrasti
|
||||||
|
|
||||||
err_user_gid = neizdevās iestatīt lietotāja GID
|
err_user_gid = neizdevās iestatīt lietotāja GID
|
||||||
err_user_init = neizdevās inicializēt lietotāju
|
err_user_init = neizdevās inicializēt lietotāju
|
||||||
err_user_uid = neizdevās iestatīt lietotāja UID
|
err_user_uid = neizdevās iestatīt lietotāja UID
|
||||||
@@ -53,6 +60,7 @@ err_xauth = xauth komanda neizdevās
|
|||||||
err_xcb_conn = xcb savienojums neizdevās
|
err_xcb_conn = xcb savienojums neizdevās
|
||||||
err_xsessions_dir = neizdevās atrast sesiju mapi
|
err_xsessions_dir = neizdevās atrast sesiju mapi
|
||||||
err_xsessions_open = neizdevās atvērt sesiju mapi
|
err_xsessions_open = neizdevās atvērt sesiju mapi
|
||||||
|
|
||||||
insert = ievietot
|
insert = ievietot
|
||||||
login = lietotājs
|
login = lietotājs
|
||||||
logout = iziet
|
logout = iziet
|
||||||
@@ -68,4 +76,3 @@ sleep = snauda
|
|||||||
wayland = wayland
|
wayland = wayland
|
||||||
x11 = x11
|
x11 = x11
|
||||||
xinitrc = xinitrc
|
xinitrc = xinitrc
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,26 @@ authenticating = uwierzytelnianie...
|
|||||||
brightness_down = zmniejsz jasność
|
brightness_down = zmniejsz jasność
|
||||||
brightness_up = zwiększ jasność
|
brightness_up = zwiększ jasność
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
custom = własny
|
||||||
err_alloc = nieudana alokacja pamięci
|
err_alloc = nieudana alokacja pamięci
|
||||||
|
|
||||||
|
err_autologin_session = nie znaleziono sesji autologowania
|
||||||
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_clock_too_long = ciąg znaków zegara jest za długi
|
||||||
err_config = nie można przetworzyć pliku konfiguracyjnego
|
err_config = nie można przetworzyć pliku konfiguracyjnego
|
||||||
|
|
||||||
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_get_active_tty = nie udało się uzyskać aktywnego tty
|
||||||
|
|
||||||
err_hostname = nie udało się uzyskać nazwy hosta
|
err_hostname = nie udało się uzyskać nazwy hosta
|
||||||
|
|
||||||
|
err_lock_state = nie udało się uzyskać stanu blokady
|
||||||
|
err_log = nie udało się otworzyć pliku logu
|
||||||
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
|
||||||
@@ -43,8 +48,10 @@ 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_battery = nie udało się sprawdzić statusu baterii
|
||||||
|
err_switch_tty = nie można przełączyć tty
|
||||||
err_tty_ctrl = nie udało się przekazać kontroli tty
|
err_tty_ctrl = nie udało się przekazać kontroli tty
|
||||||
|
err_no_users = nie znaleziono żadnego użytkownika
|
||||||
|
|
||||||
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
|
||||||
@@ -53,6 +60,7 @@ err_xauth = polecenie xauth nie powiodło się
|
|||||||
err_xcb_conn = połączenie xcb nie powiodło się
|
err_xcb_conn = połączenie xcb nie powiodło się
|
||||||
err_xsessions_dir = nie udało się znaleźć folderu sesji
|
err_xsessions_dir = nie udało się znaleźć folderu sesji
|
||||||
err_xsessions_open = nie udało się otworzyć folderu sesji
|
err_xsessions_open = nie udało się otworzyć folderu sesji
|
||||||
|
|
||||||
insert = wstaw
|
insert = wstaw
|
||||||
login = login
|
login = login
|
||||||
logout = wylogowano
|
logout = wylogowano
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = erro ao definir o UID do utilizador
|
|||||||
err_xsessions_dir = erro ao localizar a pasta das sessões
|
err_xsessions_dir = erro ao localizar a pasta das sessões
|
||||||
err_xsessions_open = erro ao abrir a pasta das sessões
|
err_xsessions_open = erro ao abrir a pasta das sessões
|
||||||
|
|
||||||
|
|
||||||
login = iniciar sessão
|
login = iniciar sessão
|
||||||
logout = terminar sessão
|
logout = terminar sessão
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = não foi possível definir o UID do usuário
|
|||||||
err_xsessions_dir = não foi possível encontrar a pasta das sessões
|
err_xsessions_dir = não foi possível encontrar a pasta das sessões
|
||||||
err_xsessions_open = não foi possível abrir a pasta das sessões
|
err_xsessions_open = não foi possível abrir a pasta das sessões
|
||||||
|
|
||||||
|
|
||||||
login = conectar
|
login = conectar
|
||||||
logout = desconectado
|
logout = desconectado
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ capslock = capslock
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -54,6 +59,9 @@ err_perm_user = nu s-a putut face downgrade permisiunilor de utilizator
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
login = utilizator
|
login = utilizator
|
||||||
logout = opreşte sesiunea
|
logout = opreşte sesiunea
|
||||||
|
|
||||||
|
|||||||
@@ -2,24 +2,29 @@ authenticating = аутентификация...
|
|||||||
brightness_down = уменьшить яркость
|
brightness_down = уменьшить яркость
|
||||||
brightness_up = увеличить яркость
|
brightness_up = увеличить яркость
|
||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
custom = пользовательский
|
||||||
err_alloc = не удалось выделить память
|
err_alloc = не удалось выделить память
|
||||||
|
|
||||||
|
err_autologin_session = не найдена сессия с автологином
|
||||||
err_bounds = за пределами индекса
|
err_bounds = за пределами индекса
|
||||||
err_brightness_change = не удалось изменить яркость
|
err_brightness_change = не удалось изменить яркость
|
||||||
err_chdir = не удалось открыть домашнюю папку
|
err_chdir = не удалось открыть домашнюю папку
|
||||||
|
err_clock_too_long = строка часов слишком длинная
|
||||||
err_config = не удалось разобрать файл конфигурации
|
err_config = не удалось разобрать файл конфигурации
|
||||||
|
|
||||||
err_dgn_oob = отладочное сообщение (log)
|
err_dgn_oob = отладочное сообщение (log)
|
||||||
err_domain = неверный домен
|
err_domain = неверный домен
|
||||||
err_empty_password = пустой пароль не допустим
|
err_empty_password = пустой пароль не допустим
|
||||||
err_envlist = не удалось получить список переменных среды
|
err_envlist = не удалось получить список переменных среды
|
||||||
|
err_get_active_tty = не удалось получить активный tty
|
||||||
|
|
||||||
err_hostname = не удалось получить имя хоста
|
err_hostname = не удалось получить имя хоста
|
||||||
|
|
||||||
|
err_lock_state = не удалось получить состояние lock
|
||||||
|
err_log = не удалось открыть файл log
|
||||||
err_mlock = сбой блокировки памяти
|
err_mlock = сбой блокировки памяти
|
||||||
err_null = нулевой указатель
|
err_null = нулевой указатель
|
||||||
|
err_numlock = не удалось установить numlock
|
||||||
err_pam = pam транзакция не удалась
|
err_pam = pam транзакция не удалась
|
||||||
err_pam_abort = pam транзакция прервана
|
err_pam_abort = pam транзакция прервана
|
||||||
err_pam_acct_expired = срок действия аккаунта истёк
|
err_pam_acct_expired = срок действия аккаунта истёк
|
||||||
@@ -43,9 +48,11 @@ err_perm_user = не удалось понизить права доступа
|
|||||||
err_pwnam = не удалось получить информацию о пользователе
|
err_pwnam = не удалось получить информацию о пользователе
|
||||||
err_sleep = не удалось выполнить команду sleep
|
err_sleep = не удалось выполнить команду sleep
|
||||||
|
|
||||||
|
err_battery = не удалось получить статус батареи
|
||||||
err_switch_tty = не удалось переключить tty
|
err_switch_tty = не удалось переключить tty
|
||||||
err_tty_ctrl = передача управления tty не удалась
|
err_tty_ctrl = передача управления tty не удалась
|
||||||
err_no_users = пользователи не найдены
|
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 пользователя
|
||||||
@@ -54,10 +61,11 @@ err_xcb_conn = ошибка подключения xcb
|
|||||||
err_xsessions_dir = не удалось найти сессионную папку
|
err_xsessions_dir = не удалось найти сессионную папку
|
||||||
err_xsessions_open = не удалось открыть сессионную папку
|
err_xsessions_open = не удалось открыть сессионную папку
|
||||||
|
|
||||||
|
insert = вставка
|
||||||
login = логин
|
login = логин
|
||||||
logout = вышел из системы
|
logout = вышел из системы
|
||||||
no_x11_support = поддержка x11 отключена во время компиляции
|
no_x11_support = поддержка x11 отключена во время компиляции
|
||||||
|
normal = обычный
|
||||||
numlock = numlock
|
numlock = numlock
|
||||||
other = прочие
|
other = прочие
|
||||||
password = пароль
|
password = пароль
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = neuspijesno postavljanje UID-a korisnika
|
|||||||
err_xsessions_dir = neuspijesno pronalazenje foldera sesija
|
err_xsessions_dir = neuspijesno pronalazenje foldera sesija
|
||||||
err_xsessions_open = neuspijesno otvaranje foldera sesija
|
err_xsessions_open = neuspijesno otvaranje foldera sesija
|
||||||
|
|
||||||
|
|
||||||
login = korisnik
|
login = korisnik
|
||||||
logout = izlogovan
|
logout = izlogovan
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = misslyckades att ställa in användar-UID
|
|||||||
err_xsessions_dir = misslyckades att hitta sessionskatalog
|
err_xsessions_dir = misslyckades att hitta sessionskatalog
|
||||||
err_xsessions_open = misslyckades att öppna sessionskatalog
|
err_xsessions_open = misslyckades att öppna sessionskatalog
|
||||||
|
|
||||||
|
|
||||||
login = inloggning
|
login = inloggning
|
||||||
logout = utloggad
|
logout = utloggad
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
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_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
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ 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
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = kullanici icin UID ayarlanamadi
|
|||||||
err_xsessions_dir = oturumlar klasoru bulunamadi
|
err_xsessions_dir = oturumlar klasoru bulunamadi
|
||||||
err_xsessions_open = oturumlar klasoru acilamadi
|
err_xsessions_open = oturumlar klasoru acilamadi
|
||||||
|
|
||||||
|
|
||||||
login = kullanici
|
login = kullanici
|
||||||
logout = oturumdan cikis yapildi
|
logout = oturumdan cikis yapildi
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
capslock = capslock
|
capslock = capslock
|
||||||
|
|
||||||
err_alloc = невдале виділення пам'яті
|
err_alloc = невдале виділення пам'яті
|
||||||
|
|
||||||
|
|
||||||
err_bounds = поза межами індексу
|
err_bounds = поза межами індексу
|
||||||
|
|
||||||
err_chdir = не вдалося відкрити домашній каталог
|
err_chdir = не вдалося відкрити домашній каталог
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_dgn_oob = повідомлення журналу (log)
|
err_dgn_oob = повідомлення журналу (log)
|
||||||
err_domain = недійсний домен
|
err_domain = недійсний домен
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = не вдалося отримати ім'я хосту
|
err_hostname = не вдалося отримати ім'я хосту
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_mlock = збій блокування пам'яті
|
err_mlock = збій блокування пам'яті
|
||||||
err_null = нульовий вказівник
|
err_null = нульовий вказівник
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ err_pwnam = не вдалося отримати дані користувача
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = не вдалося змінити GID користувача
|
err_user_gid = не вдалося змінити GID користувача
|
||||||
err_user_init = не вдалося ініціалізувати користувача
|
err_user_init = не вдалося ініціалізувати користувача
|
||||||
err_user_uid = не вдалося змінити UID користувача
|
err_user_uid = не вдалося змінити UID користувача
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = не вдалося змінити UID користувача
|
|||||||
err_xsessions_dir = не вдалося знайти каталог сесій
|
err_xsessions_dir = не вдалося знайти каталог сесій
|
||||||
err_xsessions_open = не вдалося відкрити каталог сесій
|
err_xsessions_open = не вдалося відкрити каталог сесій
|
||||||
|
|
||||||
|
|
||||||
login = логін
|
login = логін
|
||||||
logout = вийти
|
logout = вийти
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,24 @@
|
|||||||
capslock = 大写锁定
|
capslock = 大写锁定
|
||||||
|
|
||||||
err_alloc = 内存分配失败
|
err_alloc = 内存分配失败
|
||||||
|
|
||||||
|
|
||||||
err_bounds = 索引越界
|
err_bounds = 索引越界
|
||||||
|
|
||||||
err_chdir = 无法打开home文件夹
|
err_chdir = 无法打开home文件夹
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_dgn_oob = 日志消息
|
err_dgn_oob = 日志消息
|
||||||
err_domain = 无效的域
|
err_domain = 无效的域
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_hostname = 获取主机名失败
|
err_hostname = 获取主机名失败
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_mlock = 锁定密码存储器失败
|
err_mlock = 锁定密码存储器失败
|
||||||
err_null = 空指针
|
err_null = 空指针
|
||||||
|
|
||||||
@@ -46,6 +51,8 @@ err_pwnam = 获取用户信息失败
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
err_user_gid = 设置用户GID失败
|
err_user_gid = 设置用户GID失败
|
||||||
err_user_init = 初始化用户失败
|
err_user_init = 初始化用户失败
|
||||||
err_user_uid = 设置用户UID失败
|
err_user_uid = 设置用户UID失败
|
||||||
@@ -54,6 +61,7 @@ err_user_uid = 设置用户UID失败
|
|||||||
err_xsessions_dir = 找不到会话文件夹
|
err_xsessions_dir = 找不到会话文件夹
|
||||||
err_xsessions_open = 无法打开会话文件夹
|
err_xsessions_open = 无法打开会话文件夹
|
||||||
|
|
||||||
|
|
||||||
login = 登录
|
login = 登录
|
||||||
logout = 注销
|
logout = 注销
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=TUI display manager
|
Description=TUI display manager
|
||||||
After=systemd-user-sessions.service plymouth-quit-wait.service
|
After=systemd-user-sessions.service plymouth-quit-wait.service
|
||||||
After=getty@tty$DEFAULT_TTY.service
|
After=getty@%I.service
|
||||||
Conflicts=getty@tty$DEFAULT_TTY.service
|
Conflicts=getty@%I.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=idle
|
Type=idle
|
||||||
ExecStart=$PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME
|
ExecStart=$PREFIX_DIRECTORY/bin/$EXECUTABLE_NAME
|
||||||
StandardInput=tty
|
StandardInput=tty
|
||||||
TTYPath=/dev/tty$DEFAULT_TTY
|
TTYPath=/dev/%I
|
||||||
TTYReset=yes
|
TTYReset=yes
|
||||||
TTYVHangup=yes
|
TTYVHangup=yes
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
Alias=display-manager.service
|
WantedBy=multi-user.target
|
||||||
9
res/pam.d/ly-freebsd-autologin
Normal file
9
res/pam.d/ly-freebsd-autologin
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#%PAM-1.0
|
||||||
|
|
||||||
|
# OpenPAM (used in FreeBSD) doesn't support prepending "-" for ignoring missing
|
||||||
|
# modules.
|
||||||
|
auth required pam_permit.so
|
||||||
|
auth include login
|
||||||
|
account include login
|
||||||
|
password include login
|
||||||
|
session include login
|
||||||
16
res/pam.d/ly-linux-autologin
Normal file
16
res/pam.d/ly-linux-autologin
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#%PAM-1.0
|
||||||
|
|
||||||
|
auth required pam_permit.so
|
||||||
|
-auth optional pam_gnome_keyring.so
|
||||||
|
-auth optional pam_kwallet5.so
|
||||||
|
|
||||||
|
account include login
|
||||||
|
|
||||||
|
password include login
|
||||||
|
-password optional pam_gnome_keyring.so use_authtok
|
||||||
|
|
||||||
|
-session optional pam_systemd.so class=greeter
|
||||||
|
-session optional pam_elogind.so
|
||||||
|
session include login
|
||||||
|
-session optional pam_gnome_keyring.so auto_start
|
||||||
|
-session optional pam_kwallet5.so auto_start
|
||||||
@@ -16,6 +16,7 @@ pub const Entry = struct { @"Desktop Entry": DesktopEntry = .{} };
|
|||||||
entry_ini: ?Ini(Entry) = null,
|
entry_ini: ?Ini(Entry) = null,
|
||||||
name: []const u8 = "",
|
name: []const u8 = "",
|
||||||
xdg_session_desktop: ?[]const u8 = null,
|
xdg_session_desktop: ?[]const u8 = null,
|
||||||
|
xdg_session_desktop_owned: bool = false,
|
||||||
xdg_desktop_names: ?[]const u8 = null,
|
xdg_desktop_names: ?[]const u8 = null,
|
||||||
cmd: ?[]const u8 = null,
|
cmd: ?[]const u8 = null,
|
||||||
specifier: []const u8 = "",
|
specifier: []const u8 = "",
|
||||||
|
|||||||
408
src/animations/DurFile.zig
Normal file
408
src/animations/DurFile.zig
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Animation = @import("../tui/Animation.zig");
|
||||||
|
const Cell = @import("../tui/Cell.zig");
|
||||||
|
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
||||||
|
const Color = TerminalBuffer.Color;
|
||||||
|
const Styling = TerminalBuffer.Styling;
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Json = std.json;
|
||||||
|
const eql = std.mem.eql;
|
||||||
|
const flate = std.compress.flate;
|
||||||
|
|
||||||
|
fn read_decompress_file(allocator: Allocator, file_path: []const u8) ![]u8 {
|
||||||
|
const file_buffer = std.fs.cwd().openFile(file_path, .{}) catch {
|
||||||
|
return error.FileNotFound;
|
||||||
|
};
|
||||||
|
defer file_buffer.close();
|
||||||
|
|
||||||
|
var file_reader_buffer: [4096]u8 = undefined;
|
||||||
|
var decompress_buffer: [flate.max_window_len]u8 = undefined;
|
||||||
|
|
||||||
|
var file_reader = file_buffer.reader(&file_reader_buffer);
|
||||||
|
var decompress: flate.Decompress = .init(&file_reader.interface, .gzip, &decompress_buffer);
|
||||||
|
|
||||||
|
const file_decompressed = decompress.reader.allocRemaining(allocator, .unlimited) catch {
|
||||||
|
return error.NotValidFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
return file_decompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Frame = struct {
|
||||||
|
frameNumber: i32,
|
||||||
|
delay: f32,
|
||||||
|
contents: [][]u8,
|
||||||
|
colorMap: [][][]i32,
|
||||||
|
|
||||||
|
// allocator must be outside of struct as it will fail the json parser
|
||||||
|
pub fn deinit(self: *const Frame, allocator: Allocator) void {
|
||||||
|
for (self.contents) |con| {
|
||||||
|
allocator.free(con);
|
||||||
|
}
|
||||||
|
allocator.free(self.contents);
|
||||||
|
|
||||||
|
for (self.colorMap) |cm| {
|
||||||
|
for (cm) |int2| {
|
||||||
|
allocator.free(int2);
|
||||||
|
}
|
||||||
|
allocator.free(cm);
|
||||||
|
}
|
||||||
|
allocator.free(self.colorMap);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://github.com/cmang/durdraw/blob/0.29.0/durformat.md
|
||||||
|
const DurFormat = struct {
|
||||||
|
allocator: Allocator,
|
||||||
|
formatVersion: ?i64 = null,
|
||||||
|
colorFormat: ?[]const u8 = null,
|
||||||
|
encoding: ?[]const u8 = null,
|
||||||
|
framerate: ?f64 = null,
|
||||||
|
columns: ?i64 = null,
|
||||||
|
lines: ?i64 = null,
|
||||||
|
frames: std.ArrayList(Frame) = undefined,
|
||||||
|
|
||||||
|
pub fn valid(self: *DurFormat) bool {
|
||||||
|
if (self.formatVersion != null and
|
||||||
|
self.colorFormat != null and
|
||||||
|
self.encoding != null and
|
||||||
|
self.framerate != null and
|
||||||
|
self.columns != null and
|
||||||
|
self.lines != null and
|
||||||
|
self.frames.items.len >= 1)
|
||||||
|
{
|
||||||
|
// v8 may have breaking changes like changing the colormap xy direction
|
||||||
|
// (https://github.com/cmang/durdraw/issues/24)
|
||||||
|
if (self.formatVersion.? != 7) return false;
|
||||||
|
|
||||||
|
// Code currently only supports 16 and 256 color format only
|
||||||
|
if (!(eql(u8, "16", self.colorFormat.?) or eql(u8, "256", self.colorFormat.?)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Code currently supports only utf-8 encoding
|
||||||
|
if (!eql(u8, self.encoding.?, "utf-8")) return false;
|
||||||
|
|
||||||
|
// Sanity check on file
|
||||||
|
if (self.columns.? <= 0) return false;
|
||||||
|
if (self.lines.? <= 0) return false;
|
||||||
|
if (self.framerate.? < 0) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_dur_from_json(self: *DurFormat, allocator: Allocator, dur_json_root: Json.Value) !void {
|
||||||
|
var dur_movie = if (dur_json_root.object.get("DurMovie")) |dm| dm.object else return error.NotValidFile;
|
||||||
|
|
||||||
|
// Depending on the version, a dur file can have different json object names (ie: columns vs sizeX)
|
||||||
|
self.formatVersion = if (dur_movie.get("formatVersion")) |x| x.integer else null;
|
||||||
|
self.colorFormat = if (dur_movie.get("colorFormat")) |x| try allocator.dupe(u8, x.string) else null;
|
||||||
|
self.encoding = if (dur_movie.get("encoding")) |x| try allocator.dupe(u8, x.string) else null;
|
||||||
|
self.framerate = if (dur_movie.get("framerate")) |x| x.float else null;
|
||||||
|
self.columns = if (dur_movie.get("columns")) |x| x.integer else if (dur_movie.get("sizeX")) |x| x.integer else null;
|
||||||
|
|
||||||
|
self.lines = if (dur_movie.get("lines")) |x| x.integer else if (dur_movie.get("sizeY")) |x| x.integer else null;
|
||||||
|
|
||||||
|
const frames = dur_movie.get("frames") orelse return error.NotValidFile;
|
||||||
|
|
||||||
|
self.frames = try .initCapacity(allocator, frames.array.items.len);
|
||||||
|
|
||||||
|
for (frames.array.items) |json_frame| {
|
||||||
|
var parsed_frame = try Json.parseFromValue(Frame, allocator, json_frame, .{});
|
||||||
|
defer parsed_frame.deinit();
|
||||||
|
|
||||||
|
const frame_val = parsed_frame.value;
|
||||||
|
|
||||||
|
// copy all fields to own the ptrs for deallocation, the parsed_frame has some other
|
||||||
|
// allocated memory making it difficult to deallocate without leaks
|
||||||
|
const frame: Frame = .{ .frameNumber = frame_val.frameNumber, .delay = frame_val.delay, .contents = try allocator.alloc([]u8, frame_val.contents.len), .colorMap = try allocator.alloc([][]i32, frame_val.colorMap.len) };
|
||||||
|
|
||||||
|
for (0..frame.contents.len) |i| {
|
||||||
|
frame.contents[i] = try allocator.dupe(u8, frame_val.contents[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// colorMap is stored as an 3d array where:
|
||||||
|
// the outer (i) most array is the horizontal position of the color
|
||||||
|
// the middle (j) is the vertical position of the color
|
||||||
|
// the inner (0/1) is the foreground/background color
|
||||||
|
for (0..frame.colorMap.len) |i| {
|
||||||
|
frame.colorMap[i] = try allocator.alloc([]i32, frame_val.colorMap[i].len);
|
||||||
|
for (0..frame.colorMap[i].len) |j| {
|
||||||
|
frame.colorMap[i][j] = try allocator.alloc(i32, 2);
|
||||||
|
frame.colorMap[i][j][0] = frame_val.colorMap[i][j][0];
|
||||||
|
frame.colorMap[i][j][1] = frame_val.colorMap[i][j][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.frames.append(allocator, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_from_file(self: *DurFormat, allocator: Allocator, file_path: []const u8) !void {
|
||||||
|
const file_decompressed = try read_decompress_file(allocator, file_path);
|
||||||
|
defer allocator.free(file_decompressed);
|
||||||
|
|
||||||
|
const parsed = try Json.parseFromSlice(Json.Value, allocator, file_decompressed, .{});
|
||||||
|
defer parsed.deinit();
|
||||||
|
|
||||||
|
try parse_dur_from_json(self, allocator, parsed.value);
|
||||||
|
|
||||||
|
if (!self.valid()) {
|
||||||
|
return error.NotValidFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(allocator: Allocator) DurFormat {
|
||||||
|
return .{ .allocator = allocator };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *DurFormat) void {
|
||||||
|
if (self.colorFormat) |str| self.allocator.free(str);
|
||||||
|
if (self.encoding) |str| self.allocator.free(str);
|
||||||
|
|
||||||
|
for (self.frames.items) |frame| {
|
||||||
|
frame.deinit(self.allocator);
|
||||||
|
}
|
||||||
|
self.frames.deinit(self.allocator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const tb_color_16 = [16]u32{
|
||||||
|
Color.ECOL_BLACK,
|
||||||
|
Color.ECOL_RED,
|
||||||
|
Color.ECOL_GREEN,
|
||||||
|
Color.ECOL_YELLOW,
|
||||||
|
Color.ECOL_BLUE,
|
||||||
|
Color.ECOL_MAGENTA,
|
||||||
|
Color.ECOL_CYAN,
|
||||||
|
Color.ECOL_WHITE,
|
||||||
|
Color.ECOL_BLACK | Styling.BOLD,
|
||||||
|
Color.ECOL_RED | Styling.BOLD,
|
||||||
|
Color.ECOL_GREEN | Styling.BOLD,
|
||||||
|
Color.ECOL_YELLOW | Styling.BOLD,
|
||||||
|
Color.ECOL_BLUE | Styling.BOLD,
|
||||||
|
Color.ECOL_MAGENTA | Styling.BOLD,
|
||||||
|
Color.ECOL_CYAN | Styling.BOLD,
|
||||||
|
Color.ECOL_WHITE | Styling.BOLD,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Using bold for bright colors allows for all 16 colors to be rendered on tty term
|
||||||
|
const rgb_color_16 = [16]u32{
|
||||||
|
Color.DEFAULT, // DEFAULT instead of TRUE_BLACK to not break compositors (the latter ignores transparency)
|
||||||
|
Color.TRUE_DIM_RED,
|
||||||
|
Color.TRUE_DIM_GREEN,
|
||||||
|
Color.TRUE_DIM_YELLOW,
|
||||||
|
Color.TRUE_DIM_BLUE,
|
||||||
|
Color.TRUE_DIM_MAGENTA,
|
||||||
|
Color.TRUE_DIM_CYAN,
|
||||||
|
Color.TRUE_DIM_WHITE,
|
||||||
|
Color.DEFAULT | Styling.BOLD,
|
||||||
|
Color.TRUE_RED | Styling.BOLD,
|
||||||
|
Color.TRUE_GREEN | Styling.BOLD,
|
||||||
|
Color.TRUE_YELLOW | Styling.BOLD,
|
||||||
|
Color.TRUE_BLUE | Styling.BOLD,
|
||||||
|
Color.TRUE_MAGENTA | Styling.BOLD,
|
||||||
|
Color.TRUE_CYAN | Styling.BOLD,
|
||||||
|
Color.TRUE_WHITE | Styling.BOLD,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Made this table from looking at colormapping in dur source, not sure whats going on with the mapping logic
|
||||||
|
// Array indexes are dur colormappings which value maps to indexes in table above. Only needed for dur 16 color
|
||||||
|
const durcolor_table_to_color16 = [17]u32{
|
||||||
|
0, // 0 black
|
||||||
|
0, // 1 nothing?? dur source did not say why 1 is unused
|
||||||
|
4, // 2 blue
|
||||||
|
2, // 3 green
|
||||||
|
6, // 4 cyan
|
||||||
|
1, // 5 red
|
||||||
|
5, // 6 magenta
|
||||||
|
3, // 7 yellow
|
||||||
|
7, // 8 light gray
|
||||||
|
8, // 9 gray
|
||||||
|
12, // 10 bright blue
|
||||||
|
10, // 11 bright green
|
||||||
|
14, // 12 bright cyan
|
||||||
|
9, // 13 bright red
|
||||||
|
13, // 14 bright magenta
|
||||||
|
11, // 15 bright yellow
|
||||||
|
15, // 16 bright white
|
||||||
|
};
|
||||||
|
|
||||||
|
fn sixcube_to_channel(sixcube: u32) u32 {
|
||||||
|
// Although the range top for the extended range is 0xFF, 6 is not divisible into 0xFF,
|
||||||
|
// so we use 0xF0 instead with a scaler
|
||||||
|
const equal_divisions = 0xF0 / 6;
|
||||||
|
|
||||||
|
// Since the range is to 0xFF but 6 isn't divisible, we must add a scaler to get it to 0xFF at the last index (5)
|
||||||
|
const scaler = 0xFF - (equal_divisions * 5);
|
||||||
|
|
||||||
|
return if (sixcube > 0) (sixcube * equal_divisions) + scaler else 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_256_to_rgb(color_256: u32) u32 {
|
||||||
|
var rgb_color: u32 = 0;
|
||||||
|
|
||||||
|
// 0 - 15 is the standard color range, map to array table
|
||||||
|
if (color_256 < 16) {
|
||||||
|
rgb_color = rgb_color_16[color_256];
|
||||||
|
}
|
||||||
|
// 16 - 231 is the extended range
|
||||||
|
else if (color_256 < 232) {
|
||||||
|
|
||||||
|
// For extended term range we subtract by 16 to get it in a 0..(6x6x6) cube (range of 216)
|
||||||
|
// divide by 36 gets the depth of the cube (6x6x1)
|
||||||
|
// divide by 6 gets the width of the cube (6x1)
|
||||||
|
// divide by 1 gets the height of the cube (divide 1 for clarity for what we are doing)
|
||||||
|
// each channel can be 6 levels of brightness hence remander operation of 6
|
||||||
|
// finally bitshift to correct rgb channel (16 for red, 8 for green, 0 for blue)
|
||||||
|
rgb_color |= sixcube_to_channel(((color_256 - 16) / 36) % 6) << 16;
|
||||||
|
rgb_color |= sixcube_to_channel(((color_256 - 16) / 6) % 6) << 8;
|
||||||
|
rgb_color |= sixcube_to_channel(((color_256 - 16) / 1) % 6);
|
||||||
|
}
|
||||||
|
// 232 - 255 is the grayscale range
|
||||||
|
else {
|
||||||
|
|
||||||
|
// For grayscale we have a space of 232 - 255 (24)
|
||||||
|
// subtract by 232 to get it into the 0..23 range
|
||||||
|
// standard colors will contain white and black, so we do not use them in the grayscale range (0 is 0x08, 23 is 0xEE)
|
||||||
|
// this results in a skip of 0x08 for the first color and divisions of 0x0A
|
||||||
|
// example: term_col 232 = scaler + equal_divisions * (232 - 232) which becomes (scaler + 0x00) == 0x08
|
||||||
|
// example: term_col 255 = scaler + equal_divisions * (255 - 232) which becomes (scaler + 0xE6) == 0xEE
|
||||||
|
const scaler = 0x08;
|
||||||
|
|
||||||
|
// to get equal parts, the equation is:
|
||||||
|
// 0xEE = equal_divisions * 23 + scaler | top of range is 0xEE, 23 is last element value (255 minus 232)
|
||||||
|
// reordered to solve for equal_divisions:
|
||||||
|
const equal_divisions = (0xEE - scaler) / 23; // evals to 0x0A
|
||||||
|
|
||||||
|
const channel = scaler + equal_divisions * (color_256 - 232);
|
||||||
|
|
||||||
|
// gray is equal value of same channel color in rgb
|
||||||
|
rgb_color = channel | (channel << 8) | (channel << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rgb_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DurFile = @This();
|
||||||
|
|
||||||
|
allocator: Allocator,
|
||||||
|
terminal_buffer: *TerminalBuffer,
|
||||||
|
frames: u64,
|
||||||
|
time_previous: i64,
|
||||||
|
x_offset: u32,
|
||||||
|
y_offset: u32,
|
||||||
|
full_color: bool,
|
||||||
|
dur_movie: DurFormat,
|
||||||
|
frame_width: u32,
|
||||||
|
frame_height: u32,
|
||||||
|
frame_time: u32,
|
||||||
|
is_color_format_16: bool,
|
||||||
|
|
||||||
|
pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, log_writer: *std.io.Writer, file_path: []const u8, x_offset: u32, y_offset: u32, full_color: bool) !DurFile {
|
||||||
|
var dur_movie: DurFormat = .init(allocator);
|
||||||
|
|
||||||
|
// error state is recoverable when thrown to main and results in no background with Dummy in main
|
||||||
|
dur_movie.create_from_file(allocator, file_path) catch |err| switch (err) {
|
||||||
|
error.FileNotFound => {
|
||||||
|
try log_writer.print("error: dur_file was not found at: {s}\n", .{file_path});
|
||||||
|
return err;
|
||||||
|
},
|
||||||
|
error.NotValidFile => {
|
||||||
|
try log_writer.print("error: dur_file loaded was invalid or not a dur file!\n", .{});
|
||||||
|
return err;
|
||||||
|
},
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 4 bit mode with 256 color is unsupported
|
||||||
|
if (!full_color and eql(u8, dur_movie.colorFormat.?, "256")) {
|
||||||
|
try log_writer.print("error: dur_file can not be 256 color encoded when not using full_color option!\n", .{});
|
||||||
|
dur_movie.deinit();
|
||||||
|
return error.InvalidColorFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
const buf_width: u32 = @intCast(terminal_buffer.width);
|
||||||
|
const buf_height: u32 = @intCast(terminal_buffer.height);
|
||||||
|
|
||||||
|
const movie_width: u32 = @intCast(dur_movie.columns.?);
|
||||||
|
const movie_height: u32 = @intCast(dur_movie.lines.?);
|
||||||
|
|
||||||
|
// Clamp to prevent user from exceeding draw window
|
||||||
|
const x_offset_clamped = std.math.clamp(x_offset, 0, buf_width - 1);
|
||||||
|
const y_offset_clamped = std.math.clamp(y_offset, 0, buf_height - 1);
|
||||||
|
|
||||||
|
// Ensure if user offsets and frame goes offscreen, it will not overflow draw
|
||||||
|
const frame_width = if ((movie_width + x_offset_clamped) < buf_width) movie_width else buf_width - x_offset_clamped;
|
||||||
|
const frame_height = if ((movie_height + y_offset_clamped) < buf_height) movie_height else buf_height - y_offset_clamped;
|
||||||
|
|
||||||
|
// Convert dur fps to frames per ms
|
||||||
|
const frame_time: u32 = @intFromFloat(1000 / dur_movie.framerate.?);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.allocator = allocator,
|
||||||
|
.terminal_buffer = terminal_buffer,
|
||||||
|
.frames = 0,
|
||||||
|
.time_previous = std.time.milliTimestamp(),
|
||||||
|
.x_offset = x_offset_clamped,
|
||||||
|
.y_offset = y_offset_clamped,
|
||||||
|
.full_color = full_color,
|
||||||
|
.dur_movie = dur_movie,
|
||||||
|
.frame_width = frame_width,
|
||||||
|
.frame_height = frame_height,
|
||||||
|
.frame_time = frame_time,
|
||||||
|
.is_color_format_16 = eql(u8, dur_movie.colorFormat.?, "16"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn animation(self: *DurFile) Animation {
|
||||||
|
return Animation.init(self, deinit, realloc, draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit(self: *DurFile) void {
|
||||||
|
self.dur_movie.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn realloc(_: *DurFile) anyerror!void {}
|
||||||
|
|
||||||
|
fn draw(self: *DurFile) void {
|
||||||
|
const current_frame = self.dur_movie.frames.items[self.frames];
|
||||||
|
|
||||||
|
for (0..self.frame_height) |y| {
|
||||||
|
var iter = std.unicode.Utf8View.initUnchecked(current_frame.contents[y]).iterator();
|
||||||
|
|
||||||
|
for (0..self.frame_width) |x| {
|
||||||
|
const codepoint: u21 = iter.nextCodepoint().?;
|
||||||
|
const color_map = current_frame.colorMap[x][y];
|
||||||
|
|
||||||
|
var color_map_0: u32 = @intCast(if (color_map[0] == -1) 0 else color_map[0]);
|
||||||
|
var color_map_1: u32 = @intCast(if (color_map[1] == -1) 0 else color_map[1]);
|
||||||
|
|
||||||
|
if (self.is_color_format_16) {
|
||||||
|
color_map_0 = durcolor_table_to_color16[color_map_0];
|
||||||
|
color_map_1 = durcolor_table_to_color16[color_map_1 + 1]; // Add 1, dur source stores it like this for some reason
|
||||||
|
}
|
||||||
|
|
||||||
|
const fg_color = if (self.full_color) convert_256_to_rgb(color_map_0) else tb_color_16[color_map_0];
|
||||||
|
const bg_color = if (self.full_color) convert_256_to_rgb(color_map_1) else tb_color_16[color_map_1];
|
||||||
|
|
||||||
|
const cell = Cell{ .ch = @intCast(codepoint), .fg = fg_color, .bg = bg_color };
|
||||||
|
|
||||||
|
cell.put(x + self.x_offset, y + self.y_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const time_current = std.time.milliTimestamp();
|
||||||
|
const delta_time = time_current - self.time_previous;
|
||||||
|
|
||||||
|
// Convert delay from sec to ms
|
||||||
|
const delay_time: u32 = @intFromFloat(current_frame.delay * 1000);
|
||||||
|
if (delta_time > (self.frame_time + delay_time)) {
|
||||||
|
self.time_previous = time_current;
|
||||||
|
|
||||||
|
const frame_count = self.dur_movie.frames.items.len;
|
||||||
|
self.frames = (self.frames + 1) % frame_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -342,7 +342,7 @@ fn createXauthFile(pwd: []const u8, buffer: []u8) ![]const u8 {
|
|||||||
dir.close();
|
dir.close();
|
||||||
|
|
||||||
// xauth_dir is a directory, use it to store Xauthority
|
// xauth_dir is a directory, use it to store Xauthority
|
||||||
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/ly", .{xauth_dir});
|
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/.config/ly", .{pwd});
|
||||||
} else {
|
} else {
|
||||||
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/ly", .{xdg_cfg_home.?});
|
xauth_dir = try std.fmt.bufPrint(&xauth_buf, "{s}/ly", .{xdg_cfg_home.?});
|
||||||
}
|
}
|
||||||
@@ -365,6 +365,9 @@ fn createXauthFile(pwd: []const u8, buffer: []u8) ![]const u8 {
|
|||||||
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 });
|
const xauthority: []u8 = try std.fmt.bufPrint(buffer, "{s}/{s}", .{ trimmed_xauth_dir, xauth_file });
|
||||||
|
|
||||||
|
std.fs.makeDirAbsolute(trimmed_xauth_dir) catch {};
|
||||||
|
|
||||||
const file = try std.fs.createFileAbsolute(xauthority, .{});
|
const file = try std.fs.createFileAbsolute(xauthority, .{});
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ animation_timeout_sec: u12 = 0,
|
|||||||
asterisk: ?u32 = '*',
|
asterisk: ?u32 = '*',
|
||||||
auth_fails: u64 = 10,
|
auth_fails: u64 = 10,
|
||||||
battery_id: ?[]const u8 = null,
|
battery_id: ?[]const u8 = null,
|
||||||
|
auto_login_service: [:0]const u8 = "ly-autologin",
|
||||||
|
auto_login_session: ?[]const u8 = null,
|
||||||
|
auto_login_user: ?[]const u8 = null,
|
||||||
bg: u32 = 0x00000000,
|
bg: u32 = 0x00000000,
|
||||||
bigclock: Bigclock = .none,
|
bigclock: Bigclock = .none,
|
||||||
bigclock_12hr: bool = false,
|
bigclock_12hr: bool = false,
|
||||||
@@ -39,6 +42,10 @@ 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,
|
||||||
|
dur_file_path: []const u8 = build_options.config_directory ++ "/ly/example.dur",
|
||||||
|
dur_x_offset: u32 = 0,
|
||||||
|
dur_y_offset: u32 = 0,
|
||||||
|
edge_margin: u8 = 0,
|
||||||
error_bg: u32 = 0x00000000,
|
error_bg: u32 = 0x00000000,
|
||||||
error_fg: u32 = 0x01FF0000,
|
error_fg: u32 = 0x01FF0000,
|
||||||
fg: u32 = 0x00FFFFFF,
|
fg: u32 = 0x00FFFFFF,
|
||||||
@@ -47,9 +54,14 @@ gameoflife_fg: u32 = 0x0000FF00,
|
|||||||
gameoflife_entropy_interval: usize = 10,
|
gameoflife_entropy_interval: usize = 10,
|
||||||
gameoflife_frame_delay: usize = 6,
|
gameoflife_frame_delay: usize = 6,
|
||||||
gameoflife_initial_density: f32 = 0.4,
|
gameoflife_initial_density: f32 = 0.4,
|
||||||
|
hibernate_cmd: ?[]const u8 = null,
|
||||||
|
hibernate_key: []const u8 = "F4",
|
||||||
hide_borders: bool = false,
|
hide_borders: bool = false,
|
||||||
hide_key_hints: bool = false,
|
hide_key_hints: bool = false,
|
||||||
|
hide_keyboard_locks: bool = false,
|
||||||
hide_version_string: bool = false,
|
hide_version_string: bool = false,
|
||||||
|
inactivity_cmd: ?[]const u8 = null,
|
||||||
|
inactivity_delay: u16 = 0,
|
||||||
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",
|
||||||
@@ -72,6 +84,7 @@ 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",
|
||||||
|
start_cmd: ?[]const u8 = null,
|
||||||
text_in_center: bool = false,
|
text_in_center: bool = false,
|
||||||
vi_default_mode: ViMode = .normal,
|
vi_default_mode: ViMode = .normal,
|
||||||
vi_mode: bool = false,
|
vi_mode: bool = false,
|
||||||
|
|||||||
@@ -9,17 +9,22 @@ brightness_up: []const u8 = "increase brightness",
|
|||||||
capslock: []const u8 = "capslock",
|
capslock: []const u8 = "capslock",
|
||||||
custom: []const u8 = "custom",
|
custom: []const u8 = "custom",
|
||||||
err_alloc: []const u8 = "failed memory allocation",
|
err_alloc: []const u8 = "failed memory allocation",
|
||||||
|
err_args: []const u8 = "unable to parse command line arguments",
|
||||||
|
err_autologin_session: []const u8 = "autologin session not found",
|
||||||
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_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_crawl: []const u8 = "failed to crawl session directories",
|
||||||
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_get_active_tty: []const u8 = "failed to get active tty",
|
||||||
|
err_hibernate: []const u8 = "failed to execute hibernate command",
|
||||||
err_hostname: []const u8 = "failed to get hostname",
|
err_hostname: []const u8 = "failed to get hostname",
|
||||||
|
err_inactivity: []const u8 = "failed to execute inactivity command",
|
||||||
err_lock_state: []const u8 = "failed to get lock state",
|
err_lock_state: []const u8 = "failed to get lock state",
|
||||||
err_log: []const u8 = "failed to open log file",
|
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",
|
||||||
@@ -47,10 +52,12 @@ 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_start: []const u8 = "failed to execute start command",
|
||||||
err_battery: []const u8 = "failed to load battery status",
|
err_battery: []const u8 = "failed to load battery status",
|
||||||
err_switch_tty: []const u8 = "failed to switch tty",
|
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_no_users: []const u8 = "no users found",
|
||||||
|
err_uid_range: []const u8 = "failed to dynamically get uid range",
|
||||||
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",
|
||||||
@@ -58,6 +65,7 @@ err_xauth: []const u8 = "xauth command failed",
|
|||||||
err_xcb_conn: []const u8 = "xcb connection failed",
|
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",
|
||||||
|
hibernate: []const u8 = "hibernate",
|
||||||
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",
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ const SavedUsers = @This();
|
|||||||
const User = struct {
|
const User = struct {
|
||||||
username: []const u8,
|
username: []const u8,
|
||||||
session_index: usize,
|
session_index: usize,
|
||||||
|
first_run: bool,
|
||||||
|
allocated_username: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
user_list: std.ArrayList(User),
|
user_list: std.ArrayList(User),
|
||||||
@@ -18,5 +20,9 @@ pub fn init() SavedUsers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *SavedUsers, allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *SavedUsers, allocator: std.mem.Allocator) void {
|
||||||
|
for (self.user_list.items) |user| {
|
||||||
|
if (user.allocated_username) allocator.free(user.username);
|
||||||
|
}
|
||||||
|
|
||||||
self.user_list.deinit(allocator);
|
self.user_list.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,12 @@ pub fn tryMigrateIniSaveFile(allocator: std.mem.Allocator, save_ini: *ini.Ini(Ol
|
|||||||
if (std.mem.eql(u8, user, username)) saved_users.last_username_index = i;
|
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 });
|
try saved_users.user_list.append(allocator, .{
|
||||||
|
.username = username,
|
||||||
|
.session_index = save.session_index orelse 0,
|
||||||
|
.first_run = false,
|
||||||
|
.allocated_username = false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
const std = @import("std");
|
||||||
pub const Animation = enum {
|
pub const Animation = enum {
|
||||||
none,
|
none,
|
||||||
doom,
|
doom,
|
||||||
matrix,
|
matrix,
|
||||||
colormix,
|
colormix,
|
||||||
gameoflife,
|
gameoflife,
|
||||||
|
dur_file,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DisplayServer = enum {
|
pub const DisplayServer = enum {
|
||||||
@@ -19,6 +21,26 @@ pub const Input = enum {
|
|||||||
session,
|
session,
|
||||||
login,
|
login,
|
||||||
password,
|
password,
|
||||||
|
|
||||||
|
/// Moves the current Input forwards by one entry. If `reverse`, then the Input
|
||||||
|
/// moves backwards. If `wrap` is true, then the entry will wrap back around
|
||||||
|
pub fn move(self: *Input, reverse: bool, wrap: bool) void {
|
||||||
|
const maxNum = @typeInfo(Input).@"enum".fields.len - 1;
|
||||||
|
const selfNum = @intFromEnum(self.*);
|
||||||
|
if (reverse) {
|
||||||
|
if (wrap) {
|
||||||
|
self.* = @enumFromInt(selfNum -% 1);
|
||||||
|
} else if (selfNum != 0) {
|
||||||
|
self.* = @enumFromInt(selfNum - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (wrap) {
|
||||||
|
self.* = @enumFromInt(selfNum +% 1);
|
||||||
|
} else if (selfNum != maxNum) {
|
||||||
|
self.* = @enumFromInt(selfNum + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ViMode = enum {
|
pub const ViMode = enum {
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ fn PlatformStruct() type {
|
|||||||
pub const vt_activate = vt.VT_ACTIVATE;
|
pub const vt_activate = vt.VT_ACTIVATE;
|
||||||
pub const vt_waitactive = vt.VT_WAITACTIVE;
|
pub const vt_waitactive = vt.VT_WAITACTIVE;
|
||||||
|
|
||||||
|
const SYSTEMD_HOMED_UID_MIN = 60001;
|
||||||
|
const SYSTEMD_HOMED_UID_MAX = 60513;
|
||||||
|
|
||||||
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
||||||
const status = grp.initgroups(username, @intCast(entry.gid));
|
const status = grp.initgroups(username, @intCast(entry.gid));
|
||||||
if (status != 0) return error.GroupInitializationFailed;
|
if (status != 0) return error.GroupInitializationFailed;
|
||||||
@@ -168,17 +171,35 @@ fn PlatformStruct() type {
|
|||||||
|
|
||||||
var iterator = std.mem.splitScalar(u8, login_defs_buffer, '\n');
|
var iterator = std.mem.splitScalar(u8, login_defs_buffer, '\n');
|
||||||
var uid_range = UidRange{};
|
var uid_range = UidRange{};
|
||||||
|
var nameFound = false;
|
||||||
|
|
||||||
while (iterator.next()) |line| {
|
while (iterator.next()) |line| {
|
||||||
const trimmed_line = std.mem.trim(u8, line, " \n\r\t");
|
const trimmed_line = std.mem.trim(u8, line, " \n\r\t");
|
||||||
|
|
||||||
if (std.mem.startsWith(u8, trimmed_line, "UID_MIN")) {
|
if (std.mem.startsWith(u8, trimmed_line, "UID_MIN")) {
|
||||||
uid_range.uid_min = try parseValue(std.posix.uid_t, "UID_MIN", trimmed_line);
|
uid_range.uid_min = try parseValue(std.posix.uid_t, "UID_MIN", trimmed_line);
|
||||||
|
nameFound = true;
|
||||||
} else if (std.mem.startsWith(u8, trimmed_line, "UID_MAX")) {
|
} else if (std.mem.startsWith(u8, trimmed_line, "UID_MAX")) {
|
||||||
uid_range.uid_max = try parseValue(std.posix.uid_t, "UID_MAX", trimmed_line);
|
uid_range.uid_max = try parseValue(std.posix.uid_t, "UID_MAX", trimmed_line);
|
||||||
|
nameFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nameFound) return error.UidNameNotFound;
|
||||||
|
|
||||||
|
// This code assumes the OS has a login.defs file with UID_MIN
|
||||||
|
// and UID_MAX values defined in it, which should be the case
|
||||||
|
// for most systemd-based Linux distributions out there.
|
||||||
|
// This should be a good enough safeguard for now, as there's
|
||||||
|
// no reliable (and clean) way to check for systemd support
|
||||||
|
if (uid_range.uid_min > SYSTEMD_HOMED_UID_MIN) {
|
||||||
|
uid_range.uid_min = SYSTEMD_HOMED_UID_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid_range.uid_max < SYSTEMD_HOMED_UID_MAX) {
|
||||||
|
uid_range.uid_max = SYSTEMD_HOMED_UID_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
return uid_range;
|
return uid_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +247,9 @@ fn PlatformStruct() type {
|
|||||||
pub const vt_activate = consio.VT_ACTIVATE;
|
pub const vt_activate = consio.VT_ACTIVATE;
|
||||||
pub const vt_waitactive = consio.VT_WAITACTIVE;
|
pub const vt_waitactive = consio.VT_WAITACTIVE;
|
||||||
|
|
||||||
|
const FREEBSD_UID_MIN = 1000;
|
||||||
|
const FREEBSD_UID_MAX = 32000;
|
||||||
|
|
||||||
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
pub fn setUserContextImpl(username: [*:0]const u8, entry: UsernameEntry) !void {
|
||||||
// FreeBSD has initgroups() in unistd
|
// FreeBSD has initgroups() in unistd
|
||||||
const status = unistd.initgroups(username, @intCast(entry.gid));
|
const status = unistd.initgroups(username, @intCast(entry.gid));
|
||||||
@@ -244,8 +268,8 @@ fn PlatformStruct() type {
|
|||||||
return .{
|
return .{
|
||||||
// Hardcoded default values chosen from
|
// Hardcoded default values chosen from
|
||||||
// /usr/src/usr.sbin/pw/pw_conf.c
|
// /usr/src/usr.sbin/pw/pw_conf.c
|
||||||
.uid_min = 1000,
|
.uid_min = FREEBSD_UID_MIN,
|
||||||
.uid_max = 32000,
|
.uid_max = FREEBSD_UID_MAX,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
399
src/main.zig
399
src/main.zig
@@ -13,6 +13,7 @@ const Doom = @import("animations/Doom.zig");
|
|||||||
const Dummy = @import("animations/Dummy.zig");
|
const Dummy = @import("animations/Dummy.zig");
|
||||||
const Matrix = @import("animations/Matrix.zig");
|
const Matrix = @import("animations/Matrix.zig");
|
||||||
const GameOfLife = @import("animations/GameOfLife.zig");
|
const GameOfLife = @import("animations/GameOfLife.zig");
|
||||||
|
const DurFile = @import("animations/DurFile.zig");
|
||||||
const Animation = @import("tui/Animation.zig");
|
const Animation = @import("tui/Animation.zig");
|
||||||
const TerminalBuffer = @import("tui/TerminalBuffer.zig");
|
const TerminalBuffer = @import("tui/TerminalBuffer.zig");
|
||||||
const Session = @import("tui/components/Session.zig");
|
const Session = @import("tui/components/Session.zig");
|
||||||
@@ -26,6 +27,7 @@ const SavedUsers = @import("config/SavedUsers.zig");
|
|||||||
const migrator = @import("config/migrator.zig");
|
const migrator = @import("config/migrator.zig");
|
||||||
const SharedError = @import("SharedError.zig");
|
const SharedError = @import("SharedError.zig");
|
||||||
const LogFile = @import("LogFile.zig");
|
const LogFile = @import("LogFile.zig");
|
||||||
|
const UidRange = @import("UidRange.zig");
|
||||||
|
|
||||||
const StringList = std.ArrayListUnmanaged([]const u8);
|
const StringList = std.ArrayListUnmanaged([]const u8);
|
||||||
const Ini = ini.Ini;
|
const Ini = ini.Ini;
|
||||||
@@ -97,7 +99,7 @@ pub fn main() !void {
|
|||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
|
|
||||||
// Allows stopping an animation after some time
|
// Allows stopping an animation after some time
|
||||||
const time_start = try interop.getTimeOfDay();
|
const animation_time_start = try interop.getTimeOfDay();
|
||||||
var animation_timed_out: bool = false;
|
var animation_timed_out: bool = false;
|
||||||
|
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
@@ -110,17 +112,20 @@ pub fn main() !void {
|
|||||||
);
|
);
|
||||||
|
|
||||||
var diag = clap.Diagnostic{};
|
var diag = clap.Diagnostic{};
|
||||||
var res = clap.parse(clap.Help, ¶ms, clap.parsers.default, .{ .diagnostic = &diag, .allocator = allocator }) catch |err| {
|
var arg_parse_error: anyerror = undefined;
|
||||||
|
var maybe_res = clap.parse(clap.Help, ¶ms, clap.parsers.default, .{ .diagnostic = &diag, .allocator = allocator }) catch |err| parse_error: {
|
||||||
|
arg_parse_error = err;
|
||||||
diag.report(stderr, err) catch {};
|
diag.report(stderr, err) catch {};
|
||||||
try stderr.flush();
|
try stderr.flush();
|
||||||
return err;
|
break :parse_error null;
|
||||||
};
|
};
|
||||||
defer res.deinit();
|
defer if (maybe_res) |*res| res.deinit();
|
||||||
|
|
||||||
var config: Config = undefined;
|
var config: Config = undefined;
|
||||||
var lang: Lang = undefined;
|
var lang: Lang = undefined;
|
||||||
var old_save_file_exists = false;
|
var old_save_file_exists = false;
|
||||||
var maybe_config_load_error: ?anyerror = null;
|
var maybe_config_load_error: ?anyerror = null;
|
||||||
|
var start_cmd_exit_code: u8 = 0;
|
||||||
var can_get_lock_state = true;
|
var can_get_lock_state = true;
|
||||||
var can_draw_clock = true;
|
var can_draw_clock = true;
|
||||||
var can_draw_battery = true;
|
var can_draw_battery = true;
|
||||||
@@ -128,17 +133,19 @@ pub fn main() !void {
|
|||||||
var saved_users = SavedUsers.init();
|
var saved_users = SavedUsers.init();
|
||||||
defer saved_users.deinit(allocator);
|
defer saved_users.deinit(allocator);
|
||||||
|
|
||||||
if (res.args.help != 0) {
|
if (maybe_res) |*res| {
|
||||||
try clap.help(stderr, clap.Help, ¶ms, .{});
|
if (res.args.help != 0) {
|
||||||
|
try clap.help(stderr, clap.Help, ¶ms, .{});
|
||||||
|
|
||||||
_ = try stderr.write("Note: if you want to configure Ly, please check the config file, which is located at " ++ build_options.config_directory ++ "/ly/config.ini.\n");
|
_ = try stderr.write("Note: if you want to configure Ly, please check the config file, which is located at " ++ build_options.config_directory ++ "/ly/config.ini.\n");
|
||||||
try stderr.flush();
|
try stderr.flush();
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
if (res.args.version != 0) {
|
if (res.args.version != 0) {
|
||||||
_ = try stderr.write("Ly version " ++ build_options.version ++ "\n");
|
_ = try stderr.write("Ly version " ++ build_options.version ++ "\n");
|
||||||
try stderr.flush();
|
try stderr.flush();
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load configuration file
|
// Load configuration file
|
||||||
@@ -161,7 +168,8 @@ pub fn main() !void {
|
|||||||
|
|
||||||
const comment_characters = "#";
|
const comment_characters = "#";
|
||||||
|
|
||||||
if (res.args.config) |s| {
|
if (maybe_res != null and maybe_res.?.args.config != null) {
|
||||||
|
const s = maybe_res.?.args.config.?;
|
||||||
const trailing_slash = if (s[s.len - 1] != '/') "/" else "";
|
const trailing_slash = if (s[s.len - 1] != '/') "/" else "";
|
||||||
|
|
||||||
const config_path = try std.fmt.allocPrint(allocator, "{s}{s}config.ini", .{ s, trailing_slash });
|
const config_path = try std.fmt.allocPrint(allocator, "{s}{s}config.ini", .{ s, trailing_slash });
|
||||||
@@ -214,7 +222,8 @@ pub fn main() !void {
|
|||||||
migrator.lateConfigFieldHandler(&config);
|
migrator.lateConfigFieldHandler(&config);
|
||||||
}
|
}
|
||||||
|
|
||||||
var usernames = try getAllUsernames(allocator, config.login_defs_path);
|
var maybe_uid_range_error: ?anyerror = null;
|
||||||
|
var usernames = try getAllUsernames(allocator, config.login_defs_path, &maybe_uid_range_error);
|
||||||
defer {
|
defer {
|
||||||
for (usernames.items) |username| allocator.free(username);
|
for (usernames.items) |username| allocator.free(username);
|
||||||
usernames.deinit(allocator);
|
usernames.deinit(allocator);
|
||||||
@@ -246,18 +255,23 @@ pub fn main() !void {
|
|||||||
const session_index = std.fmt.parseInt(usize, session_index_str, 10) catch continue;
|
const session_index = std.fmt.parseInt(usize, session_index_str, 10) catch continue;
|
||||||
|
|
||||||
try saved_users.user_list.append(allocator, .{
|
try saved_users.user_list.append(allocator, .{
|
||||||
.username = username,
|
.username = try allocator.dupe(u8, username),
|
||||||
.session_index = session_index,
|
.session_index = session_index,
|
||||||
|
.first_run = false,
|
||||||
|
.allocated_username = true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If no save file previously existed, fill it up with all usernames
|
// If no save file previously existed, fill it up with all usernames
|
||||||
if (saved_users.user_list.items.len > 0) break :read_save_file;
|
// TODO: Add new username with existing save file
|
||||||
|
if (config.save and saved_users.user_list.items.len == 0) {
|
||||||
for (usernames.items) |user| {
|
for (usernames.items) |user| {
|
||||||
try saved_users.user_list.append(allocator, .{
|
try saved_users.user_list.append(allocator, .{
|
||||||
.username = user,
|
.username = user,
|
||||||
.session_index = 0,
|
.session_index = 0,
|
||||||
|
.first_run = true,
|
||||||
|
.allocated_username = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +289,19 @@ pub fn main() !void {
|
|||||||
restart_cmd = try temporary_allocator.dupe(u8, config.restart_cmd);
|
restart_cmd = try temporary_allocator.dupe(u8, config.restart_cmd);
|
||||||
commands_allocated = true;
|
commands_allocated = true;
|
||||||
|
|
||||||
|
if (config.start_cmd) |start_cmd| {
|
||||||
|
var start = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", start_cmd }, allocator);
|
||||||
|
start.stdout_behavior = .Ignore;
|
||||||
|
start.stderr_behavior = .Ignore;
|
||||||
|
|
||||||
|
handle_start_cmd: {
|
||||||
|
const process_result = start.spawnAndWait() catch {
|
||||||
|
break :handle_start_cmd;
|
||||||
|
};
|
||||||
|
start_cmd_exit_code = process_result.Exited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize termbox
|
// Initialize termbox
|
||||||
try log_writer.writeAll("initializing termbox2\n");
|
try log_writer.writeAll("initializing termbox2\n");
|
||||||
_ = termbox.tb_init();
|
_ = termbox.tb_init();
|
||||||
@@ -330,6 +357,25 @@ pub fn main() !void {
|
|||||||
var info_line = InfoLine.init(allocator, &buffer);
|
var info_line = InfoLine.init(allocator, &buffer);
|
||||||
defer info_line.deinit();
|
defer info_line.deinit();
|
||||||
|
|
||||||
|
if (maybe_res == null) {
|
||||||
|
var longest = diag.name.longest();
|
||||||
|
if (longest.kind == .positional)
|
||||||
|
longest.name = diag.arg;
|
||||||
|
|
||||||
|
try info_line.addMessage(lang.err_args, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("unable to parse argument '{s}{s}': {s}\n", .{ longest.kind.prefix(), longest.name, @errorName(arg_parse_error) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maybe_uid_range_error) |err| {
|
||||||
|
try info_line.addMessage(lang.err_uid_range, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("failed to get uid range: {s}; falling back to default\n", .{@errorName(err)});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_cmd_exit_code != 0) {
|
||||||
|
try info_line.addMessage(lang.err_start, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("failed to execute start command: exit code {d}\n", .{start_cmd_exit_code});
|
||||||
|
}
|
||||||
|
|
||||||
if (maybe_config_load_error) |err| {
|
if (maybe_config_load_error) |err| {
|
||||||
// We can't localize this since the config failed to load so we'd fallback to the default language anyway
|
// We can't localize this since the config failed to load so we'd fallback to the default language anyway
|
||||||
try info_line.addMessage("unable to parse config file", config.error_bg, config.error_fg);
|
try info_line.addMessage("unable to parse config file", config.error_bg, config.error_fg);
|
||||||
@@ -367,6 +413,9 @@ pub fn main() !void {
|
|||||||
var session = Session.init(allocator, &buffer, &login);
|
var session = Session.init(allocator, &buffer, &login);
|
||||||
defer session.deinit();
|
defer session.deinit();
|
||||||
|
|
||||||
|
login = try UserList.init(allocator, &buffer, usernames, &saved_users, &session);
|
||||||
|
defer login.deinit();
|
||||||
|
|
||||||
addOtherEnvironment(&session, lang, .shell, null) catch |err| {
|
addOtherEnvironment(&session, lang, .shell, null) catch |err| {
|
||||||
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
try info_line.addMessage(lang.err_alloc, config.error_bg, config.error_fg);
|
||||||
try log_writer.print("failed to add shell environment: {s}\n", .{@errorName(err)});
|
try log_writer.print("failed to add shell environment: {s}\n", .{@errorName(err)});
|
||||||
@@ -384,35 +433,37 @@ pub fn main() !void {
|
|||||||
try log_writer.writeAll("x11 support disabled at compile-time\n");
|
try log_writer.writeAll("x11 support disabled at compile-time\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.initial_info_text) |text| {
|
var has_crawl_error = false;
|
||||||
try info_line.addMessage(text, config.bg, config.fg);
|
|
||||||
} else get_host_name: {
|
|
||||||
// Initialize information line with host name
|
|
||||||
var name_buf: [std.posix.HOST_NAME_MAX]u8 = undefined;
|
|
||||||
const hostname = std.posix.gethostname(&name_buf) catch |err| {
|
|
||||||
try info_line.addMessage(lang.err_hostname, config.error_bg, config.error_fg);
|
|
||||||
try log_writer.print("failed to get hostname: {s}\n", .{@errorName(err)});
|
|
||||||
break :get_host_name;
|
|
||||||
};
|
|
||||||
try info_line.addMessage(hostname, config.bg, config.fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crawl session directories (Wayland, X11 and custom respectively)
|
// Crawl session directories (Wayland, X11 and custom respectively)
|
||||||
var wayland_session_dirs = std.mem.splitScalar(u8, config.waylandsessions, ':');
|
var wayland_session_dirs = std.mem.splitScalar(u8, config.waylandsessions, ':');
|
||||||
while (wayland_session_dirs.next()) |dir| {
|
while (wayland_session_dirs.next()) |dir| {
|
||||||
try crawl(&session, lang, dir, .wayland);
|
crawl(&session, lang, dir, .wayland) catch |err| {
|
||||||
|
has_crawl_error = true;
|
||||||
|
try log_writer.print("failed to crawl wayland session directory '{s}': {s}\n", .{ dir, @errorName(err) });
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (build_options.enable_x11_support) {
|
if (build_options.enable_x11_support) {
|
||||||
var x_session_dirs = std.mem.splitScalar(u8, config.xsessions, ':');
|
var x_session_dirs = std.mem.splitScalar(u8, config.xsessions, ':');
|
||||||
while (x_session_dirs.next()) |dir| {
|
while (x_session_dirs.next()) |dir| {
|
||||||
try crawl(&session, lang, dir, .x11);
|
crawl(&session, lang, dir, .x11) catch |err| {
|
||||||
|
has_crawl_error = true;
|
||||||
|
try log_writer.print("failed to crawl x11 session directory '{s}': {s}\n", .{ dir, @errorName(err) });
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var custom_session_dirs = std.mem.splitScalar(u8, config.custom_sessions, ':');
|
var custom_session_dirs = std.mem.splitScalar(u8, config.custom_sessions, ':');
|
||||||
while (custom_session_dirs.next()) |dir| {
|
while (custom_session_dirs.next()) |dir| {
|
||||||
try crawl(&session, lang, dir, .custom);
|
crawl(&session, lang, dir, .custom) catch |err| {
|
||||||
|
has_crawl_error = true;
|
||||||
|
try log_writer.print("failed to crawl custom session directory '{s}': {s}\n", .{ dir, @errorName(err) });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_crawl_error) {
|
||||||
|
try info_line.addMessage(lang.err_crawl, config.error_bg, config.error_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usernames.items.len == 0) {
|
if (usernames.items.len == 0) {
|
||||||
@@ -424,17 +475,43 @@ pub fn main() !void {
|
|||||||
try log_writer.writeAll("no users found\n");
|
try log_writer.writeAll("no users found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
login = try UserList.init(allocator, &buffer, usernames, &saved_users, &session);
|
|
||||||
defer login.deinit();
|
|
||||||
|
|
||||||
var password = Text.init(allocator, &buffer, true, config.asterisk);
|
var password = Text.init(allocator, &buffer, true, config.asterisk);
|
||||||
defer password.deinit();
|
defer password.deinit();
|
||||||
|
|
||||||
var active_input = config.default_input;
|
var active_input = config.default_input;
|
||||||
var insert_mode = !config.vi_mode or config.vi_default_mode == .insert;
|
var insert_mode = !config.vi_mode or config.vi_default_mode == .insert;
|
||||||
|
var is_autologin = false;
|
||||||
|
|
||||||
|
check_autologin: {
|
||||||
|
const auto_user = config.auto_login_user orelse break :check_autologin;
|
||||||
|
const auto_session = config.auto_login_session orelse break :check_autologin;
|
||||||
|
|
||||||
|
if (!isValidUsername(auto_user, usernames)) {
|
||||||
|
try info_line.addMessage(lang.err_pam_user_unknown, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("autologin failed: username '{s}' not found\n", .{auto_user});
|
||||||
|
break :check_autologin;
|
||||||
|
}
|
||||||
|
|
||||||
|
const session_index = findSessionByName(&session, auto_session) orelse {
|
||||||
|
try log_writer.print("autologin failed: session '{s}' not found\n", .{auto_session});
|
||||||
|
try info_line.addMessage(lang.err_autologin_session, config.error_bg, config.error_fg);
|
||||||
|
break :check_autologin;
|
||||||
|
};
|
||||||
|
try log_writer.print("attempting autologin for user '{s}' with session '{s}'\n", .{ auto_user, auto_session });
|
||||||
|
|
||||||
|
session.label.current = session_index;
|
||||||
|
for (login.label.list.items, 0..) |username, i| {
|
||||||
|
if (std.mem.eql(u8, username.name, auto_user)) {
|
||||||
|
login.label.current = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_autologin = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Load last saved username and desktop selection, if any
|
// Load last saved username and desktop selection, if any
|
||||||
if (config.save) {
|
// Skip if autologin is active to prevent overriding autologin session
|
||||||
|
if (config.save and !is_autologin) {
|
||||||
if (saved_users.last_username_index) |index| load_last_user: {
|
if (saved_users.last_username_index) |index| load_last_user: {
|
||||||
// If the saved index isn't valid, bail out
|
// If the saved index isn't valid, bail out
|
||||||
if (index >= saved_users.user_list.items.len) break :load_last_user;
|
if (index >= saved_users.user_list.items.len) break :load_last_user;
|
||||||
@@ -501,6 +578,10 @@ pub fn main() !void {
|
|||||||
var game_of_life = try GameOfLife.init(allocator, &buffer, config.gameoflife_fg, config.gameoflife_entropy_interval, config.gameoflife_frame_delay, config.gameoflife_initial_density);
|
var game_of_life = try GameOfLife.init(allocator, &buffer, config.gameoflife_fg, config.gameoflife_entropy_interval, config.gameoflife_frame_delay, config.gameoflife_initial_density);
|
||||||
animation = game_of_life.animation();
|
animation = game_of_life.animation();
|
||||||
},
|
},
|
||||||
|
.dur_file => {
|
||||||
|
var dur = try DurFile.init(allocator, &buffer, log_writer, config.dur_file_path, config.dur_x_offset, config.dur_y_offset, config.full_color);
|
||||||
|
animation = dur.animation();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
defer animation.deinit();
|
defer animation.deinit();
|
||||||
|
|
||||||
@@ -511,6 +592,8 @@ pub fn main() !void {
|
|||||||
const restart_len = try TerminalBuffer.strWidth(lang.restart);
|
const restart_len = try TerminalBuffer.strWidth(lang.restart);
|
||||||
const sleep_key = try std.fmt.parseInt(u8, config.sleep_key[1..], 10);
|
const sleep_key = try std.fmt.parseInt(u8, config.sleep_key[1..], 10);
|
||||||
const sleep_len = try TerminalBuffer.strWidth(lang.sleep);
|
const sleep_len = try TerminalBuffer.strWidth(lang.sleep);
|
||||||
|
const hibernate_key = try std.fmt.parseInt(u8, config.hibernate_key[1..], 10);
|
||||||
|
const hibernate_len = try TerminalBuffer.strWidth(lang.hibernate);
|
||||||
const brightness_down_key = if (config.brightness_down_key) |key| try std.fmt.parseInt(u8, key[1..], 10) else null;
|
const brightness_down_key = if (config.brightness_down_key) |key| try std.fmt.parseInt(u8, key[1..], 10) else null;
|
||||||
const brightness_down_len = try TerminalBuffer.strWidth(lang.brightness_down);
|
const brightness_down_len = try TerminalBuffer.strWidth(lang.brightness_down);
|
||||||
const brightness_up_key = if (config.brightness_up_key) |key| try std.fmt.parseInt(u8, key[1..], 10) else null;
|
const brightness_up_key = if (config.brightness_up_key) |key| try std.fmt.parseInt(u8, key[1..], 10) else null;
|
||||||
@@ -521,6 +604,8 @@ pub fn main() !void {
|
|||||||
var update = true;
|
var update = true;
|
||||||
var resolution_changed = false;
|
var resolution_changed = false;
|
||||||
var auth_fails: u64 = 0;
|
var auth_fails: u64 = 0;
|
||||||
|
var inactivity_time_start = try interop.getTimeOfDay();
|
||||||
|
var inactivity_cmd_ran = false;
|
||||||
|
|
||||||
// Switch to selected TTY
|
// Switch to selected TTY
|
||||||
const active_tty = interop.getActiveTty(allocator) catch |err| no_tty_found: {
|
const active_tty = interop.getActiveTty(allocator) catch |err| no_tty_found: {
|
||||||
@@ -533,6 +618,19 @@ pub fn main() !void {
|
|||||||
try log_writer.print("failed to switch tty: {s}\n", .{@errorName(err)});
|
try log_writer.print("failed to switch tty: {s}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (config.initial_info_text) |text| {
|
||||||
|
try info_line.addMessage(text, config.bg, config.fg);
|
||||||
|
} else get_host_name: {
|
||||||
|
// Initialize information line with host name
|
||||||
|
var name_buf: [std.posix.HOST_NAME_MAX]u8 = undefined;
|
||||||
|
const hostname = std.posix.gethostname(&name_buf) catch |err| {
|
||||||
|
try info_line.addMessage(lang.err_hostname, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("failed to get hostname: {s}\n", .{@errorName(err)});
|
||||||
|
break :get_host_name;
|
||||||
|
};
|
||||||
|
try info_line.addMessage(hostname, config.bg, config.fg);
|
||||||
|
}
|
||||||
|
|
||||||
while (run) {
|
while (run) {
|
||||||
// If there's no input or there's an animation, a resolution change needs to be checked
|
// If there's no input or there's an animation, a resolution change needs to be checked
|
||||||
if (!update or animate) {
|
if (!update or animate) {
|
||||||
@@ -562,7 +660,7 @@ pub fn main() !void {
|
|||||||
|
|
||||||
if (update) {
|
if (update) {
|
||||||
// If the user entered a wrong password 10 times in a row, play a cascade animation, else update normally
|
// If the user entered a wrong password 10 times in a row, play a cascade animation, else update normally
|
||||||
if (auth_fails >= config.auth_fails) {
|
if (config.auth_fails > 0 and auth_fails >= config.auth_fails) {
|
||||||
std.Thread.sleep(std.time.ns_per_ms * 10);
|
std.Thread.sleep(std.time.ns_per_ms * 10);
|
||||||
update = buffer.cascade();
|
update = buffer.cascade();
|
||||||
|
|
||||||
@@ -577,12 +675,12 @@ pub fn main() !void {
|
|||||||
|
|
||||||
_ = termbox.tb_clear();
|
_ = termbox.tb_clear();
|
||||||
|
|
||||||
var length: usize = 0;
|
var length: usize = config.edge_margin;
|
||||||
|
|
||||||
if (!animation_timed_out) animation.draw();
|
if (!animation_timed_out) animation.draw();
|
||||||
|
|
||||||
if (!config.hide_version_string) {
|
if (!config.hide_version_string) {
|
||||||
buffer.drawLabel(ly_version_str, 0, buffer.height - 1);
|
buffer.drawLabel(ly_version_str, config.edge_margin, buffer.height - 1 - config.edge_margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.battery_id) |id| draw_battery: {
|
if (config.battery_id) |id| draw_battery: {
|
||||||
@@ -598,8 +696,11 @@ pub fn main() !void {
|
|||||||
var battery_buf: [16:0]u8 = undefined;
|
var battery_buf: [16:0]u8 = undefined;
|
||||||
const battery_str = std.fmt.bufPrintZ(&battery_buf, "BAT: {d}%", .{battery_percentage}) catch break :draw_battery;
|
const battery_str = std.fmt.bufPrintZ(&battery_buf, "BAT: {d}%", .{battery_percentage}) catch break :draw_battery;
|
||||||
|
|
||||||
const battery_y: usize = if (config.hide_key_hints) 0 else 1;
|
var battery_y: usize = config.edge_margin;
|
||||||
buffer.drawLabel(battery_str, 0, battery_y);
|
if (!config.hide_key_hints) {
|
||||||
|
battery_y += 1;
|
||||||
|
}
|
||||||
|
buffer.drawLabel(battery_str, config.edge_margin, battery_y);
|
||||||
can_draw_battery = true;
|
can_draw_battery = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,7 +761,7 @@ pub fn main() !void {
|
|||||||
break :draw_clock;
|
break :draw_clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.drawLabel(clock_str, buffer.width - @min(buffer.width, clock_str.len), 0);
|
buffer.drawLabel(clock_str, buffer.width - @min(buffer.width, clock_str.len) - config.edge_margin, config.edge_margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
const label_x = buffer.box_x + buffer.margin_box_h;
|
const label_x = buffer.box_x + buffer.margin_box_h;
|
||||||
@@ -672,44 +773,53 @@ pub fn main() !void {
|
|||||||
info_line.label.draw();
|
info_line.label.draw();
|
||||||
|
|
||||||
if (!config.hide_key_hints) {
|
if (!config.hide_key_hints) {
|
||||||
buffer.drawLabel(config.shutdown_key, length, 0);
|
buffer.drawLabel(config.shutdown_key, length, config.edge_margin);
|
||||||
length += config.shutdown_key.len + 1;
|
length += config.shutdown_key.len + 1;
|
||||||
buffer.drawLabel(" ", length - 1, 0);
|
buffer.drawLabel(" ", length - 1, config.edge_margin);
|
||||||
|
|
||||||
buffer.drawLabel(lang.shutdown, length, 0);
|
buffer.drawLabel(lang.shutdown, length, config.edge_margin);
|
||||||
length += shutdown_len + 1;
|
length += shutdown_len + 1;
|
||||||
|
|
||||||
buffer.drawLabel(config.restart_key, length, 0);
|
buffer.drawLabel(config.restart_key, length, config.edge_margin);
|
||||||
length += config.restart_key.len + 1;
|
length += config.restart_key.len + 1;
|
||||||
buffer.drawLabel(" ", length - 1, 0);
|
buffer.drawLabel(" ", length - 1, config.edge_margin);
|
||||||
|
|
||||||
buffer.drawLabel(lang.restart, length, 0);
|
buffer.drawLabel(lang.restart, length, config.edge_margin);
|
||||||
length += restart_len + 1;
|
length += restart_len + 1;
|
||||||
|
|
||||||
if (config.sleep_cmd != null) {
|
if (config.sleep_cmd != null) {
|
||||||
buffer.drawLabel(config.sleep_key, length, 0);
|
buffer.drawLabel(config.sleep_key, length, config.edge_margin);
|
||||||
length += config.sleep_key.len + 1;
|
length += config.sleep_key.len + 1;
|
||||||
buffer.drawLabel(" ", length - 1, 0);
|
buffer.drawLabel(" ", length - 1, config.edge_margin);
|
||||||
|
|
||||||
buffer.drawLabel(lang.sleep, length, 0);
|
buffer.drawLabel(lang.sleep, length, config.edge_margin);
|
||||||
length += sleep_len + 1;
|
length += sleep_len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.brightness_down_key) |key| {
|
if (config.hibernate_cmd != null) {
|
||||||
buffer.drawLabel(key, length, 0);
|
buffer.drawLabel(config.hibernate_key, length, config.edge_margin);
|
||||||
length += key.len + 1;
|
length += config.hibernate_key.len + 1;
|
||||||
buffer.drawLabel(" ", length - 1, 0);
|
buffer.drawLabel(" ", length - 1, config.edge_margin);
|
||||||
|
|
||||||
buffer.drawLabel(lang.brightness_down, length, 0);
|
buffer.drawLabel(lang.hibernate, length, config.edge_margin);
|
||||||
|
length += hibernate_len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.brightness_down_key) |key| {
|
||||||
|
buffer.drawLabel(key, length, config.edge_margin);
|
||||||
|
length += key.len + 1;
|
||||||
|
buffer.drawLabel(" ", length - 1, config.edge_margin);
|
||||||
|
|
||||||
|
buffer.drawLabel(lang.brightness_down, length, config.edge_margin);
|
||||||
length += brightness_down_len + 1;
|
length += brightness_down_len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.brightness_up_key) |key| {
|
if (config.brightness_up_key) |key| {
|
||||||
buffer.drawLabel(key, length, 0);
|
buffer.drawLabel(key, length, config.edge_margin);
|
||||||
length += key.len + 1;
|
length += key.len + 1;
|
||||||
buffer.drawLabel(" ", length - 1, 0);
|
buffer.drawLabel(" ", length - 1, config.edge_margin);
|
||||||
|
|
||||||
buffer.drawLabel(lang.brightness_up, length, 0);
|
buffer.drawLabel(lang.brightness_up, length, config.edge_margin);
|
||||||
length += brightness_up_len + 1;
|
length += brightness_up_len + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -723,7 +833,7 @@ pub fn main() !void {
|
|||||||
buffer.drawLabel(label_txt, buffer.box_x, buffer.box_y + buffer.box_height);
|
buffer.drawLabel(label_txt, buffer.box_x, buffer.box_y + buffer.box_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_get_lock_state) draw_lock_state: {
|
if (!config.hide_keyboard_locks and can_get_lock_state) draw_lock_state: {
|
||||||
const lock_state = interop.getLockState() catch |err| {
|
const lock_state = interop.getLockState() catch |err| {
|
||||||
try info_line.addMessage(lang.err_lock_state, config.error_bg, config.error_fg);
|
try info_line.addMessage(lang.err_lock_state, config.error_bg, config.error_fg);
|
||||||
can_get_lock_state = false;
|
can_get_lock_state = false;
|
||||||
@@ -731,8 +841,10 @@ pub fn main() !void {
|
|||||||
break :draw_lock_state;
|
break :draw_lock_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
var lock_state_x = buffer.width - @min(buffer.width, lang.numlock.len);
|
var lock_state_x = buffer.width - @min(buffer.width, lang.numlock.len) - config.edge_margin;
|
||||||
const lock_state_y: usize = if (config.clock != null) 1 else 0;
|
var lock_state_y: usize = config.edge_margin;
|
||||||
|
|
||||||
|
if (config.clock != null) lock_state_y += 1;
|
||||||
|
|
||||||
if (lock_state.numlock) buffer.drawLabel(lang.numlock, lock_state_x, lock_state_y);
|
if (lock_state.numlock) buffer.drawLabel(lang.numlock, lock_state_x, lock_state_y);
|
||||||
|
|
||||||
@@ -758,7 +870,7 @@ pub fn main() !void {
|
|||||||
// Check how long we've been running so we can turn off the animation
|
// Check how long we've been running so we can turn off the animation
|
||||||
const time = try interop.getTimeOfDay();
|
const time = try interop.getTimeOfDay();
|
||||||
|
|
||||||
if (config.animation_timeout_sec > 0 and time.seconds - time_start.seconds > config.animation_timeout_sec) {
|
if (config.animation_timeout_sec > 0 and time.seconds - animation_time_start.seconds > config.animation_timeout_sec) {
|
||||||
animation_timed_out = true;
|
animation_timed_out = true;
|
||||||
animation.deinit();
|
animation.deinit();
|
||||||
}
|
}
|
||||||
@@ -766,17 +878,56 @@ pub fn main() !void {
|
|||||||
const time = try interop.getTimeOfDay();
|
const time = try interop.getTimeOfDay();
|
||||||
|
|
||||||
timeout = @intCast((60 - @rem(time.seconds, 60)) * 1000 - @divTrunc(time.microseconds, 1000) + 1);
|
timeout = @intCast((60 - @rem(time.seconds, 60)) * 1000 - @divTrunc(time.microseconds, 1000) + 1);
|
||||||
} else if (config.clock != null or auth_fails >= config.auth_fails) {
|
} else if (config.clock != null or (config.auth_fails > 0 and auth_fails >= config.auth_fails)) {
|
||||||
const time = try interop.getTimeOfDay();
|
const time = try interop.getTimeOfDay();
|
||||||
|
|
||||||
timeout = @intCast(1000 - @divTrunc(time.microseconds, 1000) + 1);
|
timeout = @intCast(1000 - @divTrunc(time.microseconds, 1000) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const event_error = if (timeout == -1) termbox.tb_poll_event(&event) else termbox.tb_peek_event(&event, timeout);
|
if (config.inactivity_cmd) |inactivity_cmd| {
|
||||||
|
const time = try interop.getTimeOfDay();
|
||||||
|
|
||||||
update = timeout != -1;
|
if (!inactivity_cmd_ran and time.seconds - inactivity_time_start.seconds > config.inactivity_delay) {
|
||||||
|
var inactivity = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", inactivity_cmd }, allocator);
|
||||||
|
inactivity.stdout_behavior = .Ignore;
|
||||||
|
inactivity.stderr_behavior = .Ignore;
|
||||||
|
|
||||||
if (event_error < 0 or event.type != termbox.TB_EVENT_KEY) continue;
|
handle_inactivity_cmd: {
|
||||||
|
const process_result = inactivity.spawnAndWait() catch {
|
||||||
|
break :handle_inactivity_cmd;
|
||||||
|
};
|
||||||
|
if (process_result.Exited != 0) {
|
||||||
|
try info_line.addMessage(lang.err_inactivity, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("failed to execute inactivity command: exit code {d}\n", .{process_result.Exited});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inactivity_cmd_ran = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip event polling if autologin is set, use simulated Enter key press instead
|
||||||
|
if (is_autologin) {
|
||||||
|
event = termbox.tb_event{
|
||||||
|
.type = termbox.TB_EVENT_KEY,
|
||||||
|
.key = termbox.TB_KEY_ENTER,
|
||||||
|
.ch = 0,
|
||||||
|
.w = 0,
|
||||||
|
.h = 0,
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.mod = 0,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const event_error = if (timeout == -1) termbox.tb_poll_event(&event) else termbox.tb_peek_event(&event, timeout);
|
||||||
|
|
||||||
|
update = timeout != -1;
|
||||||
|
|
||||||
|
if (event_error < 0 or event.type != termbox.TB_EVENT_KEY) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input of some kind was detected, so reset the inactivity timer
|
||||||
|
inactivity_time_start = try interop.getTimeOfDay();
|
||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
termbox.TB_KEY_ESC => {
|
termbox.TB_KEY_ESC => {
|
||||||
@@ -809,6 +960,22 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (pressed_key == hibernate_key) {
|
||||||
|
if (config.hibernate_cmd) |hibernate_cmd| {
|
||||||
|
var hibernate = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", hibernate_cmd }, allocator);
|
||||||
|
hibernate.stdout_behavior = .Ignore;
|
||||||
|
hibernate.stderr_behavior = .Ignore;
|
||||||
|
|
||||||
|
handle_hibernate_cmd: {
|
||||||
|
const process_result = hibernate.spawnAndWait() catch {
|
||||||
|
break :handle_hibernate_cmd;
|
||||||
|
};
|
||||||
|
if (process_result.Exited != 0) {
|
||||||
|
try info_line.addMessage(lang.err_hibernate, config.error_bg, config.error_fg);
|
||||||
|
try log_writer.print("failed to execute hibernate command: exit code {d}\n", .{process_result.Exited});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (brightness_down_key != null and pressed_key == brightness_down_key.?) {
|
} else if (brightness_down_key != null and pressed_key == brightness_down_key.?) {
|
||||||
adjustBrightness(allocator, config.brightness_down_cmd) catch |err| {
|
adjustBrightness(allocator, config.brightness_down_cmd) catch |err| {
|
||||||
try info_line.addMessage(lang.err_brightness_change, config.error_bg, config.error_fg);
|
try info_line.addMessage(lang.err_brightness_change, config.error_bg, config.error_fg);
|
||||||
@@ -827,37 +994,19 @@ pub fn main() !void {
|
|||||||
update = true;
|
update = true;
|
||||||
},
|
},
|
||||||
termbox.TB_KEY_CTRL_K, termbox.TB_KEY_ARROW_UP => {
|
termbox.TB_KEY_CTRL_K, termbox.TB_KEY_ARROW_UP => {
|
||||||
active_input = switch (active_input) {
|
active_input.move(true, false);
|
||||||
.session, .info_line => .info_line,
|
|
||||||
.login => .session,
|
|
||||||
.password => .login,
|
|
||||||
};
|
|
||||||
update = true;
|
update = true;
|
||||||
},
|
},
|
||||||
termbox.TB_KEY_CTRL_J, termbox.TB_KEY_ARROW_DOWN => {
|
termbox.TB_KEY_CTRL_J, termbox.TB_KEY_ARROW_DOWN => {
|
||||||
active_input = switch (active_input) {
|
active_input.move(false, false);
|
||||||
.info_line => .session,
|
|
||||||
.session => .login,
|
|
||||||
.login, .password => .password,
|
|
||||||
};
|
|
||||||
update = true;
|
update = true;
|
||||||
},
|
},
|
||||||
termbox.TB_KEY_TAB => {
|
termbox.TB_KEY_TAB => {
|
||||||
active_input = switch (active_input) {
|
active_input.move(false, true);
|
||||||
.info_line => .session,
|
|
||||||
.session => .login,
|
|
||||||
.login => .password,
|
|
||||||
.password => .info_line,
|
|
||||||
};
|
|
||||||
update = true;
|
update = true;
|
||||||
},
|
},
|
||||||
termbox.TB_KEY_BACK_TAB => {
|
termbox.TB_KEY_BACK_TAB => {
|
||||||
active_input = switch (active_input) {
|
active_input.move(true, true);
|
||||||
.info_line => .password,
|
|
||||||
.session => .info_line,
|
|
||||||
.login => .session,
|
|
||||||
.password => .login,
|
|
||||||
};
|
|
||||||
update = true;
|
update = true;
|
||||||
},
|
},
|
||||||
termbox.TB_KEY_ENTER => authenticate: {
|
termbox.TB_KEY_ENTER => authenticate: {
|
||||||
@@ -922,9 +1071,14 @@ pub fn main() !void {
|
|||||||
session_pid = try std.posix.fork();
|
session_pid = try std.posix.fork();
|
||||||
if (session_pid == 0) {
|
if (session_pid == 0) {
|
||||||
const current_environment = session.label.list.items[session.label.current].environment;
|
const current_environment = session.label.list.items[session.label.current].environment;
|
||||||
|
|
||||||
|
// Use auto_login_service for autologin, otherwise use configured service
|
||||||
|
const service_name = if (is_autologin) config.auto_login_service else config.service_name;
|
||||||
|
const password_text = if (is_autologin) "" else password.text.items;
|
||||||
|
|
||||||
const auth_options = auth.AuthOptions{
|
const auth_options = auth.AuthOptions{
|
||||||
.tty = active_tty,
|
.tty = active_tty,
|
||||||
.service_name = config.service_name,
|
.service_name = service_name,
|
||||||
.path = config.path,
|
.path = config.path,
|
||||||
.session_log = config.session_log,
|
.session_log = config.session_log,
|
||||||
.xauth_cmd = config.xauth_cmd,
|
.xauth_cmd = config.xauth_cmd,
|
||||||
@@ -944,7 +1098,7 @@ pub fn main() !void {
|
|||||||
|
|
||||||
try log_file.reinit();
|
try log_file.reinit();
|
||||||
|
|
||||||
auth.authenticate(allocator, &log_file, auth_options, current_environment, login.getCurrentUsername(), password.text.items) catch |err| {
|
auth.authenticate(allocator, &log_file, auth_options, current_environment, login.getCurrentUsername(), password_text) catch |err| {
|
||||||
shared_err.writeError(err);
|
shared_err.writeError(err);
|
||||||
|
|
||||||
log_file.deinit();
|
log_file.deinit();
|
||||||
@@ -987,13 +1141,14 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
password.clear();
|
password.clear();
|
||||||
|
is_autologin = false;
|
||||||
try info_line.addMessage(lang.logout, config.bg, config.fg);
|
try info_line.addMessage(lang.logout, config.bg, config.fg);
|
||||||
try log_writer.writeAll("logged out\n");
|
try log_writer.writeAll("logged out\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
|
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
|
||||||
|
|
||||||
if (auth_fails < config.auth_fails) {
|
if (config.auth_fails == 0 or auth_fails < config.auth_fails) {
|
||||||
_ = termbox.tb_clear();
|
_ = termbox.tb_clear();
|
||||||
try ttyClearScreen();
|
try ttyClearScreen();
|
||||||
|
|
||||||
@@ -1008,20 +1163,12 @@ pub fn main() !void {
|
|||||||
if (!insert_mode) {
|
if (!insert_mode) {
|
||||||
switch (event.ch) {
|
switch (event.ch) {
|
||||||
'k' => {
|
'k' => {
|
||||||
active_input = switch (active_input) {
|
active_input.move(true, false);
|
||||||
.session, .info_line => .info_line,
|
|
||||||
.login => .session,
|
|
||||||
.password => .login,
|
|
||||||
};
|
|
||||||
update = true;
|
update = true;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
'j' => {
|
'j' => {
|
||||||
active_input = switch (active_input) {
|
active_input.move(false, false);
|
||||||
.info_line => .session,
|
|
||||||
.session => .login,
|
|
||||||
.login, .password => .password,
|
|
||||||
};
|
|
||||||
update = true;
|
update = true;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
@@ -1086,7 +1233,9 @@ fn addOtherEnvironment(session: *Session, lang: Lang, display_server: DisplaySer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: DisplayServer) !void {
|
fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: DisplayServer) !void {
|
||||||
var iterable_directory = std.fs.openDirAbsolute(path, .{ .iterate = true }) catch return;
|
if (!std.fs.path.isAbsolute(path)) return error.PathNotAbsolute;
|
||||||
|
|
||||||
|
var iterable_directory = try std.fs.openDirAbsolute(path, .{ .iterate = true });
|
||||||
defer iterable_directory.close();
|
defer iterable_directory.close();
|
||||||
|
|
||||||
var iterator = iterable_directory.iterate();
|
var iterator = iterable_directory.iterate();
|
||||||
@@ -1105,6 +1254,7 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
|
|||||||
const entry = entry_ini.data.@"Desktop Entry";
|
const entry = entry_ini.data.@"Desktop Entry";
|
||||||
var maybe_xdg_session_desktop: ?[]const u8 = null;
|
var maybe_xdg_session_desktop: ?[]const u8 = null;
|
||||||
var maybe_xdg_desktop_names: ?[]const u8 = null;
|
var maybe_xdg_desktop_names: ?[]const u8 = null;
|
||||||
|
var xdg_session_desktop_owned = false;
|
||||||
|
|
||||||
// Prepare the XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP environment
|
// Prepare the XDG_SESSION_DESKTOP and XDG_CURRENT_DESKTOP environment
|
||||||
// variables here
|
// variables here
|
||||||
@@ -1118,13 +1268,18 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
|
|||||||
} else if (display_server != .custom) {
|
} else if (display_server != .custom) {
|
||||||
// If DesktopNames is empty, and this isn't a custom session entry,
|
// If DesktopNames is empty, and this isn't a custom session entry,
|
||||||
// we'll take the name of the session file
|
// we'll take the name of the session file
|
||||||
maybe_xdg_session_desktop = std.fs.path.stem(item.name);
|
const stem = std.fs.path.stem(item.name);
|
||||||
|
if (stem.len > 0) {
|
||||||
|
maybe_xdg_session_desktop = try session.label.allocator.dupe(u8, stem);
|
||||||
|
xdg_session_desktop_owned = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try session.addEnvironment(.{
|
try session.addEnvironment(.{
|
||||||
.entry_ini = entry_ini,
|
.entry_ini = entry_ini,
|
||||||
.name = entry.Name,
|
.name = entry.Name,
|
||||||
.xdg_session_desktop = maybe_xdg_session_desktop,
|
.xdg_session_desktop = maybe_xdg_session_desktop,
|
||||||
|
.xdg_session_desktop_owned = xdg_session_desktop_owned,
|
||||||
.xdg_desktop_names = maybe_xdg_desktop_names,
|
.xdg_desktop_names = maybe_xdg_desktop_names,
|
||||||
.cmd = entry.Exec,
|
.cmd = entry.Exec,
|
||||||
.specifier = switch (display_server) {
|
.specifier = switch (display_server) {
|
||||||
@@ -1139,8 +1294,34 @@ fn crawl(session: *Session, lang: Lang, path: []const u8, display_server: Displa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAllUsernames(allocator: std.mem.Allocator, login_defs_path: []const u8) !StringList {
|
fn isValidUsername(username: []const u8, usernames: StringList) bool {
|
||||||
const uid_range = try interop.getUserIdRange(allocator, login_defs_path);
|
for (usernames.items) |valid_username| {
|
||||||
|
if (std.mem.eql(u8, username, valid_username)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn findSessionByName(session: *Session, name: []const u8) ?usize {
|
||||||
|
for (session.label.list.items, 0..) |env, i| {
|
||||||
|
if (env.environment.xdg_session_desktop) |session_desktop| {
|
||||||
|
if (session_desktop.len > 0 and std.ascii.eqlIgnoreCase(session_desktop, name)) return i;
|
||||||
|
}
|
||||||
|
if (env.environment.xdg_desktop_names) |session_desktop_name| {
|
||||||
|
if (std.ascii.eqlIgnoreCase(session_desktop_name, name)) return i;
|
||||||
|
}
|
||||||
|
if (std.ascii.eqlIgnoreCase(env.environment.name, name)) return i;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getAllUsernames(allocator: std.mem.Allocator, login_defs_path: []const u8, uid_range_error: *?anyerror) !StringList {
|
||||||
|
const uid_range = interop.getUserIdRange(allocator, login_defs_path) catch |err| no_uid_range: {
|
||||||
|
uid_range_error.* = err;
|
||||||
|
break :no_uid_range UidRange{
|
||||||
|
.uid_min = build_options.fallback_uid_min,
|
||||||
|
.uid_max = build_options.fallback_uid_max,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
var usernames: StringList = .empty;
|
var usernames: StringList = .empty;
|
||||||
var maybe_entry = interop.getNextUsernameEntry();
|
var maybe_entry = interop.getNextUsernameEntry();
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ pub const Color = struct {
|
|||||||
pub const TRUE_MAGENTA = 0x00FF00FF;
|
pub const TRUE_MAGENTA = 0x00FF00FF;
|
||||||
pub const TRUE_CYAN = 0x0000FFFF;
|
pub const TRUE_CYAN = 0x0000FFFF;
|
||||||
pub const TRUE_WHITE = 0x00FFFFFF;
|
pub const TRUE_WHITE = 0x00FFFFFF;
|
||||||
|
pub const TRUE_DIM_RED = 0x00800000;
|
||||||
|
pub const TRUE_DIM_GREEN = 0x00008000;
|
||||||
|
pub const TRUE_DIM_YELLOW = 0x00808000;
|
||||||
|
pub const TRUE_DIM_BLUE = 0x00000080;
|
||||||
|
pub const TRUE_DIM_MAGENTA = 0x00800080;
|
||||||
|
pub const TRUE_DIM_CYAN = 0x00008080;
|
||||||
|
pub const TRUE_DIM_WHITE = 0x00C0C0C0;
|
||||||
pub const ECOL_BLACK = 1;
|
pub const ECOL_BLACK = 1;
|
||||||
pub const ECOL_RED = 2;
|
pub const ECOL_RED = 2;
|
||||||
pub const ECOL_GREEN = 3;
|
pub const ECOL_GREEN = 3;
|
||||||
|
|||||||
@@ -17,28 +17,39 @@ const EnvironmentLabel = generic.CyclableLabel(Env, *UserList);
|
|||||||
const Session = @This();
|
const Session = @This();
|
||||||
|
|
||||||
label: EnvironmentLabel,
|
label: EnvironmentLabel,
|
||||||
|
user_list: *UserList,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, user_list: *UserList) Session {
|
pub fn init(allocator: Allocator, buffer: *TerminalBuffer, user_list: *UserList) Session {
|
||||||
return .{
|
return .{
|
||||||
.label = EnvironmentLabel.init(allocator, buffer, drawItem, sessionChanged, user_list),
|
.label = EnvironmentLabel.init(allocator, buffer, drawItem, sessionChanged, user_list),
|
||||||
|
.user_list = user_list,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Session) void {
|
pub fn deinit(self: *Session) void {
|
||||||
for (self.label.list.items) |*env| {
|
for (self.label.list.items) |*env| {
|
||||||
if (env.environment.entry_ini) |*entry_ini| entry_ini.deinit();
|
if (env.environment.entry_ini) |*entry_ini| entry_ini.deinit();
|
||||||
|
if (env.environment.xdg_session_desktop_owned) {
|
||||||
|
self.label.allocator.free(env.environment.xdg_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 });
|
const env = Env{ .environment = environment, .index = self.label.list.items.len };
|
||||||
|
|
||||||
|
try self.label.addItem(env);
|
||||||
|
sessionChanged(env, self.user_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sessionChanged(env: Env, maybe_user_list: ?*UserList) void {
|
fn sessionChanged(env: Env, maybe_user_list: ?*UserList) void {
|
||||||
if (maybe_user_list) |user_list| {
|
if (maybe_user_list) |user_list| {
|
||||||
user_list.label.list.items[user_list.label.current].session_index.* = env.index;
|
const user = user_list.label.list.items[user_list.label.current];
|
||||||
|
if (!user.first_run) return;
|
||||||
|
|
||||||
|
user.session_index.* = env.index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub const User = struct {
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
session_index: *usize,
|
session_index: *usize,
|
||||||
allocated_index: bool,
|
allocated_index: bool,
|
||||||
|
first_run: bool,
|
||||||
};
|
};
|
||||||
const UserLabel = generic.CyclableLabel(User, *Session);
|
const UserLabel = generic.CyclableLabel(User, *Session);
|
||||||
|
|
||||||
@@ -27,9 +28,11 @@ pub fn init(allocator: Allocator, buffer: *TerminalBuffer, usernames: StringList
|
|||||||
if (username.len == 0) continue;
|
if (username.len == 0) continue;
|
||||||
|
|
||||||
var maybe_session_index: ?*usize = null;
|
var maybe_session_index: ?*usize = null;
|
||||||
|
var first_run = true;
|
||||||
for (saved_users.user_list.items) |*saved_user| {
|
for (saved_users.user_list.items) |*saved_user| {
|
||||||
if (std.mem.eql(u8, username, saved_user.username)) {
|
if (std.mem.eql(u8, username, saved_user.username)) {
|
||||||
maybe_session_index = &saved_user.session_index;
|
maybe_session_index = &saved_user.session_index;
|
||||||
|
first_run = saved_user.first_run;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,6 +48,7 @@ pub fn init(allocator: Allocator, buffer: *TerminalBuffer, usernames: StringList
|
|||||||
.name = username,
|
.name = username,
|
||||||
.session_index = maybe_session_index.?,
|
.session_index = maybe_session_index.?,
|
||||||
.allocated_index = allocated_index,
|
.allocated_index = allocated_index,
|
||||||
|
.first_run = first_run,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +71,7 @@ pub fn getCurrentUsername(self: UserList) []const u8 {
|
|||||||
|
|
||||||
fn usernameChanged(user: User, maybe_session: ?*Session) void {
|
fn usernameChanged(user: User, maybe_session: ?*Session) void {
|
||||||
if (maybe_session) |session| {
|
if (maybe_session) |session| {
|
||||||
|
if (user.session_index.* >= session.label.list.items.len) return;
|
||||||
session.label.current = user.session_index.*;
|
session.label.current = user.session_index.*;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user