diff options
Diffstat (limited to 'core')
| -rw-r--r-- | core/slogin/Makefile | 33 | ||||
| -rw-r--r-- | core/slogin/config.def.h | 5 | ||||
| -rw-r--r-- | core/slogin/config.mk | 19 | ||||
| -rw-r--r-- | core/slogin/slogin.c | 193 |
4 files changed, 250 insertions, 0 deletions
diff --git a/core/slogin/Makefile b/core/slogin/Makefile new file mode 100644 index 0000000..7026ffb --- /dev/null +++ b/core/slogin/Makefile @@ -0,0 +1,33 @@ +# slogin - simple login manager +# See LICENSE file for license details. + +include config.mk + +SRC = slogin.c +OBJ = ${SRC:.c=.o} + +all: slogin + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk + +config.h: + cp config.def.h $@ + +slogin: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + rm -f slogin ${OBJ} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f slogin ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/slogin + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/slogin + +.PHONY: all clean install uninstall diff --git a/core/slogin/config.def.h b/core/slogin/config.def.h new file mode 100644 index 0000000..49866aa --- /dev/null +++ b/core/slogin/config.def.h @@ -0,0 +1,5 @@ +static const char *fontname = "monospace:size=12"; +static const char *bgcolor = "#000000"; +static const char *fgcolor = "#bbbbbb"; +/* command to run after successful login */ +static const char *logincmd[] = { "/bin/sh", "-c", "exec dwm", NULL }; diff --git a/core/slogin/config.mk b/core/slogin/config.mk new file mode 100644 index 0000000..b5c24e9 --- /dev/null +++ b/core/slogin/config.mk @@ -0,0 +1,19 @@ +VERSION = 0.1 + +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +FREETYPELIBS = -lfontconfig -lXft +FREETYPEINC = /usr/include/freetype2 + +INCS = -I${X11INC} -I${FREETYPEINC} +LIBS = -L${X11LIB} -lX11 ${FREETYPELIBS} -lcrypt + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H +CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} +LDFLAGS = ${LIBS} + +CC = cc diff --git a/core/slogin/slogin.c b/core/slogin/slogin.c new file mode 100644 index 0000000..24a534b --- /dev/null +++ b/core/slogin/slogin.c @@ -0,0 +1,193 @@ +/* See LICENSE file for license details. */ +#define _XOPEN_SOURCE 700 +#include <X11/Xlib.h> +#include <X11/Xft/Xft.h> +#include <X11/keysym.h> +#include <unistd.h> +#include <pwd.h> +#include <grp.h> +#include <shadow.h> +#include <crypt.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include "../accent.h" +#include "config.h" + +static ColorShm *accentshm; +static char accentcol[8] = "#005577"; + +static void +die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +static void +updateaccent(void) +{ + if (!readaccent(&accentshm, accentcol)) + memcpy(accentcol, "#005577", 8); +} + +static const char * +gethash(const char *user) +{ + struct passwd *pw; + const char *hash; + if (!(pw = getpwnam(user))) + return NULL; + hash = pw->pw_passwd; +#if HAVE_SHADOW_H + if (!strcmp(hash, "x")) { + struct spwd *sp; + if (!(sp = getspnam(user))) + return NULL; + hash = sp->sp_pwdp; + } +#endif + return hash; +} + +static int +auth(const char *user, const char *pass) +{ + const char *hash = gethash(user); + char *cryptpw; + if (!hash) + return 0; + if (!(cryptpw = crypt(pass, hash))) + return 0; + return !strcmp(cryptpw, hash); +} + +static void +runsession(const char *user, const char *pass) +{ + struct passwd *pw; + if (!auth(user, pass)) + return; + if (!(pw = getpwnam(user))) + return; + if (initgroups(user, pw->pw_gid) < 0) + die("slogin: initgroups failed\n"); + if (setgid(pw->pw_gid) < 0) + die("slogin: setgid failed\n"); + if (setuid(pw->pw_uid) < 0) + die("slogin: setuid failed\n"); + setenv("HOME", pw->pw_dir, 1); + chdir(pw->pw_dir); + setsid(); + execvp(logincmd[0], (char *const *)logincmd); + die("slogin: exec failed\n"); +} + +static void +drawscreen(Display *dpy, Window win, XftDraw *draw, XftFont *font, + XftColor *fg, XftColor *accent, + const char *user, const char *pass, int stage) +{ + char buf[256]; + int width = DisplayWidth(dpy, DefaultScreen(dpy)); + int height = DisplayHeight(dpy, DefaultScreen(dpy)); + int w = 400, h = 100; + int x = (width - w)/2; + int y = (height - h)/2; + GC gc = DefaultGC(dpy, DefaultScreen(dpy)); + + XClearWindow(dpy, win); + XSetForeground(dpy, gc, accent->pixel); + XDrawRectangle(dpy, win, gc, x, y, w, h); + + if (stage == 0) + snprintf(buf, sizeof buf, "login: %s", user); + else { + char stars[sizeof buf]; + size_t i, len = strlen(pass); + for (i = 0; i < len && i < sizeof stars - 1; i++) + stars[i] = '*'; + stars[i] = '\0'; + snprintf(buf, sizeof buf, "password: %s", stars); + } + XftDrawStringUtf8(draw, fg, font, x + 20, y + h/2 + font->ascent/2, + (XftChar8 *)buf, strlen(buf)); + XFlush(dpy); +} + +int +main(void) +{ + Display *dpy; + int scr; + Window root, win; + XEvent ev; + XftDraw *xdraw; + XftFont *font; + XftColor xfg, xbg, xaccent; + char user[64] = "", pass[64] = ""; + int stage = 0; + KeySym ksym; + char buf[32]; + int len; + + updateaccent(); + if (!(dpy = XOpenDisplay(NULL))) + die("slogin: cannot open display\n"); + scr = DefaultScreen(dpy); + root = RootWindow(dpy, scr); + win = XCreateSimpleWindow(dpy, root, 0, 0, + DisplayWidth(dpy, scr), DisplayHeight(dpy, scr), + 0, BlackPixel(dpy, scr), BlackPixel(dpy, scr)); + XSelectInput(dpy, win, KeyPressMask | ExposureMask); + XMapRaised(dpy, win); + + font = XftFontOpenName(dpy, scr, fontname); + if (!font) + die("slogin: cannot load font\n"); + xdraw = XftDrawCreate(dpy, win, DefaultVisual(dpy, scr), DefaultColormap(dpy, scr)); + XftColorAllocName(dpy, DefaultVisual(dpy, scr), DefaultColormap(dpy, scr), fgcolor, &xfg); + XftColorAllocName(dpy, DefaultVisual(dpy, scr), DefaultColormap(dpy, scr), bgcolor, &xbg); + XftColorAllocName(dpy, DefaultVisual(dpy, scr), DefaultColormap(dpy, scr), accentcol, &xaccent); + XSetWindowBackground(dpy, win, xbg.pixel); + XClearWindow(dpy, win); + + for (;;) { + XNextEvent(dpy, &ev); + if (ev.type == Expose) { + drawscreen(dpy, win, xdraw, font, &xfg, &xaccent, + user, pass, stage); + } else if (ev.type == KeyPress) { + len = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, NULL); + if (ksym == XK_Return) { + if (stage == 0) + stage = 1; + else { + runsession(user, pass); + stage = 0; + user[0] = pass[0] = '\0'; + } + } else if (ksym == XK_BackSpace) { + if (stage == 0 && strlen(user) > 0) + user[strlen(user)-1] = '\0'; + else if (stage == 1 && strlen(pass) > 0) + pass[strlen(pass)-1] = '\0'; + } else if (len && buf[0] >= ' ' && buf[0] <= '~') { + if (stage == 0 && strlen(user) + len < sizeof user) { + strncat(user, buf, len); + user[strlen(user)] = '\0'; + } else if (stage == 1 && strlen(pass) + len < sizeof pass) { + strncat(pass, buf, len); + pass[strlen(pass)] = '\0'; + } + } + drawscreen(dpy, win, xdraw, font, &xfg, &xaccent, + user, pass, stage); + } + } +} |
