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
blankscreen(int blank)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
error(char * fmt,...)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
usage(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
readfile(char * name,char * buf,int nbuf,int addnul)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
readline(char * buf,int nbuf)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
checkpassword(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
blanker(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
grabmouse(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
screenstring(Point p,char * s)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
lockscreen(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));
253*047f1f95SDavid du Colombier s = smprint("user %s at %d:%02.2d", getuser(), tm->hour, tm->min);
2542ce711d4SDavid 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
threadmain(int argc,char * argv[])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