2 Commits

22 changed files with 97 additions and 482 deletions

View File

@@ -132,7 +132,6 @@ jobs:
path: lidm-riscv64 path: lidm-riscv64
retention-days: 1 retention-days: 1
# This build job is only symbolic, the behavior of the packaged Void Linux version may differ.
build-linux-amd64-musl: build-linux-amd64-musl:
name: amd64-musl name: amd64-musl
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@@ -148,7 +147,7 @@ jobs:
run: | run: |
cd /workspace cd /workspace
xbps-install -Syu xbps && xbps-install -yu xbps-install -Sy
xbps-install -y git pam-devel make gcc bash git xbps-install -y git pam-devel make gcc bash git
ARCH=amd64-musl GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh ARCH=amd64-musl GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh

View File

@@ -26,7 +26,7 @@ jobs:
with: with:
packages: "shellcheck" packages: "shellcheck"
version: 1.0 version: 1.0
- run: git ls-files "*.sh" "*/PKGBUILD" | xargs shellcheck --shell=bash - run: find . -type f -name '*.sh' -not -path './assets/pkg/aur/*/src/*' | xargs shellcheck
clangcheck: clangcheck:
name: Clang name: Clang

View File

@@ -16,10 +16,10 @@ ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR)
LIBS=-lpam LIBS=-lpam
_DEPS = version.h log.h util.h ui.h ui_state.h config.h desktop.h desktop_exec.h auth.h ofield.h efield.h keys.h users.h sessions.h chvt.h macros.h launch_state.h _DEPS = version.h log.h util.h ui.h ui_state.h config.h desktop.h auth.h ofield.h efield.h keys.h users.h sessions.h chvt.h macros.h launch_state.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o log.o util.o ui.o ui_state.o config.o desktop.o desktop_exec.o auth.o ofield.o efield.o users.o sessions.o chvt.o launch_state.o _OBJ = main.o log.o util.o ui.o ui_state.o config.o desktop.o auth.o ofield.o efield.o users.o sessions.o chvt.o launch_state.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?') INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?')
@@ -134,12 +134,10 @@ install-service-s6-etc:
pre-commit: pre-commit:
codespell codespell
prettier -c "**/*.md" prettier --write "**/*.md"
git ls-files "*.sh" "*/PKGBUILD" | xargs shellcheck --shell=bash find . -type f -name '*.sh' -not -path './assets/pkg/aur/*/src/*' | xargs shellcheck
clang-format -i $$(git ls-files "*.c" "*.h") clang-format -i $$(git ls-files "*.c" "*.h")
git ls-files -z "*.h" | \ clang-tidy -p . $$(git ls-files "*.c" "*.h")
parallel -j$$(nproc) -q0 --no-notice --will-cite --tty clang-tidy --quiet |& \
grep -v "warnings generated." || true
print-version: print-version:
@echo $(VERSION) @echo $(VERSION)

View File

@@ -27,11 +27,10 @@ kmscon -l --vt /dev/tty7 --font-name "Cascadia Code" -- /usr/bin/lidm
## Features ## Features
- Simple as C, meant to depend only on standard libc and basic unix system headers. - Simple as C, you only need a C compiler and standard unix libraries to build this.
- Fully customizable: ALL strings, colors (with its ANSI keys) and most behavior. - Fully customizable, from strings, including action keys, to colors (I hope you know ansi escape codes)
- Xorg[\*](https://github.com/javalsai/lidm/issues/79) and wayland sessions, while supporting the default user shell (if enabled in config) - Automatically detects xorg and wayland sessions, plus allowing to launch the default user shell (if enabled in config)
- Init agnostinc (systemd, dinit, runit, openrc and s6). - Starts with many init systems (systemd, dinit, runit, openrc and s6).
- Supports [fido yubikeys](./docs/yubikey.md) (via pam_u2f).
# Table of Contents # Table of Contents

View File

@@ -69,13 +69,13 @@ Characters for the corners of the box (ctl = corner top left, cbr = corner botto
.SS functions .SS functions
All these are of type \fBKEY\fP. All these are of type \fBKEY\fP.
.TP .TP
\fBpoweroff, reboot, fido, refresh\fP \fBpoweroff, reboot, refresh\fP
Function key to use for such action. Function key to use for such action.
.SS strings .SS strings
Display strings to use for some elements. Display strings to use for some elements.
.TP .TP
\fBf_poweroff, f_reboot, f_fido, f_refresh\fP \fBf_poweroff, f_reboot, f_refresh\fP
Text displayed to name such functions at the bottom of the screen. Text displayed to name such functions at the bottom of the screen.
.TP .TP
\fBe_user, e_passwd\fP \fBe_user, e_passwd\fP

View File

@@ -1,32 +1,20 @@
pkgbase = lidm-bin pkgbase = lidm-bin
pkgdesc = A fully colorful customizable TUI display manager made in C. (release binary) pkgdesc = A fully colorful customizable TUI display manager made in C. (release binary)
pkgver = 1.2.3 pkgver = 1.2.3
pkgrel = 3 pkgrel = 1
url = https://github.com/javalsai/lidm url = https://github.com/javalsai/lidm
arch = x86_64 arch = x86_64
arch = i686
arch = aarch64
arch = armv7h
arch = riscv64
license = GPL license = GPL
depends = libpam.so depends = pam
provides = lidm provides = lidm
conflicts = lidm conflicts = lidm
source = lidm-default-theme-1.2.3.ini::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/themes/default.ini source = lidm-1.2.3-1::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-amd64
source = lidm-1.2.3.1::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm.1 source = lidm-default-theme-1.2.3-1.ini::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/themes/default.ini
source = lidm-config-1.2.3.5::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm-config.5 source = lidm-1.2.3-1.1::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm.1
source = lidm-config-1.2.3-1.5::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm-config.5
sha256sums = a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b
sha256sums = ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca sha256sums = ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca
sha256sums = 7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8 sha256sums = 7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8
sha256sums = 0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9 sha256sums = 0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9
source_x86_64 = lidm-1.2.3-x86_64::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-amd64
sha256sums_x86_64 = a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b
source_i686 = lidm-1.2.3-i686::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-i386
sha256sums_i686 = 75018578e68bffda9807de8a65e16eaed8a16c6cf2417a0b58c5d5bcfa603e45
source_aarch64 = lidm-1.2.3-aarch64::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-aarch64
sha256sums_aarch64 = 1b81a1537a1e31ca1902cbc3b60add4ac712aa64fd4d266685f53372cc365882
source_armv7h = lidm-1.2.3-armv7h::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-armv7
sha256sums_armv7h = e86f59509fe2366d6312b9bc9e8d89c14e9c049fd713a04c41dab49a848b1ada
source_riscv64 = lidm-1.2.3-riscv64::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-riscv64
sha256sums_riscv64 = 3f0eb0315c523d367bac332641e5cd3c86cfd9aa4e7c14b2efc036937b97a598
pkgname = lidm-bin pkgname = lidm-bin

View File

@@ -1,39 +1,30 @@
# shellcheck disable=SC2034,SC2154,SC2164 # shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
# Maintainer: javalsai <javalsai@proton.me> # Maintainer: javalsai <javalsai@proton.me>
pkgname=lidm-bin pkgname=lidm-bin
pkgver=1.2.3 pkgver=1.2.3
pkgrel=3 pkgrel=1
depends=('libpam.so') depends=('pam')
pkgdesc="A fully colorful customizable TUI display manager made in C. (release binary)" pkgdesc="A fully colorful customizable TUI display manager made in C. (release binary)"
arch=('x86_64' 'i686' 'aarch64' 'armv7h' 'riscv64') arch=('x86_64')
url="https://github.com/javalsai/lidm" url="https://github.com/javalsai/lidm"
license=('GPL') license=('GPL')
provides=('lidm') provides=('lidm')
conflicts=('lidm') conflicts=('lidm')
_ver="${pkgver}-${pkgrel}"
source=( source=(
"lidm-default-theme-${pkgver}.ini::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/themes/default.ini" "lidm-${_ver}::$url/releases/download/v$pkgver/lidm-amd64"
"lidm-${pkgver}.1::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm.1" "lidm-default-theme-${_ver}.ini::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/themes/default.ini"
"lidm-config-${pkgver}.5::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm-config.5" "lidm-${_ver}.1::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm.1"
"lidm-config-${_ver}.5::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm-config.5"
) )
source_x86_64=("lidm-${pkgver}-x86_64::$url/releases/download/v$pkgver/lidm-amd64") sha256sums=('a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b'
source_i686=("lidm-${pkgver}-i686::$url/releases/download/v$pkgver/lidm-i386") 'ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca'
source_aarch64=("lidm-${pkgver}-aarch64::$url/releases/download/v$pkgver/lidm-aarch64")
source_armv7h=("lidm-${pkgver}-armv7h::$url/releases/download/v$pkgver/lidm-armv7")
source_riscv64=("lidm-${pkgver}-riscv64::$url/releases/download/v$pkgver/lidm-riscv64")
sha256sums=('ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca'
'7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8' '7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8'
'0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9') '0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9')
sha256sums_x86_64=('a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b')
sha256sums_i686=('75018578e68bffda9807de8a65e16eaed8a16c6cf2417a0b58c5d5bcfa603e45')
sha256sums_aarch64=('1b81a1537a1e31ca1902cbc3b60add4ac712aa64fd4d266685f53372cc365882')
sha256sums_armv7h=('e86f59509fe2366d6312b9bc9e8d89c14e9c049fd713a04c41dab49a848b1ada')
sha256sums_riscv64=('3f0eb0315c523d367bac332641e5cd3c86cfd9aa4e7c14b2efc036937b97a598')
package() { package() {
cd "$srcdir" install -Dm755 "lidm-${_ver}" "${pkgdir}/usr/bin/lidm"
install -Dm644 "lidm-default-theme-${_ver}.ini" "${pkgdir}/etc/lidm.ini"
install -Dm755 "lidm-${pkgver}-$CARCH" "${pkgdir}/usr/bin/lidm" install -Dm644 "lidm-${_ver}.1" "${pkgdir}/usr/share/man/man1/lidm.1"
install -Dm644 "lidm-default-theme-${pkgver}.ini" "${pkgdir}/etc/lidm.ini" install -Dm644 "lidm-config-${_ver}.5" "${pkgdir}/usr/share/man/man5/lidm-config.5"
install -Dm644 "lidm-${pkgver}.1" "${pkgdir}/usr/share/man/man1/lidm.1"
install -Dm644 "lidm-config-${pkgver}.5" "${pkgdir}/usr/share/man/man5/lidm-config.5"
} }

View File

@@ -1,11 +1,13 @@
pkgbase = lidm-git pkgbase = lidm-git
pkgdesc = A fully colorful customizable TUI display manager made in C. (last git commit) pkgdesc = A fully colorful customizable TUI display manager made in C. (last git commit)
pkgver = 1.2.3.r3.g363deea pkgver = 1.2.3.r3.g363deea
pkgrel = 3 pkgrel = 1
url = https://github.com/javalsai/lidm url = https://github.com/javalsai/lidm
arch = any arch = any
license = GPL license = GPL
makedepends = git makedepends = git
makedepends = make
makedepends = gcc
depends = pam depends = pam
provides = lidm provides = lidm
conflicts = lidm conflicts = lidm

View File

@@ -1,8 +1,8 @@
# shellcheck disable=SC2034,SC2154,SC2164 # shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
# Maintainer: javalsai <javalsai@proton.me> # Maintainer: javalsai <javalsai@proton.me>
pkgname=lidm-git pkgname=lidm-git
pkgver=1.2.3.r3.g363deea pkgver=1.2.3.r3.g363deea
pkgrel=3 pkgrel=1
depends=('pam') depends=('pam')
makedepends=('git') makedepends=('git')
pkgdesc="A fully colorful customizable TUI display manager made in C. (last git commit)" pkgdesc="A fully colorful customizable TUI display manager made in C. (last git commit)"
@@ -15,17 +15,17 @@ source=("lidm::git+https://github.com/javalsai/lidm")
sha256sums=('SKIP') sha256sums=('SKIP')
pkgver() { pkgver() {
cd "$srcdir/lidm" cd "lidm"
git describe --long --abbrev=7 --tags | \ git describe --long --abbrev=7 --tags | \
sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
} }
build() { build() {
cd "$srcdir/lidm" cd "lidm"
make make
} }
package() { package() {
cd "$srcdir/lidm" cd "lidm"
make DESTDIR="${pkgdir}" install make install DESTDIR="${pkgdir}"
} }

View File

@@ -1,12 +1,14 @@
pkgbase = lidm pkgbase = lidm
pkgdesc = A fully colorful customizable TUI display manager made in C. (build latest tag) pkgdesc = A fully colorful customizable TUI display manager made in C. (build latest tag)
pkgver = 1.2.3 pkgver = 1.2.3
pkgrel = 3 pkgrel = 1
url = https://github.com/javalsai/lidm url = https://github.com/javalsai/lidm
arch = any arch = any
license = GPL license = GPL
makedepends = git
makedepends = gcc
depends = pam depends = pam
source = lidm-1.2.3.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.3.tar.gz source = lidm-1.2.3-1.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.3.tar.gz
sha256sums = 1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93 sha256sums = 1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93
pkgname = lidm pkgname = lidm

View File

@@ -1,21 +1,26 @@
# shellcheck disable=SC2034,SC2154,SC2164 # shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
# Maintainer: javalsai <javalsai@proton.me> # Maintainer: javalsai <javalsai@proton.me>
pkgname=lidm pkgname=lidm
pkgver=1.2.3 pkgver=1.2.3
pkgrel=3 pkgrel=2
depends=('pam') depends=('pam')
makedepends=() makedepends=('git')
pkgdesc="A fully colorful customizable TUI display manager made in C. (build latest tag)" pkgdesc="A fully colorful customizable TUI display manager made in C. (build latest tag)"
arch=('any') arch=('any')
url="https://github.com/javalsai/lidm" url="https://github.com/javalsai/lidm"
license=('GPL') license=('GPL')
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v$pkgver.tar.gz") _ver="${pkgver}-${pkgrel}"
source=("${pkgname}-${_ver}.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v$pkgver.tar.gz")
sha256sums=('1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93') sha256sums=('1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93')
build() { build() {
make -C "$srcdir/lidm-$pkgver" tar -xzf "${pkgname}-${_ver}.tar.gz"
cd "lidm-$pkgver"
make
} }
package() { package() {
make -C "$srcdir/lidm-$pkgver" DESTDIR="$pkgdir" install cd "lidm-$pkgver"
make install DESTDIR="${pkgdir}"
} }

View File

@@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -e
MYSELF=$(realpath "$0")
MYDIR=$(dirname "$MYSELF")
cd "$MYDIR"
typeset -a pkgs=(lidm{,-git,-bin})
for pkg in "${pkgs[@]}"; do
printf "\x1b[mEntering '%s'\x1b[0m\n" "$pkg"
cd "$pkg"
# shellcheck disable=SC1091
source PKGBUILD
# shellcheck disable=SC2154
for f in "${source[@]}"; do
echo "$f"
awk -F:: '{print $1}' <<<"$f" | xargs rm -rf
done
cd ..
echo
done

View File

@@ -4,19 +4,9 @@ set -e
MYSELF=$(realpath "$0") MYSELF=$(realpath "$0")
MYDIR=$(dirname "$MYSELF") MYDIR=$(dirname "$MYSELF")
cd "$MYDIR" for pkg in "$MYDIR"/*/; do
typeset -a pkgs=(lidm{,-git,-bin}) printf "\x1b[1mEntering '%s'\x1b[0m\n" "$pkg"
for pkg in "${pkgs[@]}"; do
printf "\x1b[mEntering '%s'\x1b[0m\n" "$pkg"
cd "$pkg" cd "$pkg"
makepkg -Cf makepkg -f .
cd ..
echo echo
done done
if [[ -n "${PRINT_TREE:-}" ]]; then
for pkg in "${pkgs[@]}"; do
eza --tree "$pkg/pkg/"*
done
fi

View File

@@ -1,30 +0,0 @@
# Yubikeys
Quick reference explaining how yubikeys work for now.
# Enable
Yubikeys are disabled by default, to enable them activate a keybinding for it (`[functions] fido`) in the config file.
Note that pressing this configured keybinding has no difference from trying to log in with an empty password, there's virtually no difference.
`pam_u2f` must be configured with a registered key (`pamu2fcfg`).
# Extra
All my yubikey knowledge comes from the [pr that implemented this](https://github.com/javalsai/lidm/pull/89), please refer to it for extra details. Contributions to this documentation are welcome (explaining more in detail, potential issues... really anything that improves this).
Allegedly this pam module configuration should work:
```pam
#%PAM-1.0
auth sufficient pam_u2f.so cue
auth requisite pam_nologin.so
auth include system-local-login
account include system-local-login
session include system-local-login
password include system-local-login
```
Also, I recommend giving the [arch wiki](https://wiki.archlinux.org/title/YubiKey) a read anyways.

View File

@@ -92,7 +92,6 @@ BUILD(chars, CHARS, TABLE_CHARS);
#define TABLE_FUNCTIONS(F, name) \ #define TABLE_FUNCTIONS(F, name) \
F(enum keys, poweroff, KEY, F1, name) \ F(enum keys, poweroff, KEY, F1, name) \
F(enum keys, reboot, KEY, F2, name) \ F(enum keys, reboot, KEY, F2, name) \
F(enum keys, fido, KEY, NONE, name) \
F(enum keys, refresh, KEY, F5, name) F(enum keys, refresh, KEY, F5, name)
BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS); BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
@@ -100,7 +99,6 @@ BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
#define TABLE_STRINGS(F, name) \ #define TABLE_STRINGS(F, name) \
F(char* NNULLABLE, f_poweroff, STRING, "poweroff", name) \ F(char* NNULLABLE, f_poweroff, STRING, "poweroff", name) \
F(char* NNULLABLE, f_reboot, STRING, "reboot", name) \ F(char* NNULLABLE, f_reboot, STRING, "reboot", name) \
F(char* NNULLABLE, f_fido, STRING, "fido", name) \
F(char* NNULLABLE, f_refresh, STRING, "refresh", name) \ F(char* NNULLABLE, f_refresh, STRING, "refresh", name) \
F(char* NNULLABLE, e_user, STRING, "user", name) \ F(char* NNULLABLE, e_user, STRING, "user", name) \
F(char* NNULLABLE, e_passwd, STRING, "password", name) \ F(char* NNULLABLE, e_passwd, STRING, "password", name) \

View File

@@ -1,7 +0,0 @@
#ifndef DESKTOP_EXEC_H_
#define DESKTOP_EXEC_H_
int parse_exec_string(const char* exec_s, int* arg_count, char*** args);
void free_parsed_args(int arg_count, char** args);
#endif

View File

@@ -32,11 +32,9 @@ enum keys {
END, END,
PAGE_UP, PAGE_UP,
PAGE_DOWN, PAGE_DOWN,
NONE,
}; };
static const char* const KEY_NAMES[] = { static const char* const KEY_NAMES[] = {
[NONE] = "NONE",
[ESC] = "ESC", [ESC] = "ESC",
[F1] = "F1", [F1] = "F1",
[F2] = "F2", [F2] = "F2",

View File

@@ -46,8 +46,6 @@ void setup(struct config* config);
int load(struct Vector* users, struct Vector* sessions); int load(struct Vector* users, struct Vector* sessions);
void print_err(const char* /*msg*/); void print_err(const char* /*msg*/);
void print_errno(const char* /*descr*/); void print_errno(const char* /*descr*/);
void print_pam_msg(const char* msg, int msg_style);
void clear_pam_msg(void);
void ui_update_field(enum input focused_input); void ui_update_field(enum input focused_input);
void ui_update_ffield(); void ui_update_ffield();

View File

@@ -10,18 +10,11 @@
#include "auth.h" #include "auth.h"
#include "config.h" #include "config.h"
#include "desktop_exec.h"
#include "log.h"
#include "sessions.h" #include "sessions.h"
#include "ui.h" #include "ui.h"
#include "unistd.h" #include "unistd.h"
#include "util.h" #include "util.h"
struct pam_conv_data {
char* password;
void (*display_pam_msg)(const char* msg, int msg_style);
};
int pam_conversation(int num_msg, const struct pam_message** msg, int pam_conversation(int num_msg, const struct pam_message** msg,
struct pam_response** resp, void* appdata_ptr) { struct pam_response** resp, void* appdata_ptr) {
struct pam_response* reply = struct pam_response* reply =
@@ -29,34 +22,13 @@ int pam_conversation(int num_msg, const struct pam_message** msg,
if (!reply) { if (!reply) {
return PAM_BUF_ERR; return PAM_BUF_ERR;
} }
struct pam_conv_data* conv_data = (struct pam_conv_data*)appdata_ptr;
for (size_t i = 0; i < num_msg; i++) { for (size_t i = 0; i < num_msg; i++) {
reply[i].resp = NULL; reply[i].resp = NULL;
reply[i].resp_retcode = 0; reply[i].resp_retcode = 0;
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
switch (msg[i]->msg_style) { msg[i]->msg_style == PAM_PROMPT_ECHO_ON) {
case PAM_PROMPT_ECHO_OFF: char* input = (char*)appdata_ptr;
case PAM_PROMPT_ECHO_ON: reply[i].resp = strdup(input);
reply[i].resp = strdup(conv_data->password);
if (!reply[i].resp) {
for (size_t j = 0; j < i; j++)
free(reply[j].resp);
free(reply);
return PAM_BUF_ERR;
}
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
if (conv_data->display_pam_msg && msg[i]->msg) {
conv_data->display_pam_msg(msg[i]->msg, msg[i]->msg_style);
}
break;
default:
break;
} }
} }
*resp = reply; *resp = reply;
@@ -80,9 +52,7 @@ void clear_screen() {
pam_handle_t* get_pamh(char* user, char* passwd) { pam_handle_t* get_pamh(char* user, char* passwd) {
pam_handle_t* pamh = NULL; pam_handle_t* pamh = NULL;
struct pam_conv_data conv_data = {.password = passwd, struct pam_conv pamc = {pam_conversation, (void*)passwd};
.display_pam_msg = print_pam_msg};
struct pam_conv pamc = {pam_conversation, (void*)&conv_data};
int ret; int ret;
char* pam_service_override = getenv("LIDM_PAM_SERVICE"); char* pam_service_override = getenv("LIDM_PAM_SERVICE");
@@ -196,22 +166,6 @@ void moarEnv(char* user, struct session session, struct passwd* pw,
// NOLINTBEGIN(readability-function-cognitive-complexity) // NOLINTBEGIN(readability-function-cognitive-complexity)
bool launch(char* user, char* passwd, struct session session, void (*cb)(void), bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
struct config* config) { struct config* config) {
char** desktop_exec;
int desktop_count;
if (session.type != SHELL) {
desktop_exec = NULL;
int parse_status =
parse_exec_string(session.exec, &desktop_count, &desktop_exec);
if (parse_status != 0 || desktop_count == 0 || !desktop_exec[0]) {
print_err("failure parsing exec string");
log_printf("failure parsing exec string '%s': %d\n",
session.exec ? session.exec : "NULL", parse_status);
free_parsed_args(desktop_count, desktop_exec);
return false;
}
}
struct passwd* pw = getpwnam(user); struct passwd* pw = getpwnam(user);
if (pw == NULL) { if (pw == NULL) {
print_err("could not get user info"); print_err("could not get user info");
@@ -220,10 +174,9 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
pam_handle_t* pamh = get_pamh(user, passwd); pam_handle_t* pamh = get_pamh(user, passwd);
if (pamh == NULL) { if (pamh == NULL) {
print_pam_msg("authentication failed", PAM_ERROR_MSG); print_err("error on pam authentication");
return false; return false;
} }
clear_pam_msg();
bool* reach_session = shmalloc(sizeof(bool)); bool* reach_session = shmalloc(sizeof(bool));
if (reach_session == NULL) { if (reach_session == NULL) {
@@ -284,7 +237,8 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
*reach_session = true; *reach_session = true;
// TODO: test existence of executable with TryExec // TODO: these will be different due to TryExec
// and, Exec/TryExec might contain spaces as args
printf("\x1b[0m"); printf("\x1b[0m");
// NOLINTNEXTLINE(bugprone-branch-clone) // NOLINTNEXTLINE(bugprone-branch-clone)
if (session.type == SHELL) { if (session.type == SHELL) {
@@ -294,12 +248,9 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
} else if (session.type == XORG || session.type == WAYLAND) { } else if (session.type == XORG || session.type == WAYLAND) {
clear_screen(); clear_screen();
(void)fflush(stdout); (void)fflush(stdout);
// NOLINTNEXTLINE execlp(session.exec, session.exec, NULL);
execvp(desktop_exec[0], desktop_exec);
// NOLINTNEXTLINE
free_parsed_args(desktop_count, desktop_exec);
} }
perror("exec error"); perror("execl error");
(void)fputs("failure calling session\n", stderr); (void)fputs("failure calling session\n", stderr);
} else { } else {
pid_t child_pid = (pid_t)pid; pid_t child_pid = (pid_t)pid;

View File

@@ -1,183 +0,0 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "desktop_exec.h"
// constants for exec string parsing
#define MAX_ARGS 100
// ARG_LENGTH is the initial length of a parsed argument
#define ARG_LENGTH 64
// parse Exec=/bin/prog arg1 arg2\ with\ spaces
void free_parsed_args(int arg_count, char** args) {
if (!args) return;
for (int i = 0; i < arg_count; i++) {
free(args[i]);
}
free((void*)args);
}
/* small closure-like struct to pass state to helper functions */
struct ctx {
char** pcur;
size_t* pcur_len;
size_t* pcur_cap;
char*** pargv;
int* pargc;
};
/* append_char(state, ch) -> 0 on error, 1 on success */
int append_char(struct ctx* st, char ch) {
char** pcur = st->pcur;
size_t* plen = st->pcur_len;
size_t* pcap = st->pcur_cap;
if (*plen + 1 >= *pcap) {
size_t newcap = *pcap ? (*pcap) * 2 : ARG_LENGTH;
char* cur = (char*)realloc(*pcur, newcap);
if (!cur) return 0;
*pcur = cur;
*pcap = newcap;
}
(*pcur)[(*plen)++] = ch;
return 1;
}
/* push_arg(state) -> 0 on error, 1 on success */
int push_arg(struct ctx* st) {
char** pcur = st->pcur;
size_t* plen = st->pcur_len;
size_t* pcap = st->pcur_cap;
char*** pargv = st->pargv;
int* pargc = st->pargc;
if (*pargc > MAX_ARGS) {
return 1;
}
if (!*pcur) {
char* empty = strdup("");
if (!empty) return 0;
char** na = (char**)realloc((void*)*pargv, sizeof(char*) * ((*pargc) + 1));
if (!na) {
free(empty);
return 0;
}
*pargv = na;
(*pargv)[(*pargc)++] = empty;
return 1;
}
if (!append_char(st, '\0')) return 0;
char* final = (char*)realloc(*pcur, *plen);
if (!final) final = *pcur;
*pcur = NULL;
*plen = 0;
*pcap = 0;
char** na = (char**)realloc((void*)*pargv, sizeof(char*) * ((*pargc) + 1));
if (!na) {
free(final);
return 0;
}
*pargv = na;
(*pargv)[(*pargc)++] = final;
return 1;
}
/* Return codes:
0 = success
1 = bad args
2 = memory
3 = syntax
Important: call free_parsed_args afterwards to free the passed ***args
*/
// NOLINTBEGIN(readability-function-cognitive-complexity)
int parse_exec_string(const char* exec_s, int* arg_count, char*** args) {
if (!exec_s || !args || !arg_count) return 1;
*args = NULL;
*arg_count = 0;
size_t len = strlen(exec_s);
size_t idx = 0;
char* cur = NULL;
size_t cur_len = 0;
size_t cur_cap = 0;
char** argv = NULL;
int argc = 0;
int in_quote = 0;
struct ctx ctx;
ctx.pcur = &cur;
ctx.pcur_len = &cur_len;
ctx.pcur_cap = &cur_cap;
ctx.pargv = &argv;
ctx.pargc = &argc;
while (idx < len) {
char cur_c = exec_s[idx];
if (!in_quote && (cur_c == ' ' || cur_c == '\t' || cur_c == '\n')) {
if (cur_cap) {
if (!push_arg(&ctx)) goto nomem;
}
idx++;
continue;
}
if (!in_quote && cur_c == '"') {
in_quote = 1;
idx++;
continue;
}
if (in_quote && cur_c == '"') {
in_quote = 0;
idx++;
continue;
}
if (cur_c == '\\') {
if (idx + 1 >= len) goto syntax_err;
if (!append_char(&ctx, exec_s[idx + 1])) goto nomem;
idx += 2;
continue;
}
if (cur_c == '%') {
if (idx + 1 >= len) goto syntax_err;
if (exec_s[idx + 1] == '%') {
if (!append_char(&ctx, '%')) goto nomem;
idx += 2;
continue;
}
/* drop any %X */
idx += 2;
continue;
}
if (!append_char(&ctx, cur_c)) goto nomem;
idx++;
}
if (in_quote) goto syntax_err;
if (cur_cap) {
if (!push_arg(&ctx)) goto nomem;
}
char** na = (char**)realloc((void*)argv, sizeof(char*) * (argc + 1));
if (!na) goto nomem;
argv = na;
argv[argc] = NULL;
*args = argv;
*arg_count = argc;
return 0;
nomem:
if (cur) free(cur);
free_parsed_args(argc, argv);
*args = NULL;
*arg_count = 0;
return 2;
syntax_err:
if (cur) free(cur);
free_parsed_args(argc, argv);
*args = NULL;
*arg_count = 0;
return 3;
}
// NOLINTEND(readability-function-cognitive-complexity)

110
src/ui.c
View File

@@ -5,7 +5,6 @@
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <security/pam_appl.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
@@ -110,8 +109,8 @@ static char* fmt_time(const char* fmt) {
} }
} }
char* trunc_gethostname(size_t maxlen, const char* const ELLIPSIS) { char* trunc_gethostname(const size_t MAXLEN, const char* const ELLIPSIS) {
if (utf8len(ELLIPSIS) > maxlen) return NULL; if (utf8len(ELLIPSIS) > MAXLEN) return NULL;
size_t alloc_size = HOST_NAME_MAX + strlen(ELLIPSIS) + 1; size_t alloc_size = HOST_NAME_MAX + strlen(ELLIPSIS) + 1;
char* buf = malloc(alloc_size); char* buf = malloc(alloc_size);
if (!buf) return NULL; if (!buf) return NULL;
@@ -121,8 +120,8 @@ char* trunc_gethostname(size_t maxlen, const char* const ELLIPSIS) {
return NULL; return NULL;
} }
if (utf8len(buf) > maxlen) { if (utf8len(buf) > MAXLEN) {
size_t end = utf8trunc(buf, maxlen - utf8len(ELLIPSIS)); size_t end = utf8trunc(buf, MAXLEN - utf8len(ELLIPSIS));
strcpy(&buf[end], ELLIPSIS); strcpy(&buf[end], ELLIPSIS);
} }
return buf; return buf;
@@ -296,21 +295,6 @@ int load(struct Vector* users, struct Vector* sessions) {
restore_all(); restore_all();
reboot(RB_POWER_OFF); reboot(RB_POWER_OFF);
exit(0); exit(0);
} else if (g_config->functions.fido != NONE &&
ansi_code == g_config->functions.fido) {
bool successful_write = write_launch_state((struct LaunchState){
.username = st_user().username,
.session_opt =
st_session(g_config->behavior.include_defshell).name,
});
if (!successful_write) log_puts("[E] failed to write launch state");
if (!launch(st_user().username, "",
st_session(g_config->behavior.include_defshell),
&restore_all, g_config)) {
print_passwd(utf8len(of_passwd.efield.content), true);
ui_update_cursor_focus();
}
} else if (ansi_code == A_UP || ansi_code == A_DOWN) { } else if (ansi_code == A_UP || ansi_code == A_DOWN) {
st_ch_focus(ansi_code == A_DOWN ? 1 : -1); st_ch_focus(ansi_code == A_DOWN ? 1 : -1);
} else if (ansi_code == A_RIGHT || ansi_code == A_LEFT) { } else if (ansi_code == A_RIGHT || ansi_code == A_LEFT) {
@@ -357,40 +341,25 @@ u_char get_render_pos_offset(struct opts_field* self, u_char maxlen) {
return pos - ofield_display_cursor_col(self, maxlen); return pos - ofield_display_cursor_col(self, maxlen);
} }
#define HOSTNAME_SIZE (VALUES_COL - VALUES_SEPR - BOX_HMARGIN - 1)
void print_head() { void print_head() {
char* fmtd_time = fmt_time(g_config->behavior.timefmt); // hostname doesn't just change on runtime
size_t len_tm = utf8len(fmtd_time); static char* hostname = NULL;
if (!hostname)
// calculate the space available for the host name hostname = trunc_gethostname(HOSTNAME_SIZE, g_config->strings.ellipsis);
ssize_t hostname_size = BOX_WIDTH - (BOX_HMARGIN * 2) - len_tm - VALUES_SEPR; if (!hostname) hostname = "unknown";
if (hostname_size < 0) hostname_size = 0;
// hostname doesn't just change on runtime,
// but the length of the time string might
static char* NULLABLE hostname = NULL;
static size_t hostname_calcd_size;
// save the truncated hostname and the length it truncated to,
// if said length changes recalculate this (and free previous str)
if (!hostname || hostname_calcd_size != hostname_size) {
if (hostname) free(hostname);
hostname = trunc_gethostname(hostname_size, g_config->strings.ellipsis);
hostname_calcd_size = hostname_size;
}
clean_line(box_start, HEAD_ROW); clean_line(box_start, HEAD_ROW);
// put hostname // put hostname
if (hostname_size) printf("\x1b[%dG\x1b[%sm%s\x1b[%sm",
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm", box_start.x + 1 + BOX_HMARGIN, box_start.x + VALUES_COL - VALUES_SEPR - (uint)utf8len(hostname),
g_config->colors.e_hostname, hostname ? hostname : "unknown", g_config->colors.e_hostname, hostname, g_config->colors.fg);
g_config->colors.fg);
// put date // put date
char* fmtd_time = fmt_time(g_config->behavior.timefmt);
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm", printf("\x1b[%dG\x1b[%sm%s\x1b[%sm",
box_start.x + BOX_WIDTH - 1 - BOX_HMARGIN - (uint)len_tm, box_start.x + BOX_WIDTH - 1 - BOX_HMARGIN - (uint)utf8len(fmtd_time),
g_config->colors.e_date, fmtd_time, g_config->colors.fg); g_config->colors.e_date, fmtd_time, g_config->colors.fg);
free(fmtd_time); free(fmtd_time);
} }
@@ -525,8 +494,6 @@ static void print_box() {
} }
static void print_footer() { static void print_footer() {
bool fido_enabled = g_config->functions.fido != NONE;
size_t bsize = utf8len(g_config->strings.f_poweroff) + size_t bsize = utf8len(g_config->strings.f_poweroff) +
utf8len(KEY_NAMES[g_config->functions.poweroff]) + utf8len(KEY_NAMES[g_config->functions.poweroff]) +
utf8len(g_config->strings.f_reboot) + utf8len(g_config->strings.f_reboot) +
@@ -534,31 +501,19 @@ static void print_footer() {
utf8len(g_config->strings.f_refresh) + utf8len(g_config->strings.f_refresh) +
utf8len(KEY_NAMES[g_config->functions.refresh]); utf8len(KEY_NAMES[g_config->functions.refresh]);
bsize += 2 * 2 + 3 * 1; bsize += 2 * 2 + // 2 wide separators between 3 items
3 * 1; // 3 thin separators inside every item
if (fido_enabled) {
bsize += utf8len(g_config->strings.f_fido) +
utf8len(KEY_NAMES[g_config->functions.fido]) + 2 + 1;
}
uint row = window.ws_row - 1; uint row = window.ws_row - 1;
uint col = window.ws_col - 2 - bsize; uint col = window.ws_col - 2 - bsize;
printf(
printf("\x1b[%d;%dH%s \x1b[%sm%s\x1b[%sm %s \x1b[%sm%s\x1b[%sm ", row, col, "\x1b[%3$d;%4$dH%8$s \x1b[%1$sm%5$s\x1b[%2$sm %9$s "
g_config->strings.f_poweroff, g_config->colors.e_key, "\x1b[%1$sm%6$s\x1b[%2$sm %10$s \x1b[%1$sm%7$s\x1b[%2$sm",
KEY_NAMES[g_config->functions.poweroff], g_config->colors.fg, g_config->colors.e_key, g_config->colors.fg, row, col,
g_config->strings.f_reboot, g_config->colors.e_key, KEY_NAMES[g_config->functions.poweroff],
KEY_NAMES[g_config->functions.reboot], g_config->colors.fg); KEY_NAMES[g_config->functions.reboot],
KEY_NAMES[g_config->functions.refresh], g_config->strings.f_poweroff,
if (fido_enabled) { g_config->strings.f_reboot, g_config->strings.f_refresh);
printf("%s \x1b[%sm%s\x1b[%sm ", g_config->strings.f_fido,
g_config->colors.e_key, KEY_NAMES[g_config->functions.fido],
g_config->colors.fg);
}
printf("%s \x1b[%sm%s\x1b[%sm", g_config->strings.f_refresh,
g_config->colors.e_key, KEY_NAMES[g_config->functions.refresh],
g_config->colors.fg);
} }
void print_err(const char* msg) { void print_err(const char* msg) {
@@ -566,21 +521,6 @@ void print_err(const char* msg) {
msg, errno, strerror(errno)); msg, errno, strerror(errno));
} }
void print_pam_msg(const char* msg, int msg_style) {
uint row = box_start.y + BOX_HEIGHT + 1;
const char* color =
(msg_style == PAM_ERROR_MSG) ? g_config->colors.err : g_config->colors.fg;
printf("\x1b[%d;%dH\x1b[K\x1b[%sm%.*s\x1b[%sm", row, box_start.x, color,
BOX_WIDTH, msg, g_config->colors.fg);
(void)fflush(stdout);
}
void clear_pam_msg(void) {
uint row = box_start.y + BOX_HEIGHT + 1;
printf("\x1b[%d;%dH\x1b[K", row, box_start.x);
(void)fflush(stdout);
}
void print_errno(const char* descr) { void print_errno(const char* descr) {
if (descr == NULL) if (descr == NULL)
(void)fprintf(stderr, "\x1b[%d;%dH\x1b[%smunknown error(%d): %s", (void)fprintf(stderr, "\x1b[%d;%dH\x1b[%smunknown error(%d): %s",

View File

@@ -25,13 +25,11 @@
[functions] [functions]
# poweroff = F1 # poweroff = F1
# reboot = F2 # reboot = F2
# fido = NONE
# refresh = F5 # refresh = F5
[strings] [strings]
# f_poweroff = "poweroff" # f_poweroff = "poweroff"
# f_reboot = "reboot" # f_reboot = "reboot"
# f_fido = "fido"
# f_refresh = "refresh" # f_refresh = "refresh"
# e_user = "user" # e_user = "user"
# e_passwd = "password" # e_passwd = "password"