123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- /* 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);
- }
|