mirror of https://github.com/fairyglade/ly.git
Partially rewrite utils.c
This commit is contained in:
parent
2fd2f77ac0
commit
40c7c27b88
298
src/config.zig
298
src/config.zig
|
@ -171,7 +171,8 @@ var lang_wayland: [:0]u8 = undefined;
|
|||
var lang_xinitrc: [:0]u8 = undefined;
|
||||
|
||||
pub fn config_load(cfg_path: []const u8) !void {
|
||||
var file = try std.fs.cwd().openFile(if (std.mem.eql(u8, cfg_path, "")) INI_CONFIG_PATH ++ "config.ini" else cfg_path, .{});
|
||||
var file = try std.fs.cwd().openFile(if (cfg_path.len == 0) INI_CONFIG_PATH ++ "config.ini" else cfg_path, .{});
|
||||
defer file.close();
|
||||
|
||||
config_buffer = try main.allocator.alloc(u8, INI_CONFIG_MAX_SIZE);
|
||||
|
||||
|
@ -197,45 +198,45 @@ pub fn config_load(cfg_path: []const u8) !void {
|
|||
config_xauth_cmd = try interop.c_str(ly_config.ly.xauth_cmd);
|
||||
config_xsessions = try interop.c_str(ly_config.ly.xsessions);
|
||||
|
||||
main.config.animate = ly_config.ly.animate;
|
||||
main.config.animation = ly_config.ly.animation;
|
||||
main.config.asterisk = ly_config.ly.asterisk;
|
||||
main.config.bg = ly_config.ly.bg;
|
||||
main.config.bigclock = ly_config.ly.bigclock;
|
||||
main.config.blank_box = ly_config.ly.blank_box;
|
||||
main.config.blank_password = ly_config.ly.blank_password;
|
||||
main.config.clock = config_clock.ptr;
|
||||
main.config.console_dev = config_console_dev.ptr;
|
||||
main.config.default_input = ly_config.ly.default_input;
|
||||
main.config.fg = ly_config.ly.fg;
|
||||
main.config.hide_borders = ly_config.ly.hide_borders;
|
||||
main.config.hide_f1_commands = ly_config.ly.hide_f1_commands;
|
||||
main.config.input_len = ly_config.ly.input_len;
|
||||
main.config.lang = config_lang.ptr;
|
||||
main.config.load = ly_config.ly.load;
|
||||
main.config.margin_box_h = ly_config.ly.margin_box_h;
|
||||
main.config.margin_box_v = ly_config.ly.margin_box_v;
|
||||
main.config.max_desktop_len = ly_config.ly.max_desktop_len;
|
||||
main.config.max_login_len = ly_config.ly.max_login_len;
|
||||
main.config.max_password_len = ly_config.ly.max_password_len;
|
||||
main.config.mcookie_cmd = config_mcookie_cmd.ptr;
|
||||
main.config.min_refresh_delta = ly_config.ly.min_refresh_delta;
|
||||
main.config.path = config_path.ptr;
|
||||
main.config.restart_cmd = config_restart_cmd.ptr;
|
||||
main.config.save = ly_config.ly.save;
|
||||
main.config.save_file = config_save_file.ptr;
|
||||
main.config.service_name = config_service_name.ptr;
|
||||
main.config.shutdown_cmd = config_shutdown_cmd.ptr;
|
||||
main.config.term_reset_cmd = config_term_reset_cmd.ptr;
|
||||
main.config.tty = ly_config.ly.tty;
|
||||
main.config.wayland_cmd = config_wayland_cmd.ptr;
|
||||
main.config.wayland_specifier = ly_config.ly.wayland_specifier;
|
||||
main.config.waylandsessions = config_waylandsessions.ptr;
|
||||
main.config.x_cmd = config_x_cmd.ptr;
|
||||
main.config.xinitrc = config_xinitrc.ptr;
|
||||
main.config.x_cmd_setup = config_x_cmd_setup.ptr;
|
||||
main.config.xauth_cmd = config_xauth_cmd.ptr;
|
||||
main.config.xsessions = config_xsessions.ptr;
|
||||
main.c_config.animate = ly_config.ly.animate;
|
||||
main.c_config.animation = ly_config.ly.animation;
|
||||
main.c_config.asterisk = ly_config.ly.asterisk;
|
||||
main.c_config.bg = ly_config.ly.bg;
|
||||
main.c_config.bigclock = ly_config.ly.bigclock;
|
||||
main.c_config.blank_box = ly_config.ly.blank_box;
|
||||
main.c_config.blank_password = ly_config.ly.blank_password;
|
||||
main.c_config.clock = config_clock.ptr;
|
||||
main.c_config.console_dev = config_console_dev.ptr;
|
||||
main.c_config.default_input = ly_config.ly.default_input;
|
||||
main.c_config.fg = ly_config.ly.fg;
|
||||
main.c_config.hide_borders = ly_config.ly.hide_borders;
|
||||
main.c_config.hide_f1_commands = ly_config.ly.hide_f1_commands;
|
||||
main.c_config.input_len = ly_config.ly.input_len;
|
||||
main.c_config.lang = config_lang.ptr;
|
||||
main.c_config.load = ly_config.ly.load;
|
||||
main.c_config.margin_box_h = ly_config.ly.margin_box_h;
|
||||
main.c_config.margin_box_v = ly_config.ly.margin_box_v;
|
||||
main.c_config.max_desktop_len = ly_config.ly.max_desktop_len;
|
||||
main.c_config.max_login_len = ly_config.ly.max_login_len;
|
||||
main.c_config.max_password_len = ly_config.ly.max_password_len;
|
||||
main.c_config.mcookie_cmd = config_mcookie_cmd.ptr;
|
||||
main.c_config.min_refresh_delta = ly_config.ly.min_refresh_delta;
|
||||
main.c_config.path = config_path.ptr;
|
||||
main.c_config.restart_cmd = config_restart_cmd.ptr;
|
||||
main.c_config.save = ly_config.ly.save;
|
||||
main.c_config.save_file = config_save_file.ptr;
|
||||
main.c_config.service_name = config_service_name.ptr;
|
||||
main.c_config.shutdown_cmd = config_shutdown_cmd.ptr;
|
||||
main.c_config.term_reset_cmd = config_term_reset_cmd.ptr;
|
||||
main.c_config.tty = ly_config.ly.tty;
|
||||
main.c_config.wayland_cmd = config_wayland_cmd.ptr;
|
||||
main.c_config.wayland_specifier = ly_config.ly.wayland_specifier;
|
||||
main.c_config.waylandsessions = config_waylandsessions.ptr;
|
||||
main.c_config.x_cmd = config_x_cmd.ptr;
|
||||
main.c_config.xinitrc = config_xinitrc.ptr;
|
||||
main.c_config.x_cmd_setup = config_x_cmd_setup.ptr;
|
||||
main.c_config.xauth_cmd = config_xauth_cmd.ptr;
|
||||
main.c_config.xsessions = config_xsessions.ptr;
|
||||
}
|
||||
|
||||
pub fn lang_load() !void {
|
||||
|
@ -243,6 +244,7 @@ pub fn lang_load() !void {
|
|||
defer main.allocator.free(path);
|
||||
|
||||
var file = try std.fs.cwd().openFile(path, .{});
|
||||
defer file.close();
|
||||
|
||||
lang_buffer = try main.allocator.alloc(u8, INI_CONFIG_MAX_SIZE);
|
||||
|
||||
|
@ -296,119 +298,121 @@ pub fn lang_load() !void {
|
|||
lang_wayland = try interop.c_str(ly_lang.ly.wayland);
|
||||
lang_xinitrc = try interop.c_str(ly_lang.ly.xinitrc);
|
||||
|
||||
main.lang.capslock = lang_capslock.ptr;
|
||||
main.lang.err_alloc = lang_err_alloc.ptr;
|
||||
main.lang.err_bounds = lang_err_bounds.ptr;
|
||||
main.lang.err_chdir = lang_err_chdir.ptr;
|
||||
main.lang.err_console_dev = lang_err_console_dev.ptr;
|
||||
main.lang.err_dgn_oob = lang_err_dgn_oob.ptr;
|
||||
main.lang.err_domain = lang_err_domain.ptr;
|
||||
main.lang.err_hostname = lang_err_hostname.ptr;
|
||||
main.lang.err_mlock = lang_err_mlock.ptr;
|
||||
main.lang.err_null = lang_err_null.ptr;
|
||||
main.lang.err_pam = lang_err_pam.ptr;
|
||||
main.lang.err_pam_abort = lang_err_pam_abort.ptr;
|
||||
main.lang.err_pam_acct_expired = lang_err_pam_acct_expired.ptr;
|
||||
main.lang.err_pam_auth = lang_err_pam_auth.ptr;
|
||||
main.lang.err_pam_authinfo_unavail = lang_err_pam_authinfo_unavail.ptr;
|
||||
main.lang.err_pam_authok_reqd = lang_err_pam_authok_reqd.ptr;
|
||||
main.lang.err_pam_buf = lang_err_pam_buf.ptr;
|
||||
main.lang.err_pam_cred_err = lang_err_pam_cred_err.ptr;
|
||||
main.lang.err_pam_cred_expired = lang_err_pam_cred_expired.ptr;
|
||||
main.lang.err_pam_cred_insufficient = lang_err_pam_cred_insufficient.ptr;
|
||||
main.lang.err_pam_cred_unavail = lang_err_pam_cred_unavail.ptr;
|
||||
main.lang.err_pam_maxtries = lang_err_pam_maxtries.ptr;
|
||||
main.lang.err_pam_perm_denied = lang_err_pam_perm_denied.ptr;
|
||||
main.lang.err_pam_session = lang_err_pam_session.ptr;
|
||||
main.lang.err_pam_sys = lang_err_pam_sys.ptr;
|
||||
main.lang.err_pam_user_unknown = lang_err_pam_user_unknown.ptr;
|
||||
main.lang.err_path = lang_err_path.ptr;
|
||||
main.lang.err_perm_dir = lang_err_perm_dir.ptr;
|
||||
main.lang.err_perm_group = lang_err_perm_group.ptr;
|
||||
main.lang.err_perm_user = lang_err_perm_user.ptr;
|
||||
main.lang.err_pwnam = lang_err_pwnam.ptr;
|
||||
main.lang.err_user_gid = lang_err_user_gid.ptr;
|
||||
main.lang.err_user_init = lang_err_user_init.ptr;
|
||||
main.lang.err_user_uid = lang_err_user_uid.ptr;
|
||||
main.lang.err_xsessions_dir = lang_err_xsessions_dir.ptr;
|
||||
main.lang.err_xsessions_open = lang_err_xsessions_open.ptr;
|
||||
main.lang.f1 = lang_f1.ptr;
|
||||
main.lang.f2 = lang_f2.ptr;
|
||||
main.lang.login = lang_login.ptr;
|
||||
main.lang.logout = lang_logout.ptr;
|
||||
main.lang.numlock = lang_numlock.ptr;
|
||||
main.lang.password = lang_password.ptr;
|
||||
main.lang.shell = lang_shell.ptr;
|
||||
main.lang.wayland = lang_wayland.ptr;
|
||||
main.lang.xinitrc = lang_xinitrc.ptr;
|
||||
main.c_lang.capslock = lang_capslock.ptr;
|
||||
main.c_lang.err_alloc = lang_err_alloc.ptr;
|
||||
main.c_lang.err_bounds = lang_err_bounds.ptr;
|
||||
main.c_lang.err_chdir = lang_err_chdir.ptr;
|
||||
main.c_lang.err_console_dev = lang_err_console_dev.ptr;
|
||||
main.c_lang.err_dgn_oob = lang_err_dgn_oob.ptr;
|
||||
main.c_lang.err_domain = lang_err_domain.ptr;
|
||||
main.c_lang.err_hostname = lang_err_hostname.ptr;
|
||||
main.c_lang.err_mlock = lang_err_mlock.ptr;
|
||||
main.c_lang.err_null = lang_err_null.ptr;
|
||||
main.c_lang.err_pam = lang_err_pam.ptr;
|
||||
main.c_lang.err_pam_abort = lang_err_pam_abort.ptr;
|
||||
main.c_lang.err_pam_acct_expired = lang_err_pam_acct_expired.ptr;
|
||||
main.c_lang.err_pam_auth = lang_err_pam_auth.ptr;
|
||||
main.c_lang.err_pam_authinfo_unavail = lang_err_pam_authinfo_unavail.ptr;
|
||||
main.c_lang.err_pam_authok_reqd = lang_err_pam_authok_reqd.ptr;
|
||||
main.c_lang.err_pam_buf = lang_err_pam_buf.ptr;
|
||||
main.c_lang.err_pam_cred_err = lang_err_pam_cred_err.ptr;
|
||||
main.c_lang.err_pam_cred_expired = lang_err_pam_cred_expired.ptr;
|
||||
main.c_lang.err_pam_cred_insufficient = lang_err_pam_cred_insufficient.ptr;
|
||||
main.c_lang.err_pam_cred_unavail = lang_err_pam_cred_unavail.ptr;
|
||||
main.c_lang.err_pam_maxtries = lang_err_pam_maxtries.ptr;
|
||||
main.c_lang.err_pam_perm_denied = lang_err_pam_perm_denied.ptr;
|
||||
main.c_lang.err_pam_session = lang_err_pam_session.ptr;
|
||||
main.c_lang.err_pam_sys = lang_err_pam_sys.ptr;
|
||||
main.c_lang.err_pam_user_unknown = lang_err_pam_user_unknown.ptr;
|
||||
main.c_lang.err_path = lang_err_path.ptr;
|
||||
main.c_lang.err_perm_dir = lang_err_perm_dir.ptr;
|
||||
main.c_lang.err_perm_group = lang_err_perm_group.ptr;
|
||||
main.c_lang.err_perm_user = lang_err_perm_user.ptr;
|
||||
main.c_lang.err_pwnam = lang_err_pwnam.ptr;
|
||||
main.c_lang.err_user_gid = lang_err_user_gid.ptr;
|
||||
main.c_lang.err_user_init = lang_err_user_init.ptr;
|
||||
main.c_lang.err_user_uid = lang_err_user_uid.ptr;
|
||||
main.c_lang.err_xsessions_dir = lang_err_xsessions_dir.ptr;
|
||||
main.c_lang.err_xsessions_open = lang_err_xsessions_open.ptr;
|
||||
main.c_lang.f1 = lang_f1.ptr;
|
||||
main.c_lang.f2 = lang_f2.ptr;
|
||||
main.c_lang.login = lang_login.ptr;
|
||||
main.c_lang.logout = lang_logout.ptr;
|
||||
main.c_lang.numlock = lang_numlock.ptr;
|
||||
main.c_lang.password = lang_password.ptr;
|
||||
main.c_lang.shell = lang_shell.ptr;
|
||||
main.c_lang.wayland = lang_wayland.ptr;
|
||||
main.c_lang.xinitrc = lang_xinitrc.ptr;
|
||||
}
|
||||
|
||||
pub fn config_free() void {
|
||||
main.allocator.free(config_clock);
|
||||
main.allocator.free(config_console_dev);
|
||||
main.allocator.free(config_lang);
|
||||
main.allocator.free(config_mcookie_cmd);
|
||||
main.allocator.free(config_path);
|
||||
main.allocator.free(config_restart_cmd);
|
||||
main.allocator.free(config_save_file);
|
||||
main.allocator.free(config_service_name);
|
||||
main.allocator.free(config_shutdown_cmd);
|
||||
main.allocator.free(config_term_reset_cmd);
|
||||
main.allocator.free(config_wayland_cmd);
|
||||
main.allocator.free(config_waylandsessions);
|
||||
main.allocator.free(config_x_cmd);
|
||||
main.allocator.free(config_xinitrc);
|
||||
main.allocator.free(config_x_cmd_setup);
|
||||
main.allocator.free(config_xauth_cmd);
|
||||
main.allocator.free(config_xsessions);
|
||||
interop.allocator.free(config_clock);
|
||||
interop.allocator.free(config_console_dev);
|
||||
interop.allocator.free(config_lang);
|
||||
interop.allocator.free(config_mcookie_cmd);
|
||||
interop.allocator.free(config_path);
|
||||
interop.allocator.free(config_restart_cmd);
|
||||
interop.allocator.free(config_save_file);
|
||||
interop.allocator.free(config_service_name);
|
||||
interop.allocator.free(config_shutdown_cmd);
|
||||
interop.allocator.free(config_term_reset_cmd);
|
||||
interop.allocator.free(config_wayland_cmd);
|
||||
interop.allocator.free(config_waylandsessions);
|
||||
interop.allocator.free(config_x_cmd);
|
||||
interop.allocator.free(config_xinitrc);
|
||||
interop.allocator.free(config_x_cmd_setup);
|
||||
interop.allocator.free(config_xauth_cmd);
|
||||
interop.allocator.free(config_xsessions);
|
||||
|
||||
main.allocator.free(config_buffer);
|
||||
}
|
||||
|
||||
pub fn lang_free() void {
|
||||
main.allocator.free(lang_capslock);
|
||||
main.allocator.free(lang_err_alloc);
|
||||
main.allocator.free(lang_err_bounds);
|
||||
main.allocator.free(lang_err_chdir);
|
||||
main.allocator.free(lang_err_console_dev);
|
||||
main.allocator.free(lang_err_dgn_oob);
|
||||
main.allocator.free(lang_err_domain);
|
||||
main.allocator.free(lang_err_hostname);
|
||||
main.allocator.free(lang_err_mlock);
|
||||
main.allocator.free(lang_err_null);
|
||||
main.allocator.free(lang_err_pam);
|
||||
main.allocator.free(lang_err_pam_abort);
|
||||
main.allocator.free(lang_err_pam_acct_expired);
|
||||
main.allocator.free(lang_err_pam_auth);
|
||||
main.allocator.free(lang_err_pam_authinfo_unavail);
|
||||
main.allocator.free(lang_err_pam_authok_reqd);
|
||||
main.allocator.free(lang_err_pam_buf);
|
||||
main.allocator.free(lang_err_pam_cred_err);
|
||||
main.allocator.free(lang_err_pam_cred_expired);
|
||||
main.allocator.free(lang_err_pam_cred_insufficient);
|
||||
main.allocator.free(lang_err_pam_cred_unavail);
|
||||
main.allocator.free(lang_err_pam_maxtries);
|
||||
main.allocator.free(lang_err_pam_perm_denied);
|
||||
main.allocator.free(lang_err_pam_session);
|
||||
main.allocator.free(lang_err_pam_sys);
|
||||
main.allocator.free(lang_err_pam_user_unknown);
|
||||
main.allocator.free(lang_err_path);
|
||||
main.allocator.free(lang_err_perm_dir);
|
||||
main.allocator.free(lang_err_perm_group);
|
||||
main.allocator.free(lang_err_perm_user);
|
||||
main.allocator.free(lang_err_pwnam);
|
||||
main.allocator.free(lang_err_user_gid);
|
||||
main.allocator.free(lang_err_user_init);
|
||||
main.allocator.free(lang_err_user_uid);
|
||||
main.allocator.free(lang_err_xsessions_dir);
|
||||
main.allocator.free(lang_err_xsessions_open);
|
||||
main.allocator.free(lang_f1);
|
||||
main.allocator.free(lang_f2);
|
||||
main.allocator.free(lang_login);
|
||||
main.allocator.free(lang_logout);
|
||||
main.allocator.free(lang_numlock);
|
||||
main.allocator.free(lang_password);
|
||||
main.allocator.free(lang_shell);
|
||||
main.allocator.free(lang_wayland);
|
||||
main.allocator.free(lang_xinitrc);
|
||||
interop.allocator.free(lang_capslock);
|
||||
interop.allocator.free(lang_err_alloc);
|
||||
interop.allocator.free(lang_err_bounds);
|
||||
interop.allocator.free(lang_err_chdir);
|
||||
interop.allocator.free(lang_err_console_dev);
|
||||
interop.allocator.free(lang_err_dgn_oob);
|
||||
interop.allocator.free(lang_err_domain);
|
||||
interop.allocator.free(lang_err_hostname);
|
||||
interop.allocator.free(lang_err_mlock);
|
||||
interop.allocator.free(lang_err_null);
|
||||
interop.allocator.free(lang_err_pam);
|
||||
interop.allocator.free(lang_err_pam_abort);
|
||||
interop.allocator.free(lang_err_pam_acct_expired);
|
||||
interop.allocator.free(lang_err_pam_auth);
|
||||
interop.allocator.free(lang_err_pam_authinfo_unavail);
|
||||
interop.allocator.free(lang_err_pam_authok_reqd);
|
||||
interop.allocator.free(lang_err_pam_buf);
|
||||
interop.allocator.free(lang_err_pam_cred_err);
|
||||
interop.allocator.free(lang_err_pam_cred_expired);
|
||||
interop.allocator.free(lang_err_pam_cred_insufficient);
|
||||
interop.allocator.free(lang_err_pam_cred_unavail);
|
||||
interop.allocator.free(lang_err_pam_maxtries);
|
||||
interop.allocator.free(lang_err_pam_perm_denied);
|
||||
interop.allocator.free(lang_err_pam_session);
|
||||
interop.allocator.free(lang_err_pam_sys);
|
||||
interop.allocator.free(lang_err_pam_user_unknown);
|
||||
interop.allocator.free(lang_err_path);
|
||||
interop.allocator.free(lang_err_perm_dir);
|
||||
interop.allocator.free(lang_err_perm_group);
|
||||
interop.allocator.free(lang_err_perm_user);
|
||||
interop.allocator.free(lang_err_pwnam);
|
||||
interop.allocator.free(lang_err_user_gid);
|
||||
interop.allocator.free(lang_err_user_init);
|
||||
interop.allocator.free(lang_err_user_uid);
|
||||
interop.allocator.free(lang_err_xsessions_dir);
|
||||
interop.allocator.free(lang_err_xsessions_open);
|
||||
interop.allocator.free(lang_f1);
|
||||
interop.allocator.free(lang_f2);
|
||||
interop.allocator.free(lang_login);
|
||||
interop.allocator.free(lang_logout);
|
||||
interop.allocator.free(lang_numlock);
|
||||
interop.allocator.free(lang_password);
|
||||
interop.allocator.free(lang_shell);
|
||||
interop.allocator.free(lang_wayland);
|
||||
interop.allocator.free(lang_xinitrc);
|
||||
|
||||
main.allocator.free(lang_buffer);
|
||||
}
|
||||
|
|
155
src/ini.zig
155
src/ini.zig
|
@ -1,116 +1,92 @@
|
|||
const std = @import("std");
|
||||
|
||||
// we ignore whitespace and comments
|
||||
pub const Token = union(enum) { comment, section: []const u8, key: []const u8, value: []const u8 };
|
||||
|
||||
pub const State = enum { normal, section, key, value, comment };
|
||||
|
||||
pub fn getTok(data: []const u8, pos: *usize, state: *State) ?Token {
|
||||
// if the position advances to the end of the data, there's no more tokens for us
|
||||
if (pos.* >= data.len) return null;
|
||||
var cur: u8 = 0;
|
||||
// used for slicing
|
||||
var start = pos.*;
|
||||
var end = start;
|
||||
pub fn getTok(data: []const u8, pos: *usize) ?Token {
|
||||
// If the position advances to the end of the data, there's no more tokens for us
|
||||
if (pos.* >= data.len) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (pos.* < data.len) {
|
||||
cur = data[pos.*];
|
||||
var current = data[pos.*];
|
||||
pos.* += 1;
|
||||
switch (state.*) {
|
||||
.normal => {
|
||||
switch (cur) {
|
||||
'[' => {
|
||||
state.* = .section;
|
||||
start = pos.*;
|
||||
end = start;
|
||||
},
|
||||
'=' => {
|
||||
state.* = .value;
|
||||
start = pos.*;
|
||||
if (std.ascii.isWhitespace(data[start])) start += 1;
|
||||
end = start;
|
||||
},
|
||||
';', '#' => {
|
||||
state.* = .comment;
|
||||
},
|
||||
// if it is whitespace itgets skipped over anyways
|
||||
else => if (!std.ascii.isWhitespace(cur)) {
|
||||
state.* = .key;
|
||||
start = pos.* - 1;
|
||||
end = start;
|
||||
},
|
||||
|
||||
switch (current) {
|
||||
' ', '\t', '\r', '\n' => {},
|
||||
'[' => {
|
||||
var start = pos.*;
|
||||
|
||||
current = data[pos.*];
|
||||
|
||||
while (current != ']') : (pos.* += 1) {
|
||||
current = data[pos.*];
|
||||
}
|
||||
|
||||
return Token{ .section = data[start .. pos.* - 1] };
|
||||
},
|
||||
.section => {
|
||||
end += 1;
|
||||
switch (cur) {
|
||||
']' => {
|
||||
state.* = .normal;
|
||||
pos.* += 1;
|
||||
return Token{ .section = data[start .. end - 1] };
|
||||
},
|
||||
else => {},
|
||||
'=' => {
|
||||
current = data[pos.*];
|
||||
|
||||
while (current == ' ' or current == '\t') {
|
||||
pos.* += 1;
|
||||
current = data[pos.*];
|
||||
}
|
||||
|
||||
var start = pos.*;
|
||||
|
||||
while (current != '\n') : (pos.* += 1) {
|
||||
current = data[pos.*];
|
||||
}
|
||||
|
||||
return Token{ .value = if (start == pos.*) "" else data[start .. pos.* - 1] };
|
||||
},
|
||||
.value => {
|
||||
switch (cur) {
|
||||
';', '#' => {
|
||||
state.* = .comment;
|
||||
return Token{ .value = data[start .. end - 2] };
|
||||
},
|
||||
else => {
|
||||
end += 1;
|
||||
switch (cur) {
|
||||
'\n' => {
|
||||
state.* = .normal;
|
||||
return Token{ .value = data[start .. end - 2] };
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
';', '#' => {
|
||||
current = data[pos.*];
|
||||
|
||||
while (current != '\n') : (pos.* += 1) {
|
||||
current = data[pos.*];
|
||||
}
|
||||
|
||||
return Token.comment;
|
||||
},
|
||||
.comment => {
|
||||
end += 1;
|
||||
switch (cur) {
|
||||
'\n' => {
|
||||
state.* = .normal;
|
||||
return Token.comment;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
},
|
||||
.key => {
|
||||
end += 1;
|
||||
if (!(std.ascii.isAlphanumeric(cur) or cur == '_')) {
|
||||
state.* = .normal;
|
||||
return Token{ .key = data[start..end] };
|
||||
else => {
|
||||
var start = pos.* - 1;
|
||||
|
||||
current = data[pos.*];
|
||||
|
||||
while (std.ascii.isAlphanumeric(current) or current == '_') : (pos.* += 1) {
|
||||
current = data[pos.*];
|
||||
}
|
||||
|
||||
pos.* -= 1;
|
||||
|
||||
return Token{ .key = data[start..pos.*] };
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
pub fn readToStruct(comptime T: type, data: []const u8) !T {
|
||||
var namespace: []const u8 = "";
|
||||
var pos: usize = 0;
|
||||
var state: State = .normal;
|
||||
var ret = std.mem.zeroes(T);
|
||||
while (getTok(data, &pos, &state)) |tok| {
|
||||
while (getTok(data, &pos)) |tok| {
|
||||
switch (tok) {
|
||||
.comment => {},
|
||||
.section => |ns| {
|
||||
namespace = ns;
|
||||
},
|
||||
.key => |key| {
|
||||
var next_tok = getTok(data, &pos, &state);
|
||||
var next_tok = getTok(data, &pos);
|
||||
// if there's nothing just give a comment which is also a syntax error
|
||||
switch (next_tok orelse .comment) {
|
||||
.value => |value| {
|
||||
// now we have the namespace, key, and value
|
||||
// namespace and key are runtime values, so we need to loop the struct instead of using @field
|
||||
inline for (std.meta.fields(T)) |ns_info| {
|
||||
if (std.mem.eql(u8, ns_info.name, namespace)) {
|
||||
if (eql(ns_info.name, namespace)) {
|
||||
// @field(ret, ns_info.name) contains the inner struct now
|
||||
// loop over the fields of the inner struct, and check for key matches
|
||||
inline for (std.meta.fields(@TypeOf(@field(ret, ns_info.name)))) |key_info| {
|
||||
|
@ -124,11 +100,11 @@ pub fn readToStruct(comptime T: type, data: []const u8) !T {
|
|||
}
|
||||
},
|
||||
// after a key, a value must follow
|
||||
else => return error.SyntaxError,
|
||||
else => return error.NoValueAfterKey,
|
||||
}
|
||||
},
|
||||
// if we get a value with no key, that's a bit nonsense
|
||||
.value => return error.SyntaxError,
|
||||
.value => return error.ValueWithNoKey,
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -171,6 +147,7 @@ pub fn writeStruct(struct_value: anytype, writer: anytype) !void {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Checks if the string is actually a single ASCII character, else, parse as an integer
|
||||
fn parseInt(comptime T: type, buf: []const u8, base: u8) std.fmt.ParseIntError!T {
|
||||
if (buf.len == 1) {
|
||||
var first_char = buf[0];
|
||||
|
@ -182,3 +159,21 @@ fn parseInt(comptime T: type, buf: []const u8, base: u8) std.fmt.ParseIntError!T
|
|||
|
||||
return std.fmt.parseInt(T, buf, base);
|
||||
}
|
||||
// Checks if 2 strings are equal, but comparing " " with "_"
|
||||
fn eql(a: []const u8, b: []const u8) bool {
|
||||
if (a.len != b.len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.ptr == b.ptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (a, b) |a_elem, b_elem| {
|
||||
if (a_elem != if (b_elem == ' ') '_' else b_elem) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
const main = @import("main.zig");
|
||||
const std = @import("std");
|
||||
|
||||
pub const allocator = std.heap.raw_c_allocator;
|
||||
|
||||
pub fn c_str(str: []const u8) ![:0]u8 {
|
||||
const new_str = try main.allocator.allocSentinel(u8, str.len, 0);
|
||||
const new_str = try allocator.allocSentinel(u8, str.len, 0);
|
||||
|
||||
for (str, 0..) |c, i| {
|
||||
new_str[i] = c;
|
||||
|
|
103
src/main.zig
103
src/main.zig
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const configuration = @import("config.zig");
|
||||
const config = @import("config.zig");
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
pub const c = @cImport({
|
||||
@cInclude("dragonfail.h");
|
||||
|
@ -22,12 +23,12 @@ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|||
pub const allocator = gpa.allocator();
|
||||
|
||||
// Ly general and language configuration
|
||||
pub var config: c.struct_config = undefined;
|
||||
pub var lang: c.struct_lang = undefined;
|
||||
pub var c_config: c.struct_config = undefined;
|
||||
pub var c_lang: c.struct_lang = undefined;
|
||||
|
||||
comptime {
|
||||
@export(config, .{ .name = "config" });
|
||||
@export(lang, .{ .name = "lang" });
|
||||
@export(c_config, .{ .name = "config" });
|
||||
@export(c_lang, .{ .name = "lang" });
|
||||
}
|
||||
|
||||
// Main function
|
||||
|
@ -39,8 +40,8 @@ pub fn main() !void {
|
|||
var lang_ptr = try allocator.create(c.struct_lang);
|
||||
defer allocator.destroy(lang_ptr);
|
||||
|
||||
config = config_ptr.*;
|
||||
lang = lang_ptr.*;
|
||||
c_config = config_ptr.*;
|
||||
c_lang = lang_ptr.*;
|
||||
|
||||
// Initialize error library
|
||||
log_init(c.dgn_init());
|
||||
|
@ -78,12 +79,12 @@ pub fn main() !void {
|
|||
}
|
||||
|
||||
// Load configuration and language
|
||||
try configuration.config_load(config_path);
|
||||
try configuration.lang_load();
|
||||
try config.config_load(config_path);
|
||||
try config.lang_load();
|
||||
|
||||
if (c.dgn_catch() != 0) {
|
||||
configuration.config_free();
|
||||
configuration.lang_free();
|
||||
config.config_free();
|
||||
config.lang_free();
|
||||
std.os.exit(1);
|
||||
}
|
||||
|
||||
|
@ -98,11 +99,11 @@ pub fn main() !void {
|
|||
defer allocator.destroy(password);
|
||||
|
||||
c.input_desktop(desktop);
|
||||
c.input_text(username, config.max_login_len);
|
||||
c.input_text(password, config.max_password_len);
|
||||
c.input_text(username, config.ly_config.ly.max_login_len);
|
||||
c.input_text(password, config.ly_config.ly.max_password_len);
|
||||
|
||||
c.desktop_load(desktop);
|
||||
c.load(desktop, username);
|
||||
utils.desktop_load(desktop);
|
||||
try utils.load(desktop, username);
|
||||
|
||||
// Start termbox
|
||||
_ = c.tb_init();
|
||||
|
@ -119,10 +120,10 @@ pub fn main() !void {
|
|||
// Place the cursor on the login field if there is no saved username
|
||||
// If there is, place the curser on the password field
|
||||
var active_input: u8 = 0;
|
||||
if (config.default_input == c.LOGIN_INPUT and username.text != username.end) {
|
||||
if (config.ly_config.ly.default_input == c.LOGIN_INPUT and username.text != username.end) {
|
||||
active_input = c.PASSWORD_INPUT;
|
||||
} else {
|
||||
active_input = config.default_input;
|
||||
active_input = config.ly_config.ly.default_input;
|
||||
}
|
||||
|
||||
// Initialize drawing code
|
||||
|
@ -146,11 +147,11 @@ pub fn main() !void {
|
|||
else => unreachable,
|
||||
}
|
||||
|
||||
if (config.animate) {
|
||||
if (config.ly_config.ly.animate) {
|
||||
c.animate_init(buffer);
|
||||
|
||||
if (c.dgn_catch() != 0) {
|
||||
config.animate = false;
|
||||
config.ly_config.ly.animate = false;
|
||||
c.dgn_reset();
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +189,7 @@ pub fn main() !void {
|
|||
c.draw_box(buffer);
|
||||
c.draw_clock(buffer);
|
||||
c.draw_labels(buffer);
|
||||
if (!config.hide_f1_commands) {
|
||||
if (!config.ly_config.ly.hide_f1_commands) {
|
||||
c.draw_f_commands();
|
||||
}
|
||||
c.draw_lock_state(buffer);
|
||||
|
@ -196,7 +197,7 @@ pub fn main() !void {
|
|||
c.draw_desktop(desktop);
|
||||
c.draw_input(username);
|
||||
c.draw_input_mask(password);
|
||||
update = config.animate;
|
||||
update = config.ly_config.ly.animate;
|
||||
} else {
|
||||
std.time.sleep(10000000); // Sleep 0.01 seconds
|
||||
update = c.cascade(buffer, &auth_fails);
|
||||
|
@ -207,8 +208,8 @@ pub fn main() !void {
|
|||
|
||||
var timeout: c_int = -1;
|
||||
|
||||
if (config.animate) {
|
||||
timeout = config.min_refresh_delta;
|
||||
if (config.ly_config.ly.animate) {
|
||||
timeout = config.ly_config.ly.min_refresh_delta;
|
||||
} else {
|
||||
// TODO: Use the Zig standard library directly
|
||||
var time = try allocator.create(std.os.linux.timeval);
|
||||
|
@ -216,9 +217,9 @@ pub fn main() !void {
|
|||
|
||||
_ = std.os.linux.gettimeofday(time, undefined);
|
||||
|
||||
if (config.bigclock) {
|
||||
if (config.ly_config.ly.bigclock) {
|
||||
timeout = @intCast(c_int, (60 - @mod(time.tv_sec, 60)) * 1000 - @divTrunc(time.tv_usec, 1000) + 1);
|
||||
} else if (config.clock != undefined) {
|
||||
} else if (config.ly_config.ly.clock.len > 0) {
|
||||
timeout = @intCast(c_int, 1000 - @divTrunc(time.tv_usec, 1000) + 1);
|
||||
}
|
||||
}
|
||||
|
@ -283,7 +284,7 @@ pub fn main() !void {
|
|||
update = true;
|
||||
},
|
||||
c.TB_KEY_ENTER => {
|
||||
c.save(desktop, username);
|
||||
try utils.save(desktop, username);
|
||||
c.auth(desktop, username, password, buffer);
|
||||
|
||||
if (c.dgn_catch() != 0) {
|
||||
|
@ -296,16 +297,16 @@ pub fn main() !void {
|
|||
buffer.info_line = c.dgn_output_log();
|
||||
}
|
||||
|
||||
if (config.blank_password) {
|
||||
if (config.ly_config.ly.blank_password) {
|
||||
c.input_text_clear(password);
|
||||
}
|
||||
|
||||
c.dgn_reset();
|
||||
} else {
|
||||
buffer.info_line = lang.logout;
|
||||
buffer.info_line = c_lang.logout;
|
||||
}
|
||||
|
||||
c.load(desktop, username);
|
||||
try utils.load(desktop, username);
|
||||
|
||||
// Reset cursor to its normal state
|
||||
_ = std.ChildProcess.exec(.{ .argv = &[_][]const u8{ "/usr/bin/tput", "cnorm" }, .allocator = allocator }) catch return;
|
||||
|
@ -330,45 +331,45 @@ pub fn main() !void {
|
|||
|
||||
// Unload configuration
|
||||
c.draw_free(buffer);
|
||||
configuration.lang_free();
|
||||
config.lang_free();
|
||||
|
||||
if (shutdown) {
|
||||
var shutdown_cmd = try std.fmt.allocPrint(allocator, "{s}", .{config.shutdown_cmd});
|
||||
var shutdown_cmd = try std.fmt.allocPrint(allocator, "{s}", .{config.ly_config.ly.shutdown_cmd});
|
||||
// This will never be freed! But it's fine, we're shutting down the system anyway
|
||||
defer allocator.free(shutdown_cmd);
|
||||
|
||||
configuration.config_free();
|
||||
config.config_free();
|
||||
|
||||
std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", shutdown_cmd }) catch return;
|
||||
} else if (reboot) {
|
||||
var restart_cmd = try std.fmt.allocPrint(allocator, "{s}", .{config.restart_cmd});
|
||||
var restart_cmd = try std.fmt.allocPrint(allocator, "{s}", .{config.ly_config.ly.restart_cmd});
|
||||
// This will never be freed! But it's fine, we're rebooting the system anyway
|
||||
defer allocator.free(restart_cmd);
|
||||
|
||||
configuration.config_free();
|
||||
config.config_free();
|
||||
|
||||
std.process.execv(allocator, &[_][]const u8{ "/bin/sh", "-c", restart_cmd }) catch return;
|
||||
} else {
|
||||
configuration.config_free();
|
||||
config.config_free();
|
||||
}
|
||||
}
|
||||
|
||||
// Low-level error messages
|
||||
fn log_init(log: [*c][*c]u8) void {
|
||||
log[c.DGN_OK] = lang.err_dgn_oob;
|
||||
log[c.DGN_NULL] = lang.err_null;
|
||||
log[c.DGN_ALLOC] = lang.err_alloc;
|
||||
log[c.DGN_BOUNDS] = lang.err_bounds;
|
||||
log[c.DGN_DOMAIN] = lang.err_domain;
|
||||
log[c.DGN_MLOCK] = lang.err_mlock;
|
||||
log[c.DGN_XSESSIONS_DIR] = lang.err_xsessions_dir;
|
||||
log[c.DGN_XSESSIONS_OPEN] = lang.err_xsessions_open;
|
||||
log[c.DGN_PATH] = lang.err_path;
|
||||
log[c.DGN_CHDIR] = lang.err_chdir;
|
||||
log[c.DGN_PWNAM] = lang.err_pwnam;
|
||||
log[c.DGN_USER_INIT] = lang.err_user_init;
|
||||
log[c.DGN_USER_GID] = lang.err_user_gid;
|
||||
log[c.DGN_USER_UID] = lang.err_user_uid;
|
||||
log[c.DGN_PAM] = lang.err_pam;
|
||||
log[c.DGN_HOSTNAME] = lang.err_hostname;
|
||||
log[c.DGN_OK] = c_lang.err_dgn_oob;
|
||||
log[c.DGN_NULL] = c_lang.err_null;
|
||||
log[c.DGN_ALLOC] = c_lang.err_alloc;
|
||||
log[c.DGN_BOUNDS] = c_lang.err_bounds;
|
||||
log[c.DGN_DOMAIN] = c_lang.err_domain;
|
||||
log[c.DGN_MLOCK] = c_lang.err_mlock;
|
||||
log[c.DGN_XSESSIONS_DIR] = c_lang.err_xsessions_dir;
|
||||
log[c.DGN_XSESSIONS_OPEN] = c_lang.err_xsessions_open;
|
||||
log[c.DGN_PATH] = c_lang.err_path;
|
||||
log[c.DGN_CHDIR] = c_lang.err_chdir;
|
||||
log[c.DGN_PWNAM] = c_lang.err_pwnam;
|
||||
log[c.DGN_USER_INIT] = c_lang.err_user_init;
|
||||
log[c.DGN_USER_GID] = c_lang.err_user_gid;
|
||||
log[c.DGN_USER_UID] = c_lang.err_user_uid;
|
||||
log[c.DGN_PAM] = c_lang.err_pam;
|
||||
log[c.DGN_HOSTNAME] = c_lang.err_hostname;
|
||||
}
|
||||
|
|
208
src/utils.c
208
src/utils.c
|
@ -19,142 +19,6 @@
|
|||
#include <linux/vt.h>
|
||||
#endif
|
||||
|
||||
static void config_handle_str(void* data, char** pars, const int pars_count)
|
||||
{
|
||||
if (*((char**)data) != NULL)
|
||||
{
|
||||
free(*((char**)data));
|
||||
}
|
||||
|
||||
*((char**)data) = strdup(*pars);
|
||||
}
|
||||
|
||||
void desktop_crawl(
|
||||
struct desktop* target,
|
||||
char* sessions,
|
||||
enum display_server server)
|
||||
{
|
||||
DIR* dir;
|
||||
struct dirent* dir_info;
|
||||
int ok;
|
||||
|
||||
ok = access(sessions, F_OK);
|
||||
|
||||
if (ok == -1)
|
||||
{
|
||||
dgn_throw(DGN_XSESSIONS_DIR);
|
||||
return;
|
||||
}
|
||||
|
||||
dir = opendir(sessions);
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
dgn_throw(DGN_XSESSIONS_OPEN);
|
||||
return;
|
||||
}
|
||||
|
||||
char* name = NULL;
|
||||
char* exec = NULL;
|
||||
|
||||
struct configator_param map_desktop[] =
|
||||
{
|
||||
{"Exec", &exec, config_handle_str},
|
||||
{"Name", &name, config_handle_str},
|
||||
};
|
||||
|
||||
struct configator_param* map[] =
|
||||
{
|
||||
NULL,
|
||||
map_desktop,
|
||||
};
|
||||
|
||||
struct configator_param sections[] =
|
||||
{
|
||||
{"Desktop Entry", NULL, NULL},
|
||||
};
|
||||
|
||||
uint16_t map_len[] = {0, 2};
|
||||
uint16_t sections_len = 1;
|
||||
|
||||
struct configator desktop_config;
|
||||
desktop_config.map = map;
|
||||
desktop_config.map_len = map_len;
|
||||
desktop_config.sections = sections;
|
||||
desktop_config.sections_len = sections_len;
|
||||
|
||||
#if defined(NAME_MAX)
|
||||
char path[NAME_MAX];
|
||||
#elif defined(_POSIX_PATH_MAX)
|
||||
char path[_POSIX_PATH_MAX];
|
||||
#else
|
||||
char path[1024];
|
||||
#endif
|
||||
|
||||
dir_info = readdir(dir);
|
||||
|
||||
while (dir_info != NULL)
|
||||
{
|
||||
if ((dir_info->d_name)[0] == '.')
|
||||
{
|
||||
dir_info = readdir(dir);
|
||||
continue;
|
||||
}
|
||||
|
||||
snprintf(path, (sizeof (path)) - 1, "%s/", sessions);
|
||||
strncat(path, dir_info->d_name, (sizeof (path)) - 1);
|
||||
configator(&desktop_config, path);
|
||||
|
||||
// if these are wayland sessions, add " (Wayland)" to their names,
|
||||
// as long as their names don't already contain that string
|
||||
if (server == DS_WAYLAND && config.wayland_specifier)
|
||||
{
|
||||
const char wayland_specifier[] = " (Wayland)";
|
||||
if (strstr(name, wayland_specifier) == NULL)
|
||||
{
|
||||
name = realloc(name, (strlen(name) + sizeof(wayland_specifier) + 1));
|
||||
// using strcat is safe because the string is constant
|
||||
strcat(name, wayland_specifier);
|
||||
}
|
||||
}
|
||||
|
||||
if ((name != NULL) && (exec != NULL))
|
||||
{
|
||||
input_desktop_add(target, name, exec, server);
|
||||
}
|
||||
|
||||
name = NULL;
|
||||
exec = NULL;
|
||||
dir_info = readdir(dir);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void desktop_load(struct desktop* target)
|
||||
{
|
||||
// we don't care about desktop environments presence
|
||||
// because the fallback shell is always available
|
||||
// so we just dismiss any "throw" for now
|
||||
int err = 0;
|
||||
|
||||
desktop_crawl(target, config.waylandsessions, DS_WAYLAND);
|
||||
|
||||
if (dgn_catch())
|
||||
{
|
||||
++err;
|
||||
dgn_reset();
|
||||
}
|
||||
|
||||
desktop_crawl(target, config.xsessions, DS_XORG);
|
||||
|
||||
if (dgn_catch())
|
||||
{
|
||||
++err;
|
||||
dgn_reset();
|
||||
}
|
||||
}
|
||||
|
||||
static char* hostname_backup = NULL;
|
||||
|
||||
void hostname(char** out)
|
||||
|
@ -211,76 +75,4 @@ void switch_tty(struct term_buf* buf)
|
|||
ioctl(fd, VT_WAITACTIVE, config.tty);
|
||||
|
||||
fclose(console);
|
||||
}
|
||||
|
||||
void save(struct desktop* desktop, struct text* login)
|
||||
{
|
||||
if (config.save)
|
||||
{
|
||||
FILE* fp = fopen(config.save_file, "wb+");
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
fprintf(fp, "%s\n%d", login->text, desktop->cur);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load(struct desktop* desktop, struct text* login)
|
||||
{
|
||||
if (!config.load)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE* fp = fopen(config.save_file, "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char* line = malloc(config.max_login_len + 1);
|
||||
|
||||
if (line == NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fgets(line, config.max_login_len + 1, fp))
|
||||
{
|
||||
int len = strlen(line);
|
||||
strncpy(login->text, line, login->len);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
login->end = login->text;
|
||||
}
|
||||
else
|
||||
{
|
||||
login->end = login->text + len - 1;
|
||||
login->text[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(fp);
|
||||
free(line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fgets(line, config.max_login_len + 1, fp))
|
||||
{
|
||||
int saved_cur = abs(atoi(line));
|
||||
|
||||
if (saved_cur < desktop->len)
|
||||
{
|
||||
desktop->cur = saved_cur;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
free(line);
|
||||
}
|
|
@ -9,7 +9,5 @@ void desktop_load(struct desktop* target);
|
|||
void hostname(char** out);
|
||||
void free_hostname();
|
||||
void switch_tty(struct term_buf* buf);
|
||||
void save(struct desktop* desktop, struct text* login);
|
||||
void load(struct desktop* desktop, struct text* login);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
const std = @import("std");
|
||||
const main = @import("main.zig");
|
||||
const ini = @import("ini.zig");
|
||||
const config = @import("config.zig");
|
||||
const interop = @import("interop.zig");
|
||||
|
||||
const DESKTOP_ENTRY_MAX_SIZE: usize = 8 * 1024;
|
||||
|
||||
const Entry = struct {
|
||||
Desktop_Entry: struct {
|
||||
Name: []const u8,
|
||||
Comment: []const u8,
|
||||
Exec: []const u8,
|
||||
Type: []const u8,
|
||||
DesktopNames: []const u8,
|
||||
},
|
||||
};
|
||||
|
||||
pub export fn desktop_load(target: *main.c.struct_desktop) void {
|
||||
// We don't care about desktop environments presence
|
||||
// because the fallback shell is always available
|
||||
// so we just dismiss any "throw" for now
|
||||
var err: c_int = 0;
|
||||
|
||||
desktop_crawl(target, config.ly_config.ly.waylandsessions, main.c.DS_WAYLAND) catch {};
|
||||
|
||||
if (main.c.dgn_catch() != 0) {
|
||||
err += 1;
|
||||
main.c.dgn_reset();
|
||||
}
|
||||
|
||||
desktop_crawl(target, config.ly_config.ly.xsessions, main.c.DS_XORG) catch {};
|
||||
|
||||
if (main.c.dgn_catch() != 0) {
|
||||
err += 1;
|
||||
main.c.dgn_reset();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(desktop: *main.c.struct_desktop, login: *main.c.struct_text) !void {
|
||||
if (!config.ly_config.ly.save) {
|
||||
return;
|
||||
}
|
||||
|
||||
var file = std.fs.openFileAbsolute(config.ly_config.ly.save_file, .{ .mode = .write_only }) catch {
|
||||
return;
|
||||
};
|
||||
defer file.close();
|
||||
|
||||
var buffer = try std.fmt.allocPrint(main.allocator, "{s}\n{d}", .{ login.*.text, desktop.*.cur });
|
||||
defer main.allocator.free(buffer);
|
||||
|
||||
try file.writeAll(buffer);
|
||||
}
|
||||
|
||||
pub fn load(desktop: *main.c.struct_desktop, login: *main.c.struct_text) !void {
|
||||
if (!config.ly_config.ly.load) {
|
||||
return;
|
||||
}
|
||||
|
||||
var file = std.fs.openFileAbsolute(config.ly_config.ly.save_file, .{}) catch {
|
||||
return;
|
||||
};
|
||||
defer file.close();
|
||||
|
||||
var buffer = try main.allocator.alloc(u8, config.ly_config.ly.max_login_len * 2 + 1);
|
||||
defer main.allocator.free(buffer);
|
||||
|
||||
_ = try file.readAll(buffer);
|
||||
|
||||
var array = std.mem.splitSequence(u8, buffer, "\n");
|
||||
|
||||
login.*.text = try interop.c_str(array.first()); // TODO: Free?
|
||||
desktop.*.cur = try std.fmt.parseUnsigned(u16, array.next().?, 0);
|
||||
}
|
||||
|
||||
fn desktop_crawl(target: *main.c.struct_desktop, sessions: []const u8, server: main.c.enum_display_server) !void {
|
||||
var iterable_dir = std.fs.openIterableDirAbsolute(sessions, .{}) catch {
|
||||
main.c.dgn_throw(main.c.DGN_XSESSIONS_OPEN);
|
||||
return;
|
||||
};
|
||||
defer iterable_dir.close();
|
||||
|
||||
var iterator = iterable_dir.iterate();
|
||||
|
||||
var dir = std.fs.openDirAbsolute(sessions, .{}) catch {
|
||||
main.c.dgn_throw(main.c.DGN_XSESSIONS_OPEN);
|
||||
return;
|
||||
};
|
||||
defer dir.close();
|
||||
|
||||
while (try iterator.next()) |item| {
|
||||
if (!std.mem.endsWith(u8, item.name, ".desktop")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var file = try dir.openFile(item.name, .{});
|
||||
defer file.close();
|
||||
|
||||
var buffer = try main.allocator.alloc(u8, DESKTOP_ENTRY_MAX_SIZE); // TODO: Free
|
||||
var length = try file.readAll(buffer);
|
||||
var entry = try ini.readToStruct(Entry, buffer[0..length]);
|
||||
|
||||
// TODO: If it's a wayland session, add " (Wayland)" to its name,
|
||||
// as long as it doesn't already contain that string
|
||||
|
||||
const name = entry.Desktop_Entry.Name;
|
||||
const exec = entry.Desktop_Entry.Exec;
|
||||
|
||||
if (name.len > 0 and exec.len > 0) {
|
||||
main.c.input_desktop_add(target, (try interop.c_str(name)).ptr, (try interop.c_str(exec)).ptr, server);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue