diff options
| author | auric <104602845+ihateamongus@users.noreply.github.com> | 2025-09-08 21:08:47 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-08 21:08:47 -0500 |
| commit | 9835e81684ffb53cb258c7de754998621661c15f (patch) | |
| tree | 9c2b8e58b02ef1ae1440dd40101a7736d090fccc /slogin/slogin.c | |
| parent | e2ec2e4acbf07da282c7ce4d4370ed1a83e11e70 (diff) | |
| parent | 04cfeeb799b4ee6ac990e5d6e1b5302251133d77 (diff) | |
Merge pull request #18 from ihateamongus/codex/add-staggering-color-effect-demo-in-tools
Add color staggering demo and minimal login manager
Diffstat (limited to 'slogin/slogin.c')
| -rw-r--r-- | slogin/slogin.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/slogin/slogin.c b/slogin/slogin.c new file mode 100644 index 0000000..856585b --- /dev/null +++ b/slogin/slogin.c @@ -0,0 +1,166 @@ +#define _XOPEN_SOURCE 700 +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <ctype.h> +#include <grp.h> +#include <pwd.h> +#if HAVE_SHADOW_H +#include <shadow.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <crypt.h> +#include "../accent.h" + +#define WIDTH 400 +#define HEIGHT 100 + +static int +auth(const char *user, const char *pass) +{ + struct passwd *pw = getpwnam(user); + const char *hash; + if (!pw) + return 0; +#if HAVE_SHADOW_H + struct spwd *sp = getspnam(user); + hash = sp ? sp->sp_pwdp : pw->pw_passwd; +#else + hash = pw->pw_passwd; +#endif + if (!hash || hash[0] == '!' || hash[0] == '*') + return 0; + return strcmp(crypt(pass, hash), hash) == 0; +} + +static void +draw(Display *dpy, Window win, GC gc, const char *prompt, + const char *input, int hidden) +{ + XClearWindow(dpy, win); + XDrawString(dpy, win, gc, 10, 25, prompt, strlen(prompt)); + if (input && *input) { + char buf[128]; + const char *show = input; + if (hidden) { + size_t n = strlen(input); + if (n >= sizeof buf) + n = sizeof buf - 1; + memset(buf, '*', n); + buf[n] = '\0'; + show = buf; + } + XDrawString(dpy, win, gc, 10, 50, show, strlen(show)); + } + XFlush(dpy); +} + +int +main(void) +{ + Display *dpy; + Window win; + XEvent ev; + GC gc; + XFontStruct *font; + int screen; + Colormap cmap; + XColor xcol; + ColorShm *blk = NULL; + char accent[8] = "#005577"; + + if (!(dpy = XOpenDisplay(NULL))) { + fprintf(stderr, "slogin: cannot open display\n"); + return 1; + } + readaccent(&blk, accent); + screen = DefaultScreen(dpy); + cmap = DefaultColormap(dpy, screen); + XParseColor(dpy, cmap, accent, &xcol); + XAllocColor(dpy, cmap, &xcol); + win = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), + DisplayWidth(dpy, screen)/2 - WIDTH/2, + DisplayHeight(dpy, screen)/2 - HEIGHT/2, + WIDTH, HEIGHT, 2, xcol.pixel, BlackPixel(dpy, screen)); + XStoreName(dpy, win, "slogin"); + XSelectInput(dpy, win, ExposureMask | KeyPressMask); + XMapRaised(dpy, win); + gc = XCreateGC(dpy, win, 0, NULL); + XSetForeground(dpy, gc, xcol.pixel); + font = XLoadQueryFont(dpy, "fixed"); + if (font) + XSetFont(dpy, gc, font->fid); + + char user[64] = ""; + char pass[64] = ""; + int stage = 0; + draw(dpy, win, gc, "user:", user, 0); + + for (;;) { + if (XPending(dpy)) { + XNextEvent(dpy, &ev); + if (ev.type == Expose) { + draw(dpy, win, gc, stage ? "pass:" : "user:", + stage ? pass : user, stage); + } else if (ev.type == KeyPress) { + char buf[32]; + KeySym ksym; + int len = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, NULL); + if (ksym == XK_Return) { + if (stage == 0) { + stage = 1; + draw(dpy, win, gc, "pass:", pass, 1); + } else { + if (auth(user, pass)) { + struct passwd *pw = getpwnam(user); + if (!pw) + exit(1); + chdir(pw->pw_dir); + setenv("HOME", pw->pw_dir, 1); + setenv("SHELL", pw->pw_shell, 1); + setenv("USER", pw->pw_name, 1); + setenv("LOGNAME", pw->pw_name, 1); + initgroups(pw->pw_name, pw->pw_gid); + setgid(pw->pw_gid); + setuid(pw->pw_uid); + execlp(pw->pw_shell, pw->pw_shell, "-l", NULL); + perror("execlp"); + exit(1); + } else { + user[0] = pass[0] = '\0'; + stage = 0; + draw(dpy, win, gc, "user:", user, 0); + } + } + } else if (ksym == XK_BackSpace) { + if (stage == 0) { + size_t n = strlen(user); + if (n) user[n-1] = '\0'; + draw(dpy, win, gc, "user:", user, 0); + } else { + size_t n = strlen(pass); + if (n) pass[n-1] = '\0'; + draw(dpy, win, gc, "pass:", pass, 1); + } + } else if (len && !iscntrl((unsigned char)buf[0])) { + if (stage == 0 && strlen(user) + len < sizeof user - 1) { + strncat(user, buf, len); + draw(dpy, win, gc, "user:", user, 0); + } else if (stage == 1 && strlen(pass) + len < sizeof pass - 1) { + strncat(pass, buf, len); + draw(dpy, win, gc, "pass:", pass, 1); + } + } + } + } + if (readaccent(&blk, accent)) { + XParseColor(dpy, cmap, accent, &xcol); + XAllocColor(dpy, cmap, &xcol); + XSetForeground(dpy, gc, xcol.pixel); + XSetWindowBorder(dpy, win, xcol.pixel); + } + usleep(20000); + } +} |
