mirror of
https://github.com/javalsai/lidm.git
synced 2026-02-27 12:00:44 +01:00
Compare commits
8 Commits
v2.0.0
...
64a1368717
| Author | SHA1 | Date | |
|---|---|---|---|
|
64a1368717
|
|||
|
570a68c586
|
|||
|
ff3e58ee5b
|
|||
|
109c9bd0be
|
|||
|
056ec64bcb
|
|||
|
b58bd50e64
|
|||
|
6d9107b360
|
|||
|
b56aa19671
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ valgrind-out.txt
|
||||
|
||||
# nix build result
|
||||
result
|
||||
|
||||
include/version.h
|
||||
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,10 +0,0 @@
|
||||
<!-- Unspecified dates shall be in CET/CEST -->
|
||||
|
||||
<!-- Add only very relevant changes, bottom to top -->
|
||||
<!-- By "very relevant" I mean big features or something manual packagers should know, like leftover files -->
|
||||
<!-- Once a release would be opened, group the last bunch of dangling changes, add release version as header and its date -->
|
||||
|
||||
- Most stuff (most of `/etc` being a notable exception) now installs to `/usr/local` by default, check [`docs/PACKAGERS.md`](./docs/PACKAGERS.md).
|
||||
- Added a changelog.
|
||||
- Finally add proper (experimental) xorg support.
|
||||
- Systemd service install path changed to `/usr/local/lib/systemd`, there could be a leftover file at `/etc/systemd/system/lidm.service`.
|
||||
140
Makefile
140
Makefile
@@ -1,32 +1,41 @@
|
||||
VERSION = 2.0.0
|
||||
VERSION = 1.2.3
|
||||
.DEFAULT_GOAL := lidm
|
||||
|
||||
CDIR = src
|
||||
LDIR = lib
|
||||
IDIR = include
|
||||
ODIR = dist
|
||||
CDIR=src
|
||||
LDIR=lib
|
||||
IDIR=include
|
||||
ODIR=dist
|
||||
|
||||
PREFIX = /usr/local
|
||||
PREFIX=/usr
|
||||
|
||||
INFO_GIT_REV ?= $(shell git describe --long --tags --always || echo '?')
|
||||
INFO_BUILD_TS ?= $(shell date +%s)
|
||||
|
||||
CFLAGS ?= -O3 -Wall -Wextra -fdata-sections -ffunction-sections
|
||||
CC?=gcc
|
||||
CFLAGS?=-O3 -Wall -Wextra -fdata-sections -ffunction-sections
|
||||
# C PreProcessor flags, not C Plus Plus
|
||||
CPPFLAGS ?=
|
||||
_DFLAGS?= \
|
||||
-DLIDM_VERSION=\"$(VERSION)\" \
|
||||
-DLIDM_GIT_REV=\"$(INFO_GIT_REV)\" \
|
||||
-DLIDM_BUILD_TS=$(INFO_BUILD_TS)
|
||||
ALLFLAGS = $(_DFLAGS) $(CFLAGS) $(CPPFLAGS) -I$(IDIR)
|
||||
LDFLAGS ?= -Wl,--gc-sections
|
||||
CPPFLAGS?=
|
||||
ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR)
|
||||
LDFLAGS?=-Wl,--gc-sections
|
||||
|
||||
LIBS = -lpam
|
||||
LIBS=-lpam
|
||||
|
||||
# includes all headers in `$(IDIR)` and compiles everything in `$(CDIR)`
|
||||
DEPS = $(wildcard $(IDIR)/*.h)
|
||||
_SOURCES = $(notdir $(wildcard $(CDIR)/*.c))
|
||||
OBJ = $(patsubst %.c,$(ODIR)/%.o,$(_SOURCES))
|
||||
_DEPS = version.h log.h util.h ui.h ui_state.h config.h pam.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 = $(patsubst %,$(IDIR)/%,$(_DEPS))
|
||||
|
||||
_OBJ = main.o log.o util.o ui.o ui_state.o config.o pam.o desktop.o desktop_exec.o auth.o ofield.o efield.o users.o sessions.o chvt.o launch_state.o
|
||||
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
|
||||
|
||||
INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?')
|
||||
INFO_BUILD_TS?=$$(date +%s)
|
||||
|
||||
$(IDIR)/version.h: Makefile
|
||||
@tmp=$$(mktemp); \
|
||||
printf '' > $$tmp; \
|
||||
echo '#define LIDM_VERSION "'$(VERSION)'"' >> $$tmp; \
|
||||
echo '#define LIDM_GIT_REV "'$(INFO_GIT_REV)'"' >> $$tmp; \
|
||||
echo '#define LIDM_BUILD_TS '$(INFO_BUILD_TS) >> $$tmp; \
|
||||
if ! cmp -s $$tmp $@; then \
|
||||
mv $$tmp $@; \
|
||||
fi; \
|
||||
rm -f $$tmp;
|
||||
|
||||
$(ODIR)/%.o: $(CDIR)/%.c $(DEPS)
|
||||
@mkdir -p $(ODIR)
|
||||
@@ -38,6 +47,7 @@ lidm: $(OBJ)
|
||||
clean:
|
||||
rm -f $(ODIR)/*.o lidm
|
||||
|
||||
# Copy lidm to ${DESTDIR}${PREFIX}/bin (/usr/bin)
|
||||
install: lidm
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin ${DESTDIR}${PREFIX}/share/man/man{1,5}
|
||||
install -Dm755 ./lidm ${DESTDIR}${PREFIX}/bin/
|
||||
@@ -45,11 +55,83 @@ install: lidm
|
||||
install -Dm644 ./assets/man/lidm.1 ${DESTDIR}${PREFIX}/share/man/man1/
|
||||
install -Dm644 ./assets/man/lidm-config.5 ${DESTDIR}${PREFIX}/share/man/man5/
|
||||
|
||||
uninstall: uninstall-service
|
||||
uninstall:
|
||||
rm -rf ${DESTDIR}${PREFIX}/bin/lidm ${DESTDIR}/etc/lidm.ini
|
||||
rm -rf ${DESTDIR}${PREFIX}/share/man/man{1/lidm.1,5/lidm-config.5}.gz
|
||||
rm -rf ${DESTDIR}/usr/share/man/man{1/lidm.1,5/lidm-config.5}.gz
|
||||
rm -rf ${DESTDIR}/etc/systemd/system/lidm.service ${DESTDIR}/etc/dinit.d/lidm ${DESTDIR}/etc/runit/sv/lidm
|
||||
|
||||
include services.mk
|
||||
install-service:
|
||||
@if command -v systemctl &> /dev/null; then \
|
||||
make install-service-systemd; \
|
||||
elif command -v dinitctl &> /dev/null; then \
|
||||
make install-service-dinit; \
|
||||
elif command -v sv &> /dev/null; then \
|
||||
if [ -d /etc/sv ]; then \
|
||||
make install-service-runit; \
|
||||
elif [ -d /etc/runit/sv ]; then \
|
||||
make install-service-runit-etc; \
|
||||
else \
|
||||
printf '\033[31m%s\033[0m\n' "Unknown init system structure, skipping service install..." >&2; \
|
||||
fi \
|
||||
elif command -v rc-update &> /dev/null; then \
|
||||
make install-service-openrc; \
|
||||
elif command -v s6-service &> /dev/null; then \
|
||||
if [ -d /etc/sv ]; then \
|
||||
make install-service-s6; \
|
||||
elif [ -d /etc/r6nit/sv ]; then \
|
||||
make install-service-s6-etc; \
|
||||
else \
|
||||
printf '\033[31m%s\033[0m\n' "Unknown init system structure, skipping service install..." >&2; \
|
||||
fi \
|
||||
else \
|
||||
printf '\033[1;31m%s\033[0m\n' "Unknown init system, skipping service install..." >&2; \
|
||||
fi
|
||||
|
||||
install-service-systemd:
|
||||
install -m644 ./assets/services/systemd.service ${DESTDIR}/etc/systemd/system/lidm.service
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'systemctl enable lidm'"
|
||||
install-service-dinit:
|
||||
install -m644 ./assets/services/dinit ${DESTDIR}/etc/dinit.d/lidm
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'dinitctl enable lidm'"
|
||||
install-service-runit:
|
||||
@if [ ! -e /etc/sv ] && [ -d /etc/runit/sv ] && [ -z "$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/sv doesn't exist but /etc/runit/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-runit-etc'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/sv/lidm
|
||||
cp -r --update=all ./assets/services/runit/* ${DESTDIR}/etc/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'ln -s ${DESTDIR}/etc/sv/lidm /var/service' or your distro equivalent"
|
||||
install-service-runit-etc:
|
||||
@if [ ! -e /etc/runit/sv ] && [ -d /etc/sv ] && [ -z "$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/runit/sv doesn't exist but /etc/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-runit'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/runit/sv/lidm
|
||||
cp -r --update=all ./assets/services/runit/* ${DESTDIR}/etc/runit/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'ln -s ${DESTDIR}/etc/runit/sv/lidm /run/runit/service' or your distro equivalent"
|
||||
install-service-openrc:
|
||||
install -m755 ./assets/services/openrc ${DESTDIR}/etc/init.d/lidm
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'rc-update add lidm'"
|
||||
install-service-s6:
|
||||
@if [ ! -e /etc/sv ] && [ -d /etc/s6/sv ] && [ -z "$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/sv doesn't exist but /etc/s6/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-s6-etc'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/sv/lidm
|
||||
cp -r --update=all ./assets/services/s6/* ${DESTDIR}/etc/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 's6-service add default lidm' and 's6-db-reload'"
|
||||
install-service-s6-etc:
|
||||
@if [ ! -e /etc/s6/sv ] && [ -d /etc/sv ] && [ -z "$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/s6/sv doesn't exist but /etc/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-s6'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/s6/sv/lidm
|
||||
cp -r --update=all ./assets/services/s6/* ${DESTDIR}/etc/s6/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 's6-service add default lidm' and 's6-db-reload'"
|
||||
|
||||
pre-commit:
|
||||
codespell
|
||||
@@ -65,5 +147,13 @@ print-version:
|
||||
|
||||
.PHONY: clean \
|
||||
install uninstall \
|
||||
install-service \
|
||||
install-service-s6 \
|
||||
install-service-s6-etc \
|
||||
install-service-dinit \
|
||||
install-service-runit \
|
||||
install-service-runit-etc \
|
||||
install-service-openrc \
|
||||
install-service-systemd \
|
||||
pre-commit \
|
||||
print-version
|
||||
|
||||
20
README.md
20
README.md
@@ -15,27 +15,22 @@ LiDM is like any [Display Manager](https://en.wikipedia.org/wiki/X_display_manag
|
||||
shown as in a featured terminal emulator, actual linux console doesn't support as much color and decorations
|
||||
</i></summary>
|
||||
|
||||
If you want to add fancy color and font support to your TTYs you can try wrapping lidm in [`kmscon`](https://wiki.archlinux.org/title/KMSCON). (edit appropriate service files). e.g:
|
||||
If you want to add fancy color and font support to your TTYs you can wrap lidm in [`kmscon`](https://wiki.archlinux.org/title/KMSCON). (edit appropriate service files). e.g:
|
||||
|
||||
```sh
|
||||
kmscon -l --vt /dev/tty7 --font-name "Cascadia Code" -- /usr/bin/lidm
|
||||
```
|
||||
|
||||
Kmscon is NOT officially supported so you are on your own when trying this, [according to the arch wiki](https://wiki.archlinux.org/title/KMSCON#Window_managers_cannot_be_started_from_KMS_console) it's not possible to start window managers if you do this.
|
||||
|
||||
But [according to farouk](https://github.com/javalsai/lidm/issues/91#issuecomment-3708503568) you can make it work if you tell kmscon to work in `no-drm` mode. There's still input grabbing issues which cause <kbd><kbd>Ctrl</kbd> + <kbd>C</kbd></kbd> to kill lidm, they are likely fixable though.
|
||||
|
||||
</details></blockquote>
|
||||
|
||||
> _however, all colors and strings are fully customizable_
|
||||
|
||||
## Features
|
||||
|
||||
- Simple as C, meant to depend only on standard libc and basic unix system headers.
|
||||
- Fully customizable: ALL strings, colors (with its ANSI keys) and most behavior.
|
||||
- Experimental Xorg support[\*](https://github.com/javalsai/lidm/pull/80?#issuecomment-3764073217) and wayland sessions, while supporting the default user shell (if enabled in config)
|
||||
- Init agnostinc (systemd, dinit, runit, openrc and s6).
|
||||
- Supports [fido yubikeys](./docs/yubikey.md) (via pam_u2f).
|
||||
- Simple as C, you only need a C compiler and standard unix libraries to build this.
|
||||
- Fully customizable, from strings, including action keys, to colors (I hope you know ansi escape codes)
|
||||
- Automatically detects xorg and wayland sessions, plus allowing to launch the default user shell (if enabled in config)
|
||||
- Starts with many init systems (systemd, dinit, runit, openrc and s6).
|
||||
|
||||
# Table of Contents
|
||||
|
||||
@@ -48,7 +43,6 @@ But [according to farouk](https://github.com/javalsai/lidm/issues/91#issuecommen
|
||||
- [Configuring](#configuring)
|
||||
- [PAM](#pam)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
- [Inspiration](#inspiration)
|
||||
- [Contributors](#contributors)
|
||||
|
||||
@@ -122,10 +116,6 @@ When the env variable is empty it defaults to the `login` PAM service or whateve
|
||||
|
||||
If you want to contribute check the [contribution guide](docs/CONTRIBUTING.md).
|
||||
|
||||
# License
|
||||
|
||||
This project is licensed under the GNU General Public License v3.0 **only**.
|
||||
|
||||
# Inspiration
|
||||
|
||||
This project was started after facing some issues building [ly](https://github.com/fairyglade/ly) on an ancient laptop, the UI is heavily inspired by it.
|
||||
|
||||
@@ -69,13 +69,13 @@ Characters for the corners of the box (ctl = corner top left, cbr = corner botto
|
||||
.SS functions
|
||||
All these are of type \fBKEY\fP.
|
||||
.TP
|
||||
\fBpoweroff, reboot, fido, refresh\fP
|
||||
\fBpoweroff, reboot, refresh\fP
|
||||
Function key to use for such action.
|
||||
|
||||
.SS strings
|
||||
Display strings to use for some elements.
|
||||
.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.
|
||||
.TP
|
||||
\fBe_user, e_passwd\fP
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
pkgbase = lidm-bin
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (release binary)
|
||||
pkgver = 1.2.3
|
||||
pkgrel = 4
|
||||
pkgrel = 3
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = x86_64
|
||||
arch = i686
|
||||
arch = aarch64
|
||||
arch = armv7h
|
||||
arch = riscv64
|
||||
license = GPL-3.0-only
|
||||
license = GPL
|
||||
depends = libpam.so
|
||||
depends = lidm-service
|
||||
provides = lidm
|
||||
conflicts = lidm
|
||||
source = lidm-default-theme-1.2.3.ini::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/themes/default.ini
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm-bin
|
||||
pkgver=1.2.3
|
||||
pkgrel=4
|
||||
depends=('libpam.so' 'lidm-service')
|
||||
pkgrel=3
|
||||
depends=('libpam.so')
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (release binary)"
|
||||
arch=('x86_64' 'i686' 'aarch64' 'armv7h' 'riscv64')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
license=('GPL-3.0-only')
|
||||
license=('GPL')
|
||||
provides=('lidm')
|
||||
conflicts=('lidm')
|
||||
source=(
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
pkgbase = lidm-dinit
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (dinit service files)
|
||||
pkgver = 1.2.3
|
||||
pkgrel = 1
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = any
|
||||
license = GPL-3.0-only
|
||||
provides = lidm-service
|
||||
source = lidm-dinit-1.2.3-dinit::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/services/dinit
|
||||
sha256sums = 185cd76c1d29ddc73cf96be999f13278a427bb80aa9169f25f30673ad2de3770
|
||||
|
||||
pkgname = lidm-dinit
|
||||
3
assets/pkg/aur/lidm-dinit/.gitignore
vendored
3
assets/pkg/aur/lidm-dinit/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
*
|
||||
!PKGBUILD
|
||||
!.SRCINFO
|
||||
@@ -1,17 +0,0 @@
|
||||
# shellcheck disable=SC2034,SC2154,SC2164
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm-dinit
|
||||
pkgver=1.2.3
|
||||
pkgrel=1
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (dinit service files)"
|
||||
provides=('lidm-service')
|
||||
arch=('any')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
license=('GPL-3.0-only')
|
||||
source=("${pkgname}-${pkgver}-dinit::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/services/dinit")
|
||||
sha256sums=('185cd76c1d29ddc73cf96be999f13278a427bb80aa9169f25f30673ad2de3770')
|
||||
|
||||
package() {
|
||||
cd "$srcdir"
|
||||
install -Dm0644 "${pkgname}-${pkgver}-dinit" "$pkgdir/etc/dinit.d/lidm"
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
pkgbase = lidm-git
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (last git commit)
|
||||
pkgver = 1.2.3.r12.g7e7a297
|
||||
pkgrel = 1
|
||||
pkgver = 1.2.3.r3.g363deea
|
||||
pkgrel = 3
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = any
|
||||
license = GPL-3.0-only
|
||||
license = GPL
|
||||
makedepends = git
|
||||
depends = pam
|
||||
depends = lidm-service
|
||||
provides = lidm
|
||||
conflicts = lidm
|
||||
source = lidm::git+https://github.com/javalsai/lidm
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# shellcheck disable=SC2034,SC2154,SC2164
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm-git
|
||||
pkgver=1.2.3.r13.g9cf5297
|
||||
pkgrel=1
|
||||
depends=('pam' 'lidm-service')
|
||||
pkgver=1.2.3.r3.g363deea
|
||||
pkgrel=3
|
||||
depends=('pam')
|
||||
makedepends=('git')
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (last git commit)"
|
||||
arch=('any')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
license=('GPL-3.0-only')
|
||||
license=('GPL')
|
||||
provides=('lidm')
|
||||
conflicts=('lidm')
|
||||
source=("lidm::git+https://github.com/javalsai/lidm")
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
pkgbase = lidm-systemd
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (systemd service files)
|
||||
pkgver = 1.2.3
|
||||
pkgrel = 1
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = any
|
||||
license = GPL-3.0-only
|
||||
provides = lidm-service
|
||||
source = lidm-systemd-1.2.3-systemd::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/services/systemd.service
|
||||
sha256sums = e63464441a97102194994adc82159871ccd3f23d5e97224f21a460e4296364cc
|
||||
|
||||
pkgname = lidm-systemd
|
||||
3
assets/pkg/aur/lidm-systemd/.gitignore
vendored
3
assets/pkg/aur/lidm-systemd/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
*
|
||||
!PKGBUILD
|
||||
!.SRCINFO
|
||||
@@ -1,17 +0,0 @@
|
||||
# shellcheck disable=SC2034,SC2154,SC2164
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm-systemd
|
||||
pkgver=1.2.3
|
||||
pkgrel=1
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (systemd service files)"
|
||||
provides=('lidm-service')
|
||||
arch=('any')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
license=('GPL-3.0-only')
|
||||
source=("${pkgname}-${pkgver}-systemd::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/services/systemd.service")
|
||||
sha256sums=('e63464441a97102194994adc82159871ccd3f23d5e97224f21a460e4296364cc')
|
||||
|
||||
package() {
|
||||
cd "$srcdir"
|
||||
install -Dm0644 "${pkgname}-${pkgver}-systemd" "$pkgdir/usr/lib/systemd/system/lidm.service"
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
pkgbase = lidm
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (build latest tag)
|
||||
pkgver = 1.2.3
|
||||
pkgrel = 5
|
||||
pkgrel = 3
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = any
|
||||
license = GPL-3.0-only
|
||||
license = GPL
|
||||
depends = pam
|
||||
depends = lidm-service
|
||||
source = lidm-1.2.3.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.3.tar.gz
|
||||
sha256sums = 1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm
|
||||
pkgver=1.2.3
|
||||
pkgrel=5
|
||||
depends=('pam' 'lidm-service')
|
||||
pkgrel=3
|
||||
depends=('pam')
|
||||
makedepends=()
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (build latest tag)"
|
||||
arch=('any')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
license=('GPL-3.0-only')
|
||||
license=('GPL')
|
||||
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v$pkgver.tar.gz")
|
||||
sha256sums=('1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93')
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ MYSELF=$(realpath "$0")
|
||||
MYDIR=$(dirname "$MYSELF")
|
||||
|
||||
cd "$MYDIR"
|
||||
typeset -a pkgs=(lidm{,-git,-bin,-systemd,-dinit})
|
||||
typeset -a pkgs=(lidm{,-git,-bin})
|
||||
|
||||
for pkg in "${pkgs[@]}"; do
|
||||
printf "\x1b[mEntering '%s'\x1b[0m\n" "$pkg"
|
||||
|
||||
@@ -5,7 +5,7 @@ MYSELF=$(realpath "$0")
|
||||
MYDIR=$(dirname "$MYSELF")
|
||||
|
||||
cd "$MYDIR"
|
||||
typeset -a pkgs=(lidm{,-git,-bin,-systemd,-dinit})
|
||||
typeset -a pkgs=(lidm{,-git,-bin})
|
||||
|
||||
for pkg in "${pkgs[@]}"; do
|
||||
printf "\x1b[mEntering '%s'\x1b[0m\n" "$pkg"
|
||||
|
||||
@@ -11,7 +11,7 @@ fi
|
||||
version="$1"
|
||||
printf "\x1b[34mINF: Using '%s' version\x1b[0m\n" "$version"
|
||||
|
||||
for pkg in "$MYDIR"/lidm{,-bin,-systemd,-dinit}/; do
|
||||
for pkg in "$MYDIR"/lidm{,-bin}/; do
|
||||
cd "$pkg"
|
||||
printf "\x1b[1mEntering '%s'\x1b[0m\n" "$pkg"
|
||||
sed -i "s/pkgver=.*/pkgver=$1/" PKGBUILD
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
|
||||
This folder contains the files necessary to set up lidm on start up for the supported init systems, all of them are configured for tty7.
|
||||
|
||||
If you're using lidm from a packaged source, this should be included with the package. Only read this for manual installations, if you are packaging or if your package exceptionally doesn't include them.
|
||||
|
||||
If you don't know what a init system is, you're certainly using `systemd`.
|
||||
|
||||
There's make scripts to automatically copy the service files to the proper locations, you just have to run `make install-service-$INIT` (or `make install-service-$INIT-etc`). `make install-service` will attempt to detect the init system in use and install for it.
|
||||
|
||||
The manual steps for installation are:
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you think this should be packaged too, there's [a discussion](https://github.com/javalsai/lidm/discussions/39) to talk about this.
|
||||
|
||||
## Systemd
|
||||
|
||||
- Copy `systemd.service` to `/usr/local/lib/systemd/system/lidm.service` (if the directory doesn't exist, create it first) or `/usr/lib/systemd/system/lidm.service` (if you wish to install along your system files).
|
||||
- Copy `systemd.service` to `/etc/systemd/system/lidm.service`
|
||||
- To enable it you can run `systemctl enable lidm`
|
||||
|
||||
## Dinit
|
||||
@@ -22,10 +23,8 @@ The manual steps for installation are:
|
||||
|
||||
## Runit
|
||||
|
||||
Your runit service path can be either `/etc/runit/sv` or `/etc/sv`.
|
||||
|
||||
- Copy `runit/` to `runit-path/lidm/`
|
||||
- Add the service with `ln -s runit-path/lidm /run/runit/service`
|
||||
- Copy `runit/` to `/etc/runit/sv/lidm/`
|
||||
- Add the service with `ln -s /etc/runit/sv/lidm /run/runit/service`
|
||||
- And to enable it `sv enable lidm`
|
||||
|
||||
## OpenRC
|
||||
@@ -35,9 +34,7 @@ Your runit service path can be either `/etc/runit/sv` or `/etc/sv`.
|
||||
|
||||
## S6
|
||||
|
||||
Your S6 service path can be either `/etc/s6/sv` or `/etc/sv`.
|
||||
|
||||
- Copy `s6/` to `s6-path/lidm/`
|
||||
- Copy `s6/` to `/etc/s6/sv/lidm/`
|
||||
- Add the service with `s6-service add default lidm`
|
||||
- Reload the database with `s6-db-reload` (you might have to run this every time the service file changes)
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ StandardError=tty
|
||||
TTYPath=/dev/tty7
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
Alias=display-manager.service
|
||||
|
||||
134
docs/INSTALL.md
134
docs/INSTALL.md
@@ -1,73 +1,63 @@
|
||||
# Table of Contents
|
||||
|
||||
- [Packages](#packages)
|
||||
- [Void Linux](#void-linux)
|
||||
- [Fedora](#fedora)
|
||||
- [AUR](#aur)
|
||||
- [Nix Flake](#nix-flake)
|
||||
- [Nix Module](#nix-module)
|
||||
- [Installing from Source](#installing-from-source)
|
||||
- [AUR](#aur)
|
||||
- [Nix Flake](#nix-flake)
|
||||
- [Nix Module](#nix-module)
|
||||
|
||||
# Packages
|
||||
> [!CAUTION]
|
||||
> I encourage you to read the manual installation steps to understand what will get installed in your computer by this package.
|
||||
|
||||
Lidm relies on its community to package lidm for distributions and make the installation easier for everyone. Please raise any issues on the packages themselves and not the source repository.
|
||||
# Installing from Source
|
||||
|
||||
If you packaged lidm for any distribution not listed here or keep your own version of an inactive package, feel free to contact me to be added here. (could be a GitHub discussion or an email if you don't use GitHub)
|
||||
Firstly, you'll need to build the package, this also includes man pages, default config, themes and other files you might need.
|
||||
|
||||
These packages just install lidm, once installed you have to enable it. It depends on your init system, but if you're using systemd (most likely), first find your currently active display manager (if any, examples are `sddm`, `gdm`, `ly`) and disable it:
|
||||
To build it you only need to have some basic packages (should come pre-installed in almost all distros): `make`, `gcc` or another `gcc`ish compiler, and libpam headers. If it builds, it surely works anyways.
|
||||
|
||||
```sh
|
||||
systemctl disable <display manager name here>
|
||||
git clone https://github.com/javalsai/lidm.git
|
||||
cd lidm
|
||||
make # 👍
|
||||
```
|
||||
|
||||
And then enable lidm:
|
||||
> [!NOTE]
|
||||
> There's pre-built binaries on the [releases tab](https://github.com/javalsai/lidm/releases) too.
|
||||
|
||||
Then you can install the files onto your filesystem with:
|
||||
|
||||
```sh
|
||||
systemctl enable lidm
|
||||
make install
|
||||
```
|
||||
|
||||
Lidm now should show on the next boot!
|
||||
|
||||
If you are on a TTY and don't wish to reboot, you should be able to use `--now` with both commands. It's likely to kill your current desktop environment if it was launched from it.
|
||||
|
||||
## Void Linux
|
||||
|
||||
Lidm can be installed from the official Void Linux packages:
|
||||
And additionally, to install service files (start-up behavior). <sup>[more docs](../assets/services/README.md)</sup>
|
||||
|
||||
```sh
|
||||
xbps-install lidm
|
||||
# automatically detects your init system
|
||||
# and install service file (for tty7)
|
||||
make install-service
|
||||
|
||||
# or if you don't like autodetection
|
||||
make install-service-systemd # systemd
|
||||
make install-service-dinit # dinit
|
||||
make install-service-runit # runit (/etc/sv)
|
||||
make install-service-runit-etc # runit (/etc/runit/sv)
|
||||
make install-service-openrc # openrc
|
||||
make install-service-s6 # s6 (/etc/sv)
|
||||
make install-service-s6-etc # s6 (/etc/s6/sv)
|
||||
|
||||
# For runit and s6, some distros (e.g. Artix) like to put it in /etc/<init>/sv
|
||||
# to better isolate their packages while other distros (e.g. Void) just put it
|
||||
# in /etc/sv
|
||||
```
|
||||
|
||||
To enable the service that starts on boot:
|
||||
# AUR
|
||||
|
||||
```sh
|
||||
ln -s /etc/sv/lidm /var/service/
|
||||
```
|
||||
[AUR packages](https://aur.archlinux.org/packages?K=lidm&SeB=n) will automatically install most files.
|
||||
|
||||
It is recommended to disable any other display managers that are still enabled:
|
||||
> [!CAUTION]
|
||||
> [service files](../assets/pkg/aur#services) have to be manually installed by now.
|
||||
|
||||
```sh
|
||||
touch /etc/sv/lightdm/down # replace lightdm with your previous display manager (e.g., sddm, gdm)
|
||||
```
|
||||
|
||||
|
||||
## Fedora
|
||||
|
||||
Thanks to @KernelFreeze there's a COPR repo available at <https://copr.fedorainfracloud.org/coprs/celestelove/lidm/> to install lidm. (<https://github.com/javalsai/lidm/discussions/92>)
|
||||
|
||||
## AUR
|
||||
|
||||
There are several [AUR packages](https://aur.archlinux.org/packages?K=lidm&SeB=n) for most things. You only need to install one of the following:
|
||||
|
||||
* `lidm`
|
||||
* `lidm-bin`
|
||||
* `lidm-git`
|
||||
|
||||
Each of those depend on `lidm-service` which is provided by `lidm-systemd` and `lidm-dinit` (you'll have to pick one). I maintain both but I'm open to anyone that actually uses systemd to take the first one.
|
||||
|
||||
There's packagers needed for openrc, s6 and runit. If you know how to make AUR packages, feel free to take any of those if you use each init system.
|
||||
|
||||
## Nix Flake
|
||||
# Nix Flake
|
||||
|
||||
You can install by doing
|
||||
|
||||
@@ -82,9 +72,9 @@ nix run github:javalsai/lidm
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> This doesn't include [service files](../assets/pkg/aur#services)
|
||||
> This doesn't include [service files](../assets/pkg/aur#services) neither
|
||||
|
||||
## Nix Module
|
||||
# Nix Module
|
||||
|
||||
<details>
|
||||
<summary>Sidenote</summary>
|
||||
@@ -136,47 +126,3 @@ with config.lidm.keysEnum; {
|
||||
|
||||
> [!NOTE]
|
||||
> [service files](../assets/pkg/aur#services) **are** included and enabled
|
||||
|
||||
# Installing from Source
|
||||
|
||||
Firstly, you'll need to build the package, this also includes man pages, default config, themes and other files you might need.
|
||||
|
||||
To build it you only need to have some basic packages (should come pre-installed in almost all distros): `make`, `gcc` or another `gcc`ish compiler, and libpam headers. If it builds, it surely works anyways.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/javalsai/lidm.git
|
||||
cd lidm
|
||||
make # 👍
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> There are pre-built binaries on the [releases tab](https://github.com/javalsai/lidm/releases) too.
|
||||
|
||||
Then you can install the files onto your filesystem with:
|
||||
|
||||
```sh
|
||||
make install
|
||||
```
|
||||
|
||||
This will install mostly into `/usr/local` by default, this path is mostly unused nowadays (systemd can load services from it but man usually doesn't find manual pages in there) and could feel like lidm didn't install at all. You can add `PREFIX=/usr` to install along the rest of your system packages if you wish.
|
||||
|
||||
And additionally, to install service files (start-up behavior). <sup>[more docs](../assets/services/README.md)</sup>
|
||||
|
||||
```sh
|
||||
# automatically detects your init system
|
||||
# and install service file (for tty7)
|
||||
make install-service
|
||||
|
||||
# or if you don't like autodetection
|
||||
make install-service-systemd # systemd
|
||||
make install-service-dinit # dinit
|
||||
make install-service-runit # runit (/etc/sv)
|
||||
make install-service-runit-etc # runit (/etc/runit/sv)
|
||||
make install-service-openrc # openrc
|
||||
make install-service-s6 # s6 (/etc/sv)
|
||||
make install-service-s6-etc # s6 (/etc/s6/sv)
|
||||
|
||||
# For runit and s6, some distros (e.g. Artix) like to put it in /etc/<init>/sv
|
||||
# to better isolate their packages while other distros (e.g. Void) just put it
|
||||
# in /etc/sv
|
||||
```
|
||||
|
||||
@@ -21,14 +21,12 @@ make \
|
||||
|
||||
The list of possible `#define`s is:
|
||||
|
||||
| Name | Default | Description | Env Override? |
|
||||
| -------------------------- | ------------------------------------- | -------------------------------------------------------------------------- | ------------------------ |
|
||||
| `PAM_SERVICE_FALLBACK` | `"login"` | Name of the default PAM module to use. Defaults to the distro's `"login"`. | Yes (`LIDM_PAM_SERVICE`) |
|
||||
| `SESSIONS_XSESSIONS` | `"/usr/share/xsessions"` | | No |
|
||||
| `SESSIONS_XSESSIONS_LOCAL` | `"/usr/local/share/xsessions"` | | No |
|
||||
| `SESSIONS_WAYLAND` | `"/usr/share/wayland-sessions"` | | No |
|
||||
| `SESSIONS_WAYLAND_LOCAL` | `"/usr/local/share/wayland-sessions"` | | No |
|
||||
| `LIDM_CONF_PATH` | `"/etc/lidm.ini"` | Path of the default configuration. | Yes (`LIDM_CONF`) |
|
||||
| Name | Default | Description | Env Override? |
|
||||
| ---------------------- | ------------------------------- | -------------------------------------------------------------------------- | ------------------------ |
|
||||
| `PAM_SERVICE_FALLBACK` | `"login"` | Name of the default PAM module to use. Defaults to the distro's `"login"`. | Yes (`LIDM_PAM_SERVICE`) |
|
||||
| `SESSIONS_XSESSIONS` | `"/usr/share/xsessions"` | | No |
|
||||
| `SESSIONS_WAYLAND` | `"/usr/share/wayland-sessions"` | | No |
|
||||
| `LIDM_CONF_PATH` | `"/etc/lidm.ini"` | Path of the default configuration. | Yes (`LIDM_CONF`) |
|
||||
|
||||
# Other Build Settings
|
||||
|
||||
@@ -53,9 +51,7 @@ But this can be changed by just passing those env variables, for example, in the
|
||||
|
||||
## Target Directory
|
||||
|
||||
`DESTDIR` can be used to for installation recipes to install on alternative root directories. Along with `PREFIX` (defaults to `/usr/local`, packaging this you'll probably want to make it `/usr`) for systems which don't use the common `/usr` structure. e.g. `make install DESTDIR=$out PREFIX=`
|
||||
|
||||
`/etc` is sometimes in that `PREFIX` and sometimes not, be careful.
|
||||
`DESTDIR` can be used to for installation recipes to install on alternative root directories. Along with `PREFIX` (defaults to `/usr`) for systems which don't use the common `/usr` structure. e.g. `make install DESTDIR=$out PREFIX=`
|
||||
|
||||
```txt
|
||||
$ fd -t f . --base-directory $out
|
||||
@@ -71,7 +67,7 @@ To ease most of the installation process there's several `make` recipes to insta
|
||||
|
||||
- `make` / `make lidm`: Builds the app binary.
|
||||
- `make install`: Attempts to install the binary, place a default config file in `/etc/lidm.ini` and install the man pages.
|
||||
- `make install-service-(systemd|dinit|runit|openrc|s6)(|-etc)`: Just check the source, service files for different init systems and `-etc` variants for alternative paths. You might need `FORCE=1` in the environment if you are packaging for other init system or scripting.
|
||||
- `make install-service-(systemd|dinit|runit|openrc|s6)(|-etc)`: Just check the source, service files for different init systems and `-etc` variants for alternative paths.
|
||||
- `make print-version`: Outputs the current version in the `Makefile` for scripts that might want to extract that info.
|
||||
|
||||
You can choose to use these packages or create your own service files / etc. There's are merely suggestions on what to use.
|
||||
|
||||
@@ -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.
|
||||
@@ -92,7 +92,6 @@ BUILD(chars, CHARS, TABLE_CHARS);
|
||||
#define TABLE_FUNCTIONS(F, name) \
|
||||
F(enum Keys, poweroff, KEY, F1, name) \
|
||||
F(enum Keys, reboot, KEY, F2, name) \
|
||||
F(enum Keys, fido, KEY, NONE, name) \
|
||||
F(enum Keys, refresh, KEY, F5, name)
|
||||
|
||||
BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
|
||||
@@ -100,7 +99,6 @@ BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
|
||||
#define TABLE_STRINGS(F, name) \
|
||||
F(char* NNULLABLE, f_poweroff, STRING, "poweroff", 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, e_user, STRING, "user", name) \
|
||||
F(char* NNULLABLE, e_passwd, STRING, "password", name) \
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
// TODO: rewrite properly
|
||||
// NOLINTBEGIN(clang-diagnostic-nullability-completeness)
|
||||
|
||||
#ifndef DESKTOP_EXEC_H_
|
||||
#define DESKTOP_EXEC_H_
|
||||
#define DESKTOP_EXEC_H_
|
||||
|
||||
#include "macros.h"
|
||||
#include "macros.h"
|
||||
|
||||
char* NULLABLE search_path(const char* NNULLABLE for_binary);
|
||||
int execvpe_desktop(char** args, char* NNULLABLE* NNULLABLE envlist);
|
||||
int parse_exec_string(const char* exec_s, int* arg_count, char*** args);
|
||||
void free_parsed_args(int arg_count, char** args);
|
||||
|
||||
#endif
|
||||
// NOLINTEND(clang-diagnostic-nullability-completeness)
|
||||
|
||||
@@ -32,11 +32,9 @@ enum Keys {
|
||||
END,
|
||||
PAGE_UP,
|
||||
PAGE_DOWN,
|
||||
NONE,
|
||||
};
|
||||
|
||||
static const char* const KEY_NAMES[] = {
|
||||
[NONE] = "NONE",
|
||||
[ESC] = "ESC",
|
||||
[F1] = "F1",
|
||||
[F2] = "F2",
|
||||
|
||||
@@ -7,25 +7,25 @@
|
||||
#endif
|
||||
|
||||
// Do we just replace the compiler with clang??
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__)
|
||||
#define NULLABLE _Nullable
|
||||
#else
|
||||
#define NULLABLE
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__)
|
||||
#define NNULLABLE _Nonnull
|
||||
#else
|
||||
#define NNULLABLE
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__)
|
||||
#define UNULLABLE _Null_unspecified
|
||||
#else
|
||||
#define UNULLABLE
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__)
|
||||
#define COMPILER_VERSION __VERSION__
|
||||
#elif defined(__GNUC__)
|
||||
#define xstr(s) str(s)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef SIGNALHANDLERH_
|
||||
#define SIGNALHANDLERH_
|
||||
|
||||
// handle SIGTERM by sending SIGTERM to all children, resulting
|
||||
// in a graceful graphical shutdown
|
||||
void setup_sigterm();
|
||||
|
||||
#endif /* SIGNALHANDLERH_ */
|
||||
@@ -46,8 +46,6 @@ void setup(struct config* config);
|
||||
int load(struct Vector* users, struct Vector* sessions);
|
||||
void print_err(const char* /*msg*/);
|
||||
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_ffield();
|
||||
|
||||
90
services.mk
90
services.mk
@@ -1,90 +0,0 @@
|
||||
install-service:
|
||||
@if command -v systemctl &> /dev/null; then \
|
||||
make install-service-systemd; \
|
||||
elif command -v dinitctl &> /dev/null; then \
|
||||
make install-service-dinit; \
|
||||
elif command -v sv &> /dev/null; then \
|
||||
if [ -d /etc/sv ]; then \
|
||||
make install-service-runit; \
|
||||
elif [ -d /etc/runit/sv ]; then \
|
||||
make install-service-runit-etc; \
|
||||
else \
|
||||
printf '\033[31m%s\033[0m\n' "Unknown init system structure, skipping service install..." >&2; \
|
||||
fi \
|
||||
elif command -v rc-update &> /dev/null; then \
|
||||
make install-service-openrc; \
|
||||
elif command -v s6-service &> /dev/null; then \
|
||||
if [ -d /etc/sv ]; then \
|
||||
make install-service-s6; \
|
||||
elif [ -d /etc/r6nit/sv ]; then \
|
||||
make install-service-s6-etc; \
|
||||
else \
|
||||
printf '\033[31m%s\033[0m\n' "Unknown init system structure, skipping service install..." >&2; \
|
||||
fi \
|
||||
else \
|
||||
printf '\033[1;31m%s\033[0m\n' "Unknown init system, skipping service install..." >&2; \
|
||||
fi
|
||||
|
||||
install-service-systemd:
|
||||
install -Dm644 ./assets/services/systemd.service ${DESTDIR}${PREFIX}/lib/systemd/system/lidm.service
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'systemctl enable lidm'"
|
||||
install-service-dinit:
|
||||
install -m644 ./assets/services/dinit ${DESTDIR}/etc/dinit.d/lidm
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'dinitctl enable lidm'"
|
||||
install-service-runit:
|
||||
@if [ ! -e /etc/sv ] && [ -d /etc/runit/sv ] && [ -z "$$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/sv doesn't exist but /etc/runit/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-runit-etc'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/sv/lidm
|
||||
cp -r --update=all ./assets/services/runit/* ${DESTDIR}/etc/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'ln -s ${DESTDIR}/etc/sv/lidm /var/service' or your distro equivalent"
|
||||
install-service-runit-etc:
|
||||
@if [ ! -e /etc/runit/sv ] && [ -d /etc/sv ] && [ -z "$$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/runit/sv doesn't exist but /etc/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-runit'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/runit/sv/lidm
|
||||
cp -r --update=all ./assets/services/runit/* ${DESTDIR}/etc/runit/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'ln -s ${DESTDIR}/etc/runit/sv/lidm /run/runit/service' or your distro equivalent"
|
||||
install-service-openrc:
|
||||
install -m755 ./assets/services/openrc ${DESTDIR}/etc/init.d/lidm
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 'rc-update add lidm'"
|
||||
install-service-s6:
|
||||
@if [ ! -e /etc/sv ] && [ -d /etc/s6/sv ] && [ -z "$$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/sv doesn't exist but /etc/s6/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-s6-etc'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/sv/lidm
|
||||
cp -r --update=all ./assets/services/s6/* ${DESTDIR}/etc/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 's6-service add default lidm' and 's6-db-reload'"
|
||||
install-service-s6-etc:
|
||||
@if [ ! -e /etc/s6/sv ] && [ -d /etc/sv ] && [ -z "$$FORCE" ]; then \
|
||||
printf '\033[31m%s\033[0m\n' "/etc/s6/sv doesn't exist but /etc/sv does" >&2; \
|
||||
printf '\033[31m%s\033[0m\n' "you probably meant to 'make install-service-s6'" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
mkdir -p ${DESTDIR}/etc/s6/sv/lidm
|
||||
cp -r --update=all ./assets/services/s6/* ${DESTDIR}/etc/s6/sv/lidm/
|
||||
@printf '\033[1m%s\033[0m\n\n' " don't forget to run 's6-service add default lidm' and 's6-db-reload'"
|
||||
|
||||
uninstall-service:
|
||||
rm -rf \
|
||||
${DESTDIR}${PREFIX}/lib/systemd/system/lidm.service \
|
||||
${DESTDIR}/etc/dinit.d/lidm \
|
||||
${DESTDIR}/etc/sv/lidm \
|
||||
${DESTDIR}/etc/runit/sv/lidm \
|
||||
${DESTDIR}/etc/init.d/lidm \
|
||||
${DESTDIR}/etc/s6/sv/lidm
|
||||
|
||||
.PHONY: install-service uninstall-service \
|
||||
install-service-s6 \
|
||||
install-service-s6-etc \
|
||||
install-service-dinit \
|
||||
install-service-runit \
|
||||
install-service-runit-etc \
|
||||
install-service-openrc \
|
||||
install-service-systemd
|
||||
173
src/auth.c
173
src/auth.c
@@ -1,4 +1,4 @@
|
||||
// TODO: handle `fork() == -1`// TODO: handle `fork() == -1`s
|
||||
// TODO: handle `fork() == -1`s
|
||||
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
@@ -23,7 +23,9 @@
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
|
||||
#define XORG_MESSAGE_LENGTH 16
|
||||
#define DEFAULT_XORG_DISPLAY 0
|
||||
// no PATH search for now
|
||||
#define XORG_COMMAND "/usr/bin/X"
|
||||
|
||||
static void try_source_file(struct Vector* NNULLABLE vec_envlist,
|
||||
char* NNULLABLE filepath) {
|
||||
@@ -96,121 +98,64 @@ struct child_msg {
|
||||
bool err;
|
||||
};
|
||||
|
||||
/// block until X returns the display number or an error occurs
|
||||
static bool x_get_display(const int xorg_pipefd[2], int* display) {
|
||||
char buffer[XORG_MESSAGE_LENGTH];
|
||||
bool status;
|
||||
|
||||
close(xorg_pipefd[1]);
|
||||
ssize_t bytes_read = read(xorg_pipefd[0], buffer, sizeof(buffer) - 1);
|
||||
buffer[bytes_read] = '\0';
|
||||
|
||||
if (bytes_read > 0) {
|
||||
char* endptr;
|
||||
int val = (int)strtol(buffer, &endptr, 10);
|
||||
if (endptr == buffer) {
|
||||
(void)fputs("failed to parse Xorg display response\n", stderr);
|
||||
status = false;
|
||||
} else {
|
||||
*display = val;
|
||||
status = true;
|
||||
}
|
||||
} else if (bytes_read == 0) {
|
||||
(void)fputs("Xorg pipe closed\n", stderr);
|
||||
status = false;
|
||||
} else {
|
||||
perror("read");
|
||||
status = false;
|
||||
}
|
||||
|
||||
close(xorg_pipefd[0]);
|
||||
return status;
|
||||
}
|
||||
|
||||
/// small helper to push dyn arr
|
||||
static void push_dyn_arr(void*** arr, void* item) {
|
||||
struct Vector vec = vec_from_raw(*arr);
|
||||
vec_push(&vec, item);
|
||||
*arr = vec_as_raw(vec);
|
||||
// TODO: OR check if xorg_pid fail exited
|
||||
static int wait_for_x_ready(const int xorg_pipefd[1], __pid_t xorg_pid) {
|
||||
// TODO
|
||||
UNUSED(xorg_pipefd);
|
||||
UNUSED(xorg_pid);
|
||||
sleep(2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: properly pass this down
|
||||
extern int vt;
|
||||
|
||||
static void start_xorg_server(struct passwd* pw, char** NNULLABLE envlist,
|
||||
int xorg_pipefd[2]) {
|
||||
close(xorg_pipefd[0]);
|
||||
if (!pw->pw_dir) _exit(EXIT_FAILURE);
|
||||
// !!!!!!!!!! ATTENTION: this fails silently, of course add failure msgs but
|
||||
// for now I can't so be careful
|
||||
if (vt == -1) _exit(EXIT_FAILURE);
|
||||
|
||||
// pass the pipe so Xorg can write the DISPLAY value in there
|
||||
char* fd_str;
|
||||
asprintf(&fd_str, "%d", xorg_pipefd[1]);
|
||||
if (!fd_str) _exit(EXIT_FAILURE);
|
||||
|
||||
char* vt_path;
|
||||
asprintf(&vt_path, "vt%d", vt);
|
||||
if (!vt_path) {
|
||||
free(fd_str);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char* xorg_path = search_path("Xorg");
|
||||
if (!xorg_path) {
|
||||
(void)fputs("couldn't find Xorg binary in PATH, sure it's installed?\n",
|
||||
stderr);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int exit = execle(xorg_path, xorg_path, "-displayfd", fd_str, vt_path, NULL,
|
||||
envlist);
|
||||
perror("exec");
|
||||
|
||||
free(vt_path);
|
||||
free(fd_str);
|
||||
free(xorg_path);
|
||||
_exit(exit);
|
||||
}
|
||||
|
||||
// TODO: add error msgs
|
||||
/// returns on completion
|
||||
static void launch_with_xorg_server(struct session_exec* NNULLABLE exec,
|
||||
struct passwd* pw,
|
||||
char** NNULLABLE envlist) {
|
||||
int xorg_pipefd[2];
|
||||
if (pipe(xorg_pipefd) == -1) _exit(EXIT_FAILURE);
|
||||
|
||||
pipe(xorg_pipefd);
|
||||
(void)fflush(NULL);
|
||||
pid_t xorg_pid = fork();
|
||||
__pid_t xorg_pid = fork();
|
||||
if (xorg_pid == 0) {
|
||||
start_xorg_server(pw, envlist, xorg_pipefd);
|
||||
if (!pw->pw_dir) _exit(EXIT_FAILURE);
|
||||
// !!!!!!!!!! ATTENTION: this fails silently, of course add failure msgs but
|
||||
// for now I can't so be careful
|
||||
if (vt == -1) _exit(EXIT_FAILURE);
|
||||
|
||||
char* display_thing;
|
||||
asprintf(&display_thing, ":%d", DEFAULT_XORG_DISPLAY);
|
||||
if (!display_thing) _exit(EXIT_FAILURE);
|
||||
|
||||
char* vt_path;
|
||||
asprintf(&vt_path, "vt%d", vt);
|
||||
if (!vt_path) {
|
||||
free(display_thing);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// dup2(xorg_pipefd[1], STDERR_FILENO);
|
||||
// dup2(xorg_pipefd[1], STDOUT_FILENO);
|
||||
// close(xorg_pipefd[0]);
|
||||
// close(xorg_pipefd[1]);
|
||||
|
||||
int exit = execle(XORG_COMMAND, XORG_COMMAND, display_thing, vt_path, NULL,
|
||||
envlist);
|
||||
perror("exec");
|
||||
// execle("X", "X", display_thing, vt_path, "-auth", xauth_path,
|
||||
// "-nolisten", "tcp", "-background", "none", NULL, envlist);
|
||||
|
||||
printf("wtf3\n");
|
||||
(void)fflush(stdout);
|
||||
|
||||
free(vt_path);
|
||||
free(display_thing);
|
||||
_exit(exit);
|
||||
}
|
||||
|
||||
int display = 0;
|
||||
if (!x_get_display(xorg_pipefd, &display)) {
|
||||
(void)fputs("failed to get X display, aborting\n", stderr);
|
||||
int status;
|
||||
waitpid(xorg_pid, &status, 0);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
wait_for_x_ready(xorg_pipefd, xorg_pid);
|
||||
|
||||
char* display_env;
|
||||
asprintf(&display_env, "DISPLAY=:%d", display);
|
||||
if (!display_env) {
|
||||
(void)fputs("failure allocating memory for DISPLAY string\n", stderr);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
// convert back for convenient push-ing
|
||||
push_dyn_arr((void***)&envlist, display_env);
|
||||
if (!envlist) {
|
||||
(void)fputs("failure allocating memory for DISPLAY env\n", stderr);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
(void)fflush(NULL);
|
||||
pid_t xorg_session_pid = fork();
|
||||
__pid_t xorg_session_pid = fork();
|
||||
if (xorg_session_pid == 0) {
|
||||
int exit = session_exec_exec(exec, envlist);
|
||||
perror("exec error");
|
||||
@@ -220,16 +165,20 @@ static void launch_with_xorg_server(struct session_exec* NNULLABLE exec,
|
||||
|
||||
// looks weird, waiting on -1 should wait on any child and then just check if
|
||||
// its xorg server or the session and kill the other waiting on it
|
||||
pid_t pid;
|
||||
__pid_t pid;
|
||||
int status; // not even read for now
|
||||
while ((pid = waitpid(-1, &status, 0)) > 0) {
|
||||
if (pid == xorg_pid || pid == xorg_session_pid) {
|
||||
pid_t pid_to_kill = pid ^ xorg_pid ^ xorg_session_pid;
|
||||
__pid_t pid_to_kill = pid ^ xorg_pid ^ xorg_session_pid;
|
||||
if (pid == xorg_pid) printf("Xorg server died\n");
|
||||
if (pid == xorg_session_pid) printf("Xorg session died\n");
|
||||
|
||||
kill(pid_to_kill, SIGTERM);
|
||||
waitpid(pid_to_kill, &status, 0);
|
||||
printf("wtf %d, x%d s%d - k%d\n", status, xorg_pid, xorg_session_pid,
|
||||
pid_to_kill);
|
||||
(void)fflush(stdout);
|
||||
sleep(10);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -269,7 +218,6 @@ inline static void forked(int pipefd[2], struct passwd* pw,
|
||||
|
||||
if (session->type == XORG) {
|
||||
launch_with_xorg_server(&session->exec, pw, envlist);
|
||||
_exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
int exit = session_exec_exec(&session->exec, envlist);
|
||||
perror("exec error");
|
||||
@@ -292,10 +240,9 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||
|
||||
pam_handle_t* pamh = get_pamh(user, passwd);
|
||||
if (pamh == NULL) {
|
||||
print_pam_msg("authentication failed", PAM_ERROR_MSG);
|
||||
print_err("error on pam authentication");
|
||||
return false;
|
||||
}
|
||||
clear_pam_msg();
|
||||
|
||||
struct pamh_getenv_status env_ret =
|
||||
pamh_get_complete_env(pamh, pw, session.type);
|
||||
@@ -312,6 +259,16 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||
|
||||
struct Vector envlist_vec = vec_from_raw((void**)env_ret.envlist);
|
||||
|
||||
if (session.type == XORG) {
|
||||
char* display_env;
|
||||
asprintf(&display_env, "DISPLAY=:%d", DEFAULT_XORG_DISPLAY);
|
||||
if (!display_env) {
|
||||
print_err("alloc error");
|
||||
return false;
|
||||
}
|
||||
vec_push(&envlist_vec, display_env);
|
||||
}
|
||||
|
||||
source_paths(&envlist_vec, &config->behavior.source, pw->pw_dir,
|
||||
&config->behavior.user_source);
|
||||
char** envlist = (char**)vec_as_raw(envlist_vec);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// TODO: rewrite properly
|
||||
// NOLINTBEGIN(clang-diagnostic-nullability-completeness)
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -17,14 +15,8 @@
|
||||
|
||||
// returns NULL on any error
|
||||
// otherwise it returns the absolute path of the program that MUST BE FREED
|
||||
char* NULLABLE search_path(const char* NNULLABLE for_binary) {
|
||||
if (strchr(for_binary, '/') != NULL) {
|
||||
// skip absolute paths
|
||||
return strdup(for_binary);
|
||||
}
|
||||
char* path_env = getenv("PATH");
|
||||
if (!path_env) return NULL;
|
||||
char* path = strdup(path_env);
|
||||
static char* NULLABLE search_path(const char* NNULLABLE for_binary) {
|
||||
char* path = strdup(getenv("PATH"));
|
||||
if (!path) return NULL;
|
||||
|
||||
char* tok = strtok(path, ":");
|
||||
@@ -48,7 +40,6 @@ char* NULLABLE search_path(const char* NNULLABLE for_binary) {
|
||||
tok = strtok(NULL, ":");
|
||||
}
|
||||
|
||||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -60,10 +51,7 @@ int execvpe_desktop(char** args, char* NNULLABLE* NNULLABLE envlist) {
|
||||
free(args[0]);
|
||||
args[0] = new_arg;
|
||||
|
||||
int status = execve(args[0], args, envlist);
|
||||
free(new_arg);
|
||||
|
||||
return status;
|
||||
return execve(args[0], args, envlist);
|
||||
}
|
||||
|
||||
// parse Exec=/bin/prog arg1 arg2\ with\ spaces
|
||||
@@ -145,7 +133,6 @@ int push_arg(struct ctx* st) {
|
||||
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;
|
||||
@@ -239,4 +226,3 @@ syntax_err:
|
||||
return 3;
|
||||
}
|
||||
// NOLINTEND(readability-function-cognitive-complexity)
|
||||
// NOLINTEND(clang-diagnostic-nullability-completeness)
|
||||
|
||||
@@ -21,17 +21,15 @@ int read_launch_state(struct LaunchState* NNULLABLE state) {
|
||||
};
|
||||
|
||||
size_t num = 0;
|
||||
ssize_t chars = getline(&state->username, &num, state_fd);
|
||||
if (chars < 0) goto fail;
|
||||
if (state->username[chars] == '\n') state->username[chars] = 0;
|
||||
if (getline(&state->username, &num, state_fd) < 0) goto fail;
|
||||
state->username[strcspn(state->username, "\n")] = 0;
|
||||
|
||||
num = 0;
|
||||
chars = getline(&state->session_opt, &num, state_fd);
|
||||
if (chars < 0) {
|
||||
if (getline(&state->session_opt, &num, state_fd) < 0) {
|
||||
free(state->session_opt);
|
||||
goto fail;
|
||||
}
|
||||
if (state->session_opt[chars] == '\n') state->session_opt[chars] = 0;
|
||||
state->session_opt[strcspn(state->session_opt, "\n")] = 0;
|
||||
|
||||
(void)fclose(state_fd);
|
||||
return 0;
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
#include "log.h"
|
||||
#include "macros.h"
|
||||
#include "sessions.h"
|
||||
#include "signal_handler.h"
|
||||
#include "ui.h"
|
||||
#include "users.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
|
||||
#define DATESTR_MAXBUFSIZE 0x20
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Logger
|
||||
char* log_output = getenv("LIDM_LOG");
|
||||
@@ -86,8 +85,6 @@ int main(int argc, char* argv[]) {
|
||||
struct Vector users = get_human_users();
|
||||
struct Vector sessions = get_avaliable_sessions();
|
||||
|
||||
setup_sigterm();
|
||||
|
||||
int ret = load(&users, &sessions);
|
||||
if (ret == 0) execl(argv[0], argv[0], NULL);
|
||||
}
|
||||
|
||||
39
src/pam.c
39
src/pam.c
@@ -9,7 +9,6 @@
|
||||
#include "macros.h"
|
||||
#include "pam.h"
|
||||
#include "sessions.h"
|
||||
#include "ui.h"
|
||||
|
||||
struct envpair {
|
||||
const char* NNULLABLE name;
|
||||
@@ -114,45 +113,19 @@ struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
|
||||
|
||||
///////////////
|
||||
|
||||
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,
|
||||
struct pam_response** resp, void* appdata_ptr) {
|
||||
struct pam_response* reply = malloc(sizeof(struct pam_response) * num_msg);
|
||||
if (!reply) {
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
|
||||
struct pam_conv_data* conv_data = (struct pam_conv_data*)appdata_ptr;
|
||||
|
||||
for (int i = 0; i < num_msg; i++) {
|
||||
reply[i].resp = NULL;
|
||||
reply[i].resp_retcode = 0;
|
||||
|
||||
switch (msg[i]->msg_style) {
|
||||
case PAM_PROMPT_ECHO_OFF:
|
||||
case PAM_PROMPT_ECHO_ON:
|
||||
reply[i].resp = strdup(conv_data->password);
|
||||
if (!reply[i].resp) {
|
||||
for (int 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;
|
||||
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
|
||||
msg[i]->msg_style == PAM_PROMPT_ECHO_ON) {
|
||||
char* input = (char*)appdata_ptr;
|
||||
reply[i].resp = strdup(input);
|
||||
}
|
||||
}
|
||||
*resp = reply;
|
||||
@@ -171,9 +144,7 @@ int pam_conversation(int num_msg, const struct pam_message** msg,
|
||||
}
|
||||
pam_handle_t* get_pamh(char* user, char* passwd) {
|
||||
pam_handle_t* pamh = NULL;
|
||||
struct pam_conv_data conv_data = {.password = passwd,
|
||||
.display_pam_msg = print_pam_msg};
|
||||
struct pam_conv pamc = {pam_conversation, (void*)&conv_data};
|
||||
struct pam_conv pamc = {pam_conversation, (void*)passwd};
|
||||
int ret;
|
||||
|
||||
char* pam_service_override = getenv("LIDM_PAM_SERVICE");
|
||||
|
||||
@@ -22,19 +22,13 @@ struct source_dir {
|
||||
#ifndef SESSIONS_XSESSIONS
|
||||
#define SESSIONS_XSESSIONS "/usr/share/xsessions"
|
||||
#endif
|
||||
#ifndef SESSIONS_XSESSIONS_LOCAL
|
||||
#define SESSIONS_XSESSIONS_LOCAL "/usr/local/share/xsessions"
|
||||
#endif
|
||||
#ifndef SESSIONS_WAYLAND
|
||||
#define SESSIONS_WAYLAND "/usr/share/wayland-sessions"
|
||||
#endif
|
||||
#ifndef SESSIONS_WAYLAND_LOCAL
|
||||
#define SESSIONS_WAYLAND_LOCAL "/usr/local/share/wayland-sessions"
|
||||
#endif
|
||||
static const struct source_dir SOURCES[] = {{XORG, SESSIONS_XSESSIONS},
|
||||
{XORG, SESSIONS_XSESSIONS_LOCAL},
|
||||
{WAYLAND, SESSIONS_WAYLAND},
|
||||
{WAYLAND, SESSIONS_WAYLAND_LOCAL}};
|
||||
static const struct source_dir SOURCES[] = {
|
||||
{XORG, SESSIONS_XSESSIONS},
|
||||
{WAYLAND, SESSIONS_WAYLAND},
|
||||
};
|
||||
|
||||
static struct Vector* cb_sessions = NULL;
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "signal_handler.h"
|
||||
|
||||
static void handle_sigterm(int sig) {
|
||||
(void)sig;
|
||||
|
||||
(void)signal(SIGTERM, SIG_IGN);
|
||||
kill(-getpgrp(), SIGTERM);
|
||||
|
||||
int status;
|
||||
while (waitpid(-1, &status, 0) > 0 || errno == EINTR) {
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
void setup_sigterm() {
|
||||
setpgid(0, 0);
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handle_sigterm;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
}
|
||||
134
src/ui.c
134
src/ui.c
@@ -5,7 +5,6 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
@@ -67,11 +66,6 @@ static void process_sigwinch(int signal) {
|
||||
need_resize = 1;
|
||||
}
|
||||
|
||||
static inline void draw_bg() {
|
||||
// apply bg color to all screen
|
||||
printf("\x1b[%sm\x1b[2J", g_config->colors.bg);
|
||||
}
|
||||
|
||||
void setup(struct config* config) {
|
||||
g_config = config;
|
||||
|
||||
@@ -81,9 +75,10 @@ void setup(struct config* config) {
|
||||
term.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDOUT_FILENO, TCSANOW, &term);
|
||||
|
||||
// save cursor pos, save screen
|
||||
printf("\x1b[s\x1b[?47h");
|
||||
draw_bg();
|
||||
// save cursor pos, save screen, set color and reset screen
|
||||
// (applying color to all screen)
|
||||
printf("\x1b[s\x1b[?47h\x1b[%s;%sm\x1b[2J", g_config->colors.bg,
|
||||
g_config->colors.fg);
|
||||
|
||||
(void)atexit(restore_all);
|
||||
(void)signal(SIGINT, signal_handler);
|
||||
@@ -116,8 +111,8 @@ static char* fmt_time(const char* fmt) {
|
||||
}
|
||||
}
|
||||
|
||||
char* trunc_gethostname(size_t maxlen, const char* const ELLIPSIS) {
|
||||
if (utf8len(ELLIPSIS) > maxlen) return NULL;
|
||||
char* trunc_gethostname(const size_t MAXLEN, const char* const ELLIPSIS) {
|
||||
if (utf8len(ELLIPSIS) > MAXLEN) return NULL;
|
||||
size_t alloc_size = HOST_NAME_MAX + strlen(ELLIPSIS) + 1;
|
||||
char* buf = malloc(alloc_size);
|
||||
if (!buf) return NULL;
|
||||
@@ -127,8 +122,8 @@ char* trunc_gethostname(size_t maxlen, const char* const ELLIPSIS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (utf8len(buf) > maxlen) {
|
||||
size_t end = utf8trunc(buf, maxlen - utf8len(ELLIPSIS));
|
||||
if (utf8len(buf) > MAXLEN) {
|
||||
size_t end = utf8trunc(buf, MAXLEN - utf8len(ELLIPSIS));
|
||||
strcpy(&buf[end], ELLIPSIS);
|
||||
}
|
||||
return buf;
|
||||
@@ -190,7 +185,6 @@ void ui_update_ofield(struct opts_field* NNULLABLE self) {
|
||||
ui_update_field(input);
|
||||
}
|
||||
|
||||
/// draw everything
|
||||
void scratch_print_ui() {
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &window);
|
||||
box_start = (struct uint_point){
|
||||
@@ -198,16 +192,15 @@ void scratch_print_ui() {
|
||||
.y = ((window.ws_row - BOX_HEIGHT) / 2), // leave more space under
|
||||
};
|
||||
|
||||
if (window.ws_row < BOX_HEIGHT + (INNER_BOX_OUT_MARGIN * 2) ||
|
||||
window.ws_col < BOX_WIDTH + (INNER_BOX_OUT_MARGIN * 2)) {
|
||||
if (window.ws_row < BOX_HEIGHT + INNER_BOX_OUT_MARGIN * 2 ||
|
||||
window.ws_col < BOX_WIDTH + INNER_BOX_OUT_MARGIN * 2) {
|
||||
printf("\033[2J\033[H"); // Clear screen
|
||||
printf("\x1b[1;31mScreen too small\x1b[0m\n");
|
||||
printf("\x1b[%s;%sm\x1b[2J", g_config->colors.bg, g_config->colors.fg);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\033[2J\033[H\033c"); // Clear screen
|
||||
draw_bg();
|
||||
printf("\033[2J\033[H"); // Clear screen
|
||||
|
||||
/// PRINTING
|
||||
// printf box
|
||||
@@ -305,23 +298,6 @@ int load(struct Vector* users, struct Vector* sessions) {
|
||||
restore_all();
|
||||
reboot(RB_POWER_OFF);
|
||||
exit(0);
|
||||
} else if (g_config->functions.fido != NONE &&
|
||||
ansi_key == 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 {
|
||||
scratch_print_ui();
|
||||
}
|
||||
} else if (ansi_key == A_UP || ansi_key == A_DOWN) {
|
||||
st_ch_focus(ansi_key == A_DOWN ? 1 : -1);
|
||||
} else if (ansi_key == A_RIGHT || ansi_key == A_LEFT) {
|
||||
@@ -344,8 +320,6 @@ int load(struct Vector* users, struct Vector* sessions) {
|
||||
&restore_all, g_config)) {
|
||||
print_passwd(utf8len(of_passwd.efield.content), true);
|
||||
ui_update_cursor_focus();
|
||||
} else {
|
||||
scratch_print_ui();
|
||||
}
|
||||
} else
|
||||
st_kbd_type(seq, g_config->behavior.include_defshell);
|
||||
@@ -370,40 +344,25 @@ u_char get_render_pos_offset(struct opts_field* self, u_char maxlen) {
|
||||
return pos - ofield_display_cursor_col(self, maxlen);
|
||||
}
|
||||
|
||||
#define HOSTNAME_SIZE (VALUES_COL - VALUES_SEPR - BOX_HMARGIN - 1)
|
||||
void print_head() {
|
||||
char* fmtd_time = fmt_time(g_config->behavior.timefmt);
|
||||
size_t len_tm = utf8len(fmtd_time);
|
||||
|
||||
// calculate the space available for the host name
|
||||
ssize_t hostname_size = BOX_WIDTH - (BOX_HMARGIN * 2) - len_tm - VALUES_SEPR;
|
||||
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 ssize_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;
|
||||
}
|
||||
// hostname doesn't just change on runtime
|
||||
static char* hostname = NULL;
|
||||
if (!hostname)
|
||||
hostname = trunc_gethostname(HOSTNAME_SIZE, g_config->strings.ellipsis);
|
||||
if (!hostname) hostname = "unknown";
|
||||
|
||||
clean_line(box_start, HEAD_ROW);
|
||||
|
||||
// put hostname
|
||||
if (hostname_size)
|
||||
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm", box_start.x + 1 + BOX_HMARGIN,
|
||||
g_config->colors.e_hostname, hostname ? hostname : "unknown",
|
||||
g_config->colors.fg);
|
||||
printf("\x1b[%dG\x1b[%sm%s\x1b[%sm",
|
||||
box_start.x + VALUES_COL - VALUES_SEPR - (uint)utf8len(hostname),
|
||||
g_config->colors.e_hostname, hostname, g_config->colors.fg);
|
||||
|
||||
// put date
|
||||
char* fmtd_time = fmt_time(g_config->behavior.timefmt);
|
||||
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);
|
||||
|
||||
free(fmtd_time);
|
||||
}
|
||||
|
||||
@@ -538,8 +497,6 @@ static void print_box() {
|
||||
}
|
||||
|
||||
static void print_footer() {
|
||||
bool fido_enabled = g_config->functions.fido != NONE;
|
||||
|
||||
size_t bsize = utf8len(g_config->strings.f_poweroff) +
|
||||
utf8len(KEY_NAMES[g_config->functions.poweroff]) +
|
||||
utf8len(g_config->strings.f_reboot) +
|
||||
@@ -547,31 +504,19 @@ static void print_footer() {
|
||||
utf8len(g_config->strings.f_refresh) +
|
||||
utf8len(KEY_NAMES[g_config->functions.refresh]);
|
||||
|
||||
bsize += (2 * 2) + (3 * 1);
|
||||
|
||||
if (fido_enabled) {
|
||||
bsize += utf8len(g_config->strings.f_fido) +
|
||||
utf8len(KEY_NAMES[g_config->functions.fido]) + 2 + 1;
|
||||
}
|
||||
bsize += 2 * 2 + // 2 wide separators between 3 items
|
||||
3 * 1; // 3 thin separators inside every item
|
||||
|
||||
uint row = window.ws_row - 1;
|
||||
uint col = window.ws_col - 2 - bsize;
|
||||
|
||||
printf("\x1b[%d;%dH%s \x1b[%sm%s\x1b[%sm %s \x1b[%sm%s\x1b[%sm ", row, col,
|
||||
g_config->strings.f_poweroff, g_config->colors.e_key,
|
||||
KEY_NAMES[g_config->functions.poweroff], g_config->colors.fg,
|
||||
g_config->strings.f_reboot, g_config->colors.e_key,
|
||||
KEY_NAMES[g_config->functions.reboot], g_config->colors.fg);
|
||||
|
||||
if (fido_enabled) {
|
||||
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);
|
||||
printf(
|
||||
"\x1b[%3$d;%4$dH%8$s \x1b[%1$sm%5$s\x1b[%2$sm %9$s "
|
||||
"\x1b[%1$sm%6$s\x1b[%2$sm %10$s \x1b[%1$sm%7$s\x1b[%2$sm",
|
||||
g_config->colors.e_key, g_config->colors.fg, row, col,
|
||||
KEY_NAMES[g_config->functions.poweroff],
|
||||
KEY_NAMES[g_config->functions.reboot],
|
||||
KEY_NAMES[g_config->functions.refresh], g_config->strings.f_poweroff,
|
||||
g_config->strings.f_reboot, g_config->strings.f_refresh);
|
||||
}
|
||||
|
||||
void print_err(const char* msg) {
|
||||
@@ -579,21 +524,6 @@ void print_err(const char* msg) {
|
||||
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) {
|
||||
if (descr == NULL)
|
||||
(void)fprintf(stderr, "\x1b[%d;%dH\x1b[%smunknown error(%d): %s",
|
||||
|
||||
@@ -25,13 +25,11 @@
|
||||
[functions]
|
||||
# poweroff = F1
|
||||
# reboot = F2
|
||||
# fido = NONE
|
||||
# refresh = F5
|
||||
|
||||
[strings]
|
||||
# f_poweroff = "poweroff"
|
||||
# f_reboot = "reboot"
|
||||
# f_fido = "fido"
|
||||
# f_refresh = "refresh"
|
||||
# e_user = "user"
|
||||
# e_passwd = "password"
|
||||
|
||||
Reference in New Issue
Block a user