mirror of
https://github.com/javalsai/lidm.git
synced 2025-08-31 18:38:00 +02:00
Compare commits
44 Commits
v1.2.1
...
support-xo
Author | SHA1 | Date | |
---|---|---|---|
570a68c586
|
|||
ff3e58ee5b
|
|||
109c9bd0be
|
|||
056ec64bcb
|
|||
b58bd50e64
|
|||
6d9107b360
|
|||
b56aa19671
|
|||
ddc38ef27f
|
|||
|
b3c8d3cbea | ||
5761838112 | |||
363deeab28
|
|||
|
98b898fc08 | ||
|
6b4b64d3fc | ||
7e1ec83c7f
|
|||
8f0213db74 | |||
4a1b868b8e | |||
|
589f33ffec | ||
|
8fc6bff60f | ||
6c99675be7 | |||
663b882f34
|
|||
|
cd5a3ede52 | ||
|
3f264a66b9 | ||
ecf254bf7f
|
|||
57fedc9fd5
|
|||
3d993c6260
|
|||
ba3c15b0f4 | |||
54953a18e8 | |||
a22c6b4597
|
|||
ab7666f561
|
|||
f0ef834eaa
|
|||
d85ebc0e78
|
|||
4611ad87a8
|
|||
3625aa9426
|
|||
fcc8be77ee
|
|||
2f2a2c2696
|
|||
9af69c2417
|
|||
16901b14c8
|
|||
2574ef4ac0 | |||
689c962cc9
|
|||
be6e039a9b
|
|||
6cac2f91ed
|
|||
ee244be195
|
|||
b580b6917b
|
|||
22c75a37e1
|
34
.clang-tidy
34
.clang-tidy
@@ -16,32 +16,34 @@ Checks: >
|
|||||||
readability-*,
|
readability-*,
|
||||||
-readability-braces-around-statements,
|
-readability-braces-around-statements,
|
||||||
|
|
||||||
WarningsAsErrors: ''
|
WarningsAsErrors: ""
|
||||||
HeaderFilterRegex: '.*'
|
HeaderFilterRegex: ".*"
|
||||||
FormatStyle: file
|
FormatStyle: file
|
||||||
|
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: readability-magic-numbers.IgnoredIntegerValues
|
- key: readability-magic-numbers.IgnoredIntegerValues
|
||||||
value: '0;1;2;3;10;255'
|
value: "0;1;2;3;10;255"
|
||||||
# - key: readability-magic-numbers.IgnoredValues
|
- key: readability-identifier-naming.VariableCase
|
||||||
# value: '0;1;2;3;10;255'
|
value: lower_case
|
||||||
- key: readability-identifier-naming.VariableCase
|
- key: readability-identifier-naming.ConstantParameterCase
|
||||||
value: lower_case
|
value: UPPER_CASE
|
||||||
- key: readability-identifier-naming.ConstantParameterCase
|
|
||||||
value: UPPER_CASE
|
|
||||||
|
|
||||||
- key: readability-identifier-naming.ConstantCase
|
- key: readability-identifier-naming.ConstantCase
|
||||||
value: "UPPER_CASE"
|
value: "UPPER_CASE"
|
||||||
|
- key: readability-identifier-naming.EnumCase
|
||||||
|
value: "CamelCase"
|
||||||
|
- key: readability-identifier-naming.FunctionCase
|
||||||
|
value: "lower_case"
|
||||||
|
|
||||||
- key: readability-identifier-length.VariableThreshold
|
- key: readability-identifier-length.VariableThreshold
|
||||||
value: '2'
|
value: "2"
|
||||||
- key: readability-identifier-length.ParameterThreshold
|
- key: readability-identifier-length.ParameterThreshold
|
||||||
value: '2'
|
value: "2"
|
||||||
- key: readability-identifier-length.LocalConstantThreshold
|
- key: readability-identifier-length.LocalConstantThreshold
|
||||||
value: '2'
|
value: "2"
|
||||||
- key: readability-identifier-length.MemberThreshold
|
- key: readability-identifier-length.MemberThreshold
|
||||||
value: '2'
|
value: "2"
|
||||||
- key: readability-identifier-length.MinimumParameterNameLength
|
- key: readability-identifier-length.MinimumParameterNameLength
|
||||||
value: '2'
|
value: "2"
|
||||||
- key: readability-identifier-length.MinimumVariableNameLength
|
- key: readability-identifier-length.MinimumVariableNameLength
|
||||||
value: '2'
|
value: "2"
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
[codespell]
|
[codespell]
|
||||||
skip = ./assets/pkg/aur/*/src,./assets/pkg/aur/*/*/objects
|
skip = ./assets/pkg/aur/*/src,./assets/pkg/aur/*/*/objects,./assets/pkg/aur/*/*.tar.*
|
||||||
|
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -67,7 +67,8 @@ jobs:
|
|||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y make gcc libpam0g-dev
|
apt-get install -y make gcc libpam0g-dev
|
||||||
run: ARCH=aarch64 GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh
|
run: ARCH=aarch64 GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh
|
||||||
- run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
- if: always()
|
||||||
|
run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -94,7 +95,8 @@ jobs:
|
|||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y make gcc libpam0g-dev
|
apt-get install -y make gcc libpam0g-dev
|
||||||
run: ARCH=armv7 GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh
|
run: ARCH=armv7 GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh
|
||||||
- run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
- if: always()
|
||||||
|
run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -121,10 +123,40 @@ jobs:
|
|||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y make gcc libpam0g-dev
|
apt-get install -y make gcc libpam0g-dev
|
||||||
run: ARCH=riscv64 GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh
|
run: ARCH=riscv64 GITHUB_STEP_SUMMARY=gss.out GITHUB_OUTPUT=go.out assets/github_scripts/build.sh
|
||||||
- run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
- if: always()
|
||||||
|
run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build-riscv64
|
name: build-riscv64
|
||||||
path: lidm-riscv64
|
path: lidm-riscv64
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
|
# This build job is only symbolic, the behavior of the packaged Void Linux version may differ.
|
||||||
|
build-linux-amd64-musl:
|
||||||
|
name: amd64-musl
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions: write-all
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Run in Musl Container
|
||||||
|
uses: addnab/docker-run-action@v3
|
||||||
|
with:
|
||||||
|
image: ghcr.io/void-linux/void-musl-full
|
||||||
|
options: -v ${{ github.workspace }}:/workspace
|
||||||
|
run: |
|
||||||
|
cd /workspace
|
||||||
|
|
||||||
|
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
|
||||||
|
- if: always()
|
||||||
|
run: set +e; cat gss.out >>"$GITHUB_STEP_SUMMARY"; cat go.out >>"$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-amd64-musl
|
||||||
|
path: lidm-amd64-musl
|
||||||
|
retention-days: 1
|
||||||
|
24
.github/workflows/check.yml
vendored
24
.github/workflows/check.yml
vendored
@@ -26,18 +26,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
packages: "shellcheck"
|
packages: "shellcheck"
|
||||||
version: 1.0
|
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:
|
clangcheck:
|
||||||
name: Clang
|
name: Clang
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ubuntu:25.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
- run: apt -y update && apt install -y clang-format clang-tidy make gcc git bear libpam0g-dev
|
||||||
with:
|
|
||||||
packages: "clang-format clang-tidy bear libpam0g-dev"
|
|
||||||
version: 1.0
|
|
||||||
- run: bear -- make
|
- run: bear -- make
|
||||||
- run: clang-format -ni src/*.c include/*.h
|
- run: clang-format -version && clang-format -dump-config
|
||||||
- run: clang-tidy -p . src/*.c include/*.h
|
- run: |
|
||||||
|
set -euo pipefail
|
||||||
|
clang-format -ni src/*.c include/*.h -Werror 2>&1 | \
|
||||||
|
sed -E 's/^([^ ]+\.[ch]):([0-9]+):([0-9]+): ([a-z]+): (.*)$/::\4 file=\1,line=\2,col=\3::\5/'
|
||||||
|
- run: clang-tidy -version && clang-tidy -dump-config
|
||||||
|
- run: |
|
||||||
|
set -euo pipefail
|
||||||
|
clang-tidy -p . src/*.c include/*.h -warnings-as-errors=\* 2>&1 1>/dev/null |
|
||||||
|
sed -E 's/^([^ ]+\.[ch]):([0-9]+):([0-9]+): ([a-z]+): (.*)$/::\4 file=\1,line=\2,col=\3::\5/'
|
||||||
|
38
.github/workflows/make-release.yml
vendored
38
.github/workflows/make-release.yml
vendored
@@ -16,6 +16,8 @@ jobs:
|
|||||||
packages: "git"
|
packages: "git"
|
||||||
version: 1.0
|
version: 1.0
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
- name: Check Version Changed
|
- name: Check Version Changed
|
||||||
id: check-ver-changed
|
id: check-ver-changed
|
||||||
@@ -27,6 +29,7 @@ jobs:
|
|||||||
echo "ERR: Git tag matches makefile, did you bump Makefile up?" >&2
|
echo "ERR: Git tag matches makefile, did you bump Makefile up?" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "VERSION=$MAKE_TAG" >> "$GITHUB_OUTPUT"
|
echo "VERSION=$MAKE_TAG" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +73,6 @@ jobs:
|
|||||||
needs: [ release-checks, release ]
|
needs: [ release-checks, release ]
|
||||||
steps:
|
steps:
|
||||||
- run: pacman -Sy --noconfirm git github-cli base-devel pacman-contrib
|
- run: pacman -Sy --noconfirm git github-cli base-devel pacman-contrib
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- run: |
|
- run: |
|
||||||
@@ -96,3 +98,37 @@ jobs:
|
|||||||
--body "*This PR was created automatically*"
|
--body "*This PR was created automatically*"
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
nix-update:
|
||||||
|
name: Update NixOS module
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions: write-all
|
||||||
|
needs: [ release-checks, release ]
|
||||||
|
steps:
|
||||||
|
- uses: cachix/install-nix-action@v31
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
tmpdir=$(mktemp -d)
|
||||||
|
git archive v${{ needs.release-checks.outputs.VERSION }} | tar -xC "$tmpdir"
|
||||||
|
sha256sum=$(nix hash path "$tmpdir")
|
||||||
|
|
||||||
|
sed -i -E 's/(.*version\s*=\s*")[0-9.]*(".*)/\1'${{ needs.release-checks.outputs.VERSION }}'\2/' assets/pkg/nix/module.nix
|
||||||
|
sed -i -E 's|(.*sha256\s*=\s*")[^"]*(".*)|\1'"$sha256sum"'\2|' assets/pkg/nix/module.nix
|
||||||
|
# would be cool to be able to check the new module.nix builds
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
BRANCH=actions/update-nix-${{ needs.release-checks.outputs.VERSION }}
|
||||||
|
git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||||
|
git config user.name "GitHub Actions"
|
||||||
|
git config user.email "actions@github.com"
|
||||||
|
git checkout -b $BRANCH
|
||||||
|
git commit -am "Update NixOS module to v${{ needs.release-checks.outputs.VERSION }}"
|
||||||
|
git push -u origin $BRANCH
|
||||||
|
gh pr create --head $BRANCH \
|
||||||
|
--title "[Nix update]: Bump to ${{ needs.release-checks.outputs.VERSION }}" \
|
||||||
|
--body "*This PR was created automatically*"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
17
.github/workflows/push.yml
vendored
17
.github/workflows/push.yml
vendored
@@ -12,7 +12,24 @@ jobs:
|
|||||||
name: Check
|
name: Check
|
||||||
uses: ./.github/workflows/check.yml
|
uses: ./.github/workflows/check.yml
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
|
check_paths:
|
||||||
|
name: Paths Filter
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
code_changed: ${{ steps.filter.outputs.code }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- id: filter
|
||||||
|
uses: dorny/paths-filter@v3
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
code:
|
||||||
|
- Makefile
|
||||||
|
- 'src/**'
|
||||||
|
- 'include/**'
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
|
needs: check_paths
|
||||||
|
if: github.event_name != 'push' || needs.check_paths.outputs.code_changed == 'true'
|
||||||
uses: ./.github/workflows/build.yml
|
uses: ./.github/workflows/build.yml
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
|
31
Makefile
31
Makefile
@@ -1,4 +1,4 @@
|
|||||||
VERSION = 1.2.1
|
VERSION = 1.2.3
|
||||||
.DEFAULT_GOAL := lidm
|
.DEFAULT_GOAL := lidm
|
||||||
|
|
||||||
CDIR=src
|
CDIR=src
|
||||||
@@ -9,25 +9,29 @@ ODIR=dist
|
|||||||
PREFIX=/usr
|
PREFIX=/usr
|
||||||
|
|
||||||
CC?=gcc
|
CC?=gcc
|
||||||
CFLAGS?=-O3 -Wall
|
CFLAGS?=-O3 -Wall -Wextra -fdata-sections -ffunction-sections
|
||||||
ALLFLAGS=$(CFLAGS) -I$(IDIR)
|
# C PreProcessor flags, not C Plus Plus
|
||||||
|
CPPFLAGS?=
|
||||||
|
ALLFLAGS=$(CFLAGS) $(CPPFLAGS) -I$(IDIR)
|
||||||
|
LDFLAGS?=-Wl,--gc-sections
|
||||||
|
|
||||||
LIBS=-lpam
|
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))
|
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))
|
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); \
|
@tmp=$$(mktemp); \
|
||||||
printf '' > $$tmp; \
|
printf '' > $$tmp; \
|
||||||
echo '#define LIDM_VERSION "'$(VERSION)'"' >> $$tmp; \
|
echo '#define LIDM_VERSION "'$(VERSION)'"' >> $$tmp; \
|
||||||
echo '#define LIDM_GIT_REV "'$$(git describe --long --tags --always || echo '?')'"' >> $$tmp; \
|
echo '#define LIDM_GIT_REV "'$(INFO_GIT_REV)'"' >> $$tmp; \
|
||||||
echo '#define LIDM_BUILD_TS '$$(date +%s) >> $$tmp; \
|
echo '#define LIDM_BUILD_TS '$(INFO_BUILD_TS) >> $$tmp; \
|
||||||
if ! cmp -s $$tmp $@; then \
|
if ! cmp -s $$tmp $@; then \
|
||||||
mv $$tmp $@; \
|
mv $$tmp $@; \
|
||||||
fi; \
|
fi; \
|
||||||
@@ -38,7 +42,7 @@ $(ODIR)/%.o: $(CDIR)/%.c $(DEPS)
|
|||||||
$(CC) -c -o $@ $< $(ALLFLAGS)
|
$(CC) -c -o $@ $< $(ALLFLAGS)
|
||||||
|
|
||||||
lidm: $(OBJ)
|
lidm: $(OBJ)
|
||||||
$(CC) -o $@ $^ $(ALLFLAGS) $(LIBS)
|
$(CC) -o $@ $^ $(ALLFLAGS) $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(ODIR)/*.o lidm
|
rm -f $(ODIR)/*.o lidm
|
||||||
@@ -131,9 +135,12 @@ install-service-s6-etc:
|
|||||||
|
|
||||||
pre-commit:
|
pre-commit:
|
||||||
codespell
|
codespell
|
||||||
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-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:
|
print-version:
|
||||||
@echo $(VERSION)
|
@echo $(VERSION)
|
||||||
|
100
README.md
100
README.md
@@ -10,33 +10,41 @@ 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*
|
<blockquote><details>
|
||||||
|
<summary><i>
|
||||||
|
shown as in a featured terminal emulator, actual linux console doesn't support as much color and decorations
|
||||||
|
</i></summary>
|
||||||
|
|
||||||
> *however, all colors and strings are fully customizable*
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
</details></blockquote>
|
||||||
|
|
||||||
|
> _however, all colors and strings are fully customizable_
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Simple as C, you only need a C compiler and standard unix libraries to build this.
|
- 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)
|
- 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)
|
- 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).
|
- Starts with many init systems (systemd, dinit, runit, openrc and s6).
|
||||||
|
|
||||||
# Index
|
# Table of Contents
|
||||||
|
|
||||||
* [LiDM](#lidm)
|
- [Ideology](#ideology)
|
||||||
* [Features](#features)
|
- [Usage](#usage)
|
||||||
* [WIP](#wip)
|
- [Arguments](#arguments)
|
||||||
* [Index](#index)
|
- [Program](#program)
|
||||||
* [Ideology](#ideology)
|
- [Requirements](#requirements)
|
||||||
* [Usage](#usage)
|
- [Installation](#installation)
|
||||||
* [Arguments](#arguments)
|
- [Configuring](#configuring)
|
||||||
* [Program](#program)
|
- [PAM](#pam)
|
||||||
* [Requirements](#requirements)
|
- [Contributing](#contributing)
|
||||||
* [Installation](#installation)
|
- [Inspiration](#inspiration)
|
||||||
* [Configuring](#configuring)
|
- [Contributors](#contributors)
|
||||||
* [Contributing](#contributing)
|
|
||||||
* [Inspiration](#inspiration)
|
|
||||||
* [Contributors](#contributors)
|
|
||||||
|
|
||||||
# Ideology
|
# Ideology
|
||||||
|
|
||||||
@@ -44,7 +52,7 @@ We all know that the most important thing in a project is the ideology of the au
|
|||||||
|
|
||||||
[  ](https://stopchatcontrol.eu)
|
[  ](https://stopchatcontrol.eu)
|
||||||
|
|
||||||
> *there's also a [change.org post](https://www.change.org/p/stoppt-die-chatkontrolle-grundrechte-gelten-auch-im-netz).*
|
> _there's also a [change.org post](https://www.change.org/p/stoppt-die-chatkontrolle-grundrechte-gelten-auch-im-netz)._
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
@@ -56,25 +64,33 @@ If a single argument is provided (don't even do `--` or standard unix parsing...
|
|||||||
|
|
||||||
Base (mostly intuitive):
|
Base (mostly intuitive):
|
||||||
|
|
||||||
* Use arrow keys to navigate the inputs and type over any of them to override the default value.
|
- Use arrow keys to navigate the inputs and type over any of them to override the default value.
|
||||||
* Enter will just attempt to login.
|
- Enter will just attempt to login.
|
||||||
* If you are focused on an edited input, horizontal arrow keys will attempt to move across the text just as expected.
|
- If you are focused on an edited input, horizontal arrow keys will attempt to move across the text just as expected.
|
||||||
|
|
||||||
On top of that:
|
On top of that:
|
||||||
|
|
||||||
* Using the horizontal arrow keys if the focused input is not in text mode or the movement would overflow the input. It will try to change in such direction the option of session or the user.
|
- Using the horizontal arrow keys if the focused input is not in text mode or the movement would overflow the input. It will try to change in such direction the option of session or the user.
|
||||||
* Pressing <kbd>ESC</kbd> and then horizontal arrows will force to change the option of the focused input even if it's in edit mode.
|
- Pressing <kbd>ESC</kbd> and then horizontal arrows will force to change the option of the focused input even if it's in edit mode.
|
||||||
* Editing an option on a user or a shell session will put you in edit mode appending after the original value.
|
- Editing an option on a user or a shell session will put you in edit mode appending after the original value.
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
* Make (Also optional, but does things automatically, make sure `gcc` and `mkdir -p` work as expected).
|
- Make (Also optional, but does things automatically, make sure `gcc` and `mkdir -p` work as expected).
|
||||||
* A compiler like `cc`, `gcc` or `clang`. Make sure to use the desired `CC=<compiler>` on the `make` command.
|
- A compiler like `cc`, `gcc` or `clang`. Make sure to use the desired `CC=<compiler>` on the `make` command.
|
||||||
* PAM library, used for user authentication, just what `login` or `su` use internally. Don't worry, it's surely pre-installed.
|
- PAM library, used for user authentication, just what `login` or `su` use internally. Don't worry, it's surely pre-installed.
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
Check the [installation guide](INSTALL.md) to use your preferred installation source.
|
Check the [installation guide](./docs/INSTALL.md) to use your preferred installation source.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
<summary>Packagers read here!!</summary>
|
||||||
|
|
||||||
|
If you are a package maintainer or are willing to become one, please read [the packagers guide](./docs/PACKAGERS.md).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
# Configuring
|
# Configuring
|
||||||
|
|
||||||
@@ -90,6 +106,12 @@ Colors are gonna be put inside `\x1b[...m`, if you don't know what this is check
|
|||||||
> [!TIP]
|
> [!TIP]
|
||||||
> If you don't like seeing an element, you can change the fg color of it to be the same as the bg, making it invisible.
|
> If you don't like seeing an element, you can change the fg color of it to be the same as the bg, making it invisible.
|
||||||
|
|
||||||
|
# PAM
|
||||||
|
|
||||||
|
If your distribution does not use the standard PAM service name `login` (`/etc/pam.d/login`) for its PAM services or if you want to use another PAM file, simply set the `LIDM_PAM_SERVICE` env variable to your PAM service name.
|
||||||
|
|
||||||
|
When the env variable is empty it defaults to the `login` PAM service or whatever fallback your distribution packager has defined during compilation.
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
If you want to contribute check the [contribution guide](docs/CONTRIBUTING.md).
|
If you want to contribute check the [contribution guide](docs/CONTRIBUTING.md).
|
||||||
@@ -102,21 +124,21 @@ For this reason the project's philosophy is to be simple and minimal, such that
|
|||||||
|
|
||||||
I forgot what exactly the name came from, but it surely was a mix of a few things so:
|
I forgot what exactly the name came from, but it surely was a mix of a few things so:
|
||||||
|
|
||||||
* Obviously it's inspired by `ly`. `ly-dm` leads to "lydm".
|
- Obviously it's inspired by `ly`. `ly-dm` leads to "lydm".
|
||||||
* Wow make "lydm" simple with a "y" → "i" transformation.
|
- Wow make "lydm" simple with a "y" → "i" transformation.
|
||||||
* Associate it with the "i" in s**i**mple and other display managers like **Li**ghtDM.
|
- Associate it with the "i" in s**i**mple and other display managers like **Li**ghtDM.
|
||||||
* And the **la**ptop this project started in has a **lid**.
|
- And the **la**ptop this project started in has a **lid**.
|
||||||
|
|
||||||
# Contributors
|
# Contributors
|
||||||
|
|
||||||
[](https://github.com/javalsai/lidm/graphs/contributors)
|
[](https://github.com/javalsai/lidm/graphs/contributors)
|
||||||
|
|
||||||
[killertofus](https://github.com/killertofus), [deadvey](https://github.com/deadvey), [grialion](https://github.com/grialion/), cerealexperiments\_, [antiz96](https://github.com/Antiz96), [rmntgx](https://github.com/rmntgx) and [more...](https://github.com/javalsai/lidm/graphs/contributors)
|
[killertofus](https://github.com/killertofus), [deadvey](https://github.com/deadvey), [grialion](https://github.com/grialion/), cerealexperiments\_, [antiz96](https://github.com/Antiz96), [rmntgx](https://github.com/rmntgx) and [more...](https://github.com/javalsai/lidm/graphs/contributors)
|
||||||
|
|
||||||
With their big or small contributions, every commit has helped in its own way and encouraged me to keep putting my soul into this.
|
With their big or small contributions, every commit has helped in its own way and encouraged me to keep putting my soul into this.
|
||||||
|
|
||||||
***
|
---
|
||||||
|
|
||||||
🌟 Finally, consider starring this repo [or...](https://www.reddit.com/r/github/comments/1l2mchg/is_this_allowed) 🔪
|
🌟 Finally, consider starring this repo [or...](https://www.reddit.com/r/github/comments/1l2mchg/is_this_allowed) 🔪
|
||||||
|
|
||||||

|

|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
BAUD_RATE=38400
|
|
||||||
TERM_NAME=linux
|
|
||||||
|
|
||||||
TTY=tty7
|
|
||||||
EXEC_PATH=/bin/lidm
|
|
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
[ -r conf ] && . ./conf
|
|
||||||
|
|
||||||
exec utmpset -w $TTY
|
|
@@ -1,15 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
[ -r conf ] && . ./conf
|
|
||||||
|
|
||||||
if [ -x /sbin/getty -o -x /bin/getty ]; then
|
|
||||||
# busybox
|
|
||||||
GETTY=getty
|
|
||||||
elif [ -x /sbin/agetty -o -x /bin/agetty ]; then
|
|
||||||
# util-linux
|
|
||||||
GETTY=agetty
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec setsid ${GETTY} ${GETTY_ARGS} \
|
|
||||||
"${TTY}" "${TERM_NAME}" \
|
|
||||||
-n -l "${EXEC_PATH}" -o 7
|
|
@@ -13,8 +13,9 @@ make -j"$(nproc)" "$@" 2> /tmp/stderr || ERR=$?
|
|||||||
BSIZE=$(stat --printf="%s" lidm)
|
BSIZE=$(stat --printf="%s" lidm)
|
||||||
HSIZE=$(numfmt --to=iec-i<<<"$BSIZE")B
|
HSIZE=$(numfmt --to=iec-i<<<"$BSIZE")B
|
||||||
WARNS=$(
|
WARNS=$(
|
||||||
{ grep -E '^[^ ]+\.[ch]:[0-9]+:[0-9]+: [a-z]+:' /tmp/stderr || :; } \
|
sed -nE \
|
||||||
| sed -E 's/^([^ ]+\.[ch]):([0-9]+):([0-9]+): ([a-z]+): (.*)$/::\4 file=\1,line=\2,col=\3::\5/'
|
's/^([^ ]+\.[ch]):([0-9]+):([0-9]+): ([a-z]+): (.*)$/::\4 file=\1,line=\2,col=\3::\5/p' \
|
||||||
|
/tmp/stderr
|
||||||
)
|
)
|
||||||
WARNS_NUM=$({ [[ "$WARNS" == "" ]] && echo 0; } || wc -l <<<"$WARNS")
|
WARNS_NUM=$({ [[ "$WARNS" == "" ]] && echo 0; } || wc -l <<<"$WARNS")
|
||||||
|
|
||||||
|
@@ -4,9 +4,9 @@ These files are just for reference, I'll manually edit and publish them, at leas
|
|||||||
|
|
||||||
There are three packages that follow standard conventions:
|
There are three packages that follow standard conventions:
|
||||||
|
|
||||||
* [`lidm`](https://aur.archlinux.org/packages/lidm): Builds latest release (manually updated per release basis)
|
- [`lidm`](https://aur.archlinux.org/packages/lidm): Builds latest release (manually updated per release basis)
|
||||||
* [`lidm-bin`](https://aur.archlinux.org/packages/lidm-bin): Fetches latest release binary (compiled by GitHub Actions, also updated per release)
|
- [`lidm-bin`](https://aur.archlinux.org/packages/lidm-bin): Fetches latest release binary (compiled by GitHub Actions, also updated per release)
|
||||||
* [`lidm-git`](https://aur.archlinux.org/packages/lidm-git): Fetches latest commit and builds it (should be updated automatically)
|
- [`lidm-git`](https://aur.archlinux.org/packages/lidm-git): Fetches latest commit and builds it (should be updated automatically)
|
||||||
|
|
||||||
> \[!IMPORTANT]
|
> \[!IMPORTANT]
|
||||||
> None of those packages include the service files. [You have to do this yourself](../../services/README.md).
|
> None of those packages include the service files. [You have to do this yourself](../../services/README.md).
|
||||||
|
@@ -1,20 +1,32 @@
|
|||||||
pkgbase = lidm-bin
|
pkgbase = lidm-bin
|
||||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (release binary)
|
pkgdesc = A fully colorful customizable TUI display manager made in C. (release binary)
|
||||||
pkgver = 1.2.0
|
pkgver = 1.2.3
|
||||||
pkgrel = 1
|
pkgrel = 3
|
||||||
url = https://github.com/javalsai/lidm
|
url = https://github.com/javalsai/lidm
|
||||||
arch = x86_64
|
arch = x86_64
|
||||||
|
arch = i686
|
||||||
|
arch = aarch64
|
||||||
|
arch = armv7h
|
||||||
|
arch = riscv64
|
||||||
license = GPL
|
license = GPL
|
||||||
depends = pam
|
depends = libpam.so
|
||||||
provides = lidm
|
provides = lidm
|
||||||
conflicts = lidm
|
conflicts = lidm
|
||||||
source = lidm::https://github.com/javalsai/lidm/releases/download/v1.2.0/lidm-amd64
|
source = lidm-default-theme-1.2.3.ini::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/themes/default.ini
|
||||||
source = default-theme.ini::https://raw.githubusercontent.com/javalsai/lidm/v1.2.0/themes/default.ini
|
source = lidm-1.2.3.1::https://raw.githubusercontent.com/javalsai/lidm/v1.2.3/assets/man/lidm.1
|
||||||
source = lidm.1::https://raw.githubusercontent.com/javalsai/lidm/v1.2.0/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
|
||||||
source = lidm-config.5::https://raw.githubusercontent.com/javalsai/lidm/v1.2.0/assets/man/lidm-config.5
|
|
||||||
sha256sums = 6bf4403c21bd26607302d99d7bd1a129822e7d2506e949fb483ea445e022eb6d
|
|
||||||
sha256sums = ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca
|
sha256sums = ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca
|
||||||
sha256sums = 7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8
|
sha256sums = 7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8
|
||||||
sha256sums = 0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9
|
sha256sums = 0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9
|
||||||
|
source_x86_64 = lidm-1.2.3-x86_64::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-amd64
|
||||||
|
sha256sums_x86_64 = a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b
|
||||||
|
source_i686 = lidm-1.2.3-i686::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-i386
|
||||||
|
sha256sums_i686 = 75018578e68bffda9807de8a65e16eaed8a16c6cf2417a0b58c5d5bcfa603e45
|
||||||
|
source_aarch64 = lidm-1.2.3-aarch64::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-aarch64
|
||||||
|
sha256sums_aarch64 = 1b81a1537a1e31ca1902cbc3b60add4ac712aa64fd4d266685f53372cc365882
|
||||||
|
source_armv7h = lidm-1.2.3-armv7h::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-armv7
|
||||||
|
sha256sums_armv7h = e86f59509fe2366d6312b9bc9e8d89c14e9c049fd713a04c41dab49a848b1ada
|
||||||
|
source_riscv64 = lidm-1.2.3-riscv64::https://github.com/javalsai/lidm/releases/download/v1.2.3/lidm-riscv64
|
||||||
|
sha256sums_riscv64 = 3f0eb0315c523d367bac332641e5cd3c86cfd9aa4e7c14b2efc036937b97a598
|
||||||
|
|
||||||
pkgname = lidm-bin
|
pkgname = lidm-bin
|
||||||
|
@@ -1,29 +1,39 @@
|
|||||||
# shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
|
# shellcheck disable=SC2034,SC2154,SC2164
|
||||||
# Maintainer: javalsai <javalsai@proton.me>
|
# Maintainer: javalsai <javalsai@proton.me>
|
||||||
pkgname=lidm-bin
|
pkgname=lidm-bin
|
||||||
pkgver=1.2.0
|
pkgver=1.2.3
|
||||||
pkgrel=1
|
pkgrel=3
|
||||||
depends=('pam')
|
depends=('libpam.so')
|
||||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (release binary)"
|
pkgdesc="A fully colorful customizable TUI display manager made in C. (release binary)"
|
||||||
arch=('x86_64')
|
arch=('x86_64' 'i686' 'aarch64' 'armv7h' 'riscv64')
|
||||||
url="https://github.com/javalsai/lidm"
|
url="https://github.com/javalsai/lidm"
|
||||||
license=('GPL')
|
license=('GPL')
|
||||||
provides=('lidm')
|
provides=('lidm')
|
||||||
conflicts=('lidm')
|
conflicts=('lidm')
|
||||||
source=(
|
source=(
|
||||||
"lidm::$url/releases/download/v$pkgver/lidm-amd64"
|
"lidm-default-theme-${pkgver}.ini::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/themes/default.ini"
|
||||||
"default-theme.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.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"
|
||||||
"lidm-config.5::https://raw.githubusercontent.com/javalsai/lidm/v$pkgver/assets/man/lidm-config.5"
|
|
||||||
)
|
)
|
||||||
sha256sums=('6bf4403c21bd26607302d99d7bd1a129822e7d2506e949fb483ea445e022eb6d'
|
source_x86_64=("lidm-${pkgver}-x86_64::$url/releases/download/v$pkgver/lidm-amd64")
|
||||||
'ffaa5fe2cf5011bf53c90f81bfec8585158d35f72c0666db0bd4d3866ae041ca'
|
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'
|
'7f2fb91f55088be1a9b1c93ecf5d6c1e437f369b56df2eacc9d10b00c93c39f8'
|
||||||
'0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9')
|
'0aa5755bdcc60ea80cd9ee0f89233ffaf22c6cee9db9da277274a62c6ed477d9')
|
||||||
|
sha256sums_x86_64=('a533b5aee3ffe04268f8d3ff8d7eb87f09d31fbe25e1b8b1ed29c42ef465bd4b')
|
||||||
|
sha256sums_i686=('75018578e68bffda9807de8a65e16eaed8a16c6cf2417a0b58c5d5bcfa603e45')
|
||||||
|
sha256sums_aarch64=('1b81a1537a1e31ca1902cbc3b60add4ac712aa64fd4d266685f53372cc365882')
|
||||||
|
sha256sums_armv7h=('e86f59509fe2366d6312b9bc9e8d89c14e9c049fd713a04c41dab49a848b1ada')
|
||||||
|
sha256sums_riscv64=('3f0eb0315c523d367bac332641e5cd3c86cfd9aa4e7c14b2efc036937b97a598')
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
install -Dm755 lidm "${pkgdir}/usr/bin/lidm"
|
cd "$srcdir"
|
||||||
install -Dm644 default-theme.ini "${pkgdir}/etc/lidm.ini"
|
|
||||||
install -Dm644 lidm.1 "${pkgdir}/usr/share/man/man1/lidm.1"
|
install -Dm755 "lidm-${pkgver}-$CARCH" "${pkgdir}/usr/bin/lidm"
|
||||||
install -Dm644 lidm-config.5 "${pkgdir}/usr/share/man/man5/lidm-config.5"
|
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
|
pkgbase = lidm-git
|
||||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (last git commit)
|
pkgdesc = A fully colorful customizable TUI display manager made in C. (last git commit)
|
||||||
pkgver = 0.1.0.r0.g8071694
|
pkgver = 1.2.3.r3.g363deea
|
||||||
pkgrel = 1
|
pkgrel = 3
|
||||||
url = https://github.com/javalsai/lidm
|
url = https://github.com/javalsai/lidm
|
||||||
arch = any
|
arch = any
|
||||||
license = GPL
|
license = GPL
|
||||||
makedepends = git
|
makedepends = git
|
||||||
makedepends = make
|
|
||||||
makedepends = gcc
|
|
||||||
depends = pam
|
depends = pam
|
||||||
provides = lidm
|
provides = lidm
|
||||||
conflicts = lidm
|
conflicts = lidm
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
# shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
|
# shellcheck disable=SC2034,SC2154,SC2164
|
||||||
# Maintainer: javalsai <javalsai@proton.me>
|
# Maintainer: javalsai <javalsai@proton.me>
|
||||||
pkgname=lidm-git
|
pkgname=lidm-git
|
||||||
pkgver=1.2.0.r0.g7f75b8e
|
pkgver=1.2.3.r3.g363deea
|
||||||
pkgrel=1
|
pkgrel=3
|
||||||
depends=('pam')
|
depends=('pam')
|
||||||
makedepends=('git' 'make' 'gcc')
|
makedepends=('git')
|
||||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (last git commit)"
|
pkgdesc="A fully colorful customizable TUI display manager made in C. (last git commit)"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
url="https://github.com/javalsai/lidm"
|
url="https://github.com/javalsai/lidm"
|
||||||
@@ -15,17 +15,17 @@ source=("lidm::git+https://github.com/javalsai/lidm")
|
|||||||
sha256sums=('SKIP')
|
sha256sums=('SKIP')
|
||||||
|
|
||||||
pkgver() {
|
pkgver() {
|
||||||
cd "lidm"
|
cd "$srcdir/lidm"
|
||||||
git describe --long --abbrev=7 --tags | \
|
git describe --long --abbrev=7 --tags | \
|
||||||
sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
|
sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "lidm"
|
cd "$srcdir/lidm"
|
||||||
make CFLAGS="-O3"
|
make
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
cd "lidm"
|
cd "$srcdir/lidm"
|
||||||
make install DESTDIR="${pkgdir}"
|
make DESTDIR="${pkgdir}" install
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
pkgbase = lidm
|
pkgbase = lidm
|
||||||
pkgdesc = A fully colorful customizable TUI display manager made in C. (build latest tag)
|
pkgdesc = A fully colorful customizable TUI display manager made in C. (build latest tag)
|
||||||
pkgver = 1.2.0
|
pkgver = 1.2.3
|
||||||
pkgrel = 1
|
pkgrel = 3
|
||||||
url = https://github.com/javalsai/lidm
|
url = https://github.com/javalsai/lidm
|
||||||
arch = any
|
arch = any
|
||||||
license = GPL
|
license = GPL
|
||||||
makedepends = git
|
|
||||||
makedepends = gcc
|
|
||||||
depends = pam
|
depends = pam
|
||||||
source = tarball.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.0.tar.gz
|
source = lidm-1.2.3.tar.gz::https://github.com/javalsai/lidm/archive/refs/tags/v1.2.3.tar.gz
|
||||||
sha256sums = 0dffded5fcef45cb45fe88358b0cba8de04f614e323a9c6e4162f84b6e3a50b6
|
sha256sums = 1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93
|
||||||
|
|
||||||
pkgname = lidm
|
pkgname = lidm
|
||||||
|
@@ -1,25 +1,21 @@
|
|||||||
# shellcheck disable=SC2034,SC2148,SC2128,SC2154,SC2164
|
# shellcheck disable=SC2034,SC2154,SC2164
|
||||||
# Maintainer: javalsai <javalsai@proton.me>
|
# Maintainer: javalsai <javalsai@proton.me>
|
||||||
pkgname=lidm
|
pkgname=lidm
|
||||||
pkgver=1.2.0
|
pkgver=1.2.3
|
||||||
pkgrel=1
|
pkgrel=3
|
||||||
depends=('pam')
|
depends=('pam')
|
||||||
makedepends=('git' 'gcc')
|
makedepends=()
|
||||||
pkgdesc="A fully colorful customizable TUI display manager made in C. (build latest tag)"
|
pkgdesc="A fully colorful customizable TUI display manager made in C. (build latest tag)"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
url="https://github.com/javalsai/lidm"
|
url="https://github.com/javalsai/lidm"
|
||||||
license=('GPL')
|
license=('GPL')
|
||||||
source=("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=('0dffded5fcef45cb45fe88358b0cba8de04f614e323a9c6e4162f84b6e3a50b6')
|
sha256sums=('1ce414b510c5bbc3e32ea882f915b4d3958cb82eb1fbb5cf33e62f69c844bf93')
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
tar -xzf "tarball.tar.gz"
|
make -C "$srcdir/lidm-$pkgver"
|
||||||
cd "lidm-$pkgver"
|
|
||||||
|
|
||||||
make CFLAGS="-O3"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
cd "lidm-$pkgver"
|
make -C "$srcdir/lidm-$pkgver" DESTDIR="$pkgdir" install
|
||||||
make install DESTDIR="${pkgdir}"
|
|
||||||
}
|
}
|
||||||
|
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")
|
MYSELF=$(realpath "$0")
|
||||||
MYDIR=$(dirname "$MYSELF")
|
MYDIR=$(dirname "$MYSELF")
|
||||||
|
|
||||||
for pkg in "$MYDIR"/*/; do
|
cd "$MYDIR"
|
||||||
printf "\x1b[1mEntering '%s'\x1b[0m\n" "$pkg"
|
typeset -a pkgs=(lidm{,-git,-bin})
|
||||||
|
|
||||||
|
for pkg in "${pkgs[@]}"; do
|
||||||
|
printf "\x1b[mEntering '%s'\x1b[0m\n" "$pkg"
|
||||||
cd "$pkg"
|
cd "$pkg"
|
||||||
|
makepkg -Cf
|
||||||
# shellcheck disable=SC1091
|
cd ..
|
||||||
source "PKGBUILD"
|
|
||||||
for source in "${source[@]}"; do
|
|
||||||
awk -F'::' '{print $1}' <<<"$source" | xargs rm -rf
|
|
||||||
done
|
|
||||||
|
|
||||||
rm -rf ./*.{gz,zst} src pkg
|
|
||||||
makepkg -f .
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
done
|
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/pkgver=.*/pkgver=$1/" PKGBUILD
|
||||||
sed -i "s/pkgrel=.*/pkgrel=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
|
updpkgsums
|
||||||
makepkg --printsrcinfo | tee .SRCINFO
|
makepkg --printsrcinfo | tee .SRCINFO
|
||||||
echo
|
echo
|
||||||
|
23
assets/pkg/nix/get-cfg-file.nix
Normal file
23
assets/pkg/nix/get-cfg-file.nix
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
cfg,
|
||||||
|
src,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
maker = import ./make-cfg.nix {
|
||||||
|
inherit lib;
|
||||||
|
keys-h-file = builtins.readFile "${src}/include/keys.h";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit maker;
|
||||||
|
file = builtins.toFile "lidm.conf" (
|
||||||
|
if builtins.isString cfg then
|
||||||
|
builtins.readFile "${src}/themes/${cfg}.ini"
|
||||||
|
else if builtins.isAttrs cfg then
|
||||||
|
maker.make cfg
|
||||||
|
else
|
||||||
|
builtins.throw "invalid cfg type, expected str or attrs"
|
||||||
|
);
|
||||||
|
}
|
50
assets/pkg/nix/lidm.nix
Normal file
50
assets/pkg/nix/lidm.nix
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
get-cfg =
|
||||||
|
if config.cfg != null then
|
||||||
|
import ./get-cfg-file.nix {
|
||||||
|
inherit lib;
|
||||||
|
inherit (config) cfg src;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
cfg-file = get-cfg.file;
|
||||||
|
maker = get-cfg.maker;
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation rec {
|
||||||
|
pname = "lidm";
|
||||||
|
version = config.version;
|
||||||
|
src = config.src;
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
gcc
|
||||||
|
gnumake
|
||||||
|
linux-pam
|
||||||
|
];
|
||||||
|
|
||||||
|
makeFlags =
|
||||||
|
[
|
||||||
|
"DESTDIR=$(out)"
|
||||||
|
"PREFIX="
|
||||||
|
]
|
||||||
|
++ lib.optional (
|
||||||
|
config.xsessions != null
|
||||||
|
) "CPPFLAGS+=-DSESSIONS_XSESSIONS=\\\"${config.xsessions}\\\""
|
||||||
|
++ lib.optional (
|
||||||
|
config.wayland-sessions != null
|
||||||
|
) "CPPFLAGS+=-DSESSIONS_WAYLAND=\\\"${config.wayland-sessions}\\\""
|
||||||
|
++ lib.optional (cfg-file != null) "CPPFLAGS+=-DLIDM_CONF_PATH=\\\"${cfg-file}\\\"";
|
||||||
|
|
||||||
|
fixupPhase = ''
|
||||||
|
rm -rf $out/etc
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
keysEnum = maker.keys-enum;
|
||||||
|
};
|
||||||
|
}
|
73
assets/pkg/nix/make-cfg.nix
Normal file
73
assets/pkg/nix/make-cfg.nix
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
{ lib, keys-h-file }:
|
||||||
|
|
||||||
|
let
|
||||||
|
double-match-to-nameval = dmatch: {
|
||||||
|
name = builtins.elemAt dmatch 0;
|
||||||
|
value = builtins.elemAt dmatch 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
keys-enum =
|
||||||
|
let
|
||||||
|
key-names = builtins.replaceStrings [ "\n" " " ] [ "" "" ] (
|
||||||
|
builtins.elemAt (builtins.match ".*KEY_NAMES\\[][[:blank:]]*=[[:blank:]]*\\{([^}]*)}.*" keys-h-file) 0
|
||||||
|
);
|
||||||
|
|
||||||
|
keys-2d-list = builtins.map (builtins.match "\\[(.*)]=\"(.*)\"") (
|
||||||
|
builtins.filter (s: builtins.isString s && s != "") (builtins.split "," key-names)
|
||||||
|
);
|
||||||
|
|
||||||
|
in
|
||||||
|
builtins.listToAttrs (
|
||||||
|
builtins.map (
|
||||||
|
k:
|
||||||
|
k
|
||||||
|
// {
|
||||||
|
value = {
|
||||||
|
__enum_key = k.value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) (builtins.map double-match-to-nameval keys-2d-list)
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit keys-enum;
|
||||||
|
make =
|
||||||
|
let
|
||||||
|
name-val-to-attrs = (name: value: { inherit name value; });
|
||||||
|
map-attrs = attrset: fn: lib.map fn (lib.attrsets.mapAttrsToList name-val-to-attrs attrset);
|
||||||
|
|
||||||
|
try-foldl' =
|
||||||
|
op: nul: list:
|
||||||
|
if (builtins.length list) == 0 then "" else builtins.foldl' op nul list;
|
||||||
|
concat-with = sepr: list: try-foldl' (x: y: if x == null then y else x + sepr + y) null list;
|
||||||
|
|
||||||
|
ser-bool = bool: if bool then "true" else "false";
|
||||||
|
ser-str = str: "\"${builtins.replaceStrings [ "\n" "\"" ] [ "\\n" "\\\"" ] str}\"";
|
||||||
|
ser-kvs =
|
||||||
|
{ name, value }:
|
||||||
|
if builtins.isList value then
|
||||||
|
concat-with "\n" (builtins.map (value: ser-kvs { inherit name value; }) value)
|
||||||
|
else
|
||||||
|
"${name} = ${
|
||||||
|
if builtins.isString value then
|
||||||
|
ser-str value
|
||||||
|
else if builtins.isInt value then
|
||||||
|
builtins.toString value
|
||||||
|
else if builtins.isBool value then
|
||||||
|
ser-bool value
|
||||||
|
else if builtins.isAttrs value then
|
||||||
|
value.__enum_key
|
||||||
|
else
|
||||||
|
builtins.throw "type not supported"
|
||||||
|
}";
|
||||||
|
|
||||||
|
ser-table =
|
||||||
|
table':
|
||||||
|
let
|
||||||
|
tname = table'.name;
|
||||||
|
table = table'.value;
|
||||||
|
in
|
||||||
|
"[${tname}]\n" + (concat-with "\n" (map-attrs table ser-kvs));
|
||||||
|
in
|
||||||
|
cfg: concat-with "\n\n" (map-attrs cfg ser-table);
|
||||||
|
}
|
73
assets/pkg/nix/module.nix
Normal file
73
assets/pkg/nix/module.nix
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.lidm;
|
||||||
|
|
||||||
|
dmcfg = config.services.displayManager;
|
||||||
|
desktops = dmcfg.sessionData.desktops;
|
||||||
|
|
||||||
|
version = "1.2.3";
|
||||||
|
lidmPkg = pkgs.callPackage ./lidm.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
config = {
|
||||||
|
inherit version lib;
|
||||||
|
cfg = cfg.config;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "javalsai";
|
||||||
|
repo = "lidm";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-eKgBoh+bRcl2Y7oOxW77Kjtb9Ws2Xln1SenknIsGxD4=";
|
||||||
|
};
|
||||||
|
|
||||||
|
xsessions = "${desktops}/share/xsessions";
|
||||||
|
wayland-sessions = "${desktops}/share/wayland-sessions";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
lidm.keysEnum = lib.mkOption {
|
||||||
|
type = with lib.types; attrs;
|
||||||
|
default = lidm.passthru.keysEnum;
|
||||||
|
readOnly = true;
|
||||||
|
description = "Keys enum constants";
|
||||||
|
};
|
||||||
|
services.lidm.config = lib.mkOption {
|
||||||
|
type =
|
||||||
|
with lib.types;
|
||||||
|
oneOf [
|
||||||
|
str
|
||||||
|
attrs
|
||||||
|
];
|
||||||
|
default = { };
|
||||||
|
description = "Config options for lidm | Either attr tree or name of bundled themes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
services.displayManager.defaultSession = "lidm";
|
||||||
|
|
||||||
|
systemd.services.lidm = {
|
||||||
|
description = "TUI display manager";
|
||||||
|
aliases = [ "display-manager.service" ];
|
||||||
|
after = [
|
||||||
|
"systemd-user-sessions.service"
|
||||||
|
"plymouth-quit-wait.service"
|
||||||
|
];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "idle";
|
||||||
|
ExecStart = "${lidmPkg}/bin/lidm 7";
|
||||||
|
StandardInput = "tty";
|
||||||
|
StandardOutput = "tty";
|
||||||
|
StandardError = "tty";
|
||||||
|
TTYPath = "/dev/tty7";
|
||||||
|
TTYReset = "yes";
|
||||||
|
TTYVHangup = "yes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -13,30 +13,30 @@ The manual steps for installation are:
|
|||||||
|
|
||||||
## Systemd
|
## Systemd
|
||||||
|
|
||||||
* Copy `systemd.service` to `/etc/systemd/system/lidm.service`
|
- Copy `systemd.service` to `/etc/systemd/system/lidm.service`
|
||||||
* To enable it you can run `systemctl enable lidm`
|
- To enable it you can run `systemctl enable lidm`
|
||||||
|
|
||||||
## Dinit
|
## Dinit
|
||||||
|
|
||||||
* Copy `dinit` to `/etc/dinit.d/lidm`
|
- Copy `dinit` to `/etc/dinit.d/lidm`
|
||||||
* To enable it, run `dinitctl enable lidm`
|
- To enable it, run `dinitctl enable lidm`
|
||||||
|
|
||||||
## Runit
|
## Runit
|
||||||
|
|
||||||
* Copy `runit/` to `/etc/runit/sv/lidm/`
|
- Copy `runit/` to `/etc/runit/sv/lidm/`
|
||||||
* Add the service with `ln -s /etc/runit/sv/lidm /run/runit/service`
|
- Add the service with `ln -s /etc/runit/sv/lidm /run/runit/service`
|
||||||
* And to enable it `sv enable lidm`
|
- And to enable it `sv enable lidm`
|
||||||
|
|
||||||
## OpenRC
|
## OpenRC
|
||||||
|
|
||||||
* Copy `openrc` to `/etc/init.d/lidm`
|
- Copy `openrc` to `/etc/init.d/lidm`
|
||||||
* Enable the service with `rc-update add lidm`
|
- Enable the service with `rc-update add lidm`
|
||||||
|
|
||||||
## S6
|
## S6
|
||||||
|
|
||||||
* Copy `s6/` to `/etc/s6/sv/lidm/`
|
- Copy `s6/` to `/etc/s6/sv/lidm/`
|
||||||
* Add the service with `s6-service add default 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)
|
- Reload the database with `s6-db-reload` (you might have to run this every time the service file changes)
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Make sure to disable any other service that might run on tty7, such us lightdm or most display managers out there.
|
> Make sure to disable any other service that might run on tty7, such us lightdm or most display managers out there.
|
||||||
|
@@ -5,9 +5,9 @@ After=systemd-user-sessions.service plymouth-quit-wait.service
|
|||||||
[Service]
|
[Service]
|
||||||
Type=idle
|
Type=idle
|
||||||
ExecStart=/usr/bin/lidm 7
|
ExecStart=/usr/bin/lidm 7
|
||||||
StandardError=journal
|
|
||||||
StandardInput=tty
|
StandardInput=tty
|
||||||
StandardOutput=tty
|
StandardOutput=tty
|
||||||
|
StandardError=tty
|
||||||
TTYPath=/dev/tty7
|
TTYPath=/dev/tty7
|
||||||
TTYReset=yes
|
TTYReset=yes
|
||||||
TTYVHangup=yes
|
TTYVHangup=yes
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
Contributions are welcome! Here's how you can help:
|
Contributions are welcome! Here's how you can help:
|
||||||
|
|
||||||
* [Contributing code](#code)
|
- [Contributing](#contributing)
|
||||||
* [Reporting issues](#issues)
|
- [Code](#code)
|
||||||
* [Other](#other)
|
- [Issues](#issues)
|
||||||
|
- [Other](#other)
|
||||||
|
|
||||||
## Code
|
## Code
|
||||||
|
|
||||||
@@ -12,33 +13,33 @@ For small fixes or incremental improvements simply fork the repo and follow the
|
|||||||
|
|
||||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and [clone](https://help.github.com/articles/cloning-a-repository/) your fork.
|
1. [Fork](https://help.github.com/articles/fork-a-repo/) the repository and [clone](https://help.github.com/articles/cloning-a-repository/) your fork.
|
||||||
|
|
||||||
2. Start coding! (it might be helpful to read a [quide on the project structure and conventions](structure.md) before this)
|
2. Start coding! (it might be helpful to read a [quide on the project structure and conventions](./structure.md) before this)
|
||||||
* Configure clangd LSP by generating `compile_commands.json` (e.g. `bear -- make` or `compiledb make`)
|
- Configure clangd LSP by generating `compile_commands.json` (e.g. `bear -- make` or `compiledb make`)
|
||||||
* Implement your feature.
|
- Implement your feature.
|
||||||
* Check your code works as expected.
|
- Check your code works as expected.
|
||||||
* Run the code formatter: `clang-format -i $(git ls-files "*.c" "*.h")`
|
- Run the code formatter: `clang-format -i $(git ls-files "*.c" "*.h")`.
|
||||||
* Run the code linter: `clang-tidy -p . $(git ls-files "*.c" "*.h")`. Some checks are pretty pedantic, feel free to ignore or debate some of the rules.
|
- Run the code linter: `clang-tidy -p . $(git ls-files "*.c" "*.h")`. Some checks are pretty pedantic, feel free to ignore or debate some of the rules.
|
||||||
* If you prefer, you can run `make pre-commit` to run several code style checks like the avobe along a few extra stuff.
|
- If you prefer, you can run `make pre-commit` to run several code style checks like the above along a few extra stuff (shellcheck, spellcheck, prettier, etc).
|
||||||
|
|
||||||
3. Commit your changes to a new branch (not `master`, one change per branch) and push it:
|
3. Commit your changes to a new branch (not `master`, one change per branch) and push it:
|
||||||
* Commit messages should:
|
- Commit messages should:
|
||||||
* Header line: explain the commit in one line (use the imperative) ("feat" for features, "fix", "style", "chore", "docs", etc)
|
- Header line: explain the commit in one line (use the imperative) ("feat" for features, "fix", "style", "chore", "docs", etc)
|
||||||
* Be descriptive.
|
- Be descriptive.
|
||||||
* Don't make the title too long and add commit descriptions if you think the changes need it.
|
- Don't make the title too long and add commit descriptions if you think the changes need it.
|
||||||
* e.g. "feat: add support for X", "fix(config): config parser segfaulting", "docs(typo): fix a typo in README.md"
|
- e.g. "feat: add support for X", "fix(config): config parser segfaulting", "docs(typo): fix a typo in README.md"
|
||||||
|
|
||||||
4. Once you are happy with your changes, submit a pull request.
|
4. Once you are happy with your changes, submit a pull request.
|
||||||
* Open the pull request.
|
- Open the pull request.
|
||||||
* Add a short description explaining what you've done (or if it's a work-in-progress - what you need to do)
|
- Add a short description explaining what you've done (or if it's a work-in-progress - what you need to do)
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
1. Do a quick search on GitHub to check if the issue has already been reported.
|
1. Do a quick search on GitHub to check if the issue has already been reported.
|
||||||
2. [Open an issue](https://github.com//javalsai/lidm/issues/new) and describe the issue you are having - you could include:
|
2. [Open an issue](https://github.com//javalsai/lidm/issues/new) and describe the issue you are having - you could include:
|
||||||
* Screenshots.
|
- Screenshots.
|
||||||
* Ways to reproduce the issue.
|
- Ways to reproduce the issue.
|
||||||
* Your lidm version.
|
- Your lidm version.
|
||||||
* Your platform (e.g. arch linux or Ubuntu 15.04 x64) and init system if you know.
|
- Your platform (e.g. arch linux or Ubuntu 15.04 x64) and init system if you know.
|
||||||
|
|
||||||
After reporting you should aim to answer questions or clarifications as this helps pinpoint the cause of the issue.
|
After reporting you should aim to answer questions or clarifications as this helps pinpoint the cause of the issue.
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Index
|
# Table of Contents
|
||||||
|
|
||||||
- [Index](#index)
|
|
||||||
- [Installing from Source](#installing-from-source)
|
- [Installing from Source](#installing-from-source)
|
||||||
- [AUR](#aur)
|
- [AUR](#aur)
|
||||||
- [Nix Flake](#nix-flake)
|
- [Nix Flake](#nix-flake)
|
||||||
|
- [Nix Module](#nix-module)
|
||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> I encourage you to read the manual installation steps to understand what will get installed in your computer by this package.
|
> I encourage you to read the manual installation steps to understand what will get installed in your computer by this package.
|
||||||
@@ -29,7 +29,7 @@ Then you can install the files onto your filesystem with:
|
|||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
And additionally, to install service files (start-up behavior). <sup>[more docs](./assets/services/README.md)</sup>
|
And additionally, to install service files (start-up behavior). <sup>[more docs](../assets/services/README.md)</sup>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# automatically detects your init system
|
# automatically detects your init system
|
||||||
@@ -52,10 +52,10 @@ make install-service-s6-etc # s6 (/etc/s6/sv)
|
|||||||
|
|
||||||
# AUR
|
# AUR
|
||||||
|
|
||||||
[AUR packages](https://aur.archlinux.org/packages?K=lidm\&SeB=n) will automatically install most files.
|
[AUR packages](https://aur.archlinux.org/packages?K=lidm&SeB=n) will automatically install most files.
|
||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> [service files](./assets/pkg/aur#services) have to be manually installed by now.
|
> [service files](../assets/pkg/aur#services) have to be manually installed by now.
|
||||||
|
|
||||||
# Nix Flake
|
# Nix Flake
|
||||||
|
|
||||||
@@ -72,4 +72,57 @@ nix run github:javalsai/lidm
|
|||||||
```
|
```
|
||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> This doesn't include [service files](./assets/pkg/aur#services) neither
|
> This doesn't include [service files](../assets/pkg/aur#services) neither
|
||||||
|
|
||||||
|
# Nix Module
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Sidenote</summary>
|
||||||
|
|
||||||
|
The nix module lacks on several aspects, if you know much about nix and know
|
||||||
|
how to improve this package, feel free to open an issue or a PR to help. The
|
||||||
|
nix package maintainer position is open too.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Lidm includes a nix module in `assets/pkg/nix/module.nix` that you can add
|
||||||
|
(along the included nix files) and import in your `configuration.nix`.
|
||||||
|
|
||||||
|
Once imported you'll need to add:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services.displayManager.enable = true;
|
||||||
|
systemd.services.lidm.enable = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally, you can configure it setting `services.lidm.config`. You can either
|
||||||
|
pass:
|
||||||
|
|
||||||
|
- A string to copy the config from a theme in `themes/` with said name
|
||||||
|
(**name**, e.g `"cherry"`).
|
||||||
|
- An attribute tree with the same names as the config file, e.g:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
with config.lidm.keysEnum; {
|
||||||
|
strings = {
|
||||||
|
f_poweroff = "custom_poweroff";
|
||||||
|
};
|
||||||
|
|
||||||
|
behavior = {
|
||||||
|
include_defshell = true;
|
||||||
|
source = [
|
||||||
|
"path1"
|
||||||
|
"path2"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
functions = { poweroff = F1; };
|
||||||
|
|
||||||
|
# etc...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
> _it's not necessary to cover all keys and anything can be put there, even if it's not valid config_
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> [service files](../assets/pkg/aur#services) **are** included and enabled
|
73
docs/PACKAGERS.md
Normal file
73
docs/PACKAGERS.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
This is a guide listing all possible options packagers have to tweak behavior of lidm and the extra stuff to package.
|
||||||
|
|
||||||
|
# Components
|
||||||
|
|
||||||
|
If you want to package lidm for a distribution you have to package the binary and:
|
||||||
|
|
||||||
|
- Man pages ([`../assets/man/`](../assets/man/))
|
||||||
|
- Service files ([`../assets/services/`](../assets/services/))
|
||||||
|
- PAM (see [#preprocessor-defines](#preprocessor-defines))
|
||||||
|
- And optionally you can include some default themes in `/usr` ([`../themes/`](../themes/))
|
||||||
|
|
||||||
|
# Preprocessor Defines
|
||||||
|
|
||||||
|
Most of the behavior that can be tweaked using preprocessor `#define`s, to include some simply add `CPPFLAGS+='-D{{name}}={{value}}'` to your `make` command. e.g:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make \
|
||||||
|
CPPFLAGS+='-DSESSIONS_XSESSIONS=\"/var/empty\"' \
|
||||||
|
CPPFLAGS+='-DSESSIONS_WAYLAND=\"/var/empty\"'
|
||||||
|
```
|
||||||
|
|
||||||
|
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_WAYLAND` | `"/usr/share/wayland-sessions"` | | No |
|
||||||
|
| `LIDM_CONF_PATH` | `"/etc/lidm.ini"` | Path of the default configuration. | Yes (`LIDM_CONF`) |
|
||||||
|
|
||||||
|
# Other Build Settings
|
||||||
|
|
||||||
|
## Compiler
|
||||||
|
|
||||||
|
Lidm attempts to support being built by `gcc` and `clang` with preference over the first. However, if you wish to take advantage of LLVM's optimizations over GNU's you can change the compiler with `make CC=clang` or try any other compiler.
|
||||||
|
|
||||||
|
## Compiler Flags
|
||||||
|
|
||||||
|
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=`
|
||||||
|
|
||||||
|
```txt
|
||||||
|
$ fd -t f . --base-directory $out
|
||||||
|
bin/lidm
|
||||||
|
etc/lidm.ini
|
||||||
|
share/man/man1/lidm.1
|
||||||
|
share/man/man5/lidm-config.5
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build Recipes for Packaging
|
||||||
|
|
||||||
|
To ease most of the installation process there's several `make` recipes to install man pages and service files, I encpurage you to check their source yourself, but:
|
||||||
|
|
||||||
|
- `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.
|
||||||
|
- `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.
|
12
flake.lock
generated
12
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710146030,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1724224976,
|
"lastModified": 1751637120,
|
||||||
"narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=",
|
"narHash": "sha256-xVNy/XopSfIG9c46nRmPaKfH1Gn/56vQ8++xWA8itO4=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c374d94f1536013ca8e92341b540eba4c22f9c62",
|
"rev": "5c724ed1388e53cc231ed98330a60eb2f7be4be3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
50
flake.nix
50
flake.nix
@@ -1,46 +1,46 @@
|
|||||||
{
|
{
|
||||||
|
description = "A ✨fully✨ colorful customizable TUI display manager made in C for simplicity.";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
{ flake-utils, nixpkgs, ... }:
|
{
|
||||||
|
flake-utils,
|
||||||
|
nixpkgs,
|
||||||
|
self,
|
||||||
|
}:
|
||||||
flake-utils.lib.eachDefaultSystem (
|
flake-utils.lib.eachDefaultSystem (
|
||||||
system:
|
system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
|
||||||
name = "lidm";
|
name = "lidm";
|
||||||
version = "0.0.2";
|
version = builtins.elemAt (builtins.match "VERSION[[:blank:]]*=[[:space:]]*([^\n]*)\n.*" (builtins.readFile ./Makefile)) 0;
|
||||||
|
|
||||||
lidm = (
|
|
||||||
pkgs.stdenv.mkDerivation {
|
|
||||||
pname = name;
|
|
||||||
version = version;
|
|
||||||
|
|
||||||
|
lidm = pkgs.callPackage assets/pkg/nix/lidm.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
lib = pkgs.lib;
|
||||||
|
config = {
|
||||||
|
inherit version;
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
xsessions = null;
|
||||||
nativeBuildInputs = with pkgs; [
|
wayland-sessions = null;
|
||||||
gcc
|
cfg = null;
|
||||||
gnumake
|
# cfg = "cherry";
|
||||||
linux-pam
|
};
|
||||||
];
|
};
|
||||||
|
|
||||||
makeFlags = [
|
|
||||||
"DESTDIR=$(out)"
|
|
||||||
"PREFIX="
|
|
||||||
];
|
|
||||||
|
|
||||||
fixupPhase = ''
|
|
||||||
rm -rf $out/etc
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
in
|
in
|
||||||
rec {
|
rec {
|
||||||
defaultApp = flake-utils.lib.mkApp { drv = defaultPackage; };
|
defaultApp = flake-utils.lib.mkApp { drv = defaultPackage; };
|
||||||
defaultPackage = lidm;
|
defaultPackage = lidm;
|
||||||
devShell = pkgs.mkShell { buildInputs = lidm.nativeBuildInputs ++ [ pkgs.clang-tools ]; };
|
devShell = pkgs.mkShell { buildInputs = lidm.nativeBuildInputs ++ [ pkgs.clang-tools ]; };
|
||||||
|
formatter = nixpkgs.legacyPackages.${system}.nixfmt-tree;
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
// {
|
||||||
|
nixosModules.lidm = assets/pkg/nix/module.nix;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
|
|
||||||
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
bool launch(char* NNULLABLE user, char* NNULLABLE passwd,
|
||||||
struct config* config);
|
struct session session, void (*NULLABLE cb)(void),
|
||||||
|
struct config* NNULLABLE config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
enum introspection_type {
|
enum IntrospectionType {
|
||||||
STRING,
|
STRING,
|
||||||
BOOL,
|
BOOL,
|
||||||
NUMBER,
|
NUMBER,
|
||||||
@@ -26,7 +26,7 @@ static const char* NNULLABLE const INTROS_TYS_NAMES[] = {
|
|||||||
struct introspection_item {
|
struct introspection_item {
|
||||||
char* NNULLABLE name;
|
char* NNULLABLE name;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
enum introspection_type typ;
|
enum IntrospectionType typ;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INTROS_ITEM(key, table, ty) \
|
#define INTROS_ITEM(key, table, ty) \
|
||||||
@@ -90,9 +90,9 @@ BUILD(colors, COLORS, TABLE_COLORS);
|
|||||||
BUILD(chars, CHARS, TABLE_CHARS);
|
BUILD(chars, CHARS, TABLE_CHARS);
|
||||||
|
|
||||||
#define TABLE_FUNCTIONS(F, name) \
|
#define TABLE_FUNCTIONS(F, name) \
|
||||||
F(enum keys, poweroff, KEY, F1, name) \
|
F(enum Keys, poweroff, KEY, F1, name) \
|
||||||
F(enum keys, reboot, KEY, F2, name) \
|
F(enum Keys, reboot, KEY, F2, name) \
|
||||||
F(enum keys, refresh, KEY, F5, name)
|
F(enum Keys, refresh, KEY, F5, name)
|
||||||
|
|
||||||
BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
|
BUILD(functions, FUNCTIONS, TABLE_FUNCTIONS);
|
||||||
|
|
||||||
@@ -150,15 +150,15 @@ struct introspection_table {
|
|||||||
|
|
||||||
static const struct introspection_table CONFIG_INSTROSPECTION[] = {
|
static const struct introspection_table CONFIG_INSTROSPECTION[] = {
|
||||||
{"colors", offsetof(struct config, colors), INTROS_TABLE_COLORS,
|
{"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,
|
{"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,
|
{"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,
|
{"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,
|
{"behavior", offsetof(struct config, behavior), INTROS_TABLE_BEHAVIOR,
|
||||||
sizeof(INTROS_TABLE_BEHAVIOR) / sizeof(INTROS_TABLE_BEHAVIOR[0])},
|
LEN(INTROS_TABLE_BEHAVIOR)},
|
||||||
};
|
};
|
||||||
|
|
||||||
//// FUNCTIONS
|
//// 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>
|
#include <stdlib.h>
|
||||||
|
|
||||||
enum keys {
|
enum Keys {
|
||||||
ESC,
|
ESC,
|
||||||
F1,
|
F1,
|
||||||
F2,
|
F2,
|
||||||
@@ -66,7 +66,7 @@ static const char* const KEY_NAMES[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct key_mapping {
|
struct key_mapping {
|
||||||
enum keys key;
|
enum Keys key;
|
||||||
const char* sequences[3];
|
const char* sequences[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void log_init(FILE* fd);
|
#include "macros.h"
|
||||||
void log_puts(const char* msg);
|
|
||||||
void log_printf(const char* fmt, ...);
|
void log_init(FILE* NNULLABLE fd);
|
||||||
|
void log_puts(const char* NNULLABLE msg);
|
||||||
|
void log_printf(const char* NNULLABLE fmt, ...);
|
||||||
// NOLINTNEXTLINE(readability-identifier-length)
|
// NOLINTNEXTLINE(readability-identifier-length)
|
||||||
void log_perror(const char* s);
|
void log_perror(const char* NNULLABLE s);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
#ifndef MACROSH_
|
#ifndef MACROSH_
|
||||||
#define MACROSH_
|
#define MACROSH_
|
||||||
|
|
||||||
|
// More like constants but I'm not making yet another header file just for this
|
||||||
|
#ifndef LIDM_CONF_PATH
|
||||||
|
#define LIDM_CONF_PATH "/etc/lidm.ini"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Do we just replace the compiler with clang??
|
// Do we just replace the compiler with clang??
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define NULLABLE _Nullable
|
#define NULLABLE _Nullable
|
||||||
@@ -31,5 +36,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LEN(X) (sizeof(X) / sizeof((X)[0]))
|
#define LEN(X) (sizeof(X) / sizeof((X)[0]))
|
||||||
|
#define UNUSED(x) ((void)(x))
|
||||||
|
|
||||||
#endif
|
#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_
|
#define SESSIONSH_
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
enum session_type {
|
enum SessionType {
|
||||||
XORG,
|
XORG,
|
||||||
WAYLAND,
|
WAYLAND,
|
||||||
SHELL,
|
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 {
|
struct session {
|
||||||
char* NNULLABLE name;
|
char* NNULLABLE name;
|
||||||
char* NNULLABLE exec;
|
struct session_exec exec;
|
||||||
char* NULLABLE tryexec;
|
enum SessionType type;
|
||||||
enum session_type type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Vector get_avaliable_sessions();
|
struct Vector get_avaliable_sessions();
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
#define VALUES_SEPR 3
|
#define VALUES_SEPR 3
|
||||||
#define VALUE_MAXLEN (BOX_WIDTH - VALUES_COL + 1 - BOX_HMARGIN - 2)
|
#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;
|
extern const u_char INPUTS_N;
|
||||||
|
|
||||||
void setup(struct config* config);
|
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_err(const char* /*msg*/);
|
||||||
void print_errno(const char* /*descr*/);
|
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_ffield();
|
||||||
void ui_update_ofield(struct opts_field* self);
|
void ui_update_ofield(struct opts_field* self);
|
||||||
void ui_update_cursor_focus();
|
void ui_update_cursor_focus();
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "ui.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_session;
|
||||||
extern struct opts_field of_user;
|
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 gusers;
|
||||||
extern struct Vector* UNULLABLE gsessions;
|
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 opts_field* NNULLABLE get_opts_ffield();
|
||||||
|
|
||||||
struct user st_user();
|
struct user st_user();
|
||||||
|
@@ -1,34 +1,45 @@
|
|||||||
#ifndef UTILH_
|
#ifndef UTILH_
|
||||||
#define UTILH_
|
#define UTILH_
|
||||||
|
|
||||||
#include <bits/types/struct_timeval.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
|
||||||
int find_keyname(enum keys* at, const char* name);
|
int find_keyname(enum Keys* at, const char* name);
|
||||||
enum keys find_ansi(const char* seq);
|
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);
|
void read_press(u_char* length, char* out);
|
||||||
// non blocking, waits up to tv or interrupt, returns true if actually read
|
// 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);
|
bool read_press_nb(u_char* length, char* out, struct timeval* tv);
|
||||||
|
|
||||||
|
// UTF8
|
||||||
|
//
|
||||||
bool utf8_iscont(char byte);
|
bool utf8_iscont(char byte);
|
||||||
size_t utf8len(const char* str);
|
size_t utf8len(const char* str);
|
||||||
size_t utf8len_until(const char* str, const char* until);
|
size_t utf8len_until(const char* str, const char* until);
|
||||||
|
size_t utf8trunc(char* str, size_t n);
|
||||||
const char* utf8back(const char* str);
|
const char* utf8back(const char* str);
|
||||||
const char* utf8seek(const char* str);
|
const char* utf8seek(const char* str);
|
||||||
const char* utf8seekn(const char* str, size_t n);
|
const char* utf8seekn(const char* str, size_t n);
|
||||||
|
|
||||||
|
// Vector
|
||||||
|
//
|
||||||
struct Vector {
|
struct Vector {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
void** pages;
|
void** pages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Vector vec_from_raw(void** raw);
|
||||||
|
void** vec_as_raw(struct Vector self);
|
||||||
extern const struct Vector VEC_NEW;
|
extern const struct Vector VEC_NEW;
|
||||||
int vec_resize(struct Vector* self, size_t size);
|
int vec_resize(struct Vector* self, size_t size);
|
||||||
int vec_reserve(struct Vector* self, size_t size);
|
int vec_reserve(struct Vector* self, size_t size);
|
||||||
|
321
src/auth.c
321
src/auth.c
@@ -1,3 +1,4 @@
|
|||||||
|
#include <errno.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <security/pam_misc.h>
|
#include <security/pam_misc.h>
|
||||||
@@ -7,69 +8,24 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "pam.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "unistd.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
int pam_conversation(int num_msg, const struct pam_message** msg,
|
static void try_source_file(struct Vector* NNULLABLE vec_envlist,
|
||||||
struct pam_response** resp, void* appdata_ptr) {
|
char* NNULLABLE filepath) {
|
||||||
struct pam_response* reply =
|
log_printf("sourcing %s\n", filepath);
|
||||||
(struct pam_response*)malloc(sizeof(struct pam_response) * num_msg);
|
FILE* file2source = fopen(filepath, "r");
|
||||||
if (!reply) {
|
if (file2source == NULL) {
|
||||||
return PAM_BUF_ERR;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
CHECK_PAM_RET(pam_start("login", 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;
|
char* line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@@ -79,13 +35,10 @@ void sourceFileTry(char* file) {
|
|||||||
if (read == 0 || (read > 0 && *line == '#')) continue;
|
if (read == 0 || (read > 0 && *line == '#')) continue;
|
||||||
if (line[read - 1] == '\n') line[read - 1] = '\0';
|
if (line[read - 1] == '\n') line[read - 1] = '\0';
|
||||||
|
|
||||||
/* printf("Retrieved line of length %zu:\n", read); */
|
for (ssize_t i = 1; i < read; i++) {
|
||||||
/* printf("%s\n", line); */
|
|
||||||
for (size_t i = 1; i < read; i++) {
|
|
||||||
if (line[i] == '=') {
|
if (line[i] == '=') {
|
||||||
/* printf("FOUND '='!\n"); */
|
vec_push(vec_envlist, (void*)line);
|
||||||
line[i] = '\0';
|
line = NULL;
|
||||||
setenv(line, &line[i + 1], 1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,66 +48,89 @@ void sourceFileTry(char* file) {
|
|||||||
(void)fclose(file2source);
|
(void)fclose(file2source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void moarEnv(char* user, struct session session, struct passwd* pw,
|
static void source_paths(struct Vector* NNULLABLE vec_envlist,
|
||||||
struct config* config) {
|
struct Vector* NNULLABLE abs_source,
|
||||||
if (chdir(pw->pw_dir) == -1) print_errno("can't chdir to user home");
|
const char* NULLABLE user_home,
|
||||||
|
struct Vector* NNULLABLE user_source) {
|
||||||
setenv("HOME", pw->pw_dir, true);
|
for (size_t i = 0; i < abs_source->length; i++) {
|
||||||
setenv("USER", pw->pw_name, true);
|
char* path = vec_get(abs_source, i);
|
||||||
setenv("SHELL", pw->pw_shell, true);
|
try_source_file(vec_envlist, path);
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
/* printf("\n"); */
|
|
||||||
|
|
||||||
if (pw->pw_dir) {
|
if (user_home)
|
||||||
const char* home = pw->pw_dir;
|
for (size_t i = 0; i < user_source->length; i++) {
|
||||||
size_t home_len = strlen(home);
|
char* path = NULL;
|
||||||
|
asprintf(&path, "%s/%s", user_home, (char*)vec_get(user_source, i));
|
||||||
for (size_t i = 0; i < config->behavior.user_source.length; i++) {
|
if (!path) {
|
||||||
const char* filename = (char*)vec_get(&config->behavior.user_source, i);
|
log_puts("alloc failure on user source\n");
|
||||||
size_t filename_len = strlen(filename);
|
continue;
|
||||||
|
}
|
||||||
size_t path_len = home_len + 1 + filename_len + 1; // nullbyte and slash
|
try_source_file(vec_envlist, path);
|
||||||
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);
|
|
||||||
free(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)
|
// NOLINTBEGIN(readability-function-cognitive-complexity)
|
||||||
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
||||||
struct config* config) {
|
struct config* config) {
|
||||||
@@ -170,89 +146,64 @@ bool launch(char* user, char* passwd, struct session session, void (*cb)(void),
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool* reach_session = shmalloc(sizeof(bool));
|
struct pamh_getenv_status env_ret =
|
||||||
if (reach_session == NULL) {
|
pamh_get_complete_env(pamh, pw, session.type);
|
||||||
perror("error allocating shared memory");
|
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;
|
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();
|
uint pid = fork();
|
||||||
if (pid == 0) { // child
|
if (pid == 0)
|
||||||
char* term = NULL;
|
forked(pipefd, pw, user, &session.exec, envlist);
|
||||||
char* getterm = getenv("TERM");
|
else {
|
||||||
// TODO: handle malloc error
|
struct child_msg msg;
|
||||||
if (getterm != NULL) term = strdup(getterm);
|
read(pipefd[0], &msg, sizeof(struct child_msg));
|
||||||
if (clearenv() != 0) {
|
close(pipefd[0]);
|
||||||
print_errno("clearenv");
|
if (msg.err) {
|
||||||
_exit(EXIT_FAILURE);
|
errno = msg._errno;
|
||||||
|
print_errno(msg.msg);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char** envlist = pam_getenvlist(pamh);
|
if (cb) cb();
|
||||||
if (envlist == NULL) {
|
printf("\x1b[0m\x1b[H\x1b[J");
|
||||||
print_errno("pam_getenvlist");
|
(void)fflush(stdout);
|
||||||
_exit(EXIT_FAILURE);
|
close(pipefd[1]);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
free((void*)envlist);
|
int exit_code;
|
||||||
moarEnv(user, session, pw, config);
|
waitpid((pid_t)pid, &exit_code, 0);
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
pam_setcred(pamh, PAM_DELETE_CRED);
|
pam_setcred(pamh, PAM_DELETE_CRED);
|
||||||
pam_close_session(pamh, 0);
|
pam_close_session(pamh, 0);
|
||||||
pam_end(pamh, PAM_SUCCESS);
|
pam_end(pamh, PAM_SUCCESS);
|
||||||
|
|
||||||
if (*reach_session == false) return false;
|
if (exit_code != 0) return false;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "chvt.h"
|
#include "chvt.h"
|
||||||
|
#include "macros.h"
|
||||||
|
|
||||||
static char* vterms[] = {"/dev/tty", "/dev/tty0", "/dev/vc/0", "/dev/systty",
|
static char* vterms[] = {"/dev/tty", "/dev/tty0", "/dev/vc/0", "/dev/systty",
|
||||||
"/dev/console"};
|
"/dev/console"};
|
||||||
@@ -24,15 +25,13 @@ int chvt_str(char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int chvt(int n) {
|
int chvt(int n) {
|
||||||
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
(void)fprintf(stderr, "activating vt %d\n", n);
|
(void)fprintf(stderr, "activating vt %d\n", n);
|
||||||
// NOLINTNEXTLINE(readability-identifier-length)
|
// NOLINTNEXTLINE(readability-identifier-length)
|
||||||
char c = 0;
|
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);
|
int fd = open(vterms[i], O_RDWR);
|
||||||
if (fd >= 0 && isatty(fd) && ioctl(fd, KDGKBTYPE, &c) == 0 && c < 3) {
|
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) {
|
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);
|
(void)fprintf(stderr, "Couldn't activate vt %d\n", n);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
19
src/config.c
19
src/config.c
@@ -12,6 +12,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "desktop.h"
|
#include "desktop.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define UPPER_HALF_BYTE 4
|
#define UPPER_HALF_BYTE 4
|
||||||
@@ -116,12 +117,12 @@ union typ_ptr {
|
|||||||
char** string;
|
char** string;
|
||||||
long long* number;
|
long long* number;
|
||||||
bool* boolean;
|
bool* boolean;
|
||||||
enum keys* key;
|
enum Keys* key;
|
||||||
struct Vector* vec;
|
struct Vector* vec;
|
||||||
uintptr_t ptr;
|
uintptr_t ptr;
|
||||||
};
|
};
|
||||||
struct parser_error parse_key(enum introspection_type typ, union typ_ptr at,
|
struct parser_error parse_key(enum IntrospectionType typ, union typ_ptr at,
|
||||||
char* key, size_t offset) {
|
char* key) {
|
||||||
char* aux_str = NULL;
|
char* aux_str = NULL;
|
||||||
struct parser_error aux_err;
|
struct parser_error aux_err;
|
||||||
|
|
||||||
@@ -218,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,
|
log_printf("[I] parsing [%s.%s] as %s\n", table, k,
|
||||||
INTROS_TYS_NAMES[this_intros_key->typ]);
|
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) {
|
if (err.msg != NULL) {
|
||||||
log_printf("[E] cfg parser, failed to parse [%s.%s] (%s): %s\n", table, k,
|
log_printf("[E] cfg parser, failed to parse [%s.%s] (%s): %s\n", table, k,
|
||||||
INTROS_TYS_NAMES[this_intros_key->typ], err.msg);
|
INTROS_TYS_NAMES[this_intros_key->typ], err.msg);
|
||||||
@@ -240,12 +241,10 @@ struct status config_line_handler(void* _config, char* table, char* k,
|
|||||||
int parse_config(struct config* NNULLABLE config, char* NNULLABLE path) {
|
int parse_config(struct config* NNULLABLE config, char* NNULLABLE path) {
|
||||||
FILE* fd = fopen(path, "r");
|
FILE* fd = fopen(path, "r");
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
perror("fopen");
|
log_perror("fopen");
|
||||||
(void)fputs(
|
log_printf(" [I] No config, place one at " LIDM_CONF_PATH
|
||||||
"Please place a config file at /etc/lidm.ini or set the LIDM_CONF "
|
" or set the LIDM_CONF env variable\n");
|
||||||
"env variable",
|
return 0; // Its fine now anyways
|
||||||
stderr);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = read_desktop(fd, config, config_line_handler);
|
bool ret = read_desktop(fd, config, config_line_handler);
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,readability-function-cognitive-complexity)
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -20,6 +19,7 @@ char* trim_str(char* str) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
int read_desktop(FILE* fd, void* ctx,
|
int read_desktop(FILE* fd, void* ctx,
|
||||||
struct status (*cb)(void* ctx, char* table, char* key,
|
struct status (*cb)(void* ctx, char* table, char* key,
|
||||||
char* value)) {
|
char* value)) {
|
||||||
@@ -66,7 +66,7 @@ int read_desktop(FILE* fd, void* ctx,
|
|||||||
buf_start[eq_idx] = '\0'; // the equal
|
buf_start[eq_idx] = '\0'; // the equal
|
||||||
key = trim_str(key);
|
key = trim_str(key);
|
||||||
char* value = &buf_start[eq_idx + 1];
|
char* value = &buf_start[eq_idx + 1];
|
||||||
buf_start[read_size - 1] = '\0'; // the newline
|
if (buf_start[read_size - 1] == '\n') buf_start[read_size - 1] = '\0';
|
||||||
value = trim_str(value);
|
value = trim_str(value);
|
||||||
|
|
||||||
// Callback
|
// Callback
|
||||||
@@ -82,4 +82,3 @@ int read_desktop(FILE* fd, void* ctx,
|
|||||||
if (buf != NULL) free(buf);
|
if (buf != NULL) free(buf);
|
||||||
return ret;
|
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 "ui.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
// NOLINTBEGIN(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
|
|
||||||
struct editable_field efield_new(char* content) {
|
struct editable_field efield_new(char* content) {
|
||||||
struct editable_field efield;
|
struct editable_field efield;
|
||||||
if (content != NULL) {
|
if (content != NULL) {
|
||||||
@@ -80,5 +78,3 @@ bool efield_seek(struct editable_field* self, char seek) {
|
|||||||
self->pos = (u_char)(ptr - self->content);
|
self->pos = (u_char)(ptr - self->content);
|
||||||
return ptr != start;
|
return ptr != start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTEND(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
|
|
||||||
|
@@ -32,7 +32,7 @@ void log_perror(const char* s) {
|
|||||||
if (!logger_out) return;
|
if (!logger_out) return;
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
(void)fprintf(logger_out, "%s: %s", s, strerror(errno));
|
(void)fprintf(logger_out, "%s: %s\n", s, strerror(errno));
|
||||||
else
|
else
|
||||||
(void)fprintf(logger_out, "%s", strerror(errno));
|
(void)fprintf(logger_out, "%s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
@@ -72,9 +72,10 @@ int main(int argc, char* argv[]) {
|
|||||||
chvt_str(argv[1]);
|
chvt_str(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy
|
||||||
struct config config = DEFAULT_CONFIG;
|
struct config config = DEFAULT_CONFIG;
|
||||||
char* conf_override = getenv("LIDM_CONF");
|
char* conf_override = getenv("LIDM_CONF");
|
||||||
char* conf_path = conf_override ? conf_override : "/etc/lidm.ini";
|
char* conf_path = conf_override ? conf_override : LIDM_CONF_PATH;
|
||||||
if (parse_config(&config, conf_path) != 0) {
|
if (parse_config(&config, conf_path) != 0) {
|
||||||
(void)fputs("error parsing config\n", stderr);
|
(void)fputs("error parsing config\n", stderr);
|
||||||
return 1;
|
return 1;
|
||||||
|
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,17 +8,26 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "desktop.h"
|
#include "desktop.h"
|
||||||
|
#include "desktop_exec.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
struct source_dir {
|
struct source_dir {
|
||||||
enum session_type type;
|
enum SessionType type;
|
||||||
char* dir;
|
char* dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef SESSIONS_XSESSIONS
|
||||||
|
#define SESSIONS_XSESSIONS "/usr/share/xsessions"
|
||||||
|
#endif
|
||||||
|
#ifndef SESSIONS_WAYLAND
|
||||||
|
#define SESSIONS_WAYLAND "/usr/share/wayland-sessions"
|
||||||
|
#endif
|
||||||
static const struct source_dir SOURCES[] = {
|
static const struct source_dir SOURCES[] = {
|
||||||
{XORG, "/usr/share/xsessions"},
|
{XORG, SESSIONS_XSESSIONS},
|
||||||
{WAYLAND, "/usr/share/wayland-sessions"},
|
{WAYLAND, SESSIONS_WAYLAND},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct Vector* cb_sessions = NULL;
|
static struct Vector* cb_sessions = NULL;
|
||||||
@@ -65,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
|
// also, always return 0 or we will break parsing and we don't want a bad
|
||||||
// desktop file to break all possible sessions
|
// desktop file to break all possible sessions
|
||||||
static enum session_type session_type;
|
static enum SessionType session_type;
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
||||||
|
UNUSED(sb);
|
||||||
|
|
||||||
// guessing symlink behavior
|
// guessing symlink behavior
|
||||||
// - FTW_PHYS if set doesn't follow symlinks, so ftw() has no flags and it
|
// - FTW_PHYS if set doesn't follow symlinks, so ftw() has no flags and it
|
||||||
// follows symlinks, we should never get to handle that
|
// follows symlinks, we should never get to handle that
|
||||||
@@ -88,22 +99,33 @@ static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ret = read_desktop(fd, &ctx, &cb);
|
int ret = read_desktop(fd, &ctx, &cb);
|
||||||
if (ret < 0) { // any error
|
// any error
|
||||||
log_printf("[E] format error parsing %s", fpath);
|
if (ret < 0) goto err_close;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)fclose(fd);
|
(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
|
// just add this to the list
|
||||||
if (ctx.name != NULL && ctx.exec != NULL) {
|
if (ctx.name != NULL && ctx.exec != NULL) {
|
||||||
struct session* this_session = malloc(sizeof(struct session));
|
struct session* this_session = malloc(sizeof(struct session));
|
||||||
if (this_session == NULL) return 0;
|
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){
|
*this_session = (struct session){
|
||||||
.name = ctx.name,
|
.name = ctx.name,
|
||||||
.exec = ctx.exec,
|
.exec = session_exec_desktop(arg_count, args),
|
||||||
.tryexec = ctx.tryexec,
|
|
||||||
.type = session_type,
|
.type = session_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,6 +133,12 @@ static int fn(const char* fpath, const struct stat* sb, int typeflag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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
|
// This code is designed to be run purely single threaded
|
||||||
@@ -120,7 +148,7 @@ struct Vector get_avaliable_sessions() {
|
|||||||
vec_reserve(&sessions, LIKELY_BOUND_SESSIONS);
|
vec_reserve(&sessions, LIKELY_BOUND_SESSIONS);
|
||||||
|
|
||||||
cb_sessions = &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);
|
log_printf("[I] parsing into %s\n", SOURCES[i].dir);
|
||||||
session_type = SOURCES[i].type;
|
session_type = SOURCES[i].type;
|
||||||
ftw(SOURCES[i].dir, &fn, 1);
|
ftw(SOURCES[i].dir, &fn, 1);
|
||||||
|
62
src/ui.c
62
src/ui.c
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <asm-generic/errno.h>
|
#include <asm-generic/errno.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "launch_state.h"
|
#include "launch_state.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "ofield.h"
|
#include "ofield.h"
|
||||||
#include "sessions.h"
|
#include "sessions.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
@@ -60,6 +62,7 @@ struct config* g_config = NULL;
|
|||||||
static volatile sig_atomic_t need_resize = 0;
|
static volatile sig_atomic_t need_resize = 0;
|
||||||
|
|
||||||
static void process_sigwinch(int signal) {
|
static void process_sigwinch(int signal) {
|
||||||
|
UNUSED(signal);
|
||||||
need_resize = 1;
|
need_resize = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,30 +111,22 @@ static char* fmt_time(const char* fmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* trunc_gethostname(const size_t MAXSIZE, const char* const ELLIPSIS) {
|
char* trunc_gethostname(const size_t MAXLEN, const char* const ELLIPSIS) {
|
||||||
if (utf8len(ELLIPSIS) > MAXSIZE) return NULL;
|
if (utf8len(ELLIPSIS) > MAXLEN) return NULL;
|
||||||
size_t alloc_size = MAXSIZE + 1;
|
size_t alloc_size = HOST_NAME_MAX + strlen(ELLIPSIS) + 1;
|
||||||
char* buf = malloc(alloc_size);
|
char* buf = malloc(alloc_size);
|
||||||
if (!buf) return NULL;
|
if (!buf) return NULL;
|
||||||
while (true) {
|
|
||||||
if (gethostname(buf, alloc_size) == 0) return buf;
|
|
||||||
if (errno == ENAMETOOLONG) {
|
|
||||||
buf[alloc_size] = '\0';
|
|
||||||
if (utf8len(buf) > MAXSIZE - utf8len(ELLIPSIS)) {
|
|
||||||
strcpy(&buf[MAXSIZE - utf8len(ELLIPSIS)], ELLIPSIS);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
alloc_size *= 2;
|
if (gethostname(buf, alloc_size) != 0) {
|
||||||
char* nbuf = realloc(buf, alloc_size);
|
free(buf);
|
||||||
if (!nbuf) goto fail;
|
return NULL;
|
||||||
buf = nbuf;
|
|
||||||
} else
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
fail:
|
|
||||||
free(buf);
|
if (utf8len(buf) > MAXLEN) {
|
||||||
return NULL;
|
size_t end = utf8trunc(buf, MAXLEN - utf8len(ELLIPSIS));
|
||||||
|
strcpy(&buf[end], ELLIPSIS);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_update_cursor_focus() {
|
void ui_update_cursor_focus() {
|
||||||
@@ -158,7 +153,7 @@ void ui_update_cursor_focus() {
|
|||||||
(void)printf("\x1b[%d;%dH", line, col);
|
(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) {
|
if (focused_input == PASSWD) {
|
||||||
print_passwd(utf8len(of_passwd.efield.content), false);
|
print_passwd(utf8len(of_passwd.efield.content), false);
|
||||||
} else if (focused_input == SESSION) {
|
} else if (focused_input == SESSION) {
|
||||||
@@ -177,7 +172,7 @@ void ui_update_ffield() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ui_update_ofield(struct opts_field* NNULLABLE self) {
|
void ui_update_ofield(struct opts_field* NNULLABLE self) {
|
||||||
enum input input;
|
enum Input input;
|
||||||
if (self == &of_session)
|
if (self == &of_session)
|
||||||
input = SESSION;
|
input = SESSION;
|
||||||
else if (self == &of_user)
|
else if (self == &of_user)
|
||||||
@@ -287,28 +282,29 @@ int load(struct Vector* users, struct Vector* sessions) {
|
|||||||
(void)fflush(stdout);
|
(void)fflush(stdout);
|
||||||
if (!read_press_nb(&len, seq, &tv)) continue;
|
if (!read_press_nb(&len, seq, &tv)) continue;
|
||||||
if (*seq == '\x1b') {
|
if (*seq == '\x1b') {
|
||||||
enum keys ansi_code = find_ansi(seq);
|
struct option_keys ansi_code = find_ansi(seq);
|
||||||
if (ansi_code != -1) {
|
if (ansi_code.is_some) {
|
||||||
if (ansi_code == ESC) {
|
enum Keys ansi_key = ansi_code.key;
|
||||||
|
if (ansi_key == ESC) {
|
||||||
esc = 2;
|
esc = 2;
|
||||||
} else if (ansi_code == g_config->functions.refresh) {
|
} else if (ansi_key == g_config->functions.refresh) {
|
||||||
restore_all();
|
restore_all();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (ansi_code == g_config->functions.reboot) {
|
} else if (ansi_key == g_config->functions.reboot) {
|
||||||
restore_all();
|
restore_all();
|
||||||
reboot(RB_AUTOBOOT);
|
reboot(RB_AUTOBOOT);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (ansi_code == g_config->functions.poweroff) {
|
} else if (ansi_key == g_config->functions.poweroff) {
|
||||||
restore_all();
|
restore_all();
|
||||||
reboot(RB_POWER_OFF);
|
reboot(RB_POWER_OFF);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (ansi_code == A_UP || ansi_code == A_DOWN) {
|
} else if (ansi_key == A_UP || ansi_key == A_DOWN) {
|
||||||
st_ch_focus(ansi_code == A_DOWN ? 1 : -1);
|
st_ch_focus(ansi_key == A_DOWN ? 1 : -1);
|
||||||
} else if (ansi_code == A_RIGHT || ansi_code == A_LEFT) {
|
} else if (ansi_key == A_RIGHT || ansi_key == A_LEFT) {
|
||||||
if (esc)
|
if (esc)
|
||||||
st_ch_of_opts(ansi_code == A_RIGHT ? 1 : -1);
|
st_ch_of_opts(ansi_key == A_RIGHT ? 1 : -1);
|
||||||
else
|
else
|
||||||
st_ch_ef_col(ansi_code == A_RIGHT ? 1 : -1);
|
st_ch_ef_col(ansi_key == A_RIGHT ? 1 : -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "users.h"
|
#include "users.h"
|
||||||
|
|
||||||
enum input focused_input = PASSWD;
|
enum Input focused_input = PASSWD;
|
||||||
|
|
||||||
struct Vector* gusers;
|
struct Vector* gusers;
|
||||||
struct Vector* gsessions;
|
struct Vector* gsessions;
|
||||||
@@ -13,7 +13,7 @@ struct opts_field of_session;
|
|||||||
struct opts_field of_user;
|
struct opts_field of_user;
|
||||||
struct opts_field of_passwd;
|
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 == SESSION) return &of_session;
|
||||||
if (from == USER) return &of_user;
|
if (from == USER) return &of_user;
|
||||||
if (from == PASSWD) return &of_passwd;
|
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) {
|
if (include_defshell && of_session.current_opt == gsessions->length + 1) {
|
||||||
struct session shell_session;
|
struct session shell_session;
|
||||||
shell_session.type = SHELL;
|
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;
|
return shell_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +50,8 @@ struct session st_session(bool include_defshell) {
|
|||||||
|
|
||||||
struct session custom_session;
|
struct session custom_session;
|
||||||
custom_session.type = SHELL;
|
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;
|
return custom_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ void st_kbd_type(char* text, bool cfg_include_defshell) {
|
|||||||
start = st_user().username;
|
start = st_user().username;
|
||||||
if (focused_input == SESSION && of_session.current_opt != 0 &&
|
if (focused_input == SESSION && of_session.current_opt != 0 &&
|
||||||
st_session(cfg_include_defshell).type == SHELL)
|
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);
|
ofield_kbd_type(field, text, start);
|
||||||
ui_update_ffield();
|
ui_update_ffield();
|
||||||
|
48
src/util.c
48
src/util.c
@@ -13,10 +13,10 @@
|
|||||||
|
|
||||||
static int selret_magic();
|
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++) {
|
for (size_t i = 0; i < LEN(KEY_MAPPINGS); i++) {
|
||||||
if (strcmp(KEY_NAMES[i], name) == 0) {
|
if (strcmp(KEY_NAMES[i], name) == 0) {
|
||||||
*at = (enum keys)i;
|
*at = (enum Keys)i;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,16 +24,19 @@ int find_keyname(enum keys* at, const char* name) {
|
|||||||
return -1;
|
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++) {
|
for (size_t i = 0; i < LEN(KEY_MAPPINGS); i++) {
|
||||||
struct key_mapping mapping = KEY_MAPPINGS[i];
|
struct key_mapping mapping = KEY_MAPPINGS[i];
|
||||||
for (size_t j = 0; mapping.sequences[j] != NULL; j++) {
|
for (size_t j = 0; mapping.sequences[j] != NULL; j++) {
|
||||||
if (strcmp(mapping.sequences[j], seq) == 0) {
|
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) {
|
void read_press(u_char* length, char* out) {
|
||||||
@@ -103,6 +106,24 @@ size_t utf8len_until(const char* str, const char* until) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t utf8trunc(char* str, size_t n) {
|
||||||
|
size_t bytes = 0;
|
||||||
|
while (true) {
|
||||||
|
if (str[bytes] == '\0') break;
|
||||||
|
if (utf8_iscont(str[bytes])) {
|
||||||
|
bytes++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
str[bytes] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bytes++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
const char* utf8back(const char* str) {
|
const char* utf8back(const char* str) {
|
||||||
while (utf8_iscont(*(--str))) {
|
while (utf8_iscont(*(--str))) {
|
||||||
}
|
}
|
||||||
@@ -129,6 +150,23 @@ const struct Vector VEC_NEW = {
|
|||||||
.pages = NULL,
|
.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) {
|
int vec_resize(struct Vector* self, size_t size) {
|
||||||
void** new_location =
|
void** new_location =
|
||||||
(void**)realloc((void*)self->pages, size * sizeof(void*));
|
(void**)realloc((void*)self->pages, size * sizeof(void*));
|
||||||
|
Reference in New Issue
Block a user