Skip to content

Commit

Permalink
Merged master into branch
Browse files Browse the repository at this point in the history
  • Loading branch information
tvrzna committed Aug 15, 2020
2 parents b4d087e + 128dd9b commit bd65c1e
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 58 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Dead simple CLI Display Manager on TTY

![](screenshot.png)

[![Packaging status](https://repology.org/badge/vertical-allrepos/emptty.svg)](https://repology.org/project/emptty/versions)

## Configuration

#### /etc/emptty/conf
Expand All @@ -25,11 +27,14 @@ __NOTE:__ to enable autologin DEFAULT_USER must be in group nopasswdlogin, other

`XINITRC_LAUNCH` Starts Xorg desktop with calling "\~/.xinitrc" script, if is true, file exists and selected WM/DE is Xorg session, it overrides DBUS_LAUNCH. If `.emptty` is handled as script, this config is overriden to false.

`VERTICAL_SELECTION` Prints available WM/DE each on new line instead of printing on single line.

#### /etc/emptty/motd
Custom file, that prints your own MOTD. Reading this file supports colors (e.g. `\x1b[31m` or `\033[32m`).

#### ${HOME}/.emptty
#### ${HOME}/.config/emptty or ${HOME}/.emptty
Optional configuration file, that could be also handled as shell script. If is not presented, emptty shows selection of installed desktops.
Configuration file stored as `${HOME}/.config/emptty` has higher priority on loading.
See [samples](SAMPLES.md#emptty-as-config)

`ENVIRONMENT` Selects, which environment should be defined for following command. Possible values are "xorg" and "wayland", "xorg" is default.
Expand Down Expand Up @@ -57,9 +62,11 @@ If config `XINITRC_LAUNCH` is set to true, it enables possibility to use .xinitr
- go
- gcc
- pam-devel
- libx11-devel (libx11)

### Dependencies
- pam
- libx11
- xorg / xorg-server (optional)
- xauth / xorg-xauth (required for xorg)
- mcookie (required for xorg)
Expand Down
8 changes: 4 additions & 4 deletions SAMPLES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# emptty - Samples

## \~/.emptty as config
In your home folder you have to create `.emptty` file. If `environment` is not defined, it assumes xorg.
## \~/.config/emptty or \~/.emptty as config
In your .config folder you have to create 'emptty' file or in your home folder you have to create `.emptty` file. If `environment` is not defined, it assumes xorg.

#### Xorg session
```
Expand All @@ -15,8 +15,8 @@ command=/usr/bin/sway
environment=wayland
```

## \~/.emptty as script
In your home folder you have to create `.emptty` file. This file needs to have execution permission (`chmod +x ~/.emptty`).
## \~/.config/emptty or \~/.emptty as script
In your .config folder you have to create 'emptty' file or in your home folder you have to create `.emptty` file. This file needs to have execution permission (`chmod +x ~/.config/emptty` or `chmod +x ~/.emptty`).
```
#!/bin/sh
environment=xorg
Expand Down
37 changes: 21 additions & 16 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,30 @@ import (
)

const (
confTTYnumber = "TTY_NUMBER"
confSwitchTTY = "SWITCH_TTY"
confPrintIssue = "PRINT_ISSUE"
confDefaultUser = "DEFAULT_USER"
confAutologin = "AUTOLOGIN"
confLang = "LANG"
confDbusLaunch = "DBUS_LAUNCH"
confXinitrcLaunch = "XINITRC_LAUNCH"
confTTYnumber = "TTY_NUMBER"
confSwitchTTY = "SWITCH_TTY"
confPrintIssue = "PRINT_ISSUE"
confDefaultUser = "DEFAULT_USER"
confAutologin = "AUTOLOGIN"
confLang = "LANG"
confDbusLaunch = "DBUS_LAUNCH"
confXinitrcLaunch = "XINITRC_LAUNCH"
confVerticalSelection = "VERTICAL_SELECTION"

pathConfigFile = "/etc/emptty/conf"
)

// config defines structure of application configuration.
type config struct {
defaultUser string
autologin bool
tty int
switchTTY bool
printIssue bool
lang string
dbusLaunch bool
xinitrcLaunch bool
defaultUser string
autologin bool
tty int
switchTTY bool
printIssue bool
lang string
dbusLaunch bool
xinitrcLaunch bool
verticalSelection bool
}

// LoadConfig handles loading of application configuration.
Expand All @@ -54,6 +56,8 @@ func loadConfig() *config {
c.dbusLaunch = parseBool(value, "true")
case confXinitrcLaunch:
c.xinitrcLaunch = parseBool(value, "false")
case confVerticalSelection:
c.verticalSelection = parseBool(value, "false")
}
})
handleErr(err)
Expand All @@ -65,6 +69,7 @@ func loadConfig() *config {
os.Unsetenv(confDefaultUser)
os.Unsetenv(confAutologin)
os.Unsetenv(confDbusLaunch)
os.Unsetenv(confVerticalSelection)

return &c
}
Expand Down
43 changes: 25 additions & 18 deletions desktop.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type lastSession struct {
}

// Allows to select desktop, which could be selected.
func selectDesktop(uid int) *desktop {
func selectDesktop(uid int, conf *config) *desktop {
desktops := listAllDesktops()
if len(desktops) == 0 {
handleStrErr("Not found any installed desktop.")
Expand All @@ -70,7 +70,11 @@ func selectDesktop(uid int) *desktop {
fmt.Printf("\n")
for i, v := range desktops {
if i > 0 {
fmt.Print(", ")
if conf.verticalSelection {
fmt.Print("\n")
} else {
fmt.Print(", ")
}
}
fmt.Printf("[%d] %s", i, v.name)
}
Expand Down Expand Up @@ -161,24 +165,27 @@ func getDesktop(path string, env enEnvironment) *desktop {

// Parses user-specified configuration from file and returns it as desktop structure.
func loadUserDesktop(homeDir string) (*desktop, string) {
confFile := homeDir + "/.emptty"
homeDirConf := homeDir + "/.emptty"
confDirConf := homeDir + "/.config/emptty"

var lang string
if fileExists(confFile) {
d := desktop{isUser: true, path: confFile, env: Xorg}

err := readProperties(confFile, func(key string, value string) {
switch key {
case confCommand:
d.exec = sanitizeValue(value, "")
case confEnvironment:
d.env = parseEnv(value, constEnvXorg)
case confLang:
lang = value
}
})
handleErr(err)
return &d, lang
for _, confFile := range []string{confDirConf, homeDirConf} {
if fileExists(confFile) {
d := desktop{isUser: true, path: confFile, env: Xorg}

err := readProperties(confFile, func(key string, value string) {
switch key {
case confCommand:
d.exec = sanitizeValue(value, "")
case confEnvironment:
d.env = parseEnv(value, constEnvXorg)
case confLang:
lang = value
}
})
handleErr(err)
return &d, lang
}
}

return nil, lang
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ module github.com/tvrzna/emptty
go 1.14

require (
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/msteinert/pam v0.0.0-20190215180659-f29b9f28d6f9
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/msteinert/pam v0.0.0-20190215180659-f29b9f28d6f9 h1:ZivaaKmjs9q90zi6I4gTLW6tbVGtlBjellr3hMYaly0=
github.com/msteinert/pam v0.0.0-20190215180659-f29b9f28d6f9/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs=
35 changes: 20 additions & 15 deletions login.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"strconv"
"strings"
"syscall"
"time"

"github.com/msteinert/pam"
)
Expand Down Expand Up @@ -42,7 +41,7 @@ func login(conf *config) {
d, usrLang := loadUserDesktop(usr.homedir)

if d == nil {
d = selectDesktop(usr.uid)
d = selectDesktop(usr.uid, conf)
}

if usrLang != "" {
Expand Down Expand Up @@ -174,7 +173,7 @@ func wayland(usr *sysuser, d *desktop, conf *config) {

// start Wayland
wayland, strExec := prepareGuiCommand(usr, d, conf)
registerInterruptHandler(wayland)
registerInterruptHandler(nil, wayland)

log.Print("Starting " + strExec)
wayland.Stdout = log.Writer()
Expand Down Expand Up @@ -231,17 +230,13 @@ func xorg(usr *sysuser, d *desktop, conf *config) {
}
log.Print("Started Xorg")

for i := 0; i < 50; i++ {
if fileExists("/tmp/.X11-unix/X" + freeDisplay) {
break
} else {
time.Sleep(10 * time.Millisecond)
}
}
disp := &xdisplay{}
handleErr(disp.openXDisplay())
defer disp.openXDisplay()

// start xinit
xinit, strExec := prepareGuiCommand(usr, d, conf)
registerInterruptHandler(xorg, xinit)
registerInterruptHandler(disp, xorg, xinit)
log.Print("Starting " + strExec)
xinit.Stdout = log.Writer()
xinit.Stderr = log.Writer()
Expand All @@ -268,7 +263,10 @@ func xorg(usr *sysuser, d *desktop, conf *config) {
func prepareGuiCommand(usr *sysuser, d *desktop, conf *config) (*exec.Cmd, string) {
strExec, allowStartupPrefix := getStrExec(d)

startScript := false

if d.env == Xorg && conf.xinitrcLaunch && allowStartupPrefix && !strings.Contains(strExec, ".xinitrc") && fileExists(usr.homedir+"/.xinitrc") {
startScript = true
allowStartupPrefix = false
strExec = usr.homedir + "/.xinitrc " + strExec
}
Expand All @@ -281,7 +279,11 @@ func prepareGuiCommand(usr *sysuser, d *desktop, conf *config) (*exec.Cmd, strin

var cmd *exec.Cmd
if len(arrExec) > 1 {
cmd = exec.Command(arrExec[0], arrExec...)
if startScript {
cmd = exec.Command("/bin/sh", arrExec...)
} else {
cmd = exec.Command(arrExec[0], arrExec...)
}
} else {
cmd = exec.Command(arrExec[0])
}
Expand Down Expand Up @@ -312,19 +314,22 @@ func getFreeXDisplay() int {
}

// Registers interrupt handler, that interrupts all mentioned Cmds.
func registerInterruptHandler(cmds ...*exec.Cmd) {
func registerInterruptHandler(disp *xdisplay, cmds ...*exec.Cmd) {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGKILL)
go handleInterrupt(c, cmds...)
go handleInterrupt(c, disp, cmds...)
}

// Catch interrupt signal chan and interrupts all mentioned Cmds.
func handleInterrupt(c chan os.Signal, cmds ...*exec.Cmd) {
func handleInterrupt(c chan os.Signal, disp *xdisplay, cmds ...*exec.Cmd) {
<-c
log.Print("Catched interrupt signal")
for _, cmd := range cmds {
cmd.Process.Signal(os.Interrupt)
cmd.Wait()
}
if disp != nil {
disp.closeXDisplay()
}
os.Exit(1)
}
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package main

const version = "0.2.2"
const version = "0.2.3"

func main() {
handleArgs()
Expand Down
5 changes: 4 additions & 1 deletion res/conf
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ AUTOLOGIN=false
DBUS_LAUNCH=true

# Starts Xorg desktop with calling "~/.xinitrc" script, if is true, file exists and selected WM/DE is Xorg session, it overrides DBUS_LAUNCH.
XINITRC_LAUNCH=false
XINITRC_LAUNCH=false

# Prints available WM/DE each on new line instead of printing on single line.
VERTICAL_SELECTION=false
8 changes: 6 additions & 2 deletions res/emptty.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH EMPTTY 1 "July 2020" "emptty 0.2.2" emptty
.TH EMPTTY 1 "August 2020" "emptty 0.2.3" emptty

.SH NAME
emptty \- Dead simple CLI Display Manager on TTY
Expand Down Expand Up @@ -49,6 +49,8 @@ Starts Xorg desktop with calling
script, if is true, file exists and selected WM/DE is Xorg session, it overrides DBUS_LAUNCH. If
.I .emptty
is handled as script, this config is overriden to false.
.IP VERTICAL_SELECTION
Prints available WM/DE each on new line instead of printing on single line.

.SH CUSTOM MOTD
Optional file stored as /etc/emptty/motd
Expand All @@ -60,7 +62,9 @@ or
)

.SH USER CONFIG
Optional file stored as ${HOME}/.emptty
Optional file stored as ${HOME}/.config/emptty or ${HOME}/.emptty

Configuration file stored as ${HOME}/.config/emptty has higher priority on loading.
.IP ENVIRONMENT
Selects, which environment should be defined for following command. Possible values are "xorg" and "wayland", "xorg" is default.
.IP COMMAND
Expand Down
Binary file modified screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions xlib.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

// #cgo LDFLAGS: -lX11
// #include <stdlib.h>
// #include <X11/Xlib.h>
import "C"
import (
"errors"
"time"
"unsafe"
)

type xdisplay struct {
disp *C.Display
}

// Opens XDisplay with xlib.
func (c *xdisplay) openXDisplay() error {
if c.disp != nil {
return errors.New("X Display is already opened")
}
for i := 0; i < 50; i++ {
d := C.XOpenDisplay(nil)
if d != nil {
c.disp = d
return nil
} else {
time.Sleep(50 * time.Millisecond)
}
}
return errors.New("Could not open X Display")
}

// Closes XDisplay with xlib
func (c *xdisplay) closeXDisplay() error {
if c.disp == nil {
return errors.New("Not connected to any X Display")
}
if C.XCloseDisplay(c.disp) == 0 {
C.free(unsafe.Pointer(c.disp))
return nil
}
return errors.New("Could not close active X Display")
}

0 comments on commit bd65c1e

Please sign in to comment.