diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/screenlock.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/screenlock.c')
-rwxr-xr-x | sys/src/cmd/screenlock.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/sys/src/cmd/screenlock.c b/sys/src/cmd/screenlock.c new file mode 100755 index 000000000..7db2a13cf --- /dev/null +++ b/sys/src/cmd/screenlock.c @@ -0,0 +1,290 @@ +/* screenlock - lock a terminal */ +#include <u.h> +#include <libc.h> +#include <libsec.h> +#include <draw.h> +#include <thread.h> +#include <auth.h> + +char pic[] = "/lib/bunny.bit"; + +int vgactl; +int debug; +int doblank; +int chatty = 0; + +char user[256]; + +void +blankscreen(int blank) +{ + if(vgactl < 0) + return; + seek(vgactl, 0, 0); + if(fprint(vgactl, blank? "blank": "unblank") < 0) + fprint(2, "blankscreen: can't blank: %r\n"); +} + +void +error(char *fmt, ...) +{ + Fmt f; + char buf[64]; + va_list arg; + + fmtfdinit(&f, 1, buf, sizeof buf); + fmtprint(&f, "screenlock: "); + va_start(arg, fmt); + fmtvprint(&f, fmt, arg); + va_end(arg); + fmtprint(&f, "\n"); + fmtfdflush(&f); + threadexitsall("fatal error"); +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + + +void +readfile(char *name, char *buf, int nbuf, int addnul) +{ + int fd; + + fd = open(name, OREAD); + if(fd == -1) + error("%s - can't open: %r", name); + nbuf = read(fd, buf, nbuf-addnul); + close(fd); + if(nbuf == -1) + error("%s - can't can't read: %r", name); + if(addnul) + buf[nbuf] = '\0'; +} + +void +readline(char *buf, int nbuf) +{ + char c; + int i; + + i = 0; + while(i < nbuf-1) + if(read(0, &c, 1) != 1 || c == '\04' || c == '\177'){ + i = 0; + break; + } else if(c == '\n') + break; + else if(c == '\b' && i > 0) + --i; + else if(c == ('u' & 037)) + i = 0; + else + buf[i++] = c; + buf[i] = '\0'; +} + +void +checkpassword(void) +{ + int fd, consctl, must; + char buf[256]; + AuthInfo *ai; + static int opened; + + must = 1; + if(!opened){ + fd = open("/dev/cons", OREAD); + if(fd == -1) + error("can't open cons: %r"); + dup(fd, 0); + close(fd); + fd = open("/dev/cons", OWRITE); + if(fd == -1) + error("can't open cons: %r"); + dup(fd, 1); + dup(1, 2); + close(fd); + consctl = open("/dev/consctl", OWRITE); + if(consctl == -1) + error("can't open consctl: %r"); + if(write(consctl, "rawon", 5) != 5) + error("can't turn off echo\n"); + opened = 1; + } + + for(;;){ + if(chatty || !must) + fprint(2, "%s's screenlock password: ", user); + memset(buf, 0, sizeof buf); + readline(buf, sizeof buf); + blankscreen(0); + if(chatty || !must) + fprint(2, "\n"); + if(buf[0] == '\0' || buf[0] == '\04'){ + if(must) + continue; + error("no password typed"); + } + + /* authenticate */ + ai = auth_userpasswd(user, buf); + if(ai != nil && ai->cap != nil) + break; + auth_freeAI(ai); + + if(chatty || !must) + fprint(2, "password mismatch\n"); + doblank = 1; + } + memset(buf, 0, sizeof buf); + blankscreen(0); +} + +void +blanker(void *) +{ + int tics; + + tics = 0; + for(;;){ + if(doblank > 0){ + doblank = 0; + tics = 10; + } + if(tics > 0 && --tics == 0) + blankscreen(1); + sleep(1000); + } +} + +void +grabmouse(void*) +{ + int fd, x, y; + char ibuf[256], obuf[256]; + + if(debug) + return; + fd = open("/dev/mouse", ORDWR); + if(fd < 0) + error("can't open /dev/mouse: %r"); + + snprint(obuf, sizeof obuf, "m %d %d", + screen->r.min.x + Dx(screen->r)/2, + screen->r.min.y + Dy(screen->r)/2); + while(read(fd, ibuf, sizeof ibuf) > 0){ + ibuf[12] = 0; + ibuf[24] = 0; + x = atoi(ibuf+1); + y = atoi(ibuf+13); + if(x != screen->r.min.x + Dx(screen->r)/2 || + y != screen->r.min.y + Dy(screen->r)/2){ + fprint(fd, "%s", obuf); + doblank = 1; + } + } +} + +/* lay down text at `p' */ +static void +screenstring(Point p, char *s) +{ + string(screen, p, screen->display->white, ZP, font, s); + flushimage(display, 1); +} + +void +lockscreen(void) +{ + enum { Nfld = 5, Fldlen = 12, Cursorlen = 2*4 + 2*2*16, }; + char *s; + char buf[Nfld*Fldlen], *flds[Nfld], newcmd[128], cbuf[Cursorlen]; + int fd, dx, dy; + Image *i; + Point p; + Rectangle r; + Tm *tm; + + fd = open("/dev/screen", OREAD); + if(fd < 0) + error("can't open /dev/screen: %r"); + if(read(fd, buf, Nfld*Fldlen) != Nfld*Fldlen) + error("can't read /dev/screen: %r"); + close(fd); + buf[sizeof buf-1] = 0; + if(tokenize(buf, flds, Nfld) != Nfld) + error("can't tokenize /dev/screen header"); + snprint(newcmd, sizeof newcmd, "-r %s %s %d %d", + flds[1], flds[2], atoi(flds[3]) - 1, atoi(flds[4]) - 1); + newwindow(newcmd); + if (initdraw(nil, nil, "screenlock") < 0) + sysfatal("initdraw failed"); + if(display == nil) + error("no display"); + + /* screen is now open and covered. grab mouse and hold on tight */ + procrfork(grabmouse, nil, 4096, RFFDG); + procrfork(blanker, nil, 4096, RFFDG); + fd = open(pic, OREAD); + if(fd > 0){ + i = readimage(display, fd, 0); + if(i){ + r = screen->r; + p = Pt(r.max.x / 2, r.max.y * 2 / 3); + dx = (Dx(screen->r) - Dx(i->r)) / 2; + r.min.x += dx; + r.max.x -= dx; + dy = (Dy(screen->r) - Dy(i->r)) / 2; + r.min.y += dy; + r.max.y -= dy; + draw(screen, screen->r, display->black, nil, ZP); + draw(screen, r, i, nil, i->r.min); + flushimage(display, 1); + } + close(fd); + + /* identify the user on screen, centered */ + tm = localtime(time(0)); + s = smprint("user %s at %d:%02.2d", getuser(), tm->hour, tm->min); + p = subpt(p, Pt(stringwidth(font, "m") * strlen(s) / 2, 0)); + screenstring(p, s); + } + + /* clear the cursor */ + fd = open("/dev/cursor", OWRITE); + if(fd > 0){ + memset(cbuf, 0, sizeof cbuf); + write(fd, cbuf, sizeof cbuf); + /* leave it open */ + } +} + +void +threadmain(int argc, char *argv[]) +{ + readfile("#c/user", user, sizeof user, 1); + + if((vgactl = open("/dev/vgactl", OWRITE)) < 0) + vgactl = open("#v/vgactl", OWRITE); + + ARGBEGIN{ + case 'd': + debug++; + break; + default: + usage(); + }ARGEND + + if(argc != 0) + usage(); + + doblank = 1; + lockscreen(); + checkpassword(); + threadexitsall(nil); +} |