Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}