]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/screenlock.c
9bootfat: rename open() to fileinit and make it static as its really a internal funct...
[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
11 int vgactl;
12 int debug;
13 int doblank;
14 int chatty = 0;
15
16 char user[256];
17
18 void
19 blankscreen(int blank)
20 {
21         if(vgactl < 0)
22                 return;
23         seek(vgactl, 0, 0);
24         if(fprint(vgactl, blank? "blank": "unblank") < 0)
25                 fprint(2, "blankscreen: can't blank: %r\n");
26 }
27
28 void
29 error(char *fmt, ...)
30 {
31         Fmt f;
32         char buf[64];
33         va_list arg;
34
35         fmtfdinit(&f, 1, buf, sizeof buf);
36         fmtprint(&f, "screenlock: ");
37         va_start(arg, fmt);
38         fmtvprint(&f, fmt, arg);
39         va_end(arg);
40         fmtprint(&f, "\n");
41         fmtfdflush(&f);
42         threadexitsall("fatal error");
43 }
44
45 void
46 usage(void)
47 {
48         fprint(2, "usage: %s\n", argv0);
49         exits("usage");
50 }
51
52
53 void
54 readfile(char *name, char *buf, int nbuf, int addnul)
55 {
56         int fd;
57
58         fd = open(name, OREAD);
59         if(fd == -1)
60                 error("%s - can't open: %r", name);
61         nbuf = read(fd, buf, nbuf-addnul);
62         close(fd);
63         if(nbuf == -1)
64                 error("%s - can't can't read: %r", name);
65         if(addnul)
66                 buf[nbuf] = '\0';
67 }
68
69 void
70 readline(char *buf, int nbuf)
71 {
72         char c;
73         int i;
74
75         i = 0;
76         while(i < nbuf-1)
77                 if(read(0, &c, 1) != 1 || c == '\04' || c == '\177'){
78                         i = 0;
79                         break;
80                 } else if(c == '\n')
81                         break;
82                 else if(c == '\b' && i > 0)
83                         --i;
84                 else if(c == ('u' & 037))
85                         i = 0;
86                 else
87                         buf[i++] = c;
88         buf[i] = '\0';
89 }
90
91 void
92 checkpassword(void)
93 {
94         int fd, consctl, must;
95         char buf[256];
96         AuthInfo *ai;
97         static int opened;
98
99         must = 1;
100         if(!opened){
101                 fd = open("/dev/cons", OREAD);
102                 if(fd == -1)
103                         error("can't open cons: %r");
104                 dup(fd, 0);
105                 close(fd);
106                 fd = open("/dev/cons", OWRITE);
107                 if(fd == -1)
108                         error("can't open cons: %r");
109                 dup(fd, 1);
110                 dup(1, 2);
111                 close(fd);
112                 consctl = open("/dev/consctl", OWRITE);
113                 if(consctl == -1)
114                         error("can't open consctl: %r");
115                 if(write(consctl, "rawon", 5) != 5)
116                         error("can't turn off echo\n");
117                 opened = 1;
118         }
119
120         for(;;){
121                 if(chatty || !must)
122                         fprint(2, "%s's screenlock password: ", user);
123                 memset(buf, 0, sizeof buf);
124                 readline(buf, sizeof buf);
125                 blankscreen(0);
126                 if(chatty || !must)
127                         fprint(2, "\n");
128                 if(buf[0] == '\0' || buf[0] == '\04'){
129                         if(must)
130                                 continue;
131                         error("no password typed");
132                 }
133
134                 /* authenticate */
135                 ai = auth_userpasswd(user, buf);
136                 if(ai != nil && ai->cap != nil)
137                         break;
138                 auth_freeAI(ai);
139
140                 if(chatty || !must)
141                         fprint(2, "password mismatch\n");
142                 doblank = 1;
143         }
144         memset(buf, 0, sizeof buf);
145         blankscreen(0);
146 }
147
148 void
149 blanker(void *)
150 {
151         int tics;
152
153         tics = 0;
154         for(;;){
155                 if(doblank > 0){
156                         doblank = 0;
157                         tics = 10;
158                 }
159                 if(tics > 0 && --tics == 0)
160                         blankscreen(1);
161                 sleep(1000);
162         }
163 }
164
165 void
166 grabmouse(void*)
167 {
168         int fd, x, y;
169         char ibuf[256], obuf[256];
170
171         if(debug)
172                 return;
173         fd = open("/dev/mouse", ORDWR);
174         if(fd < 0)
175                 error("can't open /dev/mouse: %r");
176
177         snprint(obuf, sizeof obuf, "m %d %d",
178                 screen->r.min.x + Dx(screen->r)/2,
179                 screen->r.min.y + Dy(screen->r)/2);
180         while(read(fd, ibuf, sizeof ibuf) > 0){
181                 ibuf[12] = 0;
182                 ibuf[24] = 0;
183                 x = atoi(ibuf+1);
184                 y = atoi(ibuf+13);
185                 if(x != screen->r.min.x + Dx(screen->r)/2 ||
186                    y != screen->r.min.y + Dy(screen->r)/2){
187                         fprint(fd, "%s", obuf);
188                         doblank = 1;
189                 }
190         }
191 }
192
193 /* lay down text at `p' */
194 static void
195 screenstring(Point p, char *s)
196 {
197         string(screen, p, screen->display->white, ZP, font, s);
198         flushimage(display, 1);
199 }
200
201 void
202 lockscreen(void)
203 {
204         enum { Nfld = 5, Fldlen = 12, Cursorlen = 2*4 + 2*2*16, };
205         char *s;
206         char buf[Nfld*Fldlen], *flds[Nfld], newcmd[128], cbuf[Cursorlen];
207         int fd, dx, dy;
208         Image *i;
209         Point p;
210         Rectangle r;
211         Tm *tm;
212
213         fd = open("/dev/screen", OREAD);
214         if(fd < 0)
215                 error("can't open /dev/screen: %r");
216         if(read(fd, buf, Nfld*Fldlen) != Nfld*Fldlen)
217                 error("can't read /dev/screen: %r");
218         close(fd);
219         buf[sizeof buf-1] = 0;
220         if(tokenize(buf, flds, Nfld) != Nfld)
221                 error("can't tokenize /dev/screen header");
222         snprint(newcmd, sizeof newcmd, "-r %s %s %d %d",
223                 flds[1], flds[2], atoi(flds[3]) - 1, atoi(flds[4]) - 1);
224         newwindow(newcmd);
225         if (initdraw(nil, nil, "screenlock") < 0)
226                 sysfatal("initdraw failed");
227         if(display == nil)
228                 error("no display");
229
230         /* screen is now open and covered.  grab mouse and hold on tight */
231         procrfork(grabmouse, nil, 4096, RFFDG);
232         procrfork(blanker, nil, 4096, RFFDG);
233         fd = open(pic, OREAD);
234         if(fd > 0){
235                 i = readimage(display, fd, 0);
236                 if(i){
237                         r = screen->r;
238                         p = Pt(r.max.x / 2, r.max.y * 2 / 3); 
239                         dx = (Dx(screen->r) - Dx(i->r)) / 2;
240                         r.min.x += dx;
241                         r.max.x -= dx;
242                         dy = (Dy(screen->r) - Dy(i->r)) / 2;
243                         r.min.y += dy;
244                         r.max.y -= dy;
245                         draw(screen, screen->r, display->black, nil, ZP);
246                         draw(screen, r, i, nil, i->r.min);
247                         flushimage(display, 1);
248                 }
249                 close(fd);
250
251                 /* identify the user on screen, centered */
252                 tm = localtime(time(0));
253                 s = smprint("user %s at %d:%02.2d", getuser(), tm->hour, tm->min);
254                 p = subpt(p, Pt(stringwidth(font, "m") * strlen(s) / 2, 0));
255                 screenstring(p, s);
256         }
257
258         /* clear the cursor */
259         fd = open("/dev/cursor", OWRITE);
260         if(fd > 0){
261                 memset(cbuf, 0, sizeof cbuf);
262                 write(fd, cbuf, sizeof cbuf);
263                 /* leave it open */
264         }
265 }
266
267 void
268 threadmain(int argc, char *argv[])
269 {
270         readfile("#c/user", user, sizeof user, 1);
271
272         if((vgactl = open("/dev/vgactl", OWRITE)) < 0)
273                 vgactl = open("#v/vgactl", OWRITE);
274
275         ARGBEGIN{
276         case 'd':
277                 debug++;
278                 break;
279         default:
280                 usage();
281         }ARGEND
282
283         if(argc != 0)
284                 usage();
285
286         doblank = 1;
287         lockscreen();
288         checkpassword();
289         threadexitsall(nil);
290 }