]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/screenlock.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / cmd / screenlock.c
1 /* screenlock - lock a terminal */
2 #include <u.h>
3 #include <libc.h>
4 #include <libsec.h>
5 #include <draw.h>
6 #include <thread.h>
7 #include <auth.h>
8
9 char pic[] = "/lib/bunny.bit";
10 int debug;
11 long blank;
12
13 void
14 usage(void)
15 {
16         fprint(2, "usage: %s [-d]\n", argv0);
17         exits("usage");
18 }
19
20 void
21 readline(char *buf, int nbuf)
22 {
23         char c;
24         int i;
25
26         i = 0;
27         while(i < nbuf-1){
28                 if(read(0, &c, 1) != 1 || c == '\04' || c == '\177'){
29                         i = 0;
30                         break;
31                 } else if(c == '\n')
32                         break;
33                 else if(c == '\b' && i > 0)
34                         --i;
35                 else if(c == ('u' & 037))
36                         i = 0;
37                 else
38                         buf[i++] = c;
39                 blank = time(0);
40         }
41         buf[i] = '\0';
42 }
43
44 void
45 checkpassword(void)
46 {
47         char buf[256];
48         AuthInfo *ai;
49
50         for(;;){
51                 memset(buf, 0, sizeof buf);
52                 readline(buf, sizeof buf);
53
54                 border(screen, screen->r, 8, display->white, ZP);
55                 flushimage(display, 1);
56
57                 /* authenticate */
58                 ai = auth_userpasswd(getuser(), buf);
59                 if(ai != nil && ai->cap != nil)
60                         break;
61
62                 rerrstr(buf, sizeof buf);
63                 if(strncmp(buf, "needkey ", 8) == 0)
64                         break;
65
66                 auth_freeAI(ai);
67                 border(screen, screen->r, 8, display->black, ZP);
68                 flushimage(display, 1);
69         }
70         auth_freeAI(ai);
71         memset(buf, 0, sizeof buf);
72 }
73
74 void
75 blanker(void *)
76 {
77         int fd;
78
79         if((fd = open("/dev/mousectl", OWRITE)) < 0)
80                 return;
81
82         for(;;){
83                 if(blank != 0 && ((ulong)time(0) - (ulong)blank) >= 5){
84                         blank = 0;
85                         write(fd, "blank", 5);
86                 }
87                 sleep(1000);
88         }
89 }
90
91 void
92 grabmouse(void*)
93 {
94         int fd, x, y;
95         char ibuf[256], obuf[256];
96
97         if((fd = open("/dev/mouse", ORDWR)) < 0)
98                 sysfatal("can't open /dev/mouse: %r");
99
100         snprint(obuf, sizeof obuf, "m %d %d",
101                 screen->r.min.x + Dx(screen->r)/2,
102                 screen->r.min.y + Dy(screen->r)/2);
103
104         while(read(fd, ibuf, sizeof ibuf) > 0){
105                 ibuf[12] = 0;
106                 ibuf[24] = 0;
107                 x = atoi(ibuf+1);
108                 y = atoi(ibuf+13);
109                 if(x != screen->r.min.x + Dx(screen->r)/2 ||
110                    y != screen->r.min.y + Dy(screen->r)/2){
111                         if(!debug)
112                                 fprint(fd, "%s", obuf);
113                         blank = time(0);
114                 }
115         }
116 }
117
118 void
119 lockscreen(void)
120 {
121         enum { Nfld = 5, Fldlen = 12, Cursorlen = 2*4 + 2*2*16, };
122         char *s;
123         char buf[Nfld*Fldlen], *flds[Nfld], newcmd[128], cbuf[Cursorlen];
124         int fd, dx, dy;
125         Image *i;
126         Point p;
127         Rectangle r;
128         Tm *tm;
129
130         if((fd = open("/dev/screen", OREAD)) < 0)
131                 sysfatal("can't open /dev/screen: %r");
132         if(read(fd, buf, Nfld*Fldlen) != Nfld*Fldlen)
133                 sysfatal("can't read /dev/screen: %r");
134         close(fd);
135         buf[sizeof buf-1] = 0;
136         if(tokenize(buf, flds, Nfld) != Nfld)
137                 sysfatal("can't tokenize /dev/screen header");
138         snprint(newcmd, sizeof newcmd, "-r %s %s %s %s",
139                 flds[1], flds[2], flds[3], flds[4]);
140
141         newwindow(newcmd);
142         if((fd = open("/dev/consctl", OWRITE)) >= 0)
143                 write(fd, "rawon", 5);
144
145         if((fd = open("/dev/cons", OREAD)) < 0)
146                 sysfatal("can't open cons: %r");
147         dup(fd, 0);
148
149         if((fd = open("/dev/cons", OWRITE)) < 0)
150                 sysfatal("can't open cons: %r");
151         dup(fd, 1);
152         dup(fd, 2);
153
154         if(initdraw(nil, nil, "screenlock") < 0)
155                 sysfatal("initdraw failed");
156         screen = _screen->image;        /* fullscreen */
157
158         if((fd = open(pic, OREAD)) >= 0){
159                 if((i = readimage(display, fd, 0)) != nil){
160                         r = screen->r;
161                         p = Pt(r.max.x / 2, r.max.y * 2 / 3); 
162                         dx = (Dx(screen->r) - Dx(i->r)) / 2;
163                         r.min.x += dx;
164                         r.max.x -= dx;
165                         dy = (Dy(screen->r) - Dy(i->r)) / 2;
166                         r.min.y += dy;
167                         r.max.y -= dy;
168                         draw(screen, screen->r, display->black, nil, ZP);
169                         draw(screen, r, i, nil, i->r.min);
170                 }
171                 close(fd);
172
173                 /* identify the user on screen, centered */
174                 tm = localtime(time(&blank));
175                 s = smprint("user %s at %d:%02.2d", getuser(), tm->hour, tm->min);
176                 p = subpt(p, Pt(stringwidth(font, "m") * strlen(s) / 2, 0));
177                 string(screen, p, screen->display->white, ZP, font, s);
178         }
179         flushimage(display, 1);
180
181         /* screen is now open and covered.  grab mouse and hold on tight */
182         procrfork(grabmouse, nil, 8*1024, RFFDG);
183         procrfork(blanker, nil, 8*1024, RFFDG);
184
185         /* clear the cursor */
186         if((fd = open("/dev/cursor", OWRITE)) >= 0){
187                 memset(cbuf, 0, sizeof cbuf);
188                 write(fd, cbuf, sizeof cbuf);
189                 /* leave it open */
190         }
191 }
192
193 void
194 threadmain(int argc, char *argv[])
195 {
196         ARGBEGIN{
197         case 'd':
198                 debug++;
199                 break;
200         default:
201                 usage();
202         }ARGEND
203
204         if(argc != 0)
205                 usage();
206
207         lockscreen();
208         checkpassword();
209         threadexitsall(nil);
210 }