mirror of
https://github.com/javalsai/lidm.git
synced 2025-08-30 18:08:00 +02:00
Compare commits
10 Commits
947c92ce3f
...
support-xo
Author | SHA1 | Date | |
---|---|---|---|
570a68c586
|
|||
ff3e58ee5b
|
|||
109c9bd0be
|
|||
056ec64bcb
|
|||
b58bd50e64
|
|||
6d9107b360
|
|||
b56aa19671
|
|||
ddc38ef27f
|
|||
|
b3c8d3cbea | ||
5761838112 |
34
.clang-tidy
34
.clang-tidy
@@ -16,32 +16,34 @@ Checks: >
|
||||
readability-*,
|
||||
-readability-braces-around-statements,
|
||||
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: '.*'
|
||||
WarningsAsErrors: ""
|
||||
HeaderFilterRegex: ".*"
|
||||
FormatStyle: file
|
||||
|
||||
CheckOptions:
|
||||
- key: readability-magic-numbers.IgnoredIntegerValues
|
||||
value: '0;1;2;3;10;255'
|
||||
# - key: readability-magic-numbers.IgnoredValues
|
||||
# value: '0;1;2;3;10;255'
|
||||
- key: readability-identifier-naming.VariableCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.ConstantParameterCase
|
||||
value: UPPER_CASE
|
||||
- key: readability-magic-numbers.IgnoredIntegerValues
|
||||
value: "0;1;2;3;10;255"
|
||||
- key: readability-identifier-naming.VariableCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.ConstantParameterCase
|
||||
value: UPPER_CASE
|
||||
|
||||
- key: readability-identifier-naming.ConstantCase
|
||||
value: "UPPER_CASE"
|
||||
- key: readability-identifier-naming.EnumCase
|
||||
value: "CamelCase"
|
||||
- key: readability-identifier-naming.FunctionCase
|
||||
value: "lower_case"
|
||||
|
||||
- key: readability-identifier-length.VariableThreshold
|
||||
value: '2'
|
||||
value: "2"
|
||||
- key: readability-identifier-length.ParameterThreshold
|
||||
value: '2'
|
||||
value: "2"
|
||||
- key: readability-identifier-length.LocalConstantThreshold
|
||||
value: '2'
|
||||
value: "2"
|
||||
- key: readability-identifier-length.MemberThreshold
|
||||
value: '2'
|
||||
value: "2"
|
||||
- key: readability-identifier-length.MinimumParameterNameLength
|
||||
value: '2'
|
||||
value: "2"
|
||||
- key: readability-identifier-length.MinimumVariableNameLength
|
||||
value: '2'
|
||||
value: "2"
|
||||
|
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@@ -132,6 +132,7 @@ jobs:
|
||||
path: lidm-riscv64
|
||||
retention-days: 1
|
||||
|
||||
# This build job is only symbolic, the behavior of the packaged Void Linux version may differ.
|
||||
build-linux-amd64-musl:
|
||||
name: amd64-musl
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -147,7 +148,7 @@ jobs:
|
||||
run: |
|
||||
cd /workspace
|
||||
|
||||
xbps-install -Sy
|
||||
xbps-install -Syu xbps && xbps-install -yu
|
||||
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
|
||||
|
2
.github/workflows/check.yml
vendored
2
.github/workflows/check.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
with:
|
||||
packages: "shellcheck"
|
||||
version: 1.0
|
||||
- run: find . -type f -name '*.sh' -not -path './assets/pkg/aur/*/src/*' | xargs shellcheck
|
||||
- run: git ls-files "*.sh" "*/PKGBUILD" | xargs shellcheck --shell=bash
|
||||
|
||||
clangcheck:
|
||||
name: Clang
|
||||
|
26
Makefile
26
Makefile
@@ -9,27 +9,29 @@ ODIR=dist
|
||||
PREFIX=/usr
|
||||
|
||||
CC?=gcc
|
||||
CFLAGS?=-O3 -Wall
|
||||
CFLAGS?=-O3 -Wall -Wextra -fdata-sections -ffunction-sections
|
||||
# C PreProcessor flags, not C Plus Plus
|
||||
CPPFLAGS?=
|
||||
ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR)
|
||||
LDFLAGS?=-Wl,--gc-sections
|
||||
|
||||
LIBS=-lpam
|
||||
|
||||
_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 = 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 desktop.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 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))
|
||||
|
||||
.git/HEAD:
|
||||
INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?')
|
||||
INFO_BUILD_TS?=$$(date +%s)
|
||||
|
||||
$(IDIR)/version.h: Makefile .git/HEAD
|
||||
$(IDIR)/version.h: Makefile
|
||||
@tmp=$$(mktemp); \
|
||||
printf '' > $$tmp; \
|
||||
echo '#define LIDM_VERSION "'$(VERSION)'"' >> $$tmp; \
|
||||
echo '#define LIDM_GIT_REV "'$$(git describe --long --tags --always || echo '?')'"' >> $$tmp; \
|
||||
echo '#define LIDM_BUILD_TS '$$(date +%s) >> $$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; \
|
||||
@@ -40,7 +42,7 @@ $(ODIR)/%.o: $(CDIR)/%.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(ALLFLAGS)
|
||||
|
||||
lidm: $(OBJ)
|
||||
$(CC) -o $@ $^ $(ALLFLAGS) $(LIBS)
|
||||
$(CC) -o $@ $^ $(ALLFLAGS) $(LIBS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f $(ODIR)/*.o lidm
|
||||
@@ -133,10 +135,12 @@ install-service-s6-etc:
|
||||
|
||||
pre-commit:
|
||||
codespell
|
||||
prettier --write "**/*.md"
|
||||
find . -type f -name '*.sh' -not -path './assets/pkg/aur/*/src/*' | xargs shellcheck
|
||||
prettier -c "**/*.md"
|
||||
git ls-files "*.sh" "*/PKGBUILD" | xargs shellcheck --shell=bash
|
||||
clang-format -i $$(git ls-files "*.c" "*.h")
|
||||
clang-tidy -p . $$(git ls-files "*.c" "*.h")
|
||||
git ls-files -z "*.c" "*.h" | \
|
||||
parallel -j$$(nproc) -q0 --no-notice --will-cite --tty clang-tidy -warnings-as-errors=\* --quiet |& \
|
||||
grep -v "warnings generated." || true
|
||||
|
||||
print-version:
|
||||
@echo $(VERSION)
|
||||
|
@@ -1,20 +1,32 @@
|
||||
pkgbase = lidm-bin
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (release binary)
|
||||
pkgver = 1.2.3
|
||||
pkgrel = 1
|
||||
pkgrel = 3
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = x86_64
|
||||
arch = i686
|
||||
arch = aarch64
|
||||
arch = armv7h
|
||||
arch = riscv64
|
||||
license = GPL
|
||||
depends = pam
|
||||
depends = libpam.so
|
||||
provides = lidm
|
||||
conflicts = lidm
|
||||
source = lidm::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-amd64
|
||||
source = default-theme.ini::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/themes/default.ini
|
||||
source = lidm.1::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm.1
|
||||
source = lidm-config.5::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm-config.5
|
||||
sha256sums = a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b
|
||||
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://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm.1
|
||||
source = lidm-config-1.2.3.5::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm-config.5
|
||||
sha256sums = ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca
|
||||
sha256sums = 7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8
|
||||
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
|
||||
|
@@ -1,29 +1,39 @@
|
||||
# shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
|
||||
# shellcheck disable=SC2034,SC2154,SC2164
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm-bin
|
||||
pkgver=1.2.3
|
||||
pkgrel=1
|
||||
depends=('pam')
|
||||
pkgrel=3
|
||||
depends=('libpam.so')
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (release binary)"
|
||||
arch=('x86_64')
|
||||
arch=('x86_64' 'i686' 'aarch64' 'armv7h' 'riscv64')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
license=('GPL')
|
||||
provides=('lidm')
|
||||
conflicts=('lidm')
|
||||
source=(
|
||||
"lidm::$url/releases/download/v$pkgver/lidm-amd64"
|
||||
"default-theme.ini::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/themes/default.ini"
|
||||
"lidm.1::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm.1"
|
||||
"lidm-config.5::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm-config.5"
|
||||
"lidm-default-theme-${pkgver}.ini::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/themes/default.ini"
|
||||
"lidm-${pkgver}.1::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm.1"
|
||||
"lidm-config-${pkgver}.5::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm-config.5"
|
||||
)
|
||||
sha256sums=('a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b'
|
||||
'ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca'
|
||||
source_x86_64=("lidm-${pkgver}-x86_64::$url/releases/download/v$pkgver/lidm-amd64")
|
||||
source_i686=("lidm-${pkgver}-i686::$url/releases/download/v$pkgver/lidm-i386")
|
||||
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'
|
||||
'0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9')
|
||||
sha256sums_x86_64=('a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b')
|
||||
sha256sums_i686=('75018578e68bffda9807de8a65e16eaed8a16c6cf2417a0b58c5d5bcfa603e45')
|
||||
sha256sums_aarch64=('1b81a1537a1e31ca1902cbc3b60add4ac712aa64fd4d266685f53372cc365882')
|
||||
sha256sums_armv7h=('e86f59509fe2366d6312b9bc9e8d89c14e9c049fd713a04c41dab49a848b1ada')
|
||||
sha256sums_riscv64=('3f0eb0315c523d367bac332641e5cd3c86cfd9aa4e7c14b2efc036937b97a598')
|
||||
|
||||
package() {
|
||||
install -Dm755 lidm "${pkgdir}/usr/bin/lidm"
|
||||
install -Dm644 default-theme.ini "${pkgdir}/etc/lidm.ini"
|
||||
install -Dm644 lidm.1 "${pkgdir}/usr/share/man/man1/lidm.1"
|
||||
install -Dm644 lidm-config.5 "${pkgdir}/usr/share/man/man5/lidm-config.5"
|
||||
cd "$srcdir"
|
||||
|
||||
install -Dm755 "lidm-${pkgver}-$CARCH" "${pkgdir}/usr/bin/lidm"
|
||||
install -Dm644 "lidm-default-theme-${pkgver}.ini" "${pkgdir}/etc/lidm.ini"
|
||||
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"
|
||||
}
|
||||
|
@@ -1,13 +1,11 @@
|
||||
pkgbase = lidm-git
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (last git commit)
|
||||
pkgver = 0.1.0.r0.g8071694
|
||||
pkgrel = 1
|
||||
pkgver = 1.2.3.r3.g363deea
|
||||
pkgrel = 3
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = any
|
||||
license = GPL
|
||||
makedepends = git
|
||||
makedepends = make
|
||||
makedepends = gcc
|
||||
depends = pam
|
||||
provides = lidm
|
||||
conflicts = lidm
|
||||
|
@@ -1,10 +1,10 @@
|
||||
# shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
|
||||
# shellcheck disable=SC2034,SC2154,SC2164
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm-git
|
||||
pkgver=1.2.3.r0.g7e1ec83
|
||||
pkgrel=1
|
||||
pkgver=1.2.3.r3.g363deea
|
||||
pkgrel=3
|
||||
depends=('pam')
|
||||
makedepends=('git' 'make' 'gcc')
|
||||
makedepends=('git')
|
||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (last git commit)"
|
||||
arch=('any')
|
||||
url="https://github.com/javalsai/lidm"
|
||||
@@ -15,17 +15,17 @@ source=("lidm::git+https://github.com/javalsai/lidm")
|
||||
sha256sums=('SKIP')
|
||||
|
||||
pkgver() {
|
||||
cd "lidm"
|
||||
cd "$srcdir/lidm"
|
||||
git describe --long --abbrev=7 --tags | \
|
||||
sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "lidm"
|
||||
make CFLAGS="-O3"
|
||||
cd "$srcdir/lidm"
|
||||
make
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "lidm"
|
||||
make install DESTDIR="${pkgdir}"
|
||||
cd "$srcdir/lidm"
|
||||
make DESTDIR="${pkgdir}" install
|
||||
}
|
||||
|
@@ -1,14 +1,12 @@
|
||||
pkgbase = lidm
|
||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (build latest tag)
|
||||
pkgver = 1.2.3
|
||||
pkgrel = 1
|
||||
pkgrel = 3
|
||||
url = https://github.com/javalsai/lidm
|
||||
arch = any
|
||||
license = GPL
|
||||
makedepends = git
|
||||
makedepends = gcc
|
||||
depends = pam
|
||||
source = tarball.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.3.tar.gz
|
||||
source = lidm-1.2.3.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.3.tar.gz
|
||||
sha256sums = 1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93
|
||||
|
||||
pkgname = lidm
|
||||
|
@@ -1,25 +1,21 @@
|
||||
# shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
|
||||
# shellcheck disable=SC2034,SC2154,SC2164
|
||||
# Maintainer: javalsai <javalsai@proton.me>
|
||||
pkgname=lidm
|
||||
pkgver=1.2.3
|
||||
pkgrel=1
|
||||
pkgrel=3
|
||||
depends=('pam')
|
||||
makedepends=('git' 'gcc')
|
||||
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')
|
||||
source=("tarball.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v$pkgver.tar.gz")
|
||||
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v$pkgver.tar.gz")
|
||||
sha256sums=('1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93')
|
||||
|
||||
build() {
|
||||
tar -xzf "tarball.tar.gz"
|
||||
cd "lidm-$pkgver"
|
||||
|
||||
make CFLAGS="-O3"
|
||||
make -C "$srcdir/lidm-$pkgver"
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "lidm-$pkgver"
|
||||
make install DESTDIR="${pkgdir}"
|
||||
make -C "$srcdir/lidm-$pkgver" DESTDIR="$pkgdir" install
|
||||
}
|
||||
|
22
assets/pkg/aur/makepkg-clean.sh
Executable file
22
assets/pkg/aur/makepkg-clean.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/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
|
@@ -4,18 +4,19 @@ set -e
|
||||
MYSELF=$(realpath "$0")
|
||||
MYDIR=$(dirname "$MYSELF")
|
||||
|
||||
for pkg in "$MYDIR"/*/; do
|
||||
printf "\x1b[1mEntering '%s'\x1b[0m\n" "$pkg"
|
||||
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"
|
||||
for source in "${source[@]}"; do
|
||||
awk -F'::' '{print $1}' <<<"$source" | xargs rm -rf
|
||||
done
|
||||
|
||||
rm -rf ./*.{gz,zst} src pkg
|
||||
makepkg -f .
|
||||
|
||||
makepkg -Cf
|
||||
cd ..
|
||||
echo
|
||||
done
|
||||
|
||||
if [[ -n "${PRINT_TREE:-}" ]]; then
|
||||
for pkg in "${pkgs[@]}"; do
|
||||
eza --tree "$pkg/pkg/"*
|
||||
done
|
||||
fi
|
||||
|
@@ -17,12 +17,6 @@ for pkg in "$MYDIR"/lidm{,-bin}/; do
|
||||
sed -i "s/pkgver=.*/pkgver=$1/" PKGBUILD
|
||||
sed -i "s/pkgrel=.*/pkgrel=1/" PKGBUILD
|
||||
|
||||
grep 'source = ' <.SRCINFO | awk -F'= |::' '{print $2}' | \
|
||||
while read -r srcfile; do
|
||||
printf "\x1b[31mDeleting '%s'\x1b[0m\n" "$srcfile"
|
||||
rm -f "$srcfile"
|
||||
done
|
||||
|
||||
updpkgsums
|
||||
makepkg --printsrcinfo | tee .SRCINFO
|
||||
echo
|
||||
|
@@ -38,6 +38,17 @@ Lidm attempts to support being built by `gcc` and `clang` with preference over t
|
||||
|
||||
Compiler flags should be passed with `CFLAGS`, its `-O3 -Wall` by default so adding anything will overwrite this.
|
||||
|
||||
## Build Metadata
|
||||
|
||||
`lidm -v` outputs some information about the build version, this can be weaked with `INFO_GIT_REV` and `INFO_BUILD_TS`, by default they are:
|
||||
|
||||
```make
|
||||
INFO_GIT_REV?=$$(git describe --long --tags --always || echo '?')
|
||||
INFO_BUILD_TS?=$$(date +%s)
|
||||
```
|
||||
|
||||
But this can be changed by just passing those env variables, for example, in the case git is not applicable in the build environment of the package.
|
||||
|
||||
## Target Directory
|
||||
|
||||
`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=`
|
||||
|
@@ -6,7 +6,8 @@
|
||||
#include "config.h"
|
||||
#include "sessions.h"
|
||||
|
||||
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||
struct config* config);
|
||||
bool launch(char* NNULLABLE user, char* NNULLABLE passwd,
|
||||
struct session session, void (*NULLABLE cb)(void),
|
||||
struct config* NNULLABLE config);
|
||||
|
||||
#endif
|
||||
|
@@ -8,7 +8,7 @@
|
||||
#include "macros.h"
|
||||
#include "util.h"
|
||||
|
||||
enum introspection_type {
|
||||
enum IntrospectionType {
|
||||
STRING,
|
||||
BOOL,
|
||||
NUMBER,
|
||||
@@ -26,7 +26,7 @@ static const char* NNULLABLE const INTROS_TYS_NAMES[] = {
|
||||
struct introspection_item {
|
||||
char* NNULLABLE name;
|
||||
size_t offset;
|
||||
enum introspection_type typ;
|
||||
enum IntrospectionType typ;
|
||||
};
|
||||
|
||||
#define INTROS_ITEM(key, table, ty) \
|
||||
@@ -90,9 +90,9 @@ BUILD(colors, COLORS, TABLE_COLORS);
|
||||
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, refresh, KEY, F5, name)
|
||||
F(enum Keys, poweroff, KEY, F1, name) \
|
||||
F(enum Keys, reboot, KEY, F2, name) \
|
||||
F(enum Keys, refresh, KEY, F5, name)
|
||||
|
||||
BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
|
||||
|
||||
@@ -150,15 +150,15 @@ struct introspection_table {
|
||||
|
||||
static const struct introspection_table CONFIG_INSTROSPECTION[] = {
|
||||
{"colors", offsetof(struct config, colors), INTROS_TABLE_COLORS,
|
||||
sizeof(INTROS_TABLE_COLORS) / sizeof(INTROS_TABLE_COLORS[0])},
|
||||
LEN(INTROS_TABLE_COLORS)},
|
||||
{"chars", offsetof(struct config, chars), INTROS_TABLE_CHARS,
|
||||
sizeof(INTROS_TABLE_CHARS) / sizeof(INTROS_TABLE_CHARS[0])},
|
||||
LEN(INTROS_TABLE_CHARS)},
|
||||
{"functions", offsetof(struct config, functions), INTROS_TABLE_FUNCTIONS,
|
||||
sizeof(INTROS_TABLE_FUNCTIONS) / sizeof(INTROS_TABLE_FUNCTIONS[0])},
|
||||
LEN(INTROS_TABLE_FUNCTIONS)},
|
||||
{"strings", offsetof(struct config, strings), INTROS_TABLE_STRINGS,
|
||||
sizeof(INTROS_TABLE_STRINGS) / sizeof(INTROS_TABLE_STRINGS[0])},
|
||||
LEN(INTROS_TABLE_STRINGS)},
|
||||
{"behavior", offsetof(struct config, behavior), INTROS_TABLE_BEHAVIOR,
|
||||
sizeof(INTROS_TABLE_BEHAVIOR) / sizeof(INTROS_TABLE_BEHAVIOR[0])},
|
||||
LEN(INTROS_TABLE_BEHAVIOR)},
|
||||
};
|
||||
|
||||
//// FUNCTIONS
|
||||
|
7
include/desktop_exec.h
Normal file
7
include/desktop_exec.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#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
|
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
enum keys {
|
||||
enum Keys {
|
||||
ESC,
|
||||
F1,
|
||||
F2,
|
||||
@@ -66,7 +66,7 @@ static const char* const KEY_NAMES[] = {
|
||||
};
|
||||
|
||||
struct key_mapping {
|
||||
enum keys key;
|
||||
enum Keys key;
|
||||
const char* sequences[3];
|
||||
};
|
||||
|
||||
|
@@ -36,5 +36,6 @@
|
||||
#endif
|
||||
|
||||
#define LEN(X) (sizeof(X) / sizeof((X)[0]))
|
||||
#define UNUSED(x) ((void)(x))
|
||||
|
||||
#endif
|
||||
|
33
include/pam.h
Normal file
33
include/pam.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef PAM_H
|
||||
#define PAM_H
|
||||
|
||||
#include <pwd.h>
|
||||
#include <security/_pam_types.h>
|
||||
#include <security/pam_appl.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "macros.h"
|
||||
#include "sessions.h"
|
||||
|
||||
#define PAMH_ERR_NOERR 0
|
||||
#define PAMH_ERR_ALLOC 1
|
||||
#define PAMH_ERR_ERRNO 2
|
||||
#define PAMH_ERR_NOERRNO 3
|
||||
|
||||
struct pamh_getenv_status {
|
||||
char error_flag;
|
||||
union {
|
||||
char* NULLABLE* NNULLABLE envlist;
|
||||
const char* NNULLABLE errfn;
|
||||
};
|
||||
};
|
||||
|
||||
// Doesn't include `source`s
|
||||
struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* NNULLABLE handle,
|
||||
struct passwd* NNULLABLE pw,
|
||||
enum SessionType session_typ);
|
||||
|
||||
void free_envlist(char* NULLABLE* NNULLABLE envlist);
|
||||
pam_handle_t* NULLABLE get_pamh(char* NNULLABLE user, char* NNULLABLE passwd);
|
||||
|
||||
#endif /* PAM_H */
|
@@ -2,21 +2,70 @@
|
||||
#define SESSIONSH_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "macros.h"
|
||||
#include "util.h"
|
||||
|
||||
enum session_type {
|
||||
enum SessionType {
|
||||
XORG,
|
||||
WAYLAND,
|
||||
SHELL,
|
||||
};
|
||||
|
||||
enum ExecType {
|
||||
EXEC_SHELL,
|
||||
EXEC_DESKTOP,
|
||||
};
|
||||
|
||||
struct desktop_exec {
|
||||
char* NULLABLE* NNULLABLE args;
|
||||
int arg_count;
|
||||
};
|
||||
|
||||
struct session_exec {
|
||||
enum ExecType typ;
|
||||
union {
|
||||
char* NNULLABLE shell;
|
||||
struct desktop_exec desktop;
|
||||
};
|
||||
};
|
||||
|
||||
static inline struct session_exec session_exec_shell(char* NNULLABLE shell) {
|
||||
return (struct session_exec){
|
||||
.typ = EXEC_SHELL,
|
||||
.shell = shell,
|
||||
};
|
||||
}
|
||||
|
||||
static inline struct session_exec session_exec_desktop(
|
||||
int arg_count, char* NULLABLE* NNULLABLE args) {
|
||||
return (struct session_exec){
|
||||
.typ = EXEC_DESKTOP,
|
||||
.desktop =
|
||||
{
|
||||
.args = args,
|
||||
.arg_count = arg_count,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static inline int session_exec_exec(struct session_exec* NNULLABLE exec,
|
||||
char* NULLABLE* NNULLABLE envlist) {
|
||||
switch (exec->typ) {
|
||||
case EXEC_SHELL:
|
||||
return execle(exec->shell, exec->shell, NULL, envlist);
|
||||
case EXEC_DESKTOP:
|
||||
return execve(exec->desktop.args[0], exec->desktop.args, envlist);
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
struct session {
|
||||
char* NNULLABLE name;
|
||||
char* NNULLABLE exec;
|
||||
char* NULLABLE tryexec;
|
||||
enum session_type type;
|
||||
struct session_exec exec;
|
||||
enum SessionType type;
|
||||
};
|
||||
|
||||
struct Vector get_avaliable_sessions();
|
||||
|
@@ -39,7 +39,7 @@
|
||||
#define VALUES_SEPR 3
|
||||
#define VALUE_MAXLEN (BOX_WIDTH - VALUES_COL + 1 - BOX_HMARGIN - 2)
|
||||
|
||||
enum input { SESSION, USER, PASSWD };
|
||||
enum Input { SESSION, USER, PASSWD };
|
||||
extern const u_char INPUTS_N;
|
||||
|
||||
void setup(struct config* config);
|
||||
@@ -47,7 +47,7 @@ int load(struct Vector* users, struct Vector* sessions);
|
||||
void print_err(const char* /*msg*/);
|
||||
void print_errno(const char* /*descr*/);
|
||||
|
||||
void ui_update_field(enum input focused_input);
|
||||
void ui_update_field(enum Input focused_input);
|
||||
void ui_update_ffield();
|
||||
void ui_update_ofield(struct opts_field* self);
|
||||
void ui_update_cursor_focus();
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#include "macros.h"
|
||||
#include "ui.h"
|
||||
|
||||
extern enum input focused_input;
|
||||
extern enum Input focused_input;
|
||||
|
||||
extern struct opts_field of_session;
|
||||
extern struct opts_field of_user;
|
||||
@@ -15,7 +15,7 @@ extern struct opts_field of_passwd;
|
||||
extern struct Vector* UNULLABLE gusers;
|
||||
extern struct Vector* UNULLABLE gsessions;
|
||||
|
||||
struct opts_field* NNULLABLE get_opts_field(enum input from);
|
||||
struct opts_field* NNULLABLE get_opts_field(enum Input from);
|
||||
struct opts_field* NNULLABLE get_opts_ffield();
|
||||
|
||||
struct user st_user();
|
||||
|
@@ -10,12 +10,18 @@
|
||||
|
||||
#include "keys.h"
|
||||
|
||||
int find_keyname(enum keys* at, const char* name);
|
||||
enum keys find_ansi(const char* seq);
|
||||
int find_keyname(enum Keys* at, const char* name);
|
||||
struct option_keys {
|
||||
bool is_some;
|
||||
enum Keys key;
|
||||
};
|
||||
struct option_keys find_ansi(const char* seq);
|
||||
void read_press(u_char* length, char* out);
|
||||
// non blocking, waits up to tv or interrupt, returns true if actually read
|
||||
bool read_press_nb(u_char* length, char* out, struct timeval* tv);
|
||||
|
||||
// UTF8
|
||||
//
|
||||
bool utf8_iscont(char byte);
|
||||
size_t utf8len(const char* str);
|
||||
size_t utf8len_until(const char* str, const char* until);
|
||||
@@ -24,12 +30,16 @@ const char* utf8back(const char* str);
|
||||
const char* utf8seek(const char* str);
|
||||
const char* utf8seekn(const char* str, size_t n);
|
||||
|
||||
// Vector
|
||||
//
|
||||
struct Vector {
|
||||
uint32_t length;
|
||||
uint32_t capacity;
|
||||
void** pages;
|
||||
};
|
||||
|
||||
struct Vector vec_from_raw(void** raw);
|
||||
void** vec_as_raw(struct Vector self);
|
||||
extern const struct Vector VEC_NEW;
|
||||
int vec_resize(struct Vector* self, size_t size);
|
||||
int vec_reserve(struct Vector* self, size_t size);
|
||||
|
329
src/auth.c
329
src/auth.c
@@ -1,3 +1,4 @@
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <security/pam_misc.h>
|
||||
@@ -7,77 +8,24 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "auth.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "pam.h"
|
||||
#include "sessions.h"
|
||||
#include "ui.h"
|
||||
#include "unistd.h"
|
||||
#include "util.h"
|
||||
|
||||
int pam_conversation(int num_msg, const struct pam_message** msg,
|
||||
struct pam_response** resp, void* appdata_ptr) {
|
||||
struct pam_response* reply =
|
||||
(struct pam_response*)malloc(sizeof(struct pam_response) * num_msg);
|
||||
if (!reply) {
|
||||
return PAM_BUF_ERR;
|
||||
static void try_source_file(struct Vector* NNULLABLE vec_envlist,
|
||||
char* NNULLABLE filepath) {
|
||||
log_printf("sourcing %s\n", filepath);
|
||||
FILE* file2source = fopen(filepath, "r");
|
||||
if (file2source == NULL) {
|
||||
log_printf("error sourcing %s\n", filepath);
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < num_msg; i++) {
|
||||
reply[i].resp = NULL;
|
||||
reply[i].resp_retcode = 0;
|
||||
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;
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef PAM_SERVICE_FALLBACK
|
||||
#define PAM_SERVICE_FALLBACK "login"
|
||||
#endif
|
||||
|
||||
#define CHECK_PAM_RET(call) \
|
||||
ret = (call); \
|
||||
if (ret != PAM_SUCCESS) { \
|
||||
pam_end(pamh, ret); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
printf("\x1b[H\x1b[J");
|
||||
}
|
||||
|
||||
pam_handle_t* get_pamh(char* user, char* passwd) {
|
||||
pam_handle_t* pamh = NULL;
|
||||
struct pam_conv pamc = {pam_conversation, (void*)passwd};
|
||||
int ret;
|
||||
|
||||
char* pam_service_override = getenv("LIDM_PAM_SERVICE");
|
||||
char* pam_service_name =
|
||||
pam_service_override ? pam_service_override : PAM_SERVICE_FALLBACK;
|
||||
|
||||
CHECK_PAM_RET(pam_start(pam_service_name, user, &pamc, &pamh))
|
||||
CHECK_PAM_RET(pam_authenticate(pamh, 0))
|
||||
CHECK_PAM_RET(pam_acct_mgmt(pamh, 0))
|
||||
CHECK_PAM_RET(pam_setcred(pamh, PAM_ESTABLISH_CRED))
|
||||
CHECK_PAM_RET(pam_open_session(pamh, 0))
|
||||
CHECK_PAM_RET(pam_setcred(pamh, PAM_REINITIALIZE_CRED))
|
||||
|
||||
return pamh;
|
||||
}
|
||||
#undef CHECK_PAM_RET
|
||||
|
||||
void* shmalloc(size_t size) {
|
||||
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
|
||||
-1, 0);
|
||||
}
|
||||
|
||||
void sourceFileTry(char* file) {
|
||||
FILE* file2source = fopen(file, "r");
|
||||
if (file2source == NULL) return;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
@@ -87,13 +35,10 @@ void sourceFileTry(char* file) {
|
||||
if (read == 0 || (read > 0 && *line == '#')) continue;
|
||||
if (line[read - 1] == '\n') line[read - 1] = '\0';
|
||||
|
||||
/* printf("Retrieved line of length %zu:\n", read); */
|
||||
/* printf("%s\n", line); */
|
||||
for (size_t i = 1; i < read; i++) {
|
||||
for (ssize_t i = 1; i < read; i++) {
|
||||
if (line[i] == '=') {
|
||||
/* printf("FOUND '='!\n"); */
|
||||
line[i] = '\0';
|
||||
setenv(line, &line[i + 1], 1);
|
||||
vec_push(vec_envlist, (void*)line);
|
||||
line = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -103,66 +48,89 @@ void sourceFileTry(char* file) {
|
||||
(void)fclose(file2source);
|
||||
}
|
||||
|
||||
void moarEnv(char* user, struct session session, struct passwd* pw,
|
||||
struct config* config) {
|
||||
if (chdir(pw->pw_dir) == -1) print_errno("can't chdir to user home");
|
||||
|
||||
setenv("HOME", pw->pw_dir, true);
|
||||
setenv("USER", pw->pw_name, true);
|
||||
setenv("SHELL", pw->pw_shell, true);
|
||||
// TERM
|
||||
setenv("LOGNAME", pw->pw_name, true);
|
||||
// MAIL?
|
||||
|
||||
// PATH?
|
||||
|
||||
char* xdg_session_type = "unknown";
|
||||
if (session.type == SHELL) xdg_session_type = "tty";
|
||||
if (session.type == XORG) xdg_session_type = "x11";
|
||||
if (session.type == WAYLAND) xdg_session_type = "wayland";
|
||||
setenv("XDG_SESSION_TYPE", xdg_session_type, true);
|
||||
|
||||
printf("\n\n\n\n\x1b[1m");
|
||||
for (size_t i = 0; i < config->behavior.source.length; i++) {
|
||||
/* printf("DEBUG(source)!!!! %d %s\n", i, (char*)vec_get(&behavior->source,
|
||||
* i)); */
|
||||
sourceFileTry((char*)vec_get(&config->behavior.source, i));
|
||||
static void source_paths(struct Vector* NNULLABLE vec_envlist,
|
||||
struct Vector* NNULLABLE abs_source,
|
||||
const char* NULLABLE user_home,
|
||||
struct Vector* NNULLABLE user_source) {
|
||||
for (size_t i = 0; i < abs_source->length; i++) {
|
||||
char* path = vec_get(abs_source, i);
|
||||
try_source_file(vec_envlist, path);
|
||||
}
|
||||
/* printf("\n"); */
|
||||
|
||||
if (pw->pw_dir) {
|
||||
const char* home = pw->pw_dir;
|
||||
size_t home_len = strlen(home);
|
||||
|
||||
for (size_t i = 0; i < config->behavior.user_source.length; i++) {
|
||||
const char* filename = (char*)vec_get(&config->behavior.user_source, i);
|
||||
size_t filename_len = strlen(filename);
|
||||
|
||||
size_t path_len = home_len + 1 + filename_len + 1; // nullbyte and slash
|
||||
char* path = malloc(path_len);
|
||||
if (!path) continue; // can't bother
|
||||
|
||||
memcpy(path, home, home_len);
|
||||
path[home_len] = '/'; // assume pw_dir doesn't start with '/' :P
|
||||
memcpy(&path[home_len + 1], filename, filename_len);
|
||||
path[path_len - 1] = '\0';
|
||||
|
||||
sourceFileTry(path);
|
||||
if (user_home)
|
||||
for (size_t i = 0; i < user_source->length; i++) {
|
||||
char* path = NULL;
|
||||
asprintf(&path, "%s/%s", user_home, (char*)vec_get(user_source, i));
|
||||
if (!path) {
|
||||
log_puts("alloc failure on user source\n");
|
||||
continue;
|
||||
}
|
||||
try_source_file(vec_envlist, path);
|
||||
free(path);
|
||||
}
|
||||
else {
|
||||
log_puts("user has no home\n");
|
||||
}
|
||||
|
||||
/*char *buf;*/
|
||||
/*size_t bsize = snprintf(NULL, 0, "/run/user/%d", pw->pw_uid) + 1;*/
|
||||
/*buf = malloc(bsize);*/
|
||||
/*snprintf(buf, bsize, "/run/user/%d", pw->pw_uid);*/
|
||||
/*setenv("XDG_RUNTIME_DIR", buf, true);*/
|
||||
/*setenv("XDG_SESSION_CLASS", "user", true);*/
|
||||
/*setenv("XDG_SESSION_ID", "1", true);*/
|
||||
/*setenv("XDG_SESSION_DESKTOP", , true);*/
|
||||
/*setenv("XDG_SEAT", "seat0", true);*/
|
||||
}
|
||||
|
||||
/*char *buf;*/
|
||||
/*size_t bsize = snprintf(NULL, 0, "/run/user/%d", pw->pw_uid) + 1;*/
|
||||
/*buf = malloc(bsize);*/
|
||||
/*snprintf(buf, bsize, "/run/user/%d", pw->pw_uid);*/
|
||||
/*setenv("XDG_RUNTIME_DIR", buf, true);*/
|
||||
/*setenv("XDG_SESSION_CLASS", "user", true);*/
|
||||
/*setenv("XDG_SESSION_ID", "1", true);*/
|
||||
/*setenv("XDG_SESSION_DESKTOP", , true);*/
|
||||
/*setenv("XDG_SEAT", "seat0", true);*/
|
||||
|
||||
struct child_msg {
|
||||
char* msg;
|
||||
int _errno;
|
||||
bool err;
|
||||
};
|
||||
|
||||
#define SEND_MSG(MSG) \
|
||||
{ \
|
||||
write(pipefd[1], &(MSG), sizeof(struct child_msg)); \
|
||||
close(pipefd[1]); \
|
||||
}
|
||||
#define SEND_ERR(MSG) \
|
||||
{ \
|
||||
write(pipefd[1], \
|
||||
&(struct child_msg){.msg = (MSG), ._errno = errno, .err = true}, \
|
||||
sizeof(struct child_msg)); \
|
||||
close(pipefd[1]); \
|
||||
_exit(EXIT_FAILURE); \
|
||||
}
|
||||
#define DUMMY_READ() \
|
||||
{ \
|
||||
char _dummy; \
|
||||
read(pipefd[0], &_dummy, sizeof(_dummy)); \
|
||||
}
|
||||
inline static void forked(int pipefd[2], struct passwd* pw,
|
||||
char* NNULLABLE user,
|
||||
struct session_exec* NNULLABLE exec,
|
||||
char** NNULLABLE envlist) {
|
||||
if (chdir(pw->pw_dir) == -1) SEND_ERR("chdir");
|
||||
if (setgid(pw->pw_gid) == -1) SEND_ERR("setgid");
|
||||
if (initgroups(user, pw->pw_gid) == -1) SEND_ERR("initgroups");
|
||||
if (setuid(pw->pw_uid) == -1) SEND_ERR("setuid");
|
||||
|
||||
// or maybe Xorg fork should happen here
|
||||
|
||||
SEND_MSG((struct child_msg){.err = false});
|
||||
DUMMY_READ();
|
||||
close(pipefd[0]);
|
||||
|
||||
int exit = session_exec_exec(exec, envlist);
|
||||
perror("exec error");
|
||||
(void)fputs("failure calling session\n", stderr);
|
||||
_exit(exit);
|
||||
}
|
||||
#undef SEND_MSG
|
||||
#undef SEND_ERR
|
||||
#undef DUMMY_READ
|
||||
|
||||
// NOLINTBEGIN(readability-function-cognitive-complexity)
|
||||
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||
struct config* config) {
|
||||
@@ -178,89 +146,64 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||
return false;
|
||||
}
|
||||
|
||||
bool* reach_session = shmalloc(sizeof(bool));
|
||||
if (reach_session == NULL) {
|
||||
perror("error allocating shared memory");
|
||||
struct pamh_getenv_status env_ret =
|
||||
pamh_get_complete_env(pamh, pw, session.type);
|
||||
if (env_ret.error_flag != PAMH_ERR_NOERR) {
|
||||
if (env_ret.error_flag == PAMH_ERR_ALLOC) {
|
||||
print_err("allocator error");
|
||||
} else if (env_ret.error_flag == PAMH_ERR_ERRNO) {
|
||||
print_errno(env_ret.errfn);
|
||||
} else if (env_ret.error_flag == PAMH_ERR_NOERRNO) {
|
||||
print_err(env_ret.errfn);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*reach_session = false;
|
||||
|
||||
struct Vector envlist_vec = vec_from_raw((void**)env_ret.envlist);
|
||||
source_paths(&envlist_vec, &config->behavior.source, pw->pw_dir,
|
||||
&config->behavior.user_source);
|
||||
char** envlist = (char**)vec_as_raw(envlist_vec);
|
||||
if (!envlist) {
|
||||
print_err("vec alloc error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: start X server here if needed
|
||||
// e.g. spawn (also after downgrading privs):
|
||||
//
|
||||
// `X :0 tty<X> -auth <user-home>/.Xauthority -nolisten tcp -background none`
|
||||
//
|
||||
// Then `DISPLAY=:0 <xsession>`
|
||||
|
||||
int pipefd[2];
|
||||
pipe(pipefd);
|
||||
|
||||
uint pid = fork();
|
||||
if (pid == 0) { // child
|
||||
char* term = NULL;
|
||||
char* getterm = getenv("TERM");
|
||||
// TODO: handle malloc error
|
||||
if (getterm != NULL) term = strdup(getterm);
|
||||
if (clearenv() != 0) {
|
||||
print_errno("clearenv");
|
||||
_exit(EXIT_FAILURE);
|
||||
if (pid == 0)
|
||||
forked(pipefd, pw, user, &session.exec, envlist);
|
||||
else {
|
||||
struct child_msg msg;
|
||||
read(pipefd[0], &msg, sizeof(struct child_msg));
|
||||
close(pipefd[0]);
|
||||
if (msg.err) {
|
||||
errno = msg._errno;
|
||||
print_errno(msg.msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
char** envlist = pam_getenvlist(pamh);
|
||||
if (envlist == NULL) {
|
||||
print_errno("pam_getenvlist");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
for (size_t i = 0; envlist[i] != NULL; i++) {
|
||||
putenv(envlist[i]);
|
||||
}
|
||||
// FIXME: path hotfix
|
||||
putenv("PATH=/bin:/usr/bin");
|
||||
if (term != NULL) {
|
||||
setenv("TERM", term, true);
|
||||
free(term);
|
||||
}
|
||||
if (cb) cb();
|
||||
printf("\x1b[0m\x1b[H\x1b[J");
|
||||
(void)fflush(stdout);
|
||||
close(pipefd[1]);
|
||||
|
||||
free((void*)envlist);
|
||||
moarEnv(user, session, pw, config);
|
||||
|
||||
// TODO: chown stdin to user
|
||||
// does it inherit stdin from parent and
|
||||
// does parent need to reclaim it after
|
||||
// this dies?
|
||||
|
||||
if (setgid(pw->pw_gid) == -1) {
|
||||
print_errno("setgid");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
if (initgroups(user, pw->pw_gid) == -1) {
|
||||
print_errno("initgroups");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setuid(pw->pw_uid) == -1) {
|
||||
perror("setuid");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (cb != NULL) cb();
|
||||
|
||||
*reach_session = true;
|
||||
|
||||
// TODO: these will be different due to TryExec
|
||||
// and, Exec/TryExec might contain spaces as args
|
||||
printf("\x1b[0m");
|
||||
// NOLINTNEXTLINE(bugprone-branch-clone)
|
||||
if (session.type == SHELL) {
|
||||
clear_screen();
|
||||
(void)fflush(stdout);
|
||||
execlp(session.exec, session.exec, NULL);
|
||||
} else if (session.type == XORG || session.type == WAYLAND) {
|
||||
clear_screen();
|
||||
(void)fflush(stdout);
|
||||
execlp(session.exec, session.exec, NULL);
|
||||
}
|
||||
perror("execl error");
|
||||
(void)fputs("failure calling session\n", stderr);
|
||||
} else {
|
||||
pid_t child_pid = (pid_t)pid;
|
||||
waitpid(child_pid, NULL, 0);
|
||||
int exit_code;
|
||||
waitpid((pid_t)pid, &exit_code, 0);
|
||||
|
||||
pam_setcred(pamh, PAM_DELETE_CRED);
|
||||
pam_close_session(pamh, 0);
|
||||
pam_end(pamh, PAM_SUCCESS);
|
||||
|
||||
if (*reach_session == false) return false;
|
||||
if (exit_code != 0) return false;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "chvt.h"
|
||||
#include "macros.h"
|
||||
|
||||
static char* vterms[] = {"/dev/tty", "/dev/tty0", "/dev/vc/0", "/dev/systty",
|
||||
"/dev/console"};
|
||||
@@ -24,15 +25,13 @@ int chvt_str(char* str) {
|
||||
}
|
||||
|
||||
int chvt(int n) {
|
||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
||||
(void)fprintf(stderr, "activating vt %d\n", n);
|
||||
// NOLINTNEXTLINE(readability-identifier-length)
|
||||
char c = 0;
|
||||
for (size_t i = 0; i < sizeof(vterms) / sizeof(vterms[0]); i++) {
|
||||
for (size_t i = 0; i < LEN(vterms); i++) {
|
||||
int fd = open(vterms[i], O_RDWR);
|
||||
if (fd >= 0 && isatty(fd) && ioctl(fd, KDGKBTYPE, &c) == 0 && c < 3) {
|
||||
if (ioctl(fd, VT_ACTIVATE, n) < 0 || ioctl(fd, VT_WAITACTIVE, n) < 0) {
|
||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
||||
(void)fprintf(stderr, "Couldn't activate vt %d\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
@@ -117,12 +117,12 @@ union typ_ptr {
|
||||
char** string;
|
||||
long long* number;
|
||||
bool* boolean;
|
||||
enum keys* key;
|
||||
enum Keys* key;
|
||||
struct Vector* vec;
|
||||
uintptr_t ptr;
|
||||
};
|
||||
struct parser_error parse_key(enum introspection_type typ, union typ_ptr at,
|
||||
char* key, size_t offset) {
|
||||
struct parser_error parse_key(enum IntrospectionType typ, union typ_ptr at,
|
||||
char* key) {
|
||||
char* aux_str = NULL;
|
||||
struct parser_error aux_err;
|
||||
|
||||
@@ -219,7 +219,7 @@ struct status config_line_handler(void* _config, char* table, char* k,
|
||||
|
||||
log_printf("[I] parsing [%s.%s] as %s\n", table, k,
|
||||
INTROS_TYS_NAMES[this_intros_key->typ]);
|
||||
struct parser_error err = parse_key(this_intros_key->typ, k_addr, v, offset);
|
||||
struct parser_error err = parse_key(this_intros_key->typ, k_addr, v);
|
||||
if (err.msg != NULL) {
|
||||
log_printf("[E] cfg parser, failed to parse [%s.%s] (%s): %s\n", table, k,
|
||||
INTROS_TYS_NAMES[this_intros_key->typ], err.msg);
|
||||
|
@@ -1,4 +1,3 @@
|
||||
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -20,6 +19,7 @@ char* trim_str(char* str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
int read_desktop(FILE* fd, void* ctx,
|
||||
struct status (*cb)(void* ctx, char* table, char* key,
|
||||
char* value)) {
|
||||
@@ -82,4 +82,3 @@ int read_desktop(FILE* fd, void* ctx,
|
||||
if (buf != NULL) free(buf);
|
||||
return ret;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
||||
|
183
src/desktop_exec.c
Normal file
183
src/desktop_exec.c
Normal file
@@ -0,0 +1,183 @@
|
||||
#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)
|
@@ -4,8 +4,6 @@
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
|
||||
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
||||
|
||||
struct editable_field efield_new(char* content) {
|
||||
struct editable_field efield;
|
||||
if (content != NULL) {
|
||||
@@ -80,5 +78,3 @@ bool efield_seek(struct editable_field* self, char seek) {
|
||||
self->pos = (u_char)(ptr - self->content);
|
||||
return ptr != start;
|
||||
}
|
||||
|
||||
// NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
||||
|
163
src/pam.c
Normal file
163
src/pam.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include <pwd.h>
|
||||
#include <security/_pam_types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "macros.h"
|
||||
#include "pam.h"
|
||||
#include "sessions.h"
|
||||
|
||||
struct envpair {
|
||||
const char* NNULLABLE name;
|
||||
char* NULLABLE value;
|
||||
};
|
||||
|
||||
char* NULLABLE make_env_kv(const char* NNULLABLE key, char* NNULLABLE value) {
|
||||
char* buf = NULL;
|
||||
asprintf(&buf, "%s=%s", key, value);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void free_envlist(char** NNULLABLE envlist) {
|
||||
for (char** ptr = envlist; *ptr; ptr++)
|
||||
free(*ptr);
|
||||
free((void*)envlist);
|
||||
}
|
||||
|
||||
// NULL when allocation failure
|
||||
// in any case, envlist would be freed after this function
|
||||
char** NULLABLE merge_envlist(char** NNULLABLE envlist, struct envpair extra[],
|
||||
size_t extra_len) {
|
||||
size_t envlist_len = 0;
|
||||
while (envlist[envlist_len])
|
||||
envlist_len++;
|
||||
|
||||
size_t nonnullelems = 0;
|
||||
for (size_t i = 0; i < extra_len; i++) {
|
||||
if (extra[i].value) nonnullelems++;
|
||||
}
|
||||
|
||||
size_t new_envlist_len = envlist_len + nonnullelems + 1;
|
||||
char** new_envlist =
|
||||
(char**)realloc((void*)envlist, sizeof(char*) * new_envlist_len);
|
||||
if (!new_envlist) {
|
||||
free_envlist(envlist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-identifier-length)
|
||||
size_t k = 0;
|
||||
for (size_t i = 0; i < extra_len; i++) {
|
||||
if (!extra[i].value) continue;
|
||||
char* env_kv = make_env_kv(extra[i].name, extra[i].value);
|
||||
if (!env_kv) goto free_new_envlist_extra;
|
||||
new_envlist[envlist_len + k++] = env_kv;
|
||||
}
|
||||
|
||||
new_envlist[envlist_len + nonnullelems] = NULL;
|
||||
return new_envlist;
|
||||
|
||||
free_new_envlist_extra:
|
||||
for (size_t j = 0; j < envlist_len + k; j++) {
|
||||
free(new_envlist[envlist_len + j]);
|
||||
}
|
||||
free((void*)new_envlist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* NULLABLE xdg_ssession_type_str(enum SessionType typ) {
|
||||
char* xdg_session_type = NULL;
|
||||
if (typ == SHELL) xdg_session_type = "tty";
|
||||
if (typ == XORG) xdg_session_type = "x11";
|
||||
if (typ == WAYLAND) xdg_session_type = "wayland";
|
||||
return xdg_session_type;
|
||||
}
|
||||
|
||||
#define FAIL_ALLOC() \
|
||||
{ \
|
||||
return (struct pamh_getenv_status){.error_flag = PAMH_ERR_ALLOC}; \
|
||||
}
|
||||
#define FAIL(ERR, ERRFN) \
|
||||
{ \
|
||||
return (struct pamh_getenv_status){.error_flag = (ERR), .errfn = (ERRFN)}; \
|
||||
}
|
||||
|
||||
struct pamh_getenv_status pamh_get_complete_env(pam_handle_t* handle,
|
||||
struct passwd* NNULLABLE pw,
|
||||
enum SessionType session_typ) {
|
||||
char** raw_envlist = pam_getenvlist(handle);
|
||||
if (!raw_envlist) FAIL(PAMH_ERR_ERRNO, "pam_getenvlist");
|
||||
|
||||
struct envpair extra_env[] = {
|
||||
{"TERM", getenv("TERM")},
|
||||
{"PATH", getenv("PATH")},
|
||||
{"HOME", pw->pw_dir},
|
||||
{"USER", pw->pw_name},
|
||||
{"SHELL", pw->pw_shell},
|
||||
{"LOGNAME", pw->pw_name},
|
||||
{"XDG_SESSION_TYPE", xdg_ssession_type_str(session_typ)}};
|
||||
|
||||
char** envlist = merge_envlist(raw_envlist, extra_env, LEN(extra_env));
|
||||
if (!envlist) FAIL_ALLOC();
|
||||
return (struct pamh_getenv_status){
|
||||
.error_flag = PAMH_ERR_NOERR,
|
||||
.envlist = envlist,
|
||||
};
|
||||
}
|
||||
|
||||
#undef FAIL
|
||||
#undef FAIL_ALLOC
|
||||
|
||||
///////////////
|
||||
|
||||
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;
|
||||
}
|
||||
for (int i = 0; i < num_msg; i++) {
|
||||
reply[i].resp = NULL;
|
||||
reply[i].resp_retcode = 0;
|
||||
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;
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef PAM_SERVICE_FALLBACK
|
||||
#define PAM_SERVICE_FALLBACK "login"
|
||||
#endif
|
||||
|
||||
#define CHECK_PAM_RET(call) \
|
||||
ret = (call); \
|
||||
if (ret != PAM_SUCCESS) { \
|
||||
pam_end(pamh, ret); \
|
||||
return NULL; \
|
||||
}
|
||||
pam_handle_t* get_pamh(char* user, char* passwd) {
|
||||
pam_handle_t* pamh = NULL;
|
||||
struct pam_conv pamc = {pam_conversation, (void*)passwd};
|
||||
int ret;
|
||||
|
||||
char* pam_service_override = getenv("LIDM_PAM_SERVICE");
|
||||
char* pam_service_name =
|
||||
pam_service_override ? pam_service_override : PAM_SERVICE_FALLBACK;
|
||||
|
||||
CHECK_PAM_RET(pam_start(pam_service_name, user, &pamc, &pamh))
|
||||
CHECK_PAM_RET(pam_authenticate(pamh, 0))
|
||||
CHECK_PAM_RET(pam_acct_mgmt(pamh, 0))
|
||||
CHECK_PAM_RET(pam_setcred(pamh, PAM_ESTABLISH_CRED))
|
||||
CHECK_PAM_RET(pam_open_session(pamh, 0))
|
||||
CHECK_PAM_RET(pam_setcred(pamh, PAM_REINITIALIZE_CRED))
|
||||
|
||||
return pamh;
|
||||
}
|
||||
#undef CHECK_PAM_RET
|
@@ -8,12 +8,14 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "desktop.h"
|
||||
#include "desktop_exec.h"
|
||||
#include "log.h"
|
||||
#include "macros.h"
|
||||
#include "sessions.h"
|
||||
#include "util.h"
|
||||
|
||||
struct source_dir {
|
||||
enum session_type type;
|
||||
enum SessionType type;
|
||||
char* dir;
|
||||
};
|
||||
|
||||
@@ -72,9 +74,11 @@ struct status cb(void* _ctx, char* NULLABLE table, char* key, char* value) {
|
||||
|
||||
// also, always return 0 or we will break parsing and we don't want a bad
|
||||
// desktop file to break all possible sessions
|
||||
static enum session_type session_type;
|
||||
static enum SessionType session_type;
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
||||
UNUSED(sb);
|
||||
|
||||
// guessing symlink behavior
|
||||
// - FTW_PHYS if set doesn't follow symlinks, so ftw() has no flags and it
|
||||
// follows symlinks, we should never get to handle that
|
||||
@@ -95,22 +99,33 @@ static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
||||
}
|
||||
|
||||
int ret = read_desktop(fd, &ctx, &cb);
|
||||
if (ret < 0) { // any error
|
||||
log_printf("[E] format error parsing %s", fpath);
|
||||
return 0;
|
||||
}
|
||||
// any error
|
||||
if (ret < 0) goto err_close;
|
||||
|
||||
(void)fclose(fd);
|
||||
|
||||
// TODO: filter based on tryexec
|
||||
// https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html
|
||||
free(ctx.tryexec);
|
||||
|
||||
// just add this to the list
|
||||
if (ctx.name != NULL && ctx.exec != NULL) {
|
||||
struct session* this_session = malloc(sizeof(struct session));
|
||||
if (this_session == NULL) return 0;
|
||||
|
||||
int arg_count;
|
||||
char** args;
|
||||
int parse_status = parse_exec_string(ctx.exec, &arg_count, &args);
|
||||
if (parse_status != 0 || arg_count == 0 || !args[0]) {
|
||||
log_printf("[E] parsing exec string '%s': %d\n", ctx.exec, parse_status);
|
||||
free(this_session);
|
||||
goto err_parsing;
|
||||
}
|
||||
free(ctx.exec);
|
||||
|
||||
*this_session = (struct session){
|
||||
.name = ctx.name,
|
||||
.exec = ctx.exec,
|
||||
.tryexec = ctx.tryexec,
|
||||
.exec = session_exec_desktop(arg_count, args),
|
||||
.type = session_type,
|
||||
};
|
||||
|
||||
@@ -118,6 +133,12 @@ static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_close:
|
||||
(void)fclose(fd);
|
||||
err_parsing:
|
||||
log_printf("[E] format error parsing %s", fpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This code is designed to be run purely single threaded
|
||||
@@ -127,7 +148,7 @@ struct Vector get_avaliable_sessions() {
|
||||
vec_reserve(&sessions, LIKELY_BOUND_SESSIONS);
|
||||
|
||||
cb_sessions = &sessions;
|
||||
for (size_t i = 0; i < (sizeof(SOURCES) / sizeof(SOURCES[0])); i++) {
|
||||
for (size_t i = 0; i < LEN(SOURCES); i++) {
|
||||
log_printf("[I] parsing into %s\n", SOURCES[i].dir);
|
||||
session_type = SOURCES[i].type;
|
||||
ftw(SOURCES[i].dir, &fn, 1);
|
||||
|
29
src/ui.c
29
src/ui.c
@@ -25,6 +25,7 @@
|
||||
#include "keys.h"
|
||||
#include "launch_state.h"
|
||||
#include "log.h"
|
||||
#include "macros.h"
|
||||
#include "ofield.h"
|
||||
#include "sessions.h"
|
||||
#include "ui.h"
|
||||
@@ -61,6 +62,7 @@ struct config* g_config = NULL;
|
||||
static volatile sig_atomic_t need_resize = 0;
|
||||
|
||||
static void process_sigwinch(int signal) {
|
||||
UNUSED(signal);
|
||||
need_resize = 1;
|
||||
}
|
||||
|
||||
@@ -151,7 +153,7 @@ void ui_update_cursor_focus() {
|
||||
(void)printf("\x1b[%d;%dH", line, col);
|
||||
}
|
||||
|
||||
void ui_update_field(enum input focused_input) {
|
||||
void ui_update_field(enum Input focused_input) {
|
||||
if (focused_input == PASSWD) {
|
||||
print_passwd(utf8len(of_passwd.efield.content), false);
|
||||
} else if (focused_input == SESSION) {
|
||||
@@ -170,7 +172,7 @@ void ui_update_ffield() {
|
||||
}
|
||||
|
||||
void ui_update_ofield(struct opts_field* NNULLABLE self) {
|
||||
enum input input;
|
||||
enum Input input;
|
||||
if (self == &of_session)
|
||||
input = SESSION;
|
||||
else if (self == &of_user)
|
||||
@@ -280,28 +282,29 @@ int load(struct Vector* users, struct Vector* sessions) {
|
||||
(void)fflush(stdout);
|
||||
if (!read_press_nb(&len, seq, &tv)) continue;
|
||||
if (*seq == '\x1b') {
|
||||
enum keys ansi_code = find_ansi(seq);
|
||||
if (ansi_code != -1) {
|
||||
if (ansi_code == ESC) {
|
||||
struct option_keys ansi_code = find_ansi(seq);
|
||||
if (ansi_code.is_some) {
|
||||
enum Keys ansi_key = ansi_code.key;
|
||||
if (ansi_key == ESC) {
|
||||
esc = 2;
|
||||
} else if (ansi_code == g_config->functions.refresh) {
|
||||
} else if (ansi_key == g_config->functions.refresh) {
|
||||
restore_all();
|
||||
return 0;
|
||||
} else if (ansi_code == g_config->functions.reboot) {
|
||||
} else if (ansi_key == g_config->functions.reboot) {
|
||||
restore_all();
|
||||
reboot(RB_AUTOBOOT);
|
||||
exit(0);
|
||||
} else if (ansi_code == g_config->functions.poweroff) {
|
||||
} else if (ansi_key == g_config->functions.poweroff) {
|
||||
restore_all();
|
||||
reboot(RB_POWER_OFF);
|
||||
exit(0);
|
||||
} else if (ansi_code == A_UP || ansi_code == A_DOWN) {
|
||||
st_ch_focus(ansi_code == A_DOWN ? 1 : -1);
|
||||
} else if (ansi_code == A_RIGHT || ansi_code == A_LEFT) {
|
||||
} 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) {
|
||||
if (esc)
|
||||
st_ch_of_opts(ansi_code == A_RIGHT ? 1 : -1);
|
||||
st_ch_of_opts(ansi_key == A_RIGHT ? 1 : -1);
|
||||
else
|
||||
st_ch_ef_col(ansi_code == A_RIGHT ? 1 : -1);
|
||||
st_ch_ef_col(ansi_key == A_RIGHT ? 1 : -1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include "ui.h"
|
||||
#include "users.h"
|
||||
|
||||
enum input focused_input = PASSWD;
|
||||
enum Input focused_input = PASSWD;
|
||||
|
||||
struct Vector* gusers;
|
||||
struct Vector* gsessions;
|
||||
@@ -13,7 +13,7 @@ struct opts_field of_session;
|
||||
struct opts_field of_user;
|
||||
struct opts_field of_passwd;
|
||||
|
||||
struct opts_field* NNULLABLE get_opts_field(enum input from) {
|
||||
struct opts_field* NNULLABLE get_opts_field(enum Input from) {
|
||||
if (from == SESSION) return &of_session;
|
||||
if (from == USER) return &of_user;
|
||||
if (from == PASSWD) return &of_passwd;
|
||||
@@ -40,7 +40,8 @@ struct session st_session(bool include_defshell) {
|
||||
if (include_defshell && of_session.current_opt == gsessions->length + 1) {
|
||||
struct session shell_session;
|
||||
shell_session.type = SHELL;
|
||||
shell_session.exec = shell_session.name = st_user().shell;
|
||||
shell_session.exec =
|
||||
session_exec_shell(shell_session.name = st_user().shell);
|
||||
return shell_session;
|
||||
}
|
||||
|
||||
@@ -49,7 +50,8 @@ struct session st_session(bool include_defshell) {
|
||||
|
||||
struct session custom_session;
|
||||
custom_session.type = SHELL;
|
||||
custom_session.name = custom_session.exec = of_session.efield.content;
|
||||
custom_session.exec =
|
||||
session_exec_shell(custom_session.name = of_session.efield.content);
|
||||
return custom_session;
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ void st_kbd_type(char* text, bool cfg_include_defshell) {
|
||||
start = st_user().username;
|
||||
if (focused_input == SESSION && of_session.current_opt != 0 &&
|
||||
st_session(cfg_include_defshell).type == SHELL)
|
||||
start = st_session(cfg_include_defshell).exec;
|
||||
start = st_session(cfg_include_defshell).exec.shell;
|
||||
|
||||
ofield_kbd_type(field, text, start);
|
||||
ui_update_ffield();
|
||||
|
30
src/util.c
30
src/util.c
@@ -13,10 +13,10 @@
|
||||
|
||||
static int selret_magic();
|
||||
|
||||
int find_keyname(enum keys* at, const char* name) {
|
||||
int find_keyname(enum Keys* at, const char* name) {
|
||||
for (size_t i = 0; i < LEN(KEY_MAPPINGS); i++) {
|
||||
if (strcmp(KEY_NAMES[i], name) == 0) {
|
||||
*at = (enum keys)i;
|
||||
*at = (enum Keys)i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -24,16 +24,19 @@ int find_keyname(enum keys* at, const char* name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
enum keys find_ansi(const char* seq) {
|
||||
struct option_keys find_ansi(const char* seq) {
|
||||
for (size_t i = 0; i < LEN(KEY_MAPPINGS); i++) {
|
||||
struct key_mapping mapping = KEY_MAPPINGS[i];
|
||||
for (size_t j = 0; mapping.sequences[j] != NULL; j++) {
|
||||
if (strcmp(mapping.sequences[j], seq) == 0) {
|
||||
return (enum keys)i;
|
||||
return (struct option_keys){
|
||||
.is_some = true,
|
||||
.key = (enum Keys)i,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return (struct option_keys){.is_some = false};
|
||||
}
|
||||
|
||||
void read_press(u_char* length, char* out) {
|
||||
@@ -147,6 +150,23 @@ const struct Vector VEC_NEW = {
|
||||
.pages = NULL,
|
||||
};
|
||||
|
||||
struct Vector vec_from_raw(void** raw) {
|
||||
size_t len = 0;
|
||||
while (raw[len])
|
||||
len++;
|
||||
|
||||
return (struct Vector){
|
||||
.length = len,
|
||||
.capacity = len,
|
||||
.pages = raw,
|
||||
};
|
||||
}
|
||||
|
||||
void** vec_as_raw(struct Vector self) {
|
||||
if (vec_push(&self, NULL) != 0) return NULL;
|
||||
return self.pages;
|
||||
}
|
||||
|
||||
int vec_resize(struct Vector* self, size_t size) {
|
||||
void** new_location =
|
||||
(void**)realloc((void*)self->pages, size * sizeof(void*));
|
||||
|
Reference in New Issue
Block a user