150ee8570SDavid du Colombier /* screenlock - lock a terminal */ 250ee8570SDavid du Colombier #include <u.h> 350ee8570SDavid du Colombier #include <libc.h> 450ee8570SDavid du Colombier #include <libsec.h> 550ee8570SDavid du Colombier #include <draw.h> 650ee8570SDavid du Colombier #include <thread.h> 750ee8570SDavid du Colombier #include <auth.h> 850ee8570SDavid du Colombier 950ee8570SDavid du Colombier char pic[] = "/lib/bunny.bit"; 1050ee8570SDavid du Colombier 1150ee8570SDavid du Colombier int vgactl; 1250ee8570SDavid du Colombier int debug; 1350ee8570SDavid du Colombier int doblank; 1450ee8570SDavid du Colombier int chatty = 0; 1550ee8570SDavid du Colombier 1650ee8570SDavid du Colombier char user[256]; 1750ee8570SDavid du Colombier 1850ee8570SDavid du Colombier void 1950ee8570SDavid du Colombier blankscreen(int blank) 2050ee8570SDavid du Colombier { 2150ee8570SDavid du Colombier if(vgactl < 0) 2250ee8570SDavid du Colombier return; 2350ee8570SDavid du Colombier seek(vgactl, 0, 0); 2450ee8570SDavid du Colombier if(fprint(vgactl, blank? "blank": "unblank") < 0) 2550ee8570SDavid du Colombier fprint(2, "blankscreen: can't blank: %r\n"); 2650ee8570SDavid du Colombier } 2750ee8570SDavid du Colombier 2850ee8570SDavid du Colombier void 2950ee8570SDavid du Colombier error(char *fmt, ...) 3050ee8570SDavid du Colombier { 3150ee8570SDavid du Colombier Fmt f; 3250ee8570SDavid du Colombier char buf[64]; 3350ee8570SDavid du Colombier va_list arg; 3450ee8570SDavid du Colombier 3550ee8570SDavid du Colombier fmtfdinit(&f, 1, buf, sizeof buf); 3650ee8570SDavid du Colombier fmtprint(&f, "screenlock: "); 3750ee8570SDavid du Colombier va_start(arg, fmt); 3850ee8570SDavid du Colombier fmtvprint(&f, fmt, arg); 3950ee8570SDavid du Colombier va_end(arg); 4050ee8570SDavid du Colombier fmtprint(&f, "\n"); 4150ee8570SDavid du Colombier fmtfdflush(&f); 4250ee8570SDavid du Colombier threadexitsall("fatal error"); 4350ee8570SDavid du Colombier } 4450ee8570SDavid du Colombier 4550ee8570SDavid du Colombier void 4650ee8570SDavid du Colombier usage(void) 4750ee8570SDavid du Colombier { 4850ee8570SDavid du Colombier fprint(2, "usage: %s\n", argv0); 4950ee8570SDavid du Colombier exits("usage"); 5050ee8570SDavid du Colombier } 5150ee8570SDavid du Colombier 5250ee8570SDavid du Colombier 5350ee8570SDavid du Colombier void 5450ee8570SDavid du Colombier readfile(char *name, char *buf, int nbuf, int addnul) 5550ee8570SDavid du Colombier { 5650ee8570SDavid du Colombier int fd; 5750ee8570SDavid du Colombier 5850ee8570SDavid du Colombier fd = open(name, OREAD); 5950ee8570SDavid du Colombier if(fd == -1) 6050ee8570SDavid du Colombier error("%s - can't open: %r", name); 6150ee8570SDavid du Colombier nbuf = read(fd, buf, nbuf-addnul); 6250ee8570SDavid du Colombier close(fd); 6350ee8570SDavid du Colombier if(nbuf == -1) 6450ee8570SDavid du Colombier error("%s - can't can't read: %r", name); 6550ee8570SDavid du Colombier if(addnul) 6650ee8570SDavid du Colombier buf[nbuf] = '\0'; 6750ee8570SDavid du Colombier } 6850ee8570SDavid du Colombier 6950ee8570SDavid du Colombier void 7050ee8570SDavid du Colombier readline(char *buf, int nbuf) 7150ee8570SDavid du Colombier { 7250ee8570SDavid du Colombier char c; 7350ee8570SDavid du Colombier int i; 7450ee8570SDavid du Colombier 7550ee8570SDavid du Colombier i = 0; 7650ee8570SDavid du Colombier while(i < nbuf-1) 7750ee8570SDavid du Colombier if(read(0, &c, 1) != 1 || c == '\04' || c == '\177'){ 7850ee8570SDavid du Colombier i = 0; 7950ee8570SDavid du Colombier break; 8050ee8570SDavid du Colombier } else if(c == '\n') 8150ee8570SDavid du Colombier break; 8250ee8570SDavid du Colombier else if(c == '\b' && i > 0) 8350ee8570SDavid du Colombier --i; 8450ee8570SDavid du Colombier else if(c == ('u' & 037)) 8550ee8570SDavid du Colombier i = 0; 8650ee8570SDavid du Colombier else 8750ee8570SDavid du Colombier buf[i++] = c; 8850ee8570SDavid du Colombier buf[i] = '\0'; 8950ee8570SDavid du Colombier } 9050ee8570SDavid du Colombier 9150ee8570SDavid du Colombier void 9250ee8570SDavid du Colombier checkpassword(void) 9350ee8570SDavid du Colombier { 9450ee8570SDavid du Colombier int fd, consctl, must; 9550ee8570SDavid du Colombier char buf[256]; 9650ee8570SDavid du Colombier AuthInfo *ai; 9750ee8570SDavid du Colombier static int opened; 9850ee8570SDavid du Colombier 9950ee8570SDavid du Colombier must = 1; 10050ee8570SDavid du Colombier if(!opened){ 10150ee8570SDavid du Colombier fd = open("/dev/cons", OREAD); 10250ee8570SDavid du Colombier if(fd == -1) 10350ee8570SDavid du Colombier error("can't open cons: %r"); 10450ee8570SDavid du Colombier dup(fd, 0); 10550ee8570SDavid du Colombier close(fd); 10650ee8570SDavid du Colombier fd = open("/dev/cons", OWRITE); 10750ee8570SDavid du Colombier if(fd == -1) 10850ee8570SDavid du Colombier error("can't open cons: %r"); 10950ee8570SDavid du Colombier dup(fd, 1); 11050ee8570SDavid du Colombier dup(1, 2); 11150ee8570SDavid du Colombier close(fd); 11250ee8570SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 11350ee8570SDavid du Colombier if(consctl == -1) 11450ee8570SDavid du Colombier error("can't open consctl: %r"); 11550ee8570SDavid du Colombier if(write(consctl, "rawon", 5) != 5) 11650ee8570SDavid du Colombier error("can't turn off echo\n"); 11750ee8570SDavid du Colombier opened = 1; 11850ee8570SDavid du Colombier } 11950ee8570SDavid du Colombier 12050ee8570SDavid du Colombier for(;;){ 12150ee8570SDavid du Colombier if(chatty || !must) 12250ee8570SDavid du Colombier fprint(2, "%s's screenlock password: ", user); 12350ee8570SDavid du Colombier memset(buf, 0, sizeof buf); 12450ee8570SDavid du Colombier readline(buf, sizeof buf); 12550ee8570SDavid du Colombier blankscreen(0); 12650ee8570SDavid du Colombier if(chatty || !must) 12750ee8570SDavid du Colombier fprint(2, "\n"); 12850ee8570SDavid du Colombier if(buf[0] == '\0' || buf[0] == '\04'){ 12950ee8570SDavid du Colombier if(must) 13050ee8570SDavid du Colombier continue; 13150ee8570SDavid du Colombier error("no password typed"); 13250ee8570SDavid du Colombier } 13350ee8570SDavid du Colombier 13450ee8570SDavid du Colombier /* authenticate */ 13550ee8570SDavid du Colombier ai = auth_userpasswd(user, buf); 13650ee8570SDavid du Colombier if(ai != nil && ai->cap != nil) 13750ee8570SDavid du Colombier break; 13850ee8570SDavid du Colombier auth_freeAI(ai); 13950ee8570SDavid du Colombier 14050ee8570SDavid du Colombier if(chatty || !must) 14150ee8570SDavid du Colombier fprint(2, "password mismatch\n"); 14250ee8570SDavid du Colombier doblank = 1; 14350ee8570SDavid du Colombier } 14450ee8570SDavid du Colombier memset(buf, 0, sizeof buf); 14550ee8570SDavid du Colombier blankscreen(0); 14650ee8570SDavid du Colombier } 14750ee8570SDavid du Colombier 14850ee8570SDavid du Colombier void 14950ee8570SDavid du Colombier blanker(void *) 15050ee8570SDavid du Colombier { 15150ee8570SDavid du Colombier int tics; 15250ee8570SDavid du Colombier 15350ee8570SDavid du Colombier tics = 0; 15450ee8570SDavid du Colombier for(;;){ 15550ee8570SDavid du Colombier if(doblank > 0){ 15650ee8570SDavid du Colombier doblank = 0; 15750ee8570SDavid du Colombier tics = 10; 15850ee8570SDavid du Colombier } 15950ee8570SDavid du Colombier if(tics > 0 && --tics == 0) 16050ee8570SDavid du Colombier blankscreen(1); 16150ee8570SDavid du Colombier sleep(1000); 16250ee8570SDavid du Colombier } 16350ee8570SDavid du Colombier } 16450ee8570SDavid du Colombier 16550ee8570SDavid du Colombier void 16650ee8570SDavid du Colombier grabmouse(void*) 16750ee8570SDavid du Colombier { 16850ee8570SDavid du Colombier int fd, x, y; 16950ee8570SDavid du Colombier char ibuf[256], obuf[256]; 17050ee8570SDavid du Colombier 17150ee8570SDavid du Colombier if(debug) 17250ee8570SDavid du Colombier return; 17350ee8570SDavid du Colombier fd = open("/dev/mouse", ORDWR); 17450ee8570SDavid du Colombier if(fd < 0) 17550ee8570SDavid du Colombier error("can't open /dev/mouse: %r"); 17650ee8570SDavid du Colombier 17750ee8570SDavid du Colombier snprint(obuf, sizeof obuf, "m %d %d", 17850ee8570SDavid du Colombier screen->r.min.x + Dx(screen->r)/2, 17950ee8570SDavid du Colombier screen->r.min.y + Dy(screen->r)/2); 18050ee8570SDavid du Colombier while(read(fd, ibuf, sizeof ibuf) > 0){ 18150ee8570SDavid du Colombier ibuf[12] = 0; 18250ee8570SDavid du Colombier ibuf[24] = 0; 18350ee8570SDavid du Colombier x = atoi(ibuf+1); 18450ee8570SDavid du Colombier y = atoi(ibuf+13); 18550ee8570SDavid du Colombier if(x != screen->r.min.x + Dx(screen->r)/2 || 18650ee8570SDavid du Colombier y != screen->r.min.y + Dy(screen->r)/2){ 18750ee8570SDavid du Colombier fprint(fd, "%s", obuf); 18850ee8570SDavid du Colombier doblank = 1; 18950ee8570SDavid du Colombier } 19050ee8570SDavid du Colombier } 19150ee8570SDavid du Colombier } 19250ee8570SDavid du Colombier 1933468a491SDavid du Colombier /* lay down text at `p' */ 1943468a491SDavid du Colombier static void 1953468a491SDavid du Colombier screenstring(Point p, char *s) 1963468a491SDavid du Colombier { 1973468a491SDavid du Colombier string(screen, p, screen->display->white, ZP, font, s); 1983468a491SDavid du Colombier flushimage(display, 1); 1993468a491SDavid du Colombier } 2003468a491SDavid du Colombier 20150ee8570SDavid du Colombier void 20250ee8570SDavid du Colombier lockscreen(void) 20350ee8570SDavid du Colombier { 20450ee8570SDavid du Colombier enum { Nfld = 5, Fldlen = 12, Cursorlen = 2*4 + 2*2*16, }; 2053468a491SDavid du Colombier char *s; 20650ee8570SDavid du Colombier char buf[Nfld*Fldlen], *flds[Nfld], newcmd[128], cbuf[Cursorlen]; 20750ee8570SDavid du Colombier int fd, dx, dy; 20850ee8570SDavid du Colombier Image *i; 2093468a491SDavid du Colombier Point p; 21050ee8570SDavid du Colombier Rectangle r; 2113468a491SDavid du Colombier Tm *tm; 21250ee8570SDavid du Colombier 21350ee8570SDavid du Colombier fd = open("/dev/screen", OREAD); 21450ee8570SDavid du Colombier if(fd < 0) 21550ee8570SDavid du Colombier error("can't open /dev/screen: %r"); 21650ee8570SDavid du Colombier if(read(fd, buf, Nfld*Fldlen) != Nfld*Fldlen) 21750ee8570SDavid du Colombier error("can't read /dev/screen: %r"); 21850ee8570SDavid du Colombier close(fd); 21950ee8570SDavid du Colombier buf[sizeof buf-1] = 0; 22050ee8570SDavid du Colombier if(tokenize(buf, flds, Nfld) != Nfld) 22150ee8570SDavid du Colombier error("can't tokenize /dev/screen header"); 22250ee8570SDavid du Colombier snprint(newcmd, sizeof newcmd, "-r %s %s %d %d", 22350ee8570SDavid du Colombier flds[1], flds[2], atoi(flds[3]) - 1, atoi(flds[4]) - 1); 22450ee8570SDavid du Colombier newwindow(newcmd); 2253468a491SDavid du Colombier if (initdraw(nil, nil, "screenlock") < 0) 2263468a491SDavid du Colombier sysfatal("initdraw failed"); 22750ee8570SDavid du Colombier if(display == nil) 22850ee8570SDavid du Colombier error("no display"); 22950ee8570SDavid du Colombier 23050ee8570SDavid du Colombier /* screen is now open and covered. grab mouse and hold on tight */ 23150ee8570SDavid du Colombier procrfork(grabmouse, nil, 4096, RFFDG); 23250ee8570SDavid du Colombier procrfork(blanker, nil, 4096, RFFDG); 23350ee8570SDavid du Colombier fd = open(pic, OREAD); 23450ee8570SDavid du Colombier if(fd > 0){ 23550ee8570SDavid du Colombier i = readimage(display, fd, 0); 23650ee8570SDavid du Colombier if(i){ 23750ee8570SDavid du Colombier r = screen->r; 2383468a491SDavid du Colombier p = Pt(r.max.x / 2, r.max.y * 2 / 3); 23950ee8570SDavid du Colombier dx = (Dx(screen->r) - Dx(i->r)) / 2; 24050ee8570SDavid du Colombier r.min.x += dx; 24150ee8570SDavid du Colombier r.max.x -= dx; 24250ee8570SDavid du Colombier dy = (Dy(screen->r) - Dy(i->r)) / 2; 24350ee8570SDavid du Colombier r.min.y += dy; 24450ee8570SDavid du Colombier r.max.y -= dy; 24550ee8570SDavid du Colombier draw(screen, screen->r, display->black, nil, ZP); 24650ee8570SDavid du Colombier draw(screen, r, i, nil, i->r.min); 24750ee8570SDavid du Colombier flushimage(display, 1); 24850ee8570SDavid du Colombier } 24950ee8570SDavid du Colombier close(fd); 2503468a491SDavid du Colombier 2513468a491SDavid du Colombier /* identify the user on screen, centered */ 2523468a491SDavid du Colombier tm = localtime(time(0)); 2533468a491SDavid du Colombier s = smprint("user %s at %d:%2d", getuser(), tm->hour, tm->min); 254*2ce711d4SDavid du Colombier p = subpt(p, Pt(stringwidth(font, "m") * strlen(s) / 2, 0)); 2553468a491SDavid du Colombier screenstring(p, s); 25650ee8570SDavid du Colombier } 25750ee8570SDavid du Colombier 25850ee8570SDavid du Colombier /* clear the cursor */ 25950ee8570SDavid du Colombier fd = open("/dev/cursor", OWRITE); 26050ee8570SDavid du Colombier if(fd > 0){ 26150ee8570SDavid du Colombier memset(cbuf, 0, sizeof cbuf); 26250ee8570SDavid du Colombier write(fd, cbuf, sizeof cbuf); 26350ee8570SDavid du Colombier /* leave it open */ 26450ee8570SDavid du Colombier } 26550ee8570SDavid du Colombier } 26650ee8570SDavid du Colombier 26750ee8570SDavid du Colombier void 26850ee8570SDavid du Colombier threadmain(int argc, char *argv[]) 26950ee8570SDavid du Colombier { 27050ee8570SDavid du Colombier readfile("#c/user", user, sizeof user, 1); 27150ee8570SDavid du Colombier 27250ee8570SDavid du Colombier if((vgactl = open("/dev/vgactl", OWRITE)) < 0) 27350ee8570SDavid du Colombier vgactl = open("#v/vgactl", OWRITE); 27450ee8570SDavid du Colombier 27550ee8570SDavid du Colombier ARGBEGIN{ 27650ee8570SDavid du Colombier case 'd': 27750ee8570SDavid du Colombier debug++; 27850ee8570SDavid du Colombier break; 27950ee8570SDavid du Colombier default: 28050ee8570SDavid du Colombier usage(); 28150ee8570SDavid du Colombier }ARGEND 28250ee8570SDavid du Colombier 28350ee8570SDavid du Colombier if(argc != 0) 28450ee8570SDavid du Colombier usage(); 28550ee8570SDavid du Colombier 28650ee8570SDavid du Colombier doblank = 1; 28750ee8570SDavid du Colombier lockscreen(); 28850ee8570SDavid du Colombier checkpassword(); 28950ee8570SDavid du Colombier threadexitsall(nil); 29050ee8570SDavid du Colombier } 291