1 #if 0
2 static const char sccsid[] = "@(#)xlock.c 5.34 2011/05/23 xlockmore";
3
4 #endif
5
6 /*-
7 * xlock.c - X11 client to lock a display and show a screen saver.
8 *
9 * Copyright (c) 1988-1991 by Patrick J. Naughton
10 * Copyright (c) 1993-2011 by David A. Bagley
11 *
12 * xscreensaver code, Copyright (c) 1997 Jamie Zawinski <jwz AT jwz.org>
13 *
14 * Permission to use, copy, modify, and distribute this software and its
15 * documentation for any purpose and without fee is hereby granted,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation.
19 *
20 * This file is provided AS IS with no warranties of any kind. The author
21 * shall have no liability with respect to the infringement of copyrights,
22 * trade secrets or any patents by this file or any part thereof. In no
23 * event will the author be liable for any lost revenue or profits or
24 * other special, indirect and consequential damages.
25 *
26 * Revision History:
27 *
28 * Changes maintained by David Bagley <bagleyd AT verizon.net>
29 * 23-Feb-03: Timothy Reed <treed1@twcny.rr.com>
30 * Added PAM_putText to converse with passwd.c PAM_conv function
31 * to converse with any PAM.
32 * 09-Mar-01: showfps stuff corrected
33 * 01-Nov-00: Allocation checks
34 * 08-Apr-98: A way for users to unlock each others display. Kind of defeats
35 * the lock but the unlocked user is mailed and and entry is
36 * written to syslogd. Thanks to Mark Kirk <mkirk@pdi.com> for
37 * his vizlock-1.0 patch. Compile-time switch for this is
38 * GLOBAL_UNLOCK. This is probably full of security holes when
39 * enabled... :)
40 * 01-Jul-98: Eric Lassauge <lassauge AT users.sourceforge.net> &
41 * Remi Cohen-Scali <remi.cohenscali@pobox.com>
42 * Added support for locking VT switching (-/+vtlock)
43 * Added code is enclosed in USE_VTLOCK
44 * 01-May-97: Matthew Rench <mdrench@mtu.edu>
45 * Added DPMS options.
46 * 02-Dec-97: Strong user authentication, utilizing the SafeWord API.
47 * Author unknown.
48 * 01-May-97: Scott Carter <scarter@sdsc.edu>
49 * Added code to stat .xlocktext, .plan, and .signature files
50 * before reading the message; only regular files are read (no
51 * pipes or special files).
52 * Added code to replace tabs with 8 spaces in the plantext buffer.
53 * 01-Sep-96: Ron Hitchens <ron AT idiom.com>
54 * Updated xlock so it would refresh more reliably and
55 * handle window resizing.
56 * 18-Mar-96: Ron Hitchens <ron AT idiom.com>
57 * Implemented new ModeInfo hook calling scheme.
58 * Created mode_info() to gather and pass info to hooks.
59 * Watch for and use MI_PAUSE value if mode hook sets it.
60 * Catch SIGSEGV, SIGBUS and SIGFPE signals. Other should
61 * be caught. Eliminate some globals.
62 * 23-Dec-95: Ron Hitchens <ron AT idiom.com>
63 * Rewrote event loop so as not to use signals.
64 * 01-Sep-95: initPasswd function, more stuff removed to passwd.c
65 * 24-Jun-95: Cut out passwd stuff to passwd.c-> getPasswd & checkPasswd
66 * 17-Jun-95: Added xlockrc password compile time option.
67 * 12-May-95: Added defines for SunOS's Adjunct password file from
68 * Dale A. Harris <rodmur@ecst.csuchico.edu>
69 * 21-Feb-95: MANY patches from Heath A. Kehoe <hakehoe@icaen.uiowa.edu>.
70 * 24-Jan-95: time_displayed fixed from Chris Ross <cross@va.pubnix.com>.
71 * 18-Jan-95: Ultrix systems (at least DECstations) running enhanced
72 * security from Chris Fuhrman <cfuhrman@vt.edu> and friend.
73 * 26-Oct-94: In order to use extra-long passwords with the Linux changed
74 * PASSLENGTH to 64 <slouken@virtbrew.water.ca.gov>
75 * 11-Jul-94: added -inwindow option from Greg Bowering
76 * <greg@cs.adelaide.edu.au>
77 * 22-Jun-94: Modified for VMS
78 * <Anthony.D.Clarke@Support.Hatfield.Raytheon.bae.eurokom.ie>
79 * 10-Jun-94: patch for BSD from Victor Langeveld <vic@mbfys.kun.nl>
80 * 02-May-94: patched to work on Linux from Darren Senn's
81 * <sinster@scintilla.capitola.ca.us> xlock for Linux.
82 * Took out "bounce" since it was too buggy (maybe I will put
83 * it back later).
84 * 21-Mar-94: patch to to trap Shift-Ctrl-Reset courtesy of Jamie Zawinski
85 * <jwz AT jwz.org>, patched the patch (my mistake) for AIXV3
86 * and HP from <R.K.Lloyd@csc.liv.ac.uk>.
87 * 01-Dec-93: added patch for AIXV3 from Tom McConnell
88 * <tmcconne@sedona.intel.com> also added a patch for HP-UX 8.0.
89 * 29-Jul-93: "hyper", "helix", "rock", and "blot" (also tips on "maze") I
90 * got courtesy of Jamie Zawinski <jwz AT jwz.org>;
91 * at the time I could not get his stuff to work for the hpux 8.0,
92 * so I scrapped it but threw his stuff in xlock.
93 * "maze" and "sphere" I got courtesy of Sun Microsystems.
94 * "spline" I got courtesy of Jef Poskanzer <jef@netcom.com or
95 * jef@well.sf.ca.us>.
96 *
97 * Changes of Patrick J. Naughton
98 * 24-Jun-91: make foreground and background color get used on mono.
99 * 24-May-91: added -usefirst.
100 * 16-May-91: added pyro and random modes.
101 * ripped big comment block out of all other files.
102 * 08-Jan-91: fix some problems with password entry.
103 * removed renicing code.
104 * 29-Oct-90: added cast to XFree() arg.
105 * added volume arg to call to XBell().
106 * 28-Oct-90: center prompt screen.
107 * make sure Xlib input buffer does not use up all of swap.
108 * make displayed text come from resource file for better I18N.
109 * add backward compatible signal handlers for pre 4.1 machines.
110 * 31-Aug-90: added blank mode.
111 * added swarm mode.
112 * moved usleep() and seconds() out to usleep.c.
113 * added SVR4 defines to xlock.h
114 * 29-Jul-90: added support for multiple screens to be locked by one xlock.
115 * moved global defines to xlock.h
116 * removed use of allowsig().
117 * 07-Jul-90: reworked commandline args and resources to use Xrm.
118 * moved resource processing out to resource.c
119 * 02-Jul-90: reworked colors to not use dynamic colormap.
120 * 23-May-90: added autoraise when obscured.
121 * 15-Apr-90: added hostent alias searching for host authentication.
122 * 18-Feb-90: added SunOS3.5 fix.
123 * changed -mono -> -color, and -saver -> -lock.
124 * allow non-locking screensavers to display on remote machine.
125 * added -echokeys to disable echoing of '?'s on input.
126 * cleaned up all of the parameters and defaults.
127 * 20-Dec-89: added -xhost to allow access control list to be left alone.
128 * added -screensaver (do not disable screen saver) for the paranoid.
129 * Moved seconds() here from all of the display mode source files.
130 * Fixed bug with calling XUngrabHosts() in finish().
131 * 19-Dec-89: Fixed bug in GrabPointer.
132 * Changed fontname to XLFD style.
133 * 23-Sep-89: Added fix to allow local hostname:0 as a display.
134 * Put empty case for Enter/Leave events.
135 * Moved colormap installation later in startup.
136 * 20-Sep-89: Linted and made -saver mode grab the keyboard and mouse.
137 * Replaced SunView code for life mode with Jim Graham's version,
138 * so I could contrib it without legal problems.
139 * Sent to expo for X11R4 contrib.
140 * 19-Sep-89: Added '?'s on input.
141 * 27-Mar-89: Added -qix mode.
142 * Fixed GContext->GC.
143 * 20-Mar-89: Added backup font (fixed) if XQueryLoadFont() fails.
144 * Changed default font to lucida-sans-24.
145 * 08-Mar-89: Added -nice, -mode and -display, built vector for life and hop.
146 * 24-Feb-89: Replaced hopalong display with life display from SunView1.
147 * 22-Feb-89: Added fix for color servers with n < 8 planes.
148 * 16-Feb-89: Updated calling conventions for XCreateHsbColormap();
149 * Added -count for number of iterations per color.
150 * Fixed defaulting mechanism.
151 * Ripped out VMS hacks.
152 * Sent to expo for X11R3 contrib.
153 * 15-Feb-89: Changed default font to pellucida-sans-18.
154 * 20-Jan-89: Added -verbose and fixed usage message.
155 * 19-Jan-89: Fixed monochrome gc bug.
156 * 16-Dec-88: Added SunView style password prompting.
157 * 19-Sep-88: Changed -color to -mono. (default is color on color displays).
158 * Added -saver option. (just do display... do not lock.)
159 * 31-Aug-88: Added -time option.
160 * Removed code for fractals to separate file for modularity.
161 * Added signal handler to restore host access.
162 * Installs dynamic colormap with a Hue Ramp.
163 * If grabs fail then exit.
164 * Added VMS Hacks. (password 'iwiwuu').
165 * Sent to expo for X11R2 contrib.
166 * 08-Jun-88: Fixed root password pointer problem and changed PASSLENGTH to 20.
167 * 20-May-88: Added -root to allow root to unlock.
168 * 12-Apr-88: Added root password override.
169 * Added screen saver override.
170 * Removed XGrabServer/XUngrabServer.
171 * Added access control handling instead.
172 * 01-Apr-88: Added XGrabServer/XUngrabServer for more security.
173 * 30-Mar-88: Removed startup password requirement.
174 * Removed cursor to avoid phosphor burn.
175 * 27-Mar-88: Rotate fractal by 45 degrees clockwise.
176 * 24-Mar-88: Added color support. [-color]
177 * wrote the man page.
178 * 23-Mar-88: Added HOPALONG routines from Scientific American Sept. 86 p. 14.
179 * added password requirement for invocation
180 * removed option for command line password
181 * added requirement for display to be "unix:0".
182 * 22-Mar-88: Received Walter Milliken's comp.windows.x posting.
183 *
184 */
185
186 #ifdef STANDALONE
187
188 /*-
189 * xscreensaver compatibility layer for xlockmore modules.
190 * xscreensaver, Copyright (c) 1997, 1998 Jamie Zawinski <jwz AT jwz.org>
191 *
192 * Permission to use, copy, modify, distribute, and sell this software and its
193 * documentation for any purpose is hereby granted without fee, provided that
194 * the above copyright notice appear in all copies and that both that
195 * copyright notice and this permission notice appear in supporting
196 * documentation. No representations are made about the suitability of this
197 * software for any purpose. It is provided "as is" without express or
198 * implied warranty.
199 *
200 * This file, along with xlockmore.h, make it possible to compile an xlockmore
201 * module into a standalone program, and thus use it with xscreensaver.
202 * By Jamie Zawinski <jwz AT jwz.org> on 10-May-97; based on the ideas
203 * in the older xlock.h by Charles Hannum <mycroft@ai.mit.edu>. (I had
204 * to redo it, since xlockmore has diverged so far from xlock...)
205 */
206
207 #include <stdio.h>
208 #include <math.h>
209 #include <string.h>
210 #include "screenhack.h"
211 #include "mode.h"
212 #include "vis.h"
213
214 #define countof(x) (sizeof((x))/sizeof(*(x)))
215
216 extern ModeSpecOpt xlockmore_opts[];
217 extern const char *app_defaults;
218 char *message, *messagefile, *messagesfile, *program;
219 char *messagefontname;
220
221 void
pre_merge_options(void)222 pre_merge_options(void)
223 {
224 int i, j;
225 char *s;
226
227 /* Translate the xlockmore `opts[]' argument to a form that
228 screenhack.c expects.
229 */
230 for (i = 0; i < xlockmore_opts->numopts; i++) {
231 XrmOptionDescRec *old = &xlockmore_opts->opts[i];
232 XrmOptionDescRec *new = &options[i];
233
234 if (old->option[0] == '-')
235 new->option = old->option;
236 else {
237 /* Convert "+foo" to "-no-foo". */
238 if ((new->option = (char *) malloc(strlen(old->option) +
239 5)) != NULL) {
240 (void) strcpy(new->option, "-no-");
241 (void) strcat(new->option, old->option + 1);
242 }
243 }
244
245 new->specifier = strrchr(old->specifier, '.');
246 if (!new->specifier)
247 abort();
248
249 new->argKind = old->argKind;
250 new->value = old->value;
251 }
252
253 /* Add extra args, if they're mentioned in the defaults... */
254 {
255 char *args[] =
256 {"-delay", "-count", "-cycles", "-size", "-ncolors", "-bitmap",
257 "-text", "-filename", "-program",
258 "-wireframe", "-use3d", "-verbose"};
259
260 for (j = 0; j < countof(args); j++)
261 if (strstr(app_defaults, args[j] + 1)) {
262 XrmOptionDescRec *new = &options[i++];
263
264 new->option = args[j];
265 new->specifier = strdup(args[j]);
266 new->specifier[0] = '.';
267 if (!strcmp(new->option, "-wireframe")) {
268 new->argKind = XrmoptionNoArg;
269 new->value = "True";
270 new = &options[i++];
271 new->option = "-no-wireframe";
272 new->specifier = options[i - 2].specifier;
273 new->argKind = XrmoptionNoArg;
274 new->value = "False";
275 } else if (!strcmp(new->option, "-use3d")) {
276 new->option = "-3d";
277 new->argKind = XrmoptionNoArg;
278 new->value = "True";
279 new = &options[i++];
280 new->option = "-no-3d";
281 new->specifier = options[i - 2].specifier;
282 new->argKind = XrmoptionNoArg;
283 new->value = "False";
284 } else if (!strcmp(new->option, "-verbose")) {
285 new->option = "-verbose";
286 new->argKind = XrmoptionNoArg;
287 new->value = "True";
288 new = &options[i++];
289 new->option = "-no-verbose";
290 new->specifier = options[i - 2].specifier;
291 new->argKind = XrmoptionNoArg;
292 new->value = "False";
293 } else {
294 new->argKind = XrmoptionSepArg;
295 new->value = 0;
296 }
297 }
298 }
299
300
301 /* Construct the kind of `defaults' that screenhack.c expects from
302 the xlockmore `vars[]' argument.
303 */
304 i = 0;
305
306 /* Put on the PROGCLASS.background/foreground resources. */
307 if ((s = (char *) malloc(50)) != NULL) {
308 (void) strcpy(s, progclass);
309 (void) strcat(s, ".background: black");
310 defaults[i++] = s;
311 }
312
313 if ((s = (char *) malloc(50)) != NULL) {
314 (void) strcpy(s, progclass);
315 (void) strcat(s, ".foreground: white");
316 defaults[i++] = s;
317 }
318
319 /* Copy the lines out of the `app_defaults' var and into this array. */
320 s = strdup(app_defaults);
321 while (s && *s) {
322 defaults[i++] = s;
323 s = strchr(s, '\n');
324 if (s)
325 *s++ = 0;
326 }
327
328 /* Copy the defaults out of the `xlockmore_opts->' variable. */
329 for (j = 0; j < xlockmore_opts->numvarsdesc; j++) {
330 const char *def = xlockmore_opts->vars[j].def;
331
332 if (!def)
333 def = "False";
334 if (def == ((char *) 1))
335 def = "True";
336 if ((s = (char *) malloc(strlen(xlockmore_opts->vars[j].name) +
337 strlen(def) + 10)) != NULL) {
338 (void) strcpy(s, "*");
339 (void) strcat(s, xlockmore_opts->vars[j].name);
340 (void) strcat(s, ": ");
341 (void) strcat(s, def);
342 defaults[i++] = s;
343 }
344 }
345
346 defaults[i] = 0;
347 }
348
349
350 static void
xlockmore_read_resources(void)351 xlockmore_read_resources(void)
352 {
353 int i;
354
355 for (i = 0; i < xlockmore_opts->numvarsdesc; i++) {
356 void *var = xlockmore_opts->vars[i].var;
357 Bool *var_b = (Bool *) var;
358 char **var_c = (char **) var;
359 int *var_i = (int *) var;
360 float *var_f = (float *) var;
361
362 switch (xlockmore_opts->vars[i].type) {
363 case t_String:
364 *var_c = get_string_resource(xlockmore_opts->vars[i].name,
365 xlockmore_opts->vars[i].classname);
366 break;
367 case t_Float:
368 *var_f = get_float_resource(xlockmore_opts->vars[i].name,
369 xlockmore_opts->vars[i].classname);
370 break;
371 case t_Int:
372 *var_i = get_integer_resource(xlockmore_opts->vars[i].name,
373 xlockmore_opts->vars[i].classname);
374 break;
375 case t_Bool:
376 *var_b = get_boolean_resource(xlockmore_opts->vars[i].name,
377 xlockmore_opts->vars[i].classname);
378 break;
379 default:
380 abort();
381 }
382 }
383 }
384
385 void
xlockmore_screenhack(Display * dpy,Window window,Bool want_writable_colors,Bool want_uniform_colors,Bool want_smooth_colors,Bool want_bright_colors,void (* hack_init)(ModeInfo *),void (* hack_draw)(ModeInfo *),void (* hack_free)(ModeInfo *))386 xlockmore_screenhack(Display * dpy, Window window,
387 Bool want_writable_colors,
388 Bool want_uniform_colors,
389 Bool want_smooth_colors,
390 Bool want_bright_colors,
391 void (*hack_init) (ModeInfo *),
392 void (*hack_draw) (ModeInfo *),
393 void (*hack_free) (ModeInfo *))
394 {
395 ModeInfo mi;
396 XGCValues gcv;
397 XColor color;
398 int i;
399 time_t start, now;
400 struct timeval drawstart, drawstop;
401 unsigned long drawelapsed;
402 int orig_pause;
403
404 (void) memset((char *) &mi, 0, sizeof (mi));
405 mi.dpy = dpy;
406 mi.window = window;
407 (void) XGetWindowAttributes(dpy, window, &mi.xgwa);
408
409 color.flags = DoRed | DoGreen | DoBlue;
410 color.red = color.green = color.blue = 0;
411 if (!XAllocColor(dpy, mi.xgwa.colormap, &color))
412 abort();
413 mi.black = color.pixel;
414 color.red = color.green = color.blue = 0xFFFF;
415 if (!XAllocColor(dpy, mi.xgwa.colormap, &color))
416 abort();
417 mi.white = color.pixel;
418
419 if (mono_p) {
420 static unsigned long pixels[2];
421 static XColor colors[2];
422
423 MONO:
424 mi.npixels = 2;
425 mi.pixels = pixels;
426 mi.colors = colors;
427 pixels[0] = mi.black;
428 pixels[1] = mi.white;
429 colors[0].flags = DoRed | DoGreen | DoBlue;
430 colors[1].flags = DoRed | DoGreen | DoBlue;
431 colors[0].red = colors[0].green = colors[0].blue = 0;
432 colors[1].red = colors[1].green = colors[1].blue = 0xFFFF;
433 mi.writable_p = False;
434 } else {
435 mi.npixels = get_integer_resource("ncolors", "Integer");
436 if (mi.npixels <= 0)
437 mi.npixels = 64;
438 else if (mi.npixels > 256)
439 mi.npixels = 256;
440
441 mi.writable_p = want_writable_colors;
442 if ((mi.colors = (XColor *) calloc(mi.npixels,
443 sizeof (*mi.colors))) != NULL) {
444
445 if (want_uniform_colors)
446 make_uniform_colormap(dpy, mi.xgwa.visual, mi.xgwa.colormap,
447 mi.colors, &mi.npixels,
448 True, &mi.writable_p, True);
449 else if (want_smooth_colors)
450 make_smooth_colormap(dpy, mi.xgwa.visual, mi.xgwa.colormap,
451 mi.colors, &mi.npixels,
452 True, &mi.writable_p, True);
453 else
454 make_random_colormap(dpy, mi.xgwa.visual, mi.xgwa.colormap,
455 mi.colors, &mi.npixels,
456 want_bright_colors,
457 True, &mi.writable_p, True);
458 }
459
460 if (mi.npixels <= 2)
461 goto MONO;
462 else {
463 if ((mi.pixels = (unsigned long *)
464 calloc(mi.npixels, sizeof (*mi.pixels))) != NULL) {
465 int i;
466
467 for (i = 0; i < mi.npixels; i++)
468 mi.pixels[i] = mi.colors[i].pixel;
469 }
470 }
471 }
472
473 gcv.foreground = mi.white;
474 gcv.background = mi.black;
475 mi.gc = XCreateGC(dpy, window, GCForeground | GCBackground, &gcv);
476
477 mi.pause = get_integer_resource("delay", "Usecs");
478
479 mi.count = get_integer_resource("count", "Int");
480 mi.cycles = get_integer_resource("cycles", "Int");
481 mi.size = get_integer_resource("size", "Int");
482 mi.ncolors = get_integer_resource("ncolors", "Int");
483 mi.bitmap = get_string_resource("bitmap", "String");
484 messagefontname = get_string_resource("font", "String");
485 message = get_string_resource("text", "String");
486 messagefile = get_string_resource("filename", "String");
487 messagesfile = get_string_resource("fortunefile", "String");
488 program = get_string_resource("program", "String");
489
490
491 #if 0
492 decay = get_boolean_resource("decay", "Boolean");
493 if (decay)
494 mi.fullrandom = False;
495
496 trail = get_boolean_resource("trail", "Boolean");
497 if (trail)
498 mi.fullrandom = False;
499
500 grow = get_boolean_resource("grow", "Boolean");
501 if (grow)
502 mi.fullrandom = False;
503
504 liss = get_boolean_resource("liss", "Boolean");
505 if (liss)
506 mi.fullrandom = False;
507
508 ammann = get_boolean_resource("ammann", "Boolean");
509 if (ammann)
510 mi.fullrandom = False;
511
512 jong = get_boolean_resource("jong", "Boolean");
513 if (jong)
514 mi.fullrandom = False;
515
516 sine = get_boolean_resource("sine", "Boolean");
517 if (sine)
518 mi.fullrandom = False;
519 #endif
520
521 mi.threed = get_boolean_resource("use3d", "Boolean");
522 mi.threed_delta = get_float_resource("delta3d", "Boolean");
523 mi.threed_right_color = get_pixel_resource("right3d", "Color", dpy,
524 mi.xgwa.colormap);
525 mi.threed_left_color = get_pixel_resource("left3d", "Color", dpy,
526 mi.xgwa.colormap);
527 mi.threed_both_color = get_pixel_resource("both3d", "Color", dpy,
528 mi.xgwa.colormap);
529 mi.threed_none_color = get_pixel_resource("none3d", "Color", dpy,
530 mi.xgwa.colormap);
531
532 mi.wireframe_p = get_boolean_resource("wireframe", "Boolean");
533 mi.fps_p = get_boolean_resource("showfps", "Boolean");
534 mi.verbose = get_boolean_resource("verbose", "Boolean");
535
536 mi.root_p = (window == RootWindowOfScreen(mi.xgwa.screen));
537 mi.is_drawn = False;
538
539
540 if (mi.pause < 0)
541 mi.pause = 0;
542 else if (mi.pause > 100000000)
543 mi.pause = 100000000;
544 orig_pause = mi.pause;
545
546 xlockmore_read_resources();
547
548 XClearWindow(dpy, window);
549
550 i = 0;
551 start = time((time_t) 0);
552
553 hack_init(&mi);
554 do {
555 (void) gettimeofday(&drawstart, NULL);
556 hack_draw(&mi);
557 XSync(dpy, False);
558 (void) gettimeofday(&drawstop, NULL);
559 drawelapsed = (drawstop.tv_sec - drawstart.tv_sec)*1000000 +
560 (drawstop.tv_usec - drawstart.tv_usec);
561 if (mi.pause > drawelapsed)
562 (void) usleep(mi.pause - drawelapsed);
563 mi.pause = orig_pause;
564
565 if (hack_free) {
566 if (i++ > (mi.count / 4) &&
567 (start + 5) < (now = time((time_t) 0))) {
568 i = 0;
569 start = now;
570 hack_free(&mi);
571 hack_init(&mi);
572 XSync(dpy, False);
573 }
574 }
575 } while (1);
576 }
577
578 #else /* STANDALONE */
579 #include "xlock.h"
580 #include "color.h"
581 #include "util.h"
582 #include "iostuff.h"
583 #include "passwd.h"
584 #include <sys/stat.h>
585 #include <signal.h>
586 #include <errno.h>
587 #if HAVE_SYS_RESOURCE_H
588 #include <sys/resource.h>
589 #endif
590 #if HAVE_SYS_TIME_H
591 #include <sys/time.h>
592 #endif
593 #if HAVE_SYS_SELECT_H && defined(AIXV3)
594 #include <sys/select.h>
595 #endif
596
597 #ifndef WIN32
598 #include <X11/cursorfont.h>
599 #include <X11/Xatom.h>
600 #include <X11/keysym.h>
601 #else
602 #include "Xapi.h"
603 int GCCreate(void);
604 #endif /* WIN32 */
605
606 #if USE_XVMSUTILS
607 #if 0
608 #include "../xvmsutils/unix_types.h"
609 #include "../xvmsutils/unix_time.h"
610 #else
611 #include <X11/unix_types.h>
612 #include <X11/unix_time.h>
613 #endif
614 #endif /* USE_XVMSUTILS */
615 #ifdef USE_DTSAVER
616 #include <X11/Intrinsic.h>
617 #include <Dt/Saver.h>
618 #endif
619 #if defined( __hpux ) || defined( __apollo )
620 #include <X11/XHPlib.h>
621 extern int XHPEnableReset(Display * dsp);
622
623 #endif
624 #ifdef USE_DPMS
625 #ifndef MIN_DPMS
626 #define MIN_DPMS 5 /* 5 second minimum */
627 #endif
628 #if 1
629 #include <X11/Xmd.h>
630 #include <X11/Xdmcp.h>
631 #include <X11/extensions/dpms.h>
632 #ifdef SunCplusplus
633 extern Bool DPMSQueryExtension(Display *, int *, int *);
634 extern Bool DPMSGetTimeouts(Display *, unsigned short *, unsigned short *, unsigned short *);
635 extern Status DPMSSetTimeouts(Display *, unsigned short, unsigned short, unsigned short);
636 extern int DPMSCapable(Display *);
637 extern int DPMSInfo(Display *, CARD16 *, BOOL *);
638 #endif
639 #else /* XFree86 < 4.x */
640 #include <X11/extensions/dpms.h>
641 #ifndef __NetBSD
642 extern unsigned char DPMSQueryExtension(Display *, int *, int *);
643 #endif
644 extern int DPMSGetTimeouts(Display *, unsigned short *, unsigned short *, unsigned short *);
645 extern int DPMSSetTimeouts(Display *, unsigned short, unsigned short, unsigned short);
646 #endif
647 extern int dpmsstandby;
648 extern int dpmssuspend;
649 extern int dpmsoff;
650
651 #endif
652
653 #ifdef USE_XINERAMA
654 #include <X11/extensions/Xinerama.h>
655 #endif
656
657 #ifdef HAVE_KRB5
658 #include <krb5.h>
659 #endif /* HAVE_KRB5 */
660
661 #if ( HAVE_SYSLOG_H && (defined( USE_SYSLOG ) || defined( GLOBAL_UNLOCK )))
662 #include <pwd.h>
663 #include <grp.h>
664 #include <syslog.h>
665 #ifndef SYSLOG_FACILITY
666 #define SYSLOG_FACILITY LOG_AUTH
667 #endif
668 #endif
669
670 #if ( __VMS_VER >= 70000000 )
671 #include <lib$routines.h>
672 #include <mail$routines.h>
673 #include <maildef.h>
674 struct itmlst_3 {
675 unsigned short int buflen;
676 unsigned short int itmcode;
677 void *bufadr;
678 unsigned short int *retlen;
679 };
680
681 #endif
682
683 #ifdef __FreeBSD__
684 #include <floatingpoint.h>
685 #endif
686
687 extern void checkResources(void);
688 extern void defaultVisualInfo(Display * display, int screen);
689
690 #ifdef USE_OLD_EVENT_LOOP
691 extern int usleep(unsigned int);
692
693 #endif
694
695 #if defined( USE_AUTO_LOGOUT ) || defined( USE_BUTTON_LOGOUT )
696 extern void logoutUser(Display * display
697 #ifdef CLOSEDOWN_LOGOUT
698 , int screens
699 #endif
700 );
701
702 #endif
703
704 #if 0
705 /* #if !defined( AIXV3 ) && !defined( __hpux ) && !defined( __bsdi__ ) */
706 extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
707
708 #if !defined( __hpux ) && !defined( apollo )
709 extern int select(size_t, int *, int *, int *, const struct timeval *);
710
711 #endif
712
713 #endif
714
715 char *ProgramName; /* argv[0] */
716
717 #ifdef DEBUG
718 pid_t ProgramPID; /* for memcheck.c */
719
720 #endif
721 ScreenInfo *Scr = (ScreenInfo *) NULL;
722
723 /* This is a private data structure, don't touch */
724 static ModeInfo *modeinfo = (ModeInfo *) NULL;
725
726 Window parent;
727 Bool parentSet = False;
728 Display *dsp = (Display *) NULL; /* server display connection */
729
730 extern char user[PASSLENGTH];
731 extern char hostname[MAXHOSTNAMELEN];
732 extern char *displayname;
733 extern char *bitmap;
734 extern int delay;
735 extern int count;
736 extern int cycles;
737 extern int size;
738 extern int ncolors;
739 extern float saturation;
740 extern float delta3d;
741 extern Bool nolock;
742 extern Bool resetsaver;
743 extern Bool inwindow;
744 extern Bool inroot;
745 extern Bool mono;
746 extern Bool allowaccess;
747 extern Bool allowroot;
748 extern Bool debug;
749 extern Bool description;
750 extern Bool echokeys;
751 extern char* echokey;
752 extern Bool enablesaver;
753 extern Bool fullrandom;
754 extern Bool grabmouse;
755 extern Bool grabserver;
756 extern Bool install;
757 extern Bool mousemotion;
758 extern int unlockdelay;
759 extern Bool showdate;
760 extern Bool timeelapsed;
761 extern Bool usefirst;
762 extern Bool verbose;
763 extern Bool remote;
764 extern int nicelevel;
765 extern int lockdelay;
766 extern int timeout;
767 extern Bool wireframe;
768 #ifdef USE_GL
769 extern Bool showfps;
770 extern Bool fpsTop;
771 #endif
772 extern Bool use3d;
773 #ifdef HAVE_KRB5
774 extern int krb5_valid;
775 #endif
776
777 extern char *fontname;
778 extern char *planfontname;
779
780 #ifdef USE_MB
781 XFontSet fontset = NULL;
782 extern char *fontsetname;
783 XFontSet planfontset = NULL;
784 extern char *planfontsetname;
785
786 XRectangle mbRect;
787 XRectangle planmbRect;
788
789 #define fontHeight (mbRect.height)
790 #define fontDescent (mbRect.height / 5)
791 #define fontAscent (mbRect.height - fontDescent)
792 #define planFontHeight (planmbRect.height)
793 #define planFontDescent (planmbRect.height / 5)
794 #define planFontAscent (planmbRect.height - planFontDescent)
795
796 #else
797
798 #define fontHeight (font->ascent + font->descent)
799 #define fontAscent (font->ascent)
800 #define fontDescent (font->descent)
801 #define planFontHeight (planfont->ascent + planfont->descent)
802 #define planFontAscent (planfont->ascent)
803 #define planFontDescent (planfont->descent)
804
805 #endif
806 extern char *background;
807 extern char *foreground;
808 extern char *text_user;
809 extern char *text_pass;
810 extern char *text_info;
811 #ifdef HAVE_KRB5
812 extern char *text_krbinfo;
813 #endif
814 extern char *text_valid;
815 extern char *text_invalid;
816 extern char *text_invalidCapsLock;
817 extern char *failed_attempt;
818 extern char *failed_attempts;
819
820 extern char *geometry;
821 extern char *icongeometry;
822
823 #ifdef FX
824 extern char *glgeometry;
825
826 #endif
827 extern char *none3d;
828 extern char *right3d;
829 extern char *left3d;
830 extern char *both3d;
831
832 #ifdef USE_SOUND
833 extern char *locksound;
834 extern char *infosound;
835 extern char *validsound;
836 extern char *invalidsound;
837 #if 0
838 extern char *welcomesound;
839 extern char *shutdownsound;
840 #endif
841 extern void playSound(char *string, Bool verbose);
842 #ifdef USE_ESOUND
843 extern int init_sound(void);
844 extern void shutdown_sound(void);
845 #endif
846 extern Bool sound;
847
848 #endif
849
850 extern char *startCmd;
851 extern char *endCmd;
852 #ifndef VMS
853 extern char *pipepassCmd;
854 #endif
855 extern char *logoutCmd;
856
857 extern char *mailCmd;
858 extern char *mailIcon;
859 extern char *nomailIcon;
860
861 #ifdef USE_AUTO_LOGOUT
862 extern int logoutAuto;
863
864 #endif
865
866 #ifdef USE_BUTTON_LOGOUT
867 extern int logoutButton;
868 extern int enable_button;
869 extern char *logoutButtonLabel;
870 extern char *logoutButtonHelp;
871 extern char *logoutFailedString;
872
873 #endif
874
875 #ifdef USE_DTSAVER
876 extern Bool dtsaver;
877
878 #endif
879
880 static int screen = 0; /* current screen */
881 int startscreen = 0;
882 static int screens; /* number of screens */
883
884 #ifdef FX
885 static int glwidth, glheight;
886
887 #endif
888 static XFontStruct *font;
889 #ifndef WIN32
890 static Cursor mycursor; /* blank cursor */
891 static int passx, passy; /* position of the ?'s */
892 static XFontStruct *planfont;
893 static Pixmap lockc;
894 static Pixmap lockm; /* pixmaps for cursor and mask */
895 static char no_bits[] =
896 {0}; /* dummy array for the blank cursor */
897 static int iconwidth, iconheight;
898 static int lock_delay;
899 static int count_failed;
900 /* GEOMETRY STUFF */
901 static int sizeconfiguremask;
902 static XWindowChanges minisizeconfigure;
903 static int signalUSR1 = 0;
904 static int signalUSR2 = 0;
905 static int timex, timey; /* position for the times */
906 static unsigned long start_time;
907 static Bool fullscreen = False;
908 static char *plantext[TEXTLINES + 2]; /* Message is stored here */
909 #endif
910
911 static int sstimeout; /* screen saver parameters */
912 static int ssinterval;
913 static int ssblanking;
914 static int ssexposures;
915
916 #if defined( USE_AUTO_LOGOUT ) || defined( USE_BUTTON_LOGOUT )
917 static int tried_logout = 0;
918
919 #endif
920
921 #ifdef USE_SOUND
922 static int got_invalid = 0;
923
924 #endif
925
926 /* This still might not be right for Solaris, change the "1"->"0" if error */
927 #if 1
928 #if (defined( SYSV ) || defined( SVR4 )) && defined( SOLARIS2 ) && !defined( HAVE_STRUCT_SIGSET_T )
929 #if !defined( __cplusplus ) && !defined( c_plusplus ) && !defined ( _SIGSET_T )
930
931 #define _SIGSET_T
932 typedef struct { /* signal set type */
933 unsigned long __sigbits[4];
934 } sigset_t;
935
936 /* This is good for gcc compiled on Solaris-2.5 but used on Solaris-2.6 */
937
938 #endif
939 #endif
940 #endif
941 #if !defined( SYSV ) && !defined( SVR4 ) && !defined( VMS ) && !defined(__cplusplus) && !defined(c_plusplus)
942 extern int sigblock(int);
943 extern int sigsetmask(int);
944 #endif
945
946 #ifdef ORIGINAL_XPM_PATCH
947 #ifdef HAVE_XPM
948 #include <X11/xpm.h>
949 #endif
950
951 static XpmImage *mail_xpmimg = NULL;
952 static XpmImage *nomail_xpmimg = NULL;
953
954 #else
955 #ifndef WIN32
956 #include <bitmaps/mailempty.xbm>
957 #include <bitmaps/mailfull.xbm>
958
959 #define NOMAIL_WIDTH mailempty_width
960 #define NOMAIL_HEIGHT mailempty_height
961 #define NOMAIL_BITS mailempty_bits
962 #define MAIL_WIDTH mailfull_width
963 #define MAIL_HEIGHT mailfull_height
964 #define MAIL_BITS mailfull_bits
965 #endif /* !WIN32 */
966 #endif
967
968 #ifdef USE_VTLOCK
969 /* EL - RCS : for VT switching locking */
970 extern int vtlock; /* Have to lock VT switching */
971 extern int vtlocked; /* VT switching is locked */
972
973 extern void dovtlock(void); /* Actual do it */
974 extern void dovtunlock(void); /* & undo it functions */
975
976 #endif
977
978 #if defined( USE_MB ) && defined( __VMS )
979 int screenOffset = 4;
980 #else
981 int screenOffset = 0;
982 #endif
983
984 char * old_default_mode = (char *) NULL;
985
986 #define AllPointerEventMask \
987 (ButtonPressMask | ButtonReleaseMask | \
988 EnterWindowMask | LeaveWindowMask | \
989 PointerMotionMask | PointerMotionHintMask | \
990 Button1MotionMask | Button2MotionMask | \
991 Button3MotionMask | Button4MotionMask | \
992 Button5MotionMask | ButtonMotionMask | \
993 KeymapStateMask)
994
995 #ifdef USE_VROOT
996 #include "vroot.h"
997 #endif
998
999 #ifdef SAFEWORD
1000 #include "custpb.h"
1001 #include "custf.h"
1002
1003 extern char *text_dpass;
1004 extern char *text_fpass;
1005 extern char *text_chall;
1006 static int challx, chally;
1007
1008 extern pbmain();
1009
1010 struct pblk pblock; /* our instance of the pblk */
1011 struct pblk *pb; /* global pointer to the pblk */
1012
1013 extern int checkDynamic();
1014
1015 #endif
1016
1017 #if defined( HAVE_SYSLOG_H ) && defined( USE_SYSLOG )
1018 static void
syslogStart(void)1019 syslogStart(void)
1020 {
1021 struct passwd *pw = NULL;
1022 struct group *gr = NULL;
1023 char uid[16];
1024 char gid[16];
1025
1026 pw = getpwuid(getuid());
1027 gr = getgrgid(getgid());
1028 if (pw == NULL)
1029 sprintf(uid, "%ld", (long) getuid());
1030 if (gr == NULL)
1031 sprintf(gid, "%ld", (long) getgid());
1032 (void) openlog(ProgramName, LOG_PID, SYSLOG_FACILITY);
1033 syslog(SYSLOG_INFO, "Start: %s, %s, %s",
1034 (pw == NULL) ? uid : pw->pw_name,
1035 (gr == NULL) ? gid : gr->gr_name,
1036 XDisplayString(dsp));
1037 }
1038
1039 void
syslogStop(char * displayName)1040 syslogStop(char *displayName)
1041 {
1042 int secs, mins;
1043 struct passwd *pw = NULL;
1044 struct group *gr = NULL;
1045 char uid[16];
1046 char gid[16];
1047
1048 pw = getpwuid(getuid());
1049 gr = getgrgid(getgid());
1050 if (pw == NULL)
1051 sprintf(uid, "%ld", (long) getuid());
1052 if (gr == NULL)
1053 sprintf(gid, "%ld", (long) getgid());
1054 secs = (int) (seconds() - start_time);
1055 mins = secs / 60;
1056 secs %= 60;
1057 syslog(SYSLOG_INFO, "Stop: %s, %s, %s, %dm %ds",
1058 (pw == NULL) ? uid : pw->pw_name,
1059 (gr == NULL) ? gid : gr->gr_name,
1060 displayName, mins, secs);
1061 }
1062
1063 #endif
1064
1065 char error_buf[ERROR_BUF];
1066 static int error_exitcode = 1;
1067
1068 void
error(const char * buf)1069 error(const char *buf)
1070 {
1071 #if defined( HAVE_SYSLOG_H ) && defined( USE_SYSLOG )
1072 syslog(SYSLOG_WARNING, "%s", buf);
1073 if (!nolock) {
1074 if (strstr(buf, "unable to open display") == NULL)
1075 syslogStop(XDisplayString(dsp));
1076 else
1077 syslogStop("unknown display");
1078 closelog();
1079 }
1080 #else
1081 (void) fprintf(stderr, "%s", buf);
1082 #endif
1083 if (error_exitcode < 0) {
1084 int sig = -error_exitcode;
1085 signal(sig, SIG_DFL);
1086 raise(sig);
1087 /* We are still alive?? */
1088 error_exitcode = sig + 128;
1089 }
1090 exit(error_exitcode);
1091 }
1092
1093 /* Server access control support. */
1094
1095 static XHostAddress *XHosts; /* the list of "friendly" client machines */
1096 static int HostAccessCount; /* the number of machines in XHosts */
1097 static Bool HostAccessState; /* whether or not we even look at the list */
1098
1099 /* define window class (used by WindowMaker attributes configuration) */
1100 XClassHint xclasshint={(char *) DEFAULT_NAME, (char *) DEFAULT_NAME};
1101
1102 #ifndef WIN32
1103 static void
XGrabHosts(Display * display)1104 XGrabHosts(Display * display)
1105 {
1106 XHosts = XListHosts(display, &HostAccessCount, &HostAccessState);
1107 if (XHosts)
1108 XRemoveHosts(display, XHosts, HostAccessCount);
1109 XEnableAccessControl(display);
1110 }
1111 #endif
1112
1113 static void
XUngrabHosts(Display * display)1114 XUngrabHosts(Display * display)
1115 {
1116 if (XHosts) {
1117 XAddHosts(display, XHosts, HostAccessCount);
1118 XFree((caddr_t) XHosts);
1119 }
1120 if (HostAccessState == False)
1121 XDisableAccessControl(display);
1122 }
1123
1124 /* Provides support for the DPMS options. */
1125 #ifdef USE_DPMS
1126 static void
SetDPMS(Display * display,int nstandby,int nsuspend,int noff)1127 SetDPMS(Display * display, int nstandby, int nsuspend, int noff)
1128 {
1129 static unsigned short standby = 0, suspend = 0, off = 0, flag = 0;
1130 int dummy;
1131
1132 if (DPMSQueryExtension(display, &dummy, &dummy)) {
1133 if (!flag) {
1134 DPMSGetTimeouts(display, &standby, &suspend, &off);
1135 flag++;
1136 }
1137 if ((nstandby < 0) && (nsuspend < 0) && (noff < 0))
1138 DPMSSetTimeouts(display, standby, suspend, off);
1139 else
1140 DPMSSetTimeouts(display,
1141 (nstandby <= 0 ? 0 : (nstandby > MIN_DPMS ? nstandby : MIN_DPMS)),
1142 (nsuspend <= 0 ? 0 : (nsuspend > MIN_DPMS ? nsuspend : MIN_DPMS)),
1143 (noff <= 0 ? 0 : (noff > MIN_DPMS ? noff : MIN_DPMS)));
1144 }
1145 }
1146
1147 static int
monitor_powered_on_p(Display * dpy)1148 monitor_powered_on_p(Display *dpy)
1149 {
1150 int result;
1151 int event_number, error_number;
1152 BOOL onoff = False;
1153 CARD16 state;
1154
1155 if (!DPMSQueryExtension(dpy, &event_number, &error_number))
1156 /* DPMS extension is not supported */
1157 result = True;
1158
1159 else if (!DPMSCapable(dpy))
1160 /* Monitor is incapable of DPMS */
1161 result = True;
1162
1163 else
1164 {
1165 DPMSInfo(dpy, &state, &onoff);
1166 if (!onoff)
1167 /* DPMS is disabled */
1168 result = True;
1169 else {
1170 switch (state) {
1171 case DPMSModeOn: result = True; break;
1172 case DPMSModeStandby: result = False; break;
1173 case DPMSModeSuspend: result = False; break;
1174 case DPMSModeOff: result = False; break;
1175 default: result = True; break;
1176 }
1177 }
1178 }
1179 return result;
1180 }
1181 #else
1182 #ifndef WIN32
1183 static int
monitor_powered_on_p(Display * dpy)1184 monitor_powered_on_p(Display *dpy)
1185 {
1186 return 1;
1187 }
1188 #endif
1189 #endif
1190
1191
1192 #ifndef WIN32
1193 /*-
1194 * Simple wrapper to get an asynchronous grab on the keyboard and mouse. If
1195 * either grab fails, we sleep for one second and try again since some window
1196 * manager might have had the mouse grabbed to drive the menu choice that
1197 * picked "Lock Screen..". If either one fails the second time we print an
1198 * error message and exit.
1199 */
1200 static void
GrabKeyboardAndMouse(Display * display,Window window)1201 GrabKeyboardAndMouse(Display * display, Window window)
1202 {
1203 Status status;
1204
1205 status = XGrabKeyboard(display, window, True,
1206 GrabModeAsync, GrabModeAsync, CurrentTime);
1207 if (status != GrabSuccess) {
1208 (void) sleep(1);
1209 status = XGrabKeyboard(display, window, True,
1210 GrabModeAsync, GrabModeAsync, CurrentTime);
1211
1212 if (status != GrabSuccess) {
1213 (void) sprintf(error_buf,
1214 "%s, could not grab keyboard! (%d)\n",
1215 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
1216 ProgramName : DEFAULT_NAME, status);
1217 error(error_buf);
1218 }
1219 }
1220 status = XGrabPointer(display, window, True,
1221 (unsigned int) AllPointerEventMask, GrabModeAsync,
1222 GrabModeAsync, None, mycursor, CurrentTime);
1223 if (status != GrabSuccess) {
1224 (void) sleep(1);
1225 status = XGrabPointer(display, window, True,
1226 (unsigned int) AllPointerEventMask, GrabModeAsync,
1227 GrabModeAsync, None, mycursor, CurrentTime);
1228
1229 if (status != GrabSuccess) {
1230 (void) sprintf(error_buf,
1231 "%s, could not grab pointer! (%d)\n",
1232 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
1233 ProgramName : DEFAULT_NAME, status);
1234 error(error_buf);
1235 }
1236 }
1237 }
1238
1239 /* Assuming that we already have an asynch grab on the pointer, just grab it
1240 again with a new cursor shape and ignore the return code. */
1241 static void
ChangeGrabbedCursor(Display * display,Window window,Cursor cursor)1242 ChangeGrabbedCursor(Display * display, Window window, Cursor cursor)
1243 {
1244 if (!debug && grabmouse && !inwindow && !inroot)
1245 (void) XGrabPointer(display, window, True,
1246 (unsigned int) AllPointerEventMask, GrabModeAsync,
1247 GrabModeAsync, None, cursor, CurrentTime);
1248 }
1249
1250 /*-
1251 * Return True or False indicating if the given window has changed
1252 * size relative to the window geometry cached in the mode_info
1253 * struct. If the window handle given does not match the one in
1254 * the cache, or if the width/height are not the same, then True
1255 * is returned and the window handle in the cache is cleared.
1256 * This causes mode_info() to reload the window info next time
1257 * it is called.
1258 * This function has non-obvious side-effects. I feel so dirty. Rh
1259 */
1260
1261 static int
window_size_changed(int scrn,Window window)1262 window_size_changed(int scrn, Window window)
1263 {
1264 XWindowAttributes xgwa;
1265 ModeInfo *mi = &modeinfo[scrn];
1266
1267 if (MI_WINDOW(mi) != window) {
1268 MI_WINDOW(mi) = None; /* forces reload on next mode_info() */
1269 return (True);
1270 } else {
1271 (void) XGetWindowAttributes(dsp, window, &xgwa);
1272 if ((MI_WIDTH(mi) != xgwa.width) ||
1273 (MI_HEIGHT(mi) != xgwa.height)) {
1274 MI_WINDOW(mi) = None;
1275 return (True);
1276 }
1277 }
1278
1279 return (False);
1280 }
1281 #endif /* WIN32 */
1282
1283 #ifdef FX
1284 void
resetSize(ModeInfo * mi,Bool setGL)1285 resetSize(ModeInfo * mi, Bool setGL)
1286 {
1287 char *mesa_3Dfx_env;
1288 static int width = 0, height = 0;
1289
1290 mesa_3Dfx_env = getenv("MESA_GLX_FX");
1291 if (!mesa_3Dfx_env)
1292 return;
1293 if (tolower(mesa_3Dfx_env[0]) != 'f')
1294 return;
1295
1296 /*
1297 * This is not correct for multiscreens, but there are other problems
1298 * here for multiscreens as well so I am not going bother
1299 */
1300 if (!width)
1301 width = MI_WIDTH(mi);
1302 if (!height)
1303 height = MI_HEIGHT(mi);
1304
1305 if (setGL) {
1306 MI_WIDTH(mi) = glwidth;
1307 MI_HEIGHT(mi) = glheight;
1308 } else {
1309 MI_WIDTH(mi) = width;
1310 MI_HEIGHT(mi) = height;
1311 }
1312 XResizeWindow(MI_DISPLAY(mi), MI_WINDOW(mi),
1313 MI_WIDTH(mi), MI_HEIGHT(mi));
1314 }
1315 #endif
1316
1317 /*-
1318 * Return a pointer to an up-to-date ModeInfo struct for the given
1319 * screen, window and iconic mode. Because the number of screens
1320 * is limited, and much of the information is screen-specific, this
1321 * function keeps static copies of ModeInfo structs are kept for
1322 * each screen. This also eliminates redundant calls to the X server
1323 * to acquire info that does change.
1324 */
1325
1326 static ModeInfo *
mode_info(Display * display,int scrn,Window window,int iconic)1327 mode_info(Display * display, int scrn, Window window, int iconic)
1328 {
1329 XWindowAttributes xgwa;
1330 ModeInfo *mi;
1331
1332 mi = &modeinfo[scrn];
1333
1334 if (MI_FLAG_NOT_SET(mi, WI_FLAG_INFO_INITTED)) {
1335 /* This stuff only needs to be set once per screen */
1336
1337 (void) memset((char *) mi, 0, sizeof (ModeInfo));
1338
1339 MI_DISPLAY(mi) = display;
1340 MI_SCREEN(mi) = scrn;
1341 MI_REAL_SCREEN(mi) = scrn; /* TODO, for multiscreen debugging */
1342 MI_SCREENPTR(mi) = ScreenOfDisplay(display, scrn);
1343 MI_NUM_SCREENS(mi) = screens;
1344 MI_MAX_SCREENS(mi) = screens; /* TODO, for multiscreen debugging */
1345
1346 MI_SCREENINFO(mi) = &Scr[scrn];
1347
1348 /* accessing globals here */
1349 MI_SET_FLAG_STATE(mi, WI_FLAG_MONO,
1350 (mono || CellsOfScreen(MI_SCREENPTR(mi)) <= 2));
1351 MI_SET_FLAG_STATE(mi, WI_FLAG_INWINDOW, inwindow);
1352 MI_SET_FLAG_STATE(mi, WI_FLAG_INROOT, inroot);
1353 MI_SET_FLAG_STATE(mi, WI_FLAG_NOLOCK, nolock);
1354 #ifdef USE_DTSAVER
1355 MI_SET_FLAG_STATE(mi, WI_FLAG_INSTALL, install && !inroot && !dtsaver);
1356 #else
1357 MI_SET_FLAG_STATE(mi, WI_FLAG_INSTALL, install && !inroot);
1358 #endif
1359 MI_SET_FLAG_STATE(mi, WI_FLAG_DEBUG, debug);
1360 MI_SET_FLAG_STATE(mi, WI_FLAG_USE3D, use3d &&
1361 !(mono || CellsOfScreen(MI_SCREENPTR(mi)) <= 2));
1362 MI_SET_FLAG_STATE(mi, WI_FLAG_VERBOSE, verbose);
1363 #ifdef WIN32
1364 MI_SET_FLAG_STATE(mi, WI_FLAG_FULLRANDOM, True);
1365 #else
1366 MI_SET_FLAG_STATE(mi, WI_FLAG_FULLRANDOM, False);
1367 #endif
1368 MI_SET_FLAG_STATE(mi, WI_FLAG_WIREFRAME, wireframe);
1369 #ifdef USE_GL
1370 MI_SET_FLAG_STATE(mi, WI_FLAG_FPS, showfps);
1371 #endif
1372 MI_SET_FLAG_STATE(mi, WI_FLAG_INFO_INITTED, True);
1373 MI_IS_DRAWN(mi) = False;
1374 }
1375 if (MI_WINDOW(mi) != window) {
1376 MI_WINDOW(mi) = window;
1377
1378 (void) XGetWindowAttributes(display, window, &xgwa);
1379
1380 MI_WIDTH(mi) = xgwa.width;
1381 MI_HEIGHT(mi) = xgwa.height;
1382 }
1383 MI_SET_FLAG_STATE(mi, WI_FLAG_ICONIC, iconic);
1384
1385 MI_DELTA3D(mi) = delta3d;
1386
1387 MI_DELAY(mi) = delay; /* globals */
1388 MI_COUNT(mi) = count;
1389 MI_CYCLES(mi) = cycles;
1390 MI_SIZE(mi) = size;
1391 MI_NCOLORS(mi) = ncolors;
1392 MI_SATURATION(mi) = saturation;
1393 MI_BITMAP(mi) = bitmap;
1394 return (mi);
1395 }
1396
1397
1398 #if defined( GLOBAL_UNLOCK ) || defined( USE_PAM )
1399 static int unamex = 0, unamey = 0;
1400 #endif
1401 #ifdef GLOBAL_UNLOCK
1402
1403 extern char *text_guser;
1404 extern char global_user[PASSLENGTH];
1405 extern void checkUser(char *buffer);
1406 #define LOG_FACILITY LOG_LOCAL2
1407 #define LOG_LEVEL LOG_INFO
1408
1409 static int
inform()1410 inform()
1411 {
1412 /*
1413 - the time, in date(1) style, is generated with a combination of the
1414 time(2) and ctime(3C) system calls.
1415 - the owner of the xlock process is learned with getlogin(3C).
1416 - global_user is a global character array that holds the username
1417 of the person wishing to unlock the display.
1418 - the hostname is learned with gethostname(2).
1419 - the syslog(3B) call uses the syslog facility to log
1420 happenings at LOG_LEVEL to LOG_FACILITY
1421 - yes, a system(3S) call is used...
1422 - I never said it was pretty.
1423
1424 */
1425
1426 char Mail[256];
1427 time_t unlock_time;
1428
1429 /* learn what time it is and what host we are on */
1430 time(&unlock_time);
1431
1432 #if defined( HAVE_SYSLOG_H ) /* && defined( USE_SYSLOG ) */
1433 /* log this event to syslogd as defined */
1434 syslog(LOG_FACILITY | LOG_LEVEL, "%s: %s unlocked %s's display",
1435 ProgramName, global_user, getlogin());
1436 #endif
1437 /* if (mailCmd && mailCmd[0]) { */
1438 /* build a string suitable for use in system(3S) */
1439 (void) sprintf(Mail, "%s -s \"%s:\" %s << EOF\n %s unlocked "
1440 "%s's display on %s\n EOF",
1441 /* Want the mail with the subject line control */
1442 #if defined( SYSV ) || defined( SVR4 ) || ( __VMS_VER >= 70000000 )
1443 "/usr/ucb/mail" ,
1444 #else
1445 "/usr/bin/mail" ,
1446 #endif
1447 ProgramName, getlogin(),
1448 global_user, hostname, ctime(&unlock_time));
1449
1450 if (debug)
1451 (void) printf("%s\n", Mail);
1452 (void) system(Mail);
1453 /* } */
1454 }
1455 #endif
1456
1457 /* Restore all grabs, reset screensaver, restore colormap, close connection. */
1458 void
finish(Display * display,Bool closeDisplay)1459 finish(Display * display, Bool closeDisplay)
1460 {
1461 int scrn;
1462
1463 for (scrn = startscreen; scrn < screens; scrn++) {
1464 if (Scr[scrn].window != None) {
1465 release_last_mode(mode_info(display, scrn, Scr[scrn].window, False));
1466 }
1467 if (Scr[scrn].icon != None) {
1468 release_last_mode(mode_info(display, scrn, Scr[scrn].icon, True));
1469 }
1470 }
1471 #ifdef ORIGINAL_XPM_PATCH
1472 if (mail_xpmimg)
1473 free(mail_xpmimg);
1474 if (nomail_xpmimg)
1475 free(nomail_xpmimg);
1476 #endif
1477
1478 XSync(display, False);
1479 #ifdef USE_VROOT
1480 if (inroot)
1481 XClearWindow(display, Scr[startscreen].window);
1482 #endif
1483
1484 #ifdef GLOBAL_UNLOCK
1485 /* Check to see if the owner is doing the unlocking themselves,
1486 and if not then inform the display owner of who is unlocking */
1487
1488 if (strcmp(global_user, getlogin()) != 0)
1489 inform();
1490 #endif
1491
1492 if (!nolock && !allowaccess) {
1493 if (grabserver)
1494 XUngrabServer(display);
1495 XUngrabHosts(display);
1496 }
1497 XUngrabPointer(display, CurrentTime);
1498 XUngrabKeyboard(display, CurrentTime);
1499 if (!enablesaver && !nolock) {
1500 XSetScreenSaver(display, sstimeout, ssinterval, ssblanking, ssexposures);
1501 }
1502 XFlush(display);
1503 #if 0
1504 /* Report that this gives "bad file descriptor" on XFree86 4.x */
1505 #ifndef __sgi
1506 /*-
1507 * The following line seems to cause a core dump on the SGI.
1508 * More work is needed on the cleanup code.
1509 */
1510 if (closeDisplay)
1511 (void) XCloseDisplay(display);
1512 #endif
1513 #endif
1514 #ifdef HAVE_SETPRIORITY
1515 (void) setpriority(0, 0, 0);
1516 #else /* !HAVE_SETPRIORITY */
1517 (void) nice(0);
1518 #endif /* HAVE_SETPRIORITY */
1519 #ifdef USE_VTLOCK
1520 /* EL - RCS : Unlock VT switching */
1521 if (vtlock && vtlocked)
1522 dovtunlock();
1523 #endif
1524 }
1525
1526 #ifndef WIN32
1527 #ifdef __cplusplus
1528 extern "C" {
1529 #endif
1530
1531 static int
xio_error(Display * d)1532 xio_error(Display * d)
1533 {
1534 #ifdef USE_DTSAVER
1535 if (dtsaver) { /* this is normal when run as -dtsaver */
1536 /* X connection to :0.0 broken (explicit kill or server shutdown). */
1537 exit(0);
1538 }
1539 #endif
1540 (void) sprintf(error_buf,
1541 "%s: xio_error\n",
1542 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
1543 ProgramName : DEFAULT_NAME);
1544 error(error_buf);
1545 return ((debug) ? 0 : 1); /* suppress message unless debugging */
1546 }
1547
1548 #ifdef __cplusplus
1549 }
1550 #endif
1551 #endif /* WIN32 */
1552
1553 /* Convenience function for drawing text */
1554 static void
putText(Display * display,Window window,GC gc,const char * string,int bold,int left,int * px,int * py)1555 putText(Display * display, Window window, GC gc,
1556 const char *string, int bold, int left, int *px, int *py)
1557 /* which window */
1558 /* gc */
1559 /* text to write */
1560 /* 1 = make it bold */
1561 /* left edge of text */
1562 /* current x and y, input & return */
1563 {
1564 #define PT_BUFSZ 2048
1565 char buf[PT_BUFSZ], *p, *s;
1566 int x = *px, y = *py, last, len;
1567
1568 (void) strncpy(buf, string, PT_BUFSZ);
1569 buf[PT_BUFSZ - 1] = 0;
1570
1571 p = buf;
1572 last = 0;
1573 for (;;) {
1574 s = p;
1575 for (; *p; ++p)
1576 if (*p == '\n')
1577 break;
1578 if (!*p)
1579 last = 1;
1580 *p = 0;
1581
1582 if ((len = strlen(s))) { /* yes, "=", not "==" */
1583 (void) XDrawImageString(display, window, gc, x, y, s, len);
1584 if (bold)
1585 (void) XDrawString(display, window, gc, x + 1, y, s, len);
1586 }
1587 if (!last) {
1588 y += fontHeight + 6;
1589 x = left;
1590 } else {
1591 if (len)
1592 x += XTextWidth(font, s, len);
1593 break;
1594 }
1595 p++;
1596 }
1597 *px = x;
1598 *py = y;
1599 }
1600
1601 /* language dependent strings */
1602 #if defined DE
1603 #include "xlock-msg-de.h"
1604 #elif defined FR
1605 #include "xlock-msg-fr.h"
1606 #elif defined NL
1607 #include "xlock-msg-nl.h"
1608 #elif defined JA
1609 #include "xlock-msg-ja.h"
1610 #elif defined ZH
1611 #include "xlock-msg-zh_TW.h"
1612 #else
1613 #include "xlock-msg-en.h"
1614 #endif
1615
1616 #ifndef WIN32
1617 static void
statusUpdate(int isnew,int scr)1618 statusUpdate(int isnew, int scr)
1619 {
1620 int left, x, y, len;
1621 char buf[1024];
1622 XWindowAttributes xgwa;
1623 static int last_time;
1624
1625 #ifdef USE_BUTTON_LOGOUT
1626 int ysave;
1627 static int made_button, last_tried_lo = 0;
1628
1629 #endif /* USE_BUTTON_LOGOUT */
1630
1631 len = (int) (seconds() - start_time) / 60;
1632
1633 #ifdef USE_BUTTON_LOGOUT
1634 if (tried_logout && !last_tried_lo) {
1635 last_tried_lo = 1;
1636 isnew = 1;
1637 #ifdef USE_AUTO_LOGOUT
1638 logoutAuto = 0;
1639 #endif
1640 }
1641 if (isnew)
1642 made_button = 0;
1643 #endif /* USE_BUTTON_LOGOUT */
1644
1645 if (isnew || last_time != len)
1646 last_time = len;
1647 else
1648 return;
1649
1650 (void) XGetWindowAttributes(dsp, Scr[scr].window, &xgwa);
1651 x = left = timex;
1652 y = timey;
1653
1654 if (timeelapsed) {
1655 if (len < 60) {
1656 if (len == 1)
1657 (void) sprintf(buf, TIME_ELAPSED_MINUTE, len);
1658 else
1659 (void) sprintf(buf, TIME_ELAPSED_MINUTES, len);
1660 } else {
1661 (void) sprintf(buf, TIME_ELAPSED_HOURS, len / 60, len % 60);
1662 }
1663 putText(dsp, Scr[scr].window, Scr[scr].textgc, buf, False, left, &x, &y);
1664 }
1665 #ifdef USE_BUTTON_LOGOUT
1666 if (enable_button) {
1667 if (logoutButton > len) {
1668 int tmp = logoutButton - len;
1669
1670 if (tmp < 60) {
1671 if (tmp == 1)
1672 (void) sprintf(buf, BUTTON_MINUTE, tmp);
1673 else
1674 (void) sprintf(buf, BUTTON_MINUTES, tmp);
1675 } else {
1676 (void) sprintf(buf, BUTTON_HOURS, tmp / 60, tmp % 60);
1677 }
1678 putText(dsp, Scr[scr].window, Scr[scr].textgc, buf, False, left, &x, &y);
1679 } else {
1680 /* Erase previous logout button message */
1681 putText(dsp, Scr[scr].window, Scr[scr].textgc,
1682 " \n",
1683 False, left, &x, &y);
1684 if (!made_button || (isnew && tried_logout)) {
1685 made_button = 1;
1686 ysave = y;
1687
1688 y += fontHeight + 8; /* Leave a gap for validating */
1689 XUnmapWindow(dsp, Scr[scr].button);
1690 XSetForeground(dsp, Scr[scr].gc, Scr[scr].bg_pixel);
1691 XFillRectangle(dsp, Scr[scr].window, Scr[scr].gc, left, y,
1692 xgwa.width - left,
1693 5 + 2 * (fontHeight));
1694 XSetForeground(dsp, Scr[scr].gc, Scr[scr].fg_pixel);
1695
1696 if (tried_logout) {
1697 putText(dsp, Scr[scr].window, Scr[scr].textgc, logoutFailedString,
1698 True, left, &x, &y);
1699 } else {
1700 XMoveWindow(dsp, Scr[scr].button, left, y);
1701 XMapWindow(dsp, Scr[scr].button);
1702 XRaiseWindow(dsp, Scr[scr].button);
1703 (void) sprintf(buf, " %s ", logoutButtonLabel);
1704 XSetForeground(dsp, Scr[scr].gc, Scr[scr].white_pixel);
1705 (void) XDrawString(dsp, Scr[scr].button, Scr[scr].gc,
1706 0, fontAscent + 1, buf, strlen(buf));
1707 XSetForeground(dsp, Scr[scr].gc, Scr[scr].fg_pixel);
1708 y += 5 + 2 * fontHeight;
1709 putText(dsp, Scr[scr].window, Scr[scr].textgc, logoutButtonHelp,
1710 False, left, &x, &y);
1711 }
1712 y = ysave;
1713 x = left;
1714 }
1715 }
1716 }
1717 #endif /* USE_BUTTON_LOGOUT */
1718 #ifdef USE_AUTO_LOGOUT
1719 if (logoutAuto) {
1720 int tmp = logoutAuto - len;
1721
1722 if (tmp < 60) {
1723 if (tmp == 1)
1724 (void) sprintf(buf, AUTOLOGOUT_MINUTE, tmp);
1725 else
1726 (void) sprintf(buf, AUTOLOGOUT_MINUTES, tmp);
1727 } else {
1728 (void) sprintf(buf, AUTOLOGOUT_HOURS, tmp / 60, tmp % 60);
1729 }
1730 putText(dsp, Scr[scr].window, Scr[scr].textgc, buf, False, left, &x, &y);
1731 }
1732 #endif /* USE_AUTO_LOGOUT */
1733 }
1734 #endif /* WIN32 */
1735
1736 #ifdef USE_AUTO_LOGOUT
1737 static void
checkLogout(Display * display)1738 checkLogout(Display * display)
1739 {
1740 if (nolock || tried_logout || !logoutAuto)
1741 return;
1742 if (logoutAuto * 60 < (int) (seconds() - start_time)) {
1743 tried_logout = 1;
1744 logoutAuto = 0;
1745 logoutUser(display
1746 #ifdef CLOSEDOWN_LOGOUT
1747 , screens
1748 #endif
1749 );
1750 }
1751 }
1752
1753 #endif /* USE_AUTO_LOGOUT */
1754
1755 #ifndef WIN32
1756 #ifndef USE_OLD_EVENT_LOOP
1757
1758 /* subtract timer t2 from t1, return result in t3. Result is not allowed to
1759 go negative, set to zero if result underflows */
1760
1761 static
1762 void
sub_timers(struct timeval * t1,struct timeval * t2,struct timeval * t3)1763 sub_timers(struct timeval *t1, struct timeval *t2, struct timeval *t3)
1764 {
1765 struct timeval tmp;
1766 int borrow = 0;
1767
1768 if (t1->tv_usec < t2->tv_usec) {
1769 borrow++;
1770 tmp.tv_usec = (1000000 + t1->tv_usec) - t2->tv_usec;
1771 } else {
1772 tmp.tv_usec = t1->tv_usec - t2->tv_usec;
1773 }
1774
1775 /* Be careful here, timeval fields may be unsigned. To avoid
1776 underflow in an unsigned int, add the borrow value to the
1777 subtrahend for the relational test. Same effect, but avoids the
1778 possibility of a negative intermediate value. */
1779 if (t1->tv_sec < (t2->tv_sec + borrow)) {
1780 tmp.tv_usec = tmp.tv_sec = 0;
1781 } else {
1782 tmp.tv_sec = t1->tv_sec - t2->tv_sec - borrow;
1783 }
1784
1785 *t3 = tmp;
1786 }
1787
1788 /* return 0 on event received, -1 on timeout */
1789 static int
runMainLoop(int maxtime,int iconscreen)1790 runMainLoop(int maxtime, int iconscreen)
1791 {
1792 static int lastdelay = -1, lastmaxtime = -1;
1793 int fd = ConnectionNumber(dsp), r;
1794 int poweron=True;
1795 struct timeval sleep_time, first, repeat, elapsed, tmp;
1796 fd_set reads;
1797 unsigned long started;
1798
1799 #ifdef USE_NEW_EVENT_LOOP
1800 struct timeval loopStart, timeSinceLoop;
1801 unsigned long lastIter = 0, desiredIter = 0;
1802
1803 GETTIMEOFDAY(&loopStart);
1804 #endif
1805
1806 first.tv_sec = 0;
1807 first.tv_usec = 0;
1808 elapsed.tv_sec = 0;
1809 elapsed.tv_usec = 0;
1810 repeat.tv_sec = delay / 1000000;
1811 repeat.tv_usec = delay % 1000000;
1812
1813 started = seconds();
1814
1815 for (;;) {
1816 poweron= monitor_powered_on_p(dsp);
1817 if(!poweron) (void) usleep(100000);
1818
1819 if (signalUSR1 || signalUSR2) {
1820 int i;
1821
1822 if (signalUSR1) {
1823 #ifdef DEBUG
1824 (void) printf("switch to mode %s\n", "blank");
1825 #endif
1826 for (i = 0; i < numprocs; i++) {
1827 if (!strcmp(LockProcs[i].cmdline_arg, "blank")) {
1828 set_default_mode(&LockProcs[i]);
1829 break;
1830 }
1831 }
1832 } else {
1833 #ifdef DEBUG
1834 (void) printf("switch to mode %s\n", old_default_mode);
1835 #endif
1836 for (i = 0; i < numprocs; i++) {
1837 if (!strcmp(LockProcs[i].cmdline_arg, old_default_mode)) {
1838 set_default_mode(&LockProcs[i]);
1839 break;
1840 }
1841 }
1842 }
1843
1844 for (screen = startscreen; screen < screens; screen++) {
1845 call_change_hook((LockStruct *) NULL,
1846 mode_info(dsp, screen, Scr[screen].window, False));
1847 }
1848
1849 signalUSR1 = signalUSR2 = 0;
1850 }
1851 if (delay != lastdelay || maxtime != lastmaxtime) {
1852 if (!delay || (maxtime && delay / 1000000 > maxtime)) {
1853 repeat.tv_sec = maxtime;
1854 repeat.tv_usec = 0;
1855 } else {
1856 repeat.tv_sec = delay / 1000000;
1857 repeat.tv_usec = delay % 1000000;
1858 }
1859 first = repeat;
1860 lastdelay = delay;
1861 lastmaxtime = maxtime;
1862 sleep_time = first;
1863 } else {
1864 sleep_time = repeat;
1865 }
1866
1867 /* subtract time spent doing last loop iteration */
1868 sub_timers(&sleep_time, &elapsed, &sleep_time);
1869
1870 /* (void) */ FD_ZERO(&reads);
1871 FD_SET(fd, &reads);
1872 #ifdef VMS
1873 FD_SET(fd + 1, &reads);
1874 #endif
1875 #if DCE_PASSWD
1876 r = _select_sys(fd + 1,
1877 (fd_set *) & reads, (fd_set *) NULL, (fd_set *) NULL,
1878 (struct timeval *) &sleep_time);
1879 #else
1880 #if defined( __cplusplus ) || defined( c_plusplus )
1881 r = select(fd + 1,
1882 (fd_set *) & reads, (fd_set *) NULL, (fd_set *) NULL,
1883 (struct timeval *) &sleep_time);
1884 #else
1885 r = select(fd + 1,
1886 (void *) &reads, (void *) NULL, (void *) NULL,
1887 (struct timeval *) &sleep_time);
1888 #endif
1889 #endif
1890
1891 if (r == 1)
1892 return 0;
1893 if (r > 0 || (r == -1 && errno != EINTR))
1894 (void) fprintf(stderr,
1895 "Unexpected select() return value: %d (errno=%d)\n", r, errno);
1896
1897 GETTIMEOFDAY(&tmp); /* get time before calling mode proc */
1898
1899 #ifdef USE_NEW_EVENT_LOOP
1900 if (delay == 0) {
1901 desiredIter = lastIter + 1;
1902 } else {
1903 sub_timers(&tmp, &loopStart, &timeSinceLoop);
1904 desiredIter =
1905 (timeSinceLoop.tv_usec / delay) +
1906 (((timeSinceLoop.tv_sec % delay) * 1000000) / delay) +
1907 (timeSinceLoop.tv_sec / delay) * 1000000;
1908 }
1909 while (lastIter != desiredIter) {
1910 ++lastIter;
1911 #endif
1912
1913 for (screen = startscreen; screen < screens; screen++) {
1914 Window cbwin;
1915 Bool iconic;
1916 ModeInfo *mi;
1917
1918 if (screen == iconscreen) {
1919 cbwin = Scr[screen].icon;
1920 iconic = True;
1921 } else {
1922 cbwin = Scr[screen].window;
1923 iconic = False;
1924 }
1925 if (cbwin != None && poweron) {
1926 mi = mode_info(dsp, screen, cbwin, iconic);
1927 call_callback_hook((LockStruct *) NULL, mi);
1928 }
1929 }
1930
1931 if (poweron)
1932 XSync(dsp, False);
1933 else
1934 (void) usleep(100000);
1935
1936 /* check for events received during the XSync() */
1937 if (QLength(dsp)) {
1938 return 0;
1939 }
1940 if (maxtime && ((int) (seconds() - started) > maxtime)) {
1941 return -1;
1942 }
1943 #ifdef USE_NEW_EVENT_LOOP
1944 }
1945 #endif
1946 /* if (mindelay) (void) usleep(mindelay); */
1947
1948 /* get the time now, figure how long it took */
1949 GETTIMEOFDAY(&elapsed);
1950 sub_timers(&elapsed, &tmp, &elapsed);
1951 }
1952 }
1953 #endif /* !USE_OLD_EVENT_LOOP */
1954
1955 static int
ReadXString(char * s,int slen,Bool * capsLock,Bool pass)1956 ReadXString(char *s, int slen, Bool *capsLock
1957 #ifdef GLOBAL_UNLOCK
1958 , Bool pass
1959 #elif defined( USE_PAM )
1960 , Bool PAM_echokeys
1961 #endif
1962
1963 )
1964 {
1965 XEvent event;
1966 char keystr[20];
1967 char c;
1968 int i;
1969 int bp;
1970 int len;
1971 int thisscreen = screen;
1972 char pwbuf[PASSLENGTH];
1973 int first_key = 1;
1974
1975 if (capsLock != NULL)
1976 *capsLock = False;
1977 for (screen = startscreen; screen < screens; screen++)
1978 if (thisscreen == screen) {
1979 call_init_hook((LockStruct *) NULL,
1980 mode_info(dsp, screen, Scr[screen].icon, True));
1981 } else {
1982 call_init_hook((LockStruct *) NULL,
1983 mode_info(dsp, screen, Scr[screen].window, False));
1984 }
1985 statusUpdate(True, thisscreen);
1986 bp = 0;
1987 *s = 0;
1988
1989 for (;;) {
1990 unsigned long lasteventtime = seconds();
1991 KeySym keysym;
1992
1993 while (!XPending(dsp)) {
1994 #ifdef USE_OLD_EVENT_LOOP
1995 for (screen = startscreen; screen < screens; screen++)
1996 if (thisscreen == screen)
1997 call_callback_hook(NULL, mode_info(dsp, screen,
1998 Scr[screen].icon, True));
1999 else
2000 call_callback_hook(NULL, mode_info(dsp, screen,
2001 Scr[screen].window, False));
2002 statusUpdate(False, thisscreen);
2003 XSync(dsp, False);
2004 (void) usleep(delay);
2005 #else
2006 statusUpdate(False, thisscreen);
2007 if (runMainLoop(MIN(timeout, 5), thisscreen) == 0)
2008 break;
2009 #endif
2010
2011 if ((timeout < (int) (seconds() - lasteventtime))) {
2012 screen = thisscreen;
2013 return 1;
2014 }
2015 }
2016
2017 screen = thisscreen;
2018 (void) XNextEvent(dsp, &event);
2019
2020 /*
2021 * This event handling code should be unified with the
2022 * similar code in justDisplay().
2023 */
2024 switch (event.type) {
2025 case KeyPress:
2026 len = XLookupString((XKeyEvent *) & event,
2027 keystr, 20, /*(KeySym *) NULL,*/
2028 &keysym,
2029 (XComposeStatus *) NULL);
2030 if (capsLock != NULL)
2031 *capsLock = ((event.xkey.state & LockMask) != 0);
2032
2033 for (i = 0; i < len; i++) {
2034 c = keystr[i];
2035 switch (c) {
2036 case 8: /* ^H */
2037 case 127: /* DEL */
2038 if (bp > 0)
2039 bp--;
2040 break;
2041 case 10: /* ^J */
2042 case 13: /* ^M */
2043 if (first_key && usefirst)
2044 break;
2045 s[bp] = '\0';
2046 return 0;
2047 case 21: /* ^U */
2048 case 27: /* ESC */
2049 bp = 0;
2050 break;
2051 default:
2052 s[bp] = c;
2053 if (bp < slen - 1)
2054 bp++;
2055 else
2056 XSync(dsp, True); /* flush input buffer */
2057 }
2058 }
2059 XSetForeground(dsp, Scr[screen].gc, Scr[screen].bg_pixel);
2060 #ifdef GLOBAL_UNLOCK
2061 if (!pass) {
2062 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2063 unamex, unamey - fontAscent,
2064 XTextWidth(font, s, slen),
2065 fontHeight + 3);
2066 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2067 unamex, unamey, s, bp);
2068 } else
2069 #elif defined( USE_PAM )
2070 if (PAM_echokeys) {
2071
2072 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2073 unamex, unamey - fontAscent,
2074 XTextWidth(font, s, slen),
2075 fontHeight + 3);
2076
2077 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2078 unamex, unamey, s, bp);
2079 } else
2080 #endif
2081 if (echokeys) {
2082 if (bp > 0 && strcmp("swear", echokey) == 0) {
2083 char swearkeys[] = "@^!$%?#*";
2084
2085 pwbuf[bp - 1] =
2086 swearkeys[NRAND(strlen(swearkeys))];
2087 pwbuf[bp] = '\0';
2088 } else
2089 (void) memset((char *) pwbuf,
2090 echokey[0], slen);
2091 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2092 passx, passy - fontAscent,
2093 XTextWidth(font, pwbuf, slen),
2094 fontHeight + 3);
2095 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2096 passx, passy, pwbuf, bp);
2097 }
2098 /* eat all events if there are more than
2099 enough pending... this keeps the Xlib event
2100 buffer from growing larger than all
2101 available memory and crashing xlock. */
2102 if (XPending(dsp) > 100) { /* 100 is arbitrarily
2103 big enough */
2104 register Status status;
2105
2106 do {
2107 status = XCheckMaskEvent(dsp,
2108 KeyPressMask | KeyReleaseMask, &event);
2109 } while (status);
2110 XBell(dsp, 100);
2111 }
2112 break;
2113
2114 case MotionNotify:
2115 if (!mousemotion)
2116 break;
2117 /* fall through on last mouse event */
2118 case ButtonPress:
2119 if (((XButtonEvent *) & event)->window == Scr[screen].icon) {
2120 return 1;
2121 }
2122 #ifdef USE_BUTTON_LOGOUT
2123 if (((XButtonEvent *) & event)->window == Scr[screen].button) {
2124 XSetFunction(dsp, Scr[screen].gc, GXxor);
2125 XSetForeground(dsp, Scr[screen].gc, Scr[screen].fg_pixel);
2126 XFillRectangle(dsp, Scr[screen].button, Scr[screen].gc,
2127 0, 0, 500, 100);
2128 XSync(dsp, False);
2129 tried_logout = 1;
2130 logoutUser(dsp
2131 #ifdef CLOSEDOWN_LOGOUT
2132 , screens
2133 #endif
2134 );
2135 XSetFunction(dsp, Scr[screen].gc, GXcopy);
2136 }
2137 #endif
2138 break;
2139
2140 case Expose:
2141 if (event.xexpose.count != 0)
2142 break;
2143 /* fall through on last expose event */
2144 case VisibilityNotify:
2145 /* next line for -geometry */
2146 if (event.xvisibility.state != VisibilityUnobscured) {
2147 /* window was restacked or exposed */
2148 #ifndef __CYGWIN__
2149 if (!debug && !inwindow)
2150 XRaiseWindow(dsp, event.xvisibility.window);
2151 #endif
2152 call_refresh_hook((LockStruct *) NULL,
2153 mode_info(dsp, screen, Scr[screen].window, False));
2154 #ifndef USE_WINDOW_VISIBILITY
2155 s[0] = '\0';
2156 return 1;
2157 #endif
2158 }
2159 break;
2160 case ConfigureNotify:
2161 /* next line for -geometry */
2162 if (!fullscreen)
2163 break;
2164 /* window config changed */
2165 #ifndef __CYGWIN__
2166 if (!debug && !inwindow) {
2167 XRaiseWindow(dsp, event.xconfigure.window);
2168 fixColormap(mode_info(dsp, screen, Scr[screen].window, False), ncolors,
2169 saturation, mono, install, inroot, inwindow, verbose);
2170 }
2171 #endif
2172 if (window_size_changed(screen, Scr[screen].window)) {
2173 call_init_hook((LockStruct *) NULL,
2174 mode_info(dsp, screen, Scr[screen].window, False));
2175 } else if (install)
2176 /* next line : refresh would be logical. But some modes
2177 * look weird when continuing from an erased screen */
2178 call_refresh_hook((LockStruct *) NULL,
2179 mode_info(dsp, screen, Scr[screen].window, False));
2180
2181 s[0] = '\0';
2182 return 1;
2183 case KeymapNotify:
2184 case KeyRelease:
2185 case ButtonRelease:
2186 case LeaveNotify:
2187 case EnterNotify:
2188 case NoExpose:
2189 case CirculateNotify:
2190 case DestroyNotify:
2191 case GravityNotify:
2192 case MapNotify:
2193 case ReparentNotify:
2194 case UnmapNotify:
2195 break;
2196
2197 default:
2198 (void) fprintf(stderr, "%s: unexpected event: %d\n",
2199 ProgramName, event.type);
2200 break;
2201 }
2202 first_key = 0;
2203 }
2204 }
2205 #endif
2206
2207 void
modeDescription(ModeInfo * mi)2208 modeDescription(ModeInfo * mi)
2209 {
2210 int left, x, y;
2211 int scrn = MI_SCREEN(mi);
2212 XWindowAttributes xgwa;
2213
2214 (void) XGetWindowAttributes(dsp, Scr[scrn].window, &xgwa);
2215
2216 x = left = Scr[scrn].iconpos.x;
2217 y = Scr[scrn].iconpos.y - fontHeight + 8;
2218
2219 XSetForeground(dsp, Scr[scrn].gc, Scr[scrn].bg_pixel);
2220 XFillRectangle(dsp, Scr[scrn].window, Scr[scrn].gc,
2221 x, y - fontAscent - 4 + screenOffset ,
2222 xgwa.width - x, fontHeight + 6 + screenOffset);
2223
2224 putText(dsp, Scr[scrn].window, Scr[scrn].textgc, MI_NAME(mi),
2225 True, left, &x, &y);
2226 putText(dsp, Scr[scrn].window, Scr[scrn].textgc, ": ", True, left, &x, &y);
2227 putText(dsp, Scr[scrn].window, Scr[scrn].textgc, MI_DESC(mi),
2228 False, left, &x, &y);
2229 putText(dsp, Scr[scrn].window, Scr[scrn].textgc, "\n", False, left, &x, &y);
2230 }
2231
2232 /* WIN32 machines handle reading passwords automatically */
2233 #ifndef WIN32
2234
2235 static void
update_plan(void)2236 update_plan(void) /* updates current time in plantext */
2237 {
2238 if (showdate) {
2239 time_t t;
2240
2241 t = time(NULL);
2242 if (plantext[0] != NULL) {
2243 (void) strcpy(plantext[0], (char *) ctime(&t));
2244 plantext[0][strlen(plantext[0]) - 1] = '\0';
2245 }
2246 }
2247 }
2248
2249 static int
getPassword(void)2250 getPassword(void)
2251 {
2252 XWindowAttributes xgwa;
2253 int x, y, left, done, remy;
2254 char buffer[PASSLENGTH];
2255 char **planp;
2256 char *hostbuf = (char *) NULL;
2257 ModeInfo *mi = &modeinfo[screen];
2258 Bool capsLock = False;
2259 #ifdef USE_MB
2260 XFontSet backfontset;
2261 #endif
2262
2263 #ifdef FX
2264 Bool mesa_3Dfx_fullscreen;
2265 char *mesa_3Dfx_env;
2266
2267 mesa_3Dfx_env = getenv("MESA_GLX_FX");
2268 if (mesa_3Dfx_env)
2269 if (tolower(mesa_3Dfx_env[0] == 'f')) {
2270 /* disabling fullscreen HW 3dfx rendering to
2271 allow iconic mode window. */
2272 mesa_3Dfx_fullscreen = True;
2273 unsetenv("MESA_GLX_FX");
2274 }
2275 #endif
2276 #ifdef HAVE_SETPRIORITY
2277 (void) setpriority(0, 0, 0);
2278 #else /* !HAVE_SETPRIORITY */
2279 (void) nice(0);
2280 #endif /* HAVE_SETPRIORITY */
2281 if (!fullscreen)
2282 XConfigureWindow(dsp, Scr[screen].window, sizeconfiguremask,
2283 &(Scr[screen].fullsizeconfigure));
2284
2285
2286 (void) XGetWindowAttributes(dsp, Scr[screen].window, &xgwa);
2287
2288 ChangeGrabbedCursor(dsp, Scr[screen].window,
2289 XCreateFontCursor(dsp, XC_left_ptr));
2290
2291 #ifdef DIRECTCOLOR_FIX
2292 MI_CLEARWINDOWCOLOR(mi, MI_BLACK_PIXEL(mi));
2293 #else
2294 MI_CLEARWINDOWCOLOR(mi, Scr[screen].bg_pixel);
2295 #endif
2296 XMapWindow(dsp, Scr[screen].icon);
2297 XRaiseWindow(dsp, Scr[screen].icon);
2298 #ifdef DIRECTCOLOR_FIX
2299 XSetForeground(dsp, Scr[screen].textgc, MI_WHITE_PIXEL(mi));
2300 XSetForeground(dsp, Scr[screen].plantextgc, MI_WHITE_PIXEL(mi));
2301 #endif
2302 if (description)
2303 modeDescription(mi);
2304
2305 /* redraw rectangle around icon */
2306 XDrawRectangle(dsp, Scr[screen].window, Scr[screen].textgc,
2307 Scr[screen].iconpos.x - 1, Scr[screen].iconpos.y - 1,
2308 iconwidth + 3, iconheight + 3);
2309 x = left = Scr[screen].iconpos.x + iconwidth + font->max_bounds.width + 4;
2310 y = Scr[screen].iconpos.y + fontAscent;
2311
2312 if ((hostbuf = (char *) malloc(strlen(user) + strlen(hostname) +
2313 2)) != NULL) {
2314 #ifdef HAVE_KRB5
2315 if (krb5_valid) {
2316 strcpy(hostbuf, user);
2317 } else
2318 #endif /* HAVE_KRB5 */
2319 (void) sprintf(hostbuf, "%s@%s", user, hostname);
2320
2321 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_user, True, left, &x, &y);
2322 putText(dsp, Scr[screen].window, Scr[screen].textgc, hostbuf, False, left, &x, &y);
2323 free(hostbuf);
2324 }
2325 if (displayname && displayname[0] != ':') {
2326 char *displaybuf = (char *) NULL;
2327 char *colon = (char *) strchr(displayname, ':');
2328 int n = colon - displayname;
2329
2330 if ((displaybuf = (char *) malloc(n + 1)) != NULL) {
2331 (void) strncpy(displaybuf, displayname, n);
2332 displaybuf[n] = '\0';
2333 if (remote && n
2334 && strcmp(displaybuf, "unix") != 0
2335 && strcmp(displaybuf, "localhost") != 0
2336 && strcmp(displaybuf, hostname) != 0) {
2337 putText(dsp, Scr[screen].window, Scr[screen].textgc, " Display: ", True, left, &x, &y);
2338 putText(dsp, Scr[screen].window, Scr[screen].textgc, displaybuf, False, left, &x, &y);
2339 }
2340 free(displaybuf);
2341 }
2342 }
2343 putText(dsp, Scr[screen].window, Scr[screen].textgc, "\n", False, left, &x, &y);
2344
2345 #ifdef GLOBAL_UNLOCK
2346 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_guser,
2347 True, left, &x, &y);
2348 putText(dsp, Scr[screen].window, Scr[screen].textgc, " ",
2349 False, left, &x, &y);
2350 unamex = x;
2351 unamey = y;
2352 putText(dsp, Scr[screen].window, Scr[screen].textgc, "\n", False, left, &x, &y);
2353 #endif
2354
2355 #ifdef SAFEWORD
2356 if (checkDynamic()) {
2357 pb = &pblock;
2358 (void) memset((char *) &pblock, 0, sizeof (pblock));
2359 #if 0
2360 (void) strcpy(pblock.uport, "custpb");
2361 pblock.status = NO_STATUS;
2362 #endif
2363 challx = x;
2364 chally = y;
2365 putText(dsp, Scr[screen].window, Scr[screen].textgc, "\n\n",
2366 False, left, &x, &y);
2367 pb->mode = CHALLENGE;
2368 (void) strcpy(pb->id, user);
2369 pbmain(pb);
2370 if (pb->status != GOOD_USER) {
2371 chall[0] = 0;
2372 return 1;
2373 }
2374 if (pb->dynpwdf) {
2375 /* We do not really care if they also got a fixed password... */
2376 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_dpass,
2377 True, left, &x, &y);
2378 putText(dsp, Scr[screen].window, Scr[screen].textgc, " ",
2379 False, left, &x, &y);
2380 passx = x;
2381 passy = y;
2382 } else if (pb->fixpwdf) {
2383 /* In the unlikely event they only got a fixed password... */
2384 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_fpass,
2385 True, left, &x, &y);
2386 putText(dsp, Scr[screen].window, Scr[screen].textgc, " ",
2387 False, left, &x, &y);
2388 passx = x;
2389 passy = y;
2390 }
2391 } else
2392 #endif
2393 {
2394 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_pass, True, left, &x, &y);
2395 putText(dsp, Scr[screen].window, Scr[screen].textgc, " ", False, left, &x, &y);
2396
2397 passx = x;
2398 passy = y;
2399 }
2400
2401 y += fontHeight + 6;
2402 if (y < Scr[screen].iconpos.y + iconheight + fontAscent + 14)
2403 y = Scr[screen].iconpos.y + iconheight + fontAscent + 14;
2404 x = left = Scr[screen].iconpos.x;
2405 #ifdef HAVE_KRB5
2406 if (krb5_valid)
2407 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_krbinfo, False, left, &x, &y);
2408 else
2409 #endif /* HAVE_KRB5 */
2410 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_info, False, left, &x, &y);
2411 putText(dsp, Scr[screen].window, Scr[screen].textgc, "\n", False, left, &x, &y);
2412 if (count_failed > 0) {
2413 char * cnt = NULL;
2414 y += fontHeight + 6;
2415 if (y < Scr[screen].iconpos.y + iconheight + fontAscent + 14)
2416 y = Scr[screen].iconpos.y + iconheight + fontAscent + 14;
2417 x = left = Scr[screen].iconpos.x;
2418 if ((cnt = (char *) malloc(strlen((count_failed == 1) ? failed_attempt : failed_attempts) + 16)) != NULL) {
2419 (void) sprintf(cnt, "%d%s", count_failed,
2420 (count_failed == 1) ? failed_attempt : failed_attempts);
2421 putText(dsp, Scr[screen].window, Scr[screen].textgc,
2422 cnt, False, left, &x, &y);
2423 putText(dsp, Scr[screen].window, Scr[screen].textgc,
2424 "\n", False, left, &x, &y);
2425 free(cnt);
2426 y -= 2 * (fontHeight + 6); /* go up */
2427 }
2428 }
2429 timex = x;
2430 timey = y;
2431
2432 #ifdef USE_AUTO_LOGOUT
2433 if (logoutAuto) {
2434 y += fontHeight + 2;
2435 }
2436 #endif
2437 #ifdef USE_BUTTON_LOGOUT
2438 if (enable_button) {
2439 y += fontHeight + 2;
2440 }
2441 #endif
2442 if (timeelapsed) {
2443 y += fontHeight + 2;
2444 }
2445 remy = y;
2446
2447 putText(dsp, Scr[screen].window, Scr[screen].textgc,
2448 "\n", False, left, &x, &y);
2449
2450 update_plan();
2451 #ifdef USE_MB
2452 backfontset = fontset;
2453 if (planfontset != NULL)
2454 fontset = planfontset;
2455 #endif
2456 if (*plantext) {
2457 y = Scr[screen].planpos.y;
2458 for (planp = plantext; *planp; ++planp) {
2459 int size = strlen(*planp);
2460
2461 y += planFontHeight + 2;
2462 /*printf("%s:%d\n", *planp, strlen(*planp));*/
2463 (void) XDrawString
2464 (dsp, Scr[screen].window,
2465 Scr[screen].plantextgc,
2466 Scr[screen].planpos.x, y,
2467 *planp, size);
2468 }
2469 }
2470 #ifdef USE_MB
2471 fontset = backfontset;
2472 #endif
2473 XFlush(dsp);
2474
2475 if (mailCmd && mailCmd[0]) {
2476 #ifdef ORIGINAL_XPM_PATCH
2477 XpmImage *mbxpm;
2478 mailboxInfo *mbi;
2479 int x, y;
2480
2481 if (system(mailCmd)) {
2482 mbxpm = nomail_xpmimg;
2483 mbi = &Scr[screen].mb.nomail;
2484 } else {
2485 mbxpm = mail_xpmimg;
2486 mbi = &Scr[screen].mb.mail;
2487 }
2488
2489 if (mbxpm) {
2490 x = (DisplayWidth(dsp, screen) - mbxpm->width) / 2;
2491 y = (Scr[screen].planpos.y - 5) - mbxpm->height;
2492 XCopyArea(dsp, mbi->pixmap,
2493 Scr[screen].window, Scr[screen].mb.mbgc,
2494 0, 0,
2495 mbxpm->width, mbxpm->height, x, y);
2496 }
2497 #else
2498 mailboxInfo *mbi;
2499 int mbx, mby;
2500
2501 if (system(mailCmd)) {
2502 mbi = &Scr[screen].mb.nomail;
2503 } else {
2504 mbi = &Scr[screen].mb.mail;
2505 }
2506 if (mbi) {
2507 mbx = (DisplayWidth(dsp, screen) - mbi->width) / 2;
2508 mby = (Scr[screen].planpos.y - 5) - mbi->height;
2509 XSetTSOrigin(dsp, Scr[screen].mb.mbgc, mbx, mby);
2510 XSetStipple(dsp, Scr[screen].mb.mbgc, mbi->pixmap);
2511 XSetFillStyle(dsp, Scr[screen].mb.mbgc, FillOpaqueStippled);
2512 XFillRectangle(dsp, Scr[screen].window, Scr[screen].mb.mbgc,
2513 mbx, mby, mbi->width, mbi->height);
2514 }
2515 #endif
2516 }
2517 done = False;
2518 while (!done) {
2519 #ifdef USE_SOUND
2520 if (sound && !got_invalid) {
2521 playSound(infosound, verbose);
2522 }
2523 got_invalid = 0;
2524 #endif
2525
2526 #ifdef SAFEWORD
2527 pb->mode = CHALLENGE;
2528 (void) strcpy(pb->id, user);
2529 pbmain(pb);
2530 if (pb->status != GOOD_USER) {
2531 chall[0] = 0;
2532 return 1;
2533 }
2534 left = x = challx;
2535 y = chally;
2536 if (strlen(pb->chal) > 0) {
2537 (void) strcpy(chall, pb->chal);
2538 putText(dsp, Scr[screen].window, Scr[screen].textgc, text_chall,
2539 True, left, &x, &y);
2540 putText(dsp, Scr[screen].window, Scr[screen].textgc, " ",
2541 False, left, &x, &y);
2542 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2543 left + XTextWidth(font, text_chall, strlen(text_chall)),
2544 y - fontAscent, XTextWidth(font, chall, strlen(chall)),
2545 fontHeight + 5);
2546
2547 putText(dsp, Scr[screen].window, Scr[screen].textgc, chall,
2548 False, left, &x, &y);
2549 }
2550 putText(dsp, Scr[screen].window, Scr[screen].textgc, "\n",
2551 False, left, &x, &y);
2552 if (pb->dynpwdf || pb->fixpwdf) {
2553 /* If they have a dynamic passwd we do not really care about
2554 the fixed password... */
2555 putText(dsp, Scr[screen].window, Scr[screen].textgc,
2556 (pb->dynpwdf) ? text_dpass : text_fpass,
2557 True, left, &x, &y);
2558 putText(dsp, Scr[screen].window, Scr[screen].textgc, " ",
2559 False, left, &x, &y);
2560 passx = x;
2561 passy = y;
2562 }
2563 #endif
2564
2565 #ifdef GLOBAL_UNLOCK
2566 if (ReadXString(global_user, PASSLENGTH, (Bool *) NULL, False))
2567 break;
2568 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2569 unamex, unamey,
2570 global_user, strlen(global_user));
2571 checkUser(global_user);
2572 #endif
2573 if (ReadXString(buffer, PASSLENGTH, &capsLock
2574 #ifdef GLOBAL_UNLOCK
2575 , True
2576 #elif defined( USE_PAM )
2577 , False
2578 #endif
2579 ))
2580 break;
2581 y = remy + 6;
2582 #ifdef DIRECTCOLOR_FIX
2583 XSetForeground(dsp, Scr[screen].gc, MI_BLACK_PIXEL(mi));
2584 #else
2585 XSetForeground(dsp, Scr[screen].gc, Scr[screen].bg_pixel);
2586 #endif
2587 #ifdef SAFEWORD
2588 (void) strcpy(pb->dynpwd, buffer);
2589 pb->mode = EVALUATE_ALL;
2590 pbmain(pb);
2591
2592 done = (pb->status == PASS || pb->status == PASS_MASTER);
2593 pb->mode = UPDATE_LOGS;
2594 pbmain(pb);
2595 #else
2596 {
2597 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2598 Scr[screen].iconpos.x, y - fontAscent + screenOffset,
2599 2 * XTextWidth(font, text_invalidCapsLock, strlen(text_invalidCapsLock)),
2600 fontHeight + 5 + screenOffset);
2601 }
2602
2603 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2604 Scr[screen].iconpos.x, y, text_valid, strlen(text_valid));
2605 XFlush(dsp);
2606
2607 done = checkPasswd(buffer);
2608
2609 if (!done && !*buffer) {
2610 /* just hit return, and it was not his password */
2611 /* count_failed++; */ /* not really an attempt, is it? */
2612 break;
2613 } else if (!done) {
2614 /* bad password... log it... */
2615 count_failed++;
2616 #if defined( HAVE_SYSLOG_H ) && defined( USE_SYSLOG )
2617 (void) printf("failed unlock attempt on user %s\n", user);
2618 syslog(SYSLOG_NOTICE, "%s: failed unlock attempt on user %s\n",
2619 ProgramName, user);
2620 #endif
2621 }
2622 #endif
2623
2624 #ifndef VMS
2625 if (done && pipepassCmd && pipepassCmd[0]) {
2626 FILE *f;
2627 if ((f = (FILE *) popen(pipepassCmd, "w"))) {
2628 /* avoid stdio for this since we don't want to leave
2629 the plaintext password in memory */
2630 char *p = buffer;
2631 int len = strlen(buffer);
2632
2633 while (len > 0) {
2634 int wrote = write(fileno(f), p, len);
2635 if (wrote <= 0) break;
2636 len -= wrote;
2637 p += wrote;
2638 }
2639 (void) pclose(f);
2640 }
2641 }
2642 #endif
2643 /* clear plaintext password so you can not grunge around
2644 /dev/kmem */
2645 (void) memset((char *) buffer, 0, sizeof (buffer));
2646
2647 if (done) {
2648 #ifdef USE_SOUND
2649 if (sound)
2650 playSound(validsound, verbose);
2651 #endif
2652 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2653 Scr[screen].iconpos.x, y - fontAscent + screenOffset,
2654 2 * XTextWidth(font, text_invalidCapsLock, strlen(text_invalidCapsLock)),
2655 fontHeight + 5 + screenOffset);
2656
2657 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2658 Scr[screen].iconpos.x, y, text_valid, strlen(text_valid));
2659 XFlush(dsp);
2660
2661 if (!fullscreen)
2662 XConfigureWindow(dsp, Scr[screen].window, sizeconfiguremask,
2663 &minisizeconfigure);
2664 return 0;
2665 } else {
2666 char *textInvalid = (capsLock) ? text_invalidCapsLock :
2667 text_invalid;
2668
2669 XSync(dsp, True); /* flush input buffer */
2670 (void) sleep(1);
2671 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2672 Scr[screen].iconpos.x, y - fontAscent + screenOffset,
2673 XTextWidth(font, text_valid, strlen(text_valid)),
2674 fontHeight + 8 + screenOffset);
2675 (void) XDrawString(dsp, Scr[screen].window, Scr[screen].textgc,
2676 Scr[screen].iconpos.x, y, textInvalid, strlen(textInvalid));
2677 if (echokeys) /* erase old echo */
2678 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2679 passx, passy - fontAscent,
2680 xgwa.width - passx,
2681 fontHeight + 3);
2682 XSync(dsp, True); /* flush input buffer */
2683 (void) sleep(1);
2684 XFillRectangle(dsp, Scr[screen].window, Scr[screen].gc,
2685 Scr[screen].iconpos.x, y - fontAscent + screenOffset,
2686 XTextWidth(font, textInvalid, strlen(textInvalid)),
2687 fontHeight + 5 + screenOffset);
2688 if (count_failed > 0) {
2689 char * cnt = NULL;
2690 y += fontHeight + 6;
2691 if (y < Scr[screen].iconpos.y + iconheight + fontAscent + 14)
2692 y = Scr[screen].iconpos.y + iconheight + fontAscent + 14;
2693 x = left = Scr[screen].iconpos.x;
2694 if ((cnt = (char *) malloc(strlen((count_failed == 1) ? failed_attempt : failed_attempts) + 16)) != NULL) {
2695 (void) sprintf(cnt, "%d%s", count_failed,
2696 (count_failed == 1) ? failed_attempt : failed_attempts);
2697 putText(dsp, Scr[screen].window, Scr[screen].textgc,
2698 cnt, False, left, &x, &y);
2699 putText(dsp, Scr[screen].window, Scr[screen].textgc,
2700 "\n", False, left, &x, &y);
2701 free(cnt);
2702 }
2703 }
2704
2705 #ifdef USE_SOUND
2706 if (sound)
2707 playSound(invalidsound, verbose);
2708 got_invalid = 1;
2709 #endif
2710 }
2711 }
2712
2713 ChangeGrabbedCursor(dsp, Scr[screen].window, mycursor);
2714 XUnmapWindow(dsp, Scr[screen].icon);
2715 #ifdef USE_BUTTON_LOGOUT
2716 XUnmapWindow(dsp, Scr[screen].button);
2717 #endif
2718 if (!fullscreen)
2719 XConfigureWindow(dsp, Scr[screen].window, sizeconfiguremask,
2720 &minisizeconfigure);
2721 #ifdef HAVE_SETPRIORITY
2722 (void) setpriority(0, 0, nicelevel);
2723 #else /* !HAVE_SETPRIORITY */
2724 (void) nice(nicelevel);
2725 #endif /* HAVE_SETPRIORITY */
2726 #ifdef FX
2727 if (mesa_3Dfx_fullscreen)
2728 setenv("MESA_GLX_FX", "fullscreen", 0);
2729 #endif
2730 return 1;
2731 }
2732
2733 static int
event_screen(Display * display,Window event_win)2734 event_screen(Display * display, Window event_win)
2735 {
2736 int i;
2737
2738 for (i = startscreen; i < screens; i++) {
2739 if (event_win == RootWindow(display, i)) {
2740 return (i);
2741 }
2742 }
2743 return (0);
2744 }
2745
2746 static int
justDisplay(Display * display)2747 justDisplay(Display * display)
2748 {
2749 int timetodie = False;
2750 int not_done = True;
2751 XEvent event;
2752
2753 #ifdef USE_VTLOCK
2754 /* EL - RCS : lock VT switching */
2755 /*
2756 * I think it has to be done here or 'switch/restore' modes won't
2757 * ever be useful!
2758 */
2759 if (!nolock && vtlock && !vtlocked)
2760 dovtlock();
2761 #endif
2762
2763 for (screen = startscreen; screen < screens; screen++) {
2764 call_init_hook((LockStruct *) NULL,
2765 mode_info(display, screen, Scr[screen].window, False));
2766 }
2767
2768 while (not_done) {
2769 while (!XPending(display)) {
2770 #ifdef USE_OLD_EVENT_LOOP
2771 (void) usleep(delay);
2772 for (screen = startscreen; screen < screens; screen++)
2773 call_callback_hook((LockStruct *) NULL,
2774 mode_info(display, screen, Scr[screen].window, False));
2775 #ifdef USE_AUTO_LOGOUT
2776 checkLogout(display);
2777 #endif
2778 XSync(display, False);
2779 #else /* !USE_OLD_EVENT_LOOP */
2780 #ifdef USE_AUTO_LOGOUT
2781 if (runMainLoop(30, -1) == 0)
2782 break;
2783 checkLogout(display);
2784 #else
2785 (void) runMainLoop(0, -1);
2786 #endif
2787 #endif /* !USE_OLD_EVENT_LOOP */
2788 }
2789 (void) XNextEvent(display, &event);
2790 /*
2791 * This event handling code should be unified with the
2792 * similar code in ReadXString().
2793 */
2794 switch (event.type) {
2795 case Expose:
2796 if (event.xexpose.count != 0) {
2797 break;
2798 }
2799 /* fall through on last expose event of the series */
2800
2801 case VisibilityNotify:
2802 #ifndef __CYGWIN__
2803 if (!debug && !inwindow) {
2804 XRaiseWindow(display, event.xany.window);
2805 }
2806 #endif
2807 for (screen = startscreen; screen < screens; screen++) {
2808 call_refresh_hook((LockStruct *) NULL,
2809 mode_info(display, screen, Scr[screen].window, False));
2810 }
2811 break;
2812
2813 case ConfigureNotify:
2814 #ifndef __CYGWIN__
2815 if (!debug && !inwindow) {
2816 XRaiseWindow(display, event.xconfigure.window);
2817 }
2818 #endif
2819 for (screen = startscreen; screen < screens; screen++) {
2820 if (install)
2821 fixColormap(mode_info(dsp, screen, Scr[screen].window, False), ncolors, saturation,
2822 mono, install, inroot, inwindow, verbose);
2823 if (window_size_changed(screen, Scr[screen].window)) {
2824 call_init_hook((LockStruct *) NULL,
2825 mode_info(display, screen, Scr[screen].window, False));
2826 } else if (install)
2827 /* next line : refresh would be logical. But some modes
2828 * look weird when continuing from an erased screen */
2829 call_refresh_hook((LockStruct *) NULL,
2830 mode_info(display, screen, Scr[screen].window, False));
2831 }
2832 break;
2833
2834 case ButtonPress:
2835 if (event.xbutton.button == Button2) {
2836 /* call change hook only for clicked window? */
2837 for (screen = startscreen; screen < screens; screen++) {
2838 call_change_hook((LockStruct *) NULL,
2839 mode_info(display, screen, Scr[screen].window,
2840 False));
2841 }
2842 } else {
2843 screen = event_screen(display, event.xbutton.root);
2844 not_done = False;
2845 }
2846 break;
2847
2848 case MotionNotify:
2849 if (mousemotion) {
2850 screen = event_screen(display, event.xmotion.root);
2851 not_done = False;
2852 }
2853 break;
2854
2855 case KeyPress:
2856 screen = event_screen(display, event.xkey.root);
2857 not_done = False;
2858 break;
2859 }
2860
2861 if (!nolock)
2862 {
2863 if (lock_delay && (lock_delay <= (int) (seconds() - start_time))) {
2864 timetodie = True;
2865 /* not_done = False; */
2866 }
2867 else if (unlockdelay && (unlockdelay > (int) (seconds() - start_time)))
2868 {
2869 not_done = True;
2870 }
2871 }
2872 }
2873
2874 /* KLUDGE SO TVTWM AND VROOT WILL NOT MAKE XLOCK DIE */
2875 if (screen >= screens)
2876 screen = startscreen;
2877
2878 lock_delay = False;
2879 if (usefirst)
2880 (void) XPutBackEvent(display, &event);
2881 return timetodie;
2882 }
2883
2884 #ifdef __cplusplus
2885 extern "C" {
2886 #endif
2887
2888 static void
sigcatch(int signum)2889 sigcatch(int signum)
2890 {
2891 #ifndef WIN32
2892 ModeInfo *mi = mode_info(dsp, startscreen, Scr[startscreen].window, False);
2893 const char *name = (mi == NULL) ? "unknown" : MI_NAME(mi);
2894
2895 finish(dsp, True);
2896 (void) sprintf(error_buf,
2897 "Access control list restored.\n%s: caught signal %d while running %s mode (uid %ld).\n",
2898 (strlen(ProgramName) < ERROR_BUF - 2 * ERROR_LINE) ?
2899 ProgramName: DEFAULT_NAME, signum,
2900 (strlen(ProgramName) + strlen(name) <
2901 ERROR_BUF - 2 * ERROR_LINE) ? name: "?", (long) getuid());
2902 error_exitcode = -signum;
2903 error(error_buf);
2904 #endif /* !WIN32 */
2905 }
2906
2907 #ifdef __cplusplus
2908 }
2909 #endif
2910
2911 static void
lockDisplay(Display * display,Bool do_display)2912 lockDisplay(Display * display, Bool do_display)
2913 {
2914 #ifdef USE_VTLOCK
2915 /* EL - RCS : lock VT switching */
2916 if (!nolock && vtlock && !vtlocked)
2917 dovtlock();
2918 #endif
2919 #if defined( HAVE_SYSLOG_H ) && defined( USE_SYSLOG )
2920 syslogStart();
2921 #endif
2922 #ifdef USE_SOUND
2923 if (sound && !inwindow && !inroot && !lockdelay)
2924 playSound(locksound, verbose);
2925 #endif
2926 if (!allowaccess) {
2927 #if defined( SYSV ) || defined( SVR4 ) || ( __VMS_VER >= 70000000 ) || defined( __CYGWIN__ ) || defined( __linux__ )
2928 sigset_t oldsigmask;
2929 sigset_t newsigmask;
2930
2931 (void) sigemptyset(&newsigmask);
2932 #ifndef DEBUG
2933 (void) sigaddset(&newsigmask, SIGHUP);
2934 #endif
2935 (void) sigaddset(&newsigmask, SIGINT);
2936 (void) sigaddset(&newsigmask, SIGQUIT);
2937 (void) sigaddset(&newsigmask, SIGTERM);
2938 (void) sigprocmask(SIG_BLOCK, (sigset_t *)&newsigmask, (sigset_t *)&oldsigmask);
2939 #else
2940 int oldsigmask;
2941
2942 #ifndef VMS
2943 oldsigmask = sigblock(
2944 #ifndef DEBUG
2945 sigmask(SIGHUP) |
2946 #endif
2947 sigmask(SIGINT) |
2948 sigmask(SIGQUIT) |
2949 sigmask(SIGTERM));
2950 #endif
2951 #endif
2952
2953 /* (void (*)(int)) sigcatch */
2954 #ifndef DEBUG
2955 (void) signal(SIGHUP, sigcatch);
2956 #endif
2957 (void) signal(SIGINT, sigcatch);
2958 (void) signal(SIGQUIT, sigcatch);
2959 (void) signal(SIGTERM, sigcatch);
2960 /* we should trap ALL signals, especially the deadly ones */
2961 (void) signal(SIGSEGV, sigcatch);
2962 (void) signal(SIGBUS, sigcatch);
2963 (void) signal(SIGFPE, sigcatch);
2964
2965 if (grabserver)
2966 XGrabServer(display);
2967 XGrabHosts(display);
2968
2969 #if defined( SYSV ) || defined( SVR4 ) || ( __VMS_VER >= 70000000 ) || defined( __CYGWIN__ ) || defined( __linux__ )
2970 (void) sigprocmask(SIG_SETMASK, &oldsigmask, &oldsigmask);
2971 #else
2972 (void) sigsetmask(oldsigmask);
2973 #endif
2974 }
2975 #if defined( __hpux ) || defined( __apollo )
2976 XHPDisableReset(display);
2977 #endif
2978 do {
2979 if (do_display)
2980 (void) justDisplay(display);
2981 else
2982 do_display = True;
2983 } while (getPassword());
2984 #if defined( __hpux ) || defined( __apollo )
2985 XHPEnableReset(display);
2986 #endif
2987 }
2988
2989 static void
read_plan(void)2990 read_plan(void)
2991 {
2992 FILE *planf = (FILE *) NULL;
2993 char buf[121];
2994 const char *home = getenv("HOME");
2995 char *buffer;
2996 int i, j, len = 0;
2997
2998 if (!home)
2999 home = "";
3000
3001 if ((buffer = (char *) malloc(
3002 #if ( __VMS_VER >= 70000000 )
3003 255
3004
3005 #else
3006 strlen(home) + 32
3007
3008 #endif
3009 )) == NULL) {
3010 error("low memory for plan");
3011 }
3012
3013 #ifdef VMS
3014 (void) sprintf(buffer, "%s%s", home, ".xlocktext");
3015 #else
3016 (void) sprintf(buffer, "%s/%s", home, ".xlocktext");
3017 #endif
3018 planf = my_fopen(buffer, "r");
3019 if (planf == NULL) {
3020 #ifdef VMS
3021 (void) sprintf(buffer, "%s%s", home, ".plan");
3022 #else
3023 (void) sprintf(buffer, "%s/%s", home, ".plan");
3024 #endif
3025 planf = my_fopen(buffer, "r");
3026 }
3027 if (planf == NULL) {
3028 #ifndef VMS
3029 (void) sprintf(buffer, "%s/%s", home, ".signature");
3030 #else
3031 #if ( __VMS_VER >= 70000000 )
3032 /* Get signature file for VMS 7.0 and higher */
3033 char *buffer1;
3034 unsigned int ival;
3035 unsigned long int mail_context = 0;
3036 unsigned short int buflen, buflen1;
3037 struct itmlst_3 item[2], itm_d[1];
3038
3039 if ((buffer1 = (char *) malloc(256)) == NULL) {
3040 error("low memory for signature");
3041 }
3042 itm_d[0].buflen = 0;
3043 itm_d[0].itmcode = 0;
3044 item[0].buflen = 255;
3045 item[0].itmcode = MAIL$_USER_SIGFILE;
3046 item[0].bufadr = buffer1;
3047 item[0].retlen = &buflen1;
3048 item[1].buflen = 255;
3049 item[1].itmcode = MAIL$_USER_FULL_DIRECTORY;
3050 item[1].bufadr = buffer;
3051 item[1].retlen = &buflen;
3052 item[2].buflen = 0;
3053 item[2].itmcode = 0;
3054 ival = mail$user_begin(&mail_context, itm_d, item);
3055 (void) mail$user_end(&mail_context, itm_d, itm_d);
3056 (void) strncat(buffer, buffer1, buflen1);
3057 free(buffer1);
3058 #else
3059 (void) sprintf(buffer, "%s%s", home, ".signature");
3060 #endif
3061 #endif
3062 planf = my_fopen(buffer, "r");
3063 }
3064 if ((plantext[0] = (char *) malloc(30)) == NULL) {
3065 /* this is for the current time */
3066 error("low memory for plan");
3067 } else {
3068 plantext[0][0] = '\0';
3069 }
3070 if (planf != NULL) {
3071 for (i = 0; i < TEXTLINES; i++) {
3072 if (fgets(buf, 120, planf) && (len = strlen(buf)) > 0) {
3073 if (buf[len - 1] == '\n') {
3074 buf[--len] = '\0';
3075 }
3076 /* this expands tabs to 8 spaces */
3077 for (j = 0; j < len; j++) {
3078 if (buf[j] == '\t') {
3079 int k, tab = 8 - (j % 8);
3080
3081 for (k = 120 - tab; k > j; k--) {
3082 buf[k + tab - 1] = buf[k];
3083 }
3084 for (k = j; k < j + tab; k++) {
3085 buf[k] = ' ';
3086 }
3087 len += tab;
3088 if (len > 120)
3089 len = 120;
3090 }
3091 }
3092
3093 if ((plantext[i + 1] = (char *) malloc(strlen(buf) + 1)) == NULL) {
3094 error("low memory for plan");
3095 }
3096 (void) strcpy(plantext[i + 1], buf);
3097 }
3098 }
3099 plantext[i + 1] = (char *) NULL;
3100 (void) fclose(planf);
3101 } else {
3102 plantext[1] = (char *) NULL;
3103 }
3104 free(buffer);
3105 buffer = (char *) NULL;
3106 }
3107 #endif /* !WIN32 */
3108
3109 #ifdef USE_MB
3110 static XFontSet
createFontSet(Display * display,char * name)3111 createFontSet(Display * display, char *name)
3112 {
3113 XFontSet xfs;
3114 char **miss, *def;
3115 int miss_count;
3116
3117 #define DEF_FONTSET2 "fixed,-*-14-*"
3118
3119 if ((xfs = XCreateFontSet(display, name, &miss, &miss_count, &def)) == NULL) {
3120 (void) fprintf(stderr, "Could not create FontSet %s\n", name);
3121 if ((xfs = XCreateFontSet(display, DEF_FONTSET2, &miss, &miss_count, &def)) == NULL)
3122 (void) fprintf(stderr, "Could not create FontSet %s\n", DEF_FONTSET2);
3123 }
3124 #if 0
3125 /* This needs to be freed but this way is invalid */
3126 if (miss != NULL) {
3127 int i;
3128 for (i = 0; i < sizeof(miss); i++)
3129 free(miss[i]);
3130 free(miss);
3131 }
3132 #endif
3133 return xfs;
3134 }
3135 #endif
3136
3137 #ifndef WIN32
3138
3139 #ifdef __cplusplus
3140 extern "C" {
3141 #endif
3142
3143 static void SigUsr2(int sig);
3144
3145 static void
SigUsr1(int sig)3146 SigUsr1(int sig)
3147 {
3148 #ifdef DEBUG
3149 (void) printf("Signal %d received\n", sig);
3150 #endif
3151 signalUSR1 = 1;
3152 signalUSR2 = 0;
3153
3154 (void) signal(SIGUSR1, SigUsr1);
3155 (void) signal(SIGUSR2, SigUsr2);
3156 }
3157
3158 static void
SigUsr2(int sig)3159 SigUsr2(int sig)
3160 {
3161 #ifdef DEBUG
3162 (void) printf("Signal %d received\n", sig);
3163 #endif
3164 signalUSR1 = 0;
3165 signalUSR2 = 1;
3166
3167 (void) signal(SIGUSR1, SigUsr1);
3168 (void) signal(SIGUSR2, SigUsr2);
3169 }
3170
3171 #ifdef __cplusplus
3172 }
3173 #endif
3174
3175 int
main(int argc,char ** argv)3176 main(int argc, char **argv)
3177 {
3178 XSetWindowAttributes xswa;
3179 XGCValues xgcv;
3180 XColor nullcolor;
3181 uid_t ruid;
3182 pid_t cmd_pid = 0;
3183 #ifdef USE_XINERAMA
3184 int xinerama_evtbase;
3185 int xinerama_errbase;
3186 int xinerama_nscreens;
3187 XineramaScreenInfo *xinerama_info = NULL;
3188 #endif
3189
3190 #if defined( SYSV ) || defined( SVR4 ) || ( __VMS_VER >= 70000000 )
3191 static sigset_t old_sigmask;
3192
3193 #else
3194 static int old_sigmask;
3195
3196 #endif
3197
3198 #if ultrix
3199 extern gid_t rgid;
3200
3201 #else
3202 gid_t rgid;
3203
3204 #endif
3205 #if defined( HAVE_SETEUID ) || defined( HAVE_SETREUID )
3206 uid_t euid;
3207
3208 #if ultrix
3209 extern gid_t egid;
3210
3211 #else
3212 gid_t egid;
3213
3214 #endif
3215 #endif
3216
3217 #ifdef USE_MB
3218 setlocale(LC_ALL, "");
3219 #endif
3220
3221 (void) signal(SIGUSR1, SigUsr1);
3222 (void) signal(SIGUSR2, SigUsr2);
3223
3224 #if defined( __FreeBSD__ ) && !defined( DEBUG )
3225 /* do not exit on FPE */
3226 fpsetmask(0);
3227 #endif
3228
3229 #ifdef OSF1_ENH_SEC
3230 set_auth_parameters(argc, argv);
3231 #endif
3232
3233 ruid = getuid();
3234 rgid = getgid();
3235 #ifdef HAVE_SETEUID
3236 /* save effective uid and gid for later */
3237 euid = geteuid();
3238 egid = getegid();
3239
3240 /* revoke root privs temporarily, to get the correct .Xauthority */
3241 (void) setegid(rgid);
3242 (void) seteuid(ruid);
3243 #else
3244 #ifdef HAVE_SETREUID
3245 /* save effective uid and gid for later */
3246 euid = geteuid();
3247 egid = getegid();
3248
3249 /* revoke root privs temporarily, to get the correct .Xauthority */
3250 (void) setregid(egid, rgid);
3251 (void) setreuid(euid, ruid);
3252
3253 #endif
3254 #endif
3255
3256 ProgramName = strrchr(argv[0], '/');
3257 if (ProgramName)
3258 ProgramName++;
3259 else
3260 ProgramName = argv[0];
3261
3262 start_time = seconds();
3263 #ifdef DEBUG
3264 ProgramPID = getpid(); /* for memcheck.c */
3265 #endif
3266 #if 1
3267 SRAND((long) start_time); /* random mode needs the seed set. */
3268 #else
3269 SRAND((long) ProgramPID);
3270 #endif
3271
3272 getResources(&dsp, argc, argv);
3273
3274 #ifdef HAVE_SETEUID
3275 /* become root to get the password */
3276 (void) setegid(egid);
3277 (void) seteuid(euid);
3278 #else
3279 #ifdef HAVE_SETREUID
3280 /* become root to get the password */
3281 (void) setregid(rgid, egid);
3282 (void) setreuid(ruid, euid);
3283
3284 #endif
3285 #endif
3286
3287 initPasswd();
3288
3289 /* revoke root privs, if there were any */
3290 #ifdef ultrix
3291 /*-
3292 * Potential security problem on ultrix
3293 * Here's the problem. Later on you need setgid to a root group to
3294 * use the crypt program. I do not want to keep the password in memory.
3295 * That means other parts will be running setgid as well.
3296 */
3297
3298 #if 1
3299 /* Change 1 to 0 */
3300 #error UNTESTED CODE, COMMENT OUT AND SEE IF IT WORKS, PLEASE GET BACK TO ME
3301 #endif
3302
3303 #ifdef HAVE_SETEUID
3304 /* Lets try to dampen it a bit */
3305 (void) setegid(rgid);
3306
3307 #else
3308 #ifdef HAVE_SETREUID
3309 (void) setregid(egid, rgid);
3310
3311 #else
3312 (void) setgid(rgid); /* Forget it */
3313
3314 #endif
3315 #endif
3316 #else
3317 #ifdef BAD_PAM
3318 /* BAD_PAM must have root access to authenticate against shadow passwords */
3319 (void) seteuid(ruid);
3320 /* for BAD_PAM to use shadow passwords, must call seteuid() later */
3321 /* this prevent xlock from dropping privileges when using PAM modules, */
3322 /* that needs root rights (pam_unix e.g.) */
3323 #else
3324
3325 #ifdef USE_VTLOCK
3326 /* In order to lock VT switch we must issue an ioctl on console */
3327 /* (VT_LOCKSWITCH). This ioctl MUST be issued by root. */
3328 /* We need later to be able to do another seteuid(0), so let's */
3329 /* disable the overwrite of saved uid/gid */
3330
3331 if (!vtlock)
3332 #endif
3333 {
3334 (void) setgid(rgid);
3335 (void) setuid(ruid);
3336 }
3337 #endif
3338 #endif
3339
3340 #ifdef SYNCHRONIZE
3341 /* synchronize -- so I am aware of errors immediately */
3342 /* Too slow only for debugging */
3343 (void) printf("DEBUGGING: XSynchronize version\n");
3344 XSynchronize(dsp, True);
3345 #endif
3346
3347 #ifdef USE_MB
3348 fontset = createFontSet(dsp, fontsetname);
3349 if (fontset == NULL) {
3350 (void) sprintf(error_buf,
3351 "%s: can not create fonset %s!!!\n",
3352 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
3353 ProgramName : DEFAULT_NAME,
3354 (strlen(ProgramName) + strlen(fontsetname) < ERROR_BUF - ERROR_LINE) ?
3355 fontsetname: "a font");
3356 error(error_buf);
3357 }
3358 XmbTextExtents(fontset, "Aj", 1, NULL, &mbRect);
3359 planfontset = createFontSet(dsp, planfontsetname);
3360 XmbTextExtents(planfontset, "Aj", 1, NULL, &planmbRect);
3361 #endif
3362 checkResources();
3363
3364 font = XLoadQueryFont(dsp, fontname);
3365 if (font == NULL) {
3366 (void) fprintf(stderr, "%s: can not find font: %s, using %s...\n",
3367 ProgramName, fontname, FALLBACK_FONTNAME);
3368 font = XLoadQueryFont(dsp, FALLBACK_FONTNAME);
3369 if (font == NULL) {
3370 (void) sprintf(error_buf,
3371 "%s: can not even find %s!!!\n",
3372 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
3373 ProgramName : DEFAULT_NAME,
3374 (strlen(ProgramName) + strlen(FALLBACK_FONTNAME) < ERROR_BUF - ERROR_LINE) ?
3375 FALLBACK_FONTNAME: "a font");
3376 error(error_buf);
3377 }
3378 } {
3379 int flags, x, y;
3380 unsigned int w, h;
3381
3382 #ifdef FX
3383 if (!glgeometry || !*glgeometry) {
3384 glwidth = DEF_GLW;
3385 glheight = DEF_GLH;
3386 } else {
3387 flags = XParseGeometry(glgeometry, &x, &y, &w, &h);
3388 glwidth = flags & WidthValue ? w : DEF_GLW;
3389 glheight = flags & HeightValue ? h : DEF_GLH;
3390 if (glwidth < MINICONW)
3391 glwidth = MINICONW;
3392 if (glheight < MINICONH)
3393 glheight = MINICONH;
3394 }
3395 #endif
3396 if (!icongeometry || !*icongeometry) {
3397 iconwidth = DEF_ICONW;
3398 iconheight = DEF_ICONH;
3399 } else {
3400 flags = XParseGeometry(icongeometry, &x, &y, &w, &h);
3401 iconwidth = flags & WidthValue ? w : DEF_ICONW;
3402 iconheight = flags & HeightValue ? h : DEF_ICONH;
3403 if (iconwidth < MINICONW)
3404 iconwidth = MINICONW;
3405 else if (iconwidth > MAXICONW)
3406 iconwidth = MAXICONW;
3407 if (iconheight < MINICONH)
3408 iconheight = MINICONH;
3409 else if (iconheight > MAXICONH)
3410 iconheight = MAXICONH;
3411 }
3412 if (!geometry || !*geometry) {
3413 fullscreen = True;
3414 } else {
3415 flags = XParseGeometry(geometry, &x, &y, &w, &h);
3416 if (w < MINICONW)
3417 w = MINICONW;
3418 if (h < MINICONH)
3419 h = MINICONH;
3420 minisizeconfigure.x = flags & XValue ? x : 0;
3421 minisizeconfigure.y = flags & YValue ? y : 0;
3422 minisizeconfigure.width = flags & WidthValue ? w : iconwidth;
3423 minisizeconfigure.height = flags & HeightValue ? h : iconheight;
3424 }
3425 }
3426
3427 planfont = XLoadQueryFont(dsp, planfontname);
3428 if (planfont == NULL) {
3429 (void) fprintf(stderr, "%s: can't find font: %s, using %s...\n",
3430 ProgramName, planfontname, FALLBACK_FONTNAME);
3431 planfont = XLoadQueryFont(dsp, FALLBACK_FONTNAME);
3432 if (planfont == NULL) {
3433 (void) sprintf(error_buf,
3434 "%s: can not even find %s!!!\n",
3435 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
3436 ProgramName : DEFAULT_NAME,
3437 (strlen(ProgramName) + strlen(FALLBACK_FONTNAME) < ERROR_BUF - ERROR_LINE) ?
3438 FALLBACK_FONTNAME: "a font");
3439 error(error_buf);
3440 }
3441 }
3442 read_plan();
3443 update_plan();
3444
3445 screens = ScreenCount(dsp);
3446 if (((modeinfo = (ModeInfo *) calloc(screens,
3447 sizeof (ModeInfo))) == NULL) ||
3448 ((Scr = (ScreenInfo *) calloc(screens,
3449 sizeof (ScreenInfo))) == NULL)) {
3450 error("low memory for info");
3451 }
3452
3453 #ifdef FORCESINGLE
3454 /* Safer to keep this after the calloc in case ScreenCount is used */
3455 startscreen = DefaultScreen(dsp);
3456 screens = startscreen + 1;
3457 #endif
3458
3459 #if defined( USE_ESOUND )
3460 sound = (sound && (init_sound() != -1));
3461 #endif
3462
3463 #ifdef USE_XINERAMA
3464 if (XineramaQueryExtension(dsp, &xinerama_evtbase, &xinerama_errbase))
3465 xinerama_info = XineramaQueryScreens(dsp, &xinerama_nscreens);
3466 #endif
3467
3468 #ifdef USE_DTSAVER
3469 /* The CDE Session Manager provides the windows for the screen saver
3470 to draw into. */
3471 if (dtsaver) {
3472 Window *saver_wins;
3473 int num_wins;
3474 int this_win;
3475 int this_screen;
3476 XWindowAttributes xgwa;
3477
3478
3479 /* Get the list of requested windows */
3480 if (!DtSaverGetWindows(dsp, &saver_wins, &num_wins)) {
3481 (void) sprintf(error_buf,
3482 "%s: Unable to get screen saver info.\n",
3483 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
3484 ProgramName : DEFAULT_NAME);
3485 error(error_buf);
3486 }
3487 for (this_win = 0; this_win < num_wins; this_win++) {
3488 (void) XGetWindowAttributes(dsp, saver_wins[this_win], &xgwa);
3489 this_screen = XScreenNumberOfScreen(xgwa.screen);
3490 if (Scr[this_screen].window != None) {
3491 (void) sprintf(error_buf,
3492 "%s: Two windows on screen %d\n",
3493 (strlen(ProgramName) < ERROR_BUF - ERROR_LINE) ?
3494 ProgramName : DEFAULT_NAME, this_screen);
3495 error(error_buf);
3496 }
3497 Scr[this_screen].window = saver_wins[this_win];
3498 }
3499 /* Reduce to the screens that have windows. Avoid problems and */
3500 /* assume that if one fails there is only one good window. */
3501 for (this_screen = startscreen; this_screen < screens; this_screen++) {
3502 if (Scr[this_screen].window == None) {
3503 startscreen = DefaultScreen(dsp);
3504 screens = startscreen + 1;
3505 break;
3506 }
3507 }
3508 } else
3509 #endif
3510
3511 if (inwindow) {
3512 /* Reduce to the last screen requested */
3513 startscreen = DefaultScreen(dsp);
3514 screens = startscreen + 1;
3515 }
3516 for (screen = startscreen; screen < screens; screen++) {
3517 Screen *scr = ScreenOfDisplay(dsp, screen);
3518 Colormap cmap = (Colormap) NULL;
3519
3520 /* Start of MI_ROOT_PIXMAP hack */
3521 Window temp_rw;
3522 XGCValues temp_gcv;
3523 GC temp_gc;
3524 XWindowAttributes temp_xgwa;
3525
3526 temp_rw = (parentSet) ? parent : RootWindowOfScreen(scr);
3527 (void) XGetWindowAttributes(dsp, temp_rw, &temp_xgwa);
3528 temp_gcv.function = GXcopy;
3529 temp_gcv.subwindow_mode = IncludeInferiors;
3530 temp_gc = XCreateGC(dsp, temp_rw, GCFunction|GCSubwindowMode,
3531 &temp_gcv);
3532 Scr[screen].root_pixmap = XCreatePixmap(dsp, temp_rw,
3533 temp_xgwa.width,
3534 temp_xgwa.height,
3535 temp_xgwa.depth);
3536 XCopyArea(dsp, temp_rw, Scr[screen].root_pixmap,
3537 temp_gc, 0, 0, temp_xgwa.width, temp_xgwa.height,
3538 0, 0);
3539 XFreeGC(dsp, temp_gc);
3540
3541 /* End of MI_ROOT_PIXMAP hack */
3542
3543 if (*plantext) {
3544 char **planp;
3545 int tmp;
3546
3547 Scr[screen].planpos.x = Scr[screen].planpos.y = 0;
3548 for (planp = plantext; *planp; ++planp) {
3549 tmp = XTextWidth(planfont, *planp, strlen(*planp));
3550 if (tmp > Scr[screen].planpos.x)
3551 Scr[screen].planpos.x = tmp;
3552 ++Scr[screen].planpos.y;
3553 }
3554 if (debug) {
3555 Scr[screen].planpos.x = (DisplayWidth(dsp, screen) -
3556 100 - Scr[screen].planpos.x) / 2;
3557 Scr[screen].planpos.y = DisplayHeight(dsp, screen) -
3558 100 - (Scr[screen].planpos.y + 4) * (planFontHeight + 2);
3559 #ifdef USE_XINERAMA
3560 } else if (xinerama_info) {
3561 Scr[screen].planpos.x = (xinerama_info[0].width -
3562 Scr[screen].planpos.x) / 2 + xinerama_info[0].x_org;
3563 Scr[screen].planpos.y = xinerama_info[0].y_org + xinerama_info[0].height -
3564 (Scr[screen].planpos.y + 4) * (planFontHeight + 2);
3565 #endif
3566 } else {
3567 Scr[screen].planpos.x = (DisplayWidth(dsp, screen) -
3568 Scr[screen].planpos.x) / 2;
3569 Scr[screen].planpos.y = DisplayHeight(dsp, screen) -
3570 (Scr[screen].planpos.y + 4) * (planFontHeight + 2);
3571 }
3572 }
3573 #ifdef ORIGINAL_XPM_PATCH
3574 if (mailIcon && mailIcon[0]) {
3575 if ((mail_xpmimg = (XpmImage *) malloc(sizeof (XpmImage))))
3576 if (XpmReadFileToXpmImage(mailIcon, mail_xpmimg,
3577 (XpmInfo *) NULL) != XpmSuccess) {
3578 free(mail_xpmimg);
3579 mail_xpmimg = NULL;
3580 }
3581 }
3582 if (nomailIcon && nomailIcon[0]) {
3583 if ((nomail_xpmimg = (XpmImage *) malloc(sizeof (XpmImage))))
3584 if (XpmReadFileToXpmImage(nomailIcon, nomail_xpmimg,
3585 (XpmInfo *) NULL) != XpmSuccess) {
3586 free(nomail_xpmimg);
3587 nomail_xpmimg = NULL;
3588 }
3589 }
3590 #endif
3591
3592 Scr[screen].root = (parentSet) ? parent : RootWindowOfScreen(scr);
3593 defaultVisualInfo(dsp, screen);
3594
3595 /*-
3596 * Some window managers like fvwm and tvtwm do not like it when an application
3597 * thinks it can install a full screen colormap (i.e xlock). It promptly
3598 * deinstalls the colormap and this might lead to white backgrounds if
3599 * CopyFromParent is not used.
3600 * But if CopyFromParent is used one can not change the visual
3601 * and one may get White = Black on PseudoColor (see bug mode).
3602 * There is another spot in xlock.c like this one...
3603 * As far as I can tell, this problem exists only if your using MesaGL.
3604 */
3605 #if (defined( USE_GL ) && (!defined( MESA ) || defined( REALGLX ))) || !defined( COMPLIANT_COLORMAP )
3606 Scr[screen].colormap = cmap = xswa.colormap =
3607 XCreateColormap(dsp, Scr[screen].root, Scr[screen].visual, AllocNone);
3608 #else
3609 cmap = DefaultColormapOfScreen(scr);
3610 Scr[screen].colormap = None;
3611 #endif
3612
3613 xswa.override_redirect = True;
3614 xswa.background_pixel = Scr[screen].black_pixel;
3615 xswa.border_pixel = Scr[screen].white_pixel;
3616 xswa.event_mask = KeyPressMask | ButtonPressMask |
3617 VisibilityChangeMask | ExposureMask | StructureNotifyMask;
3618 if (mousemotion)
3619 xswa.event_mask |= MotionNotify;
3620
3621 #ifdef USE_VROOT
3622 if (inroot) {
3623 Scr[screen].window = Scr[screen].root;
3624 XChangeWindowAttributes(dsp, Scr[screen].window, CWBackPixel, &xswa);
3625 /* this gives us these events from the root window */
3626 XSelectInput(dsp, Scr[screen].window,
3627 VisibilityChangeMask | ExposureMask);
3628 } else
3629 #endif
3630 #ifdef USE_DTSAVER
3631 if (!dtsaver)
3632 #endif
3633 {
3634 #define WIDTH (inwindow? WidthOfScreen(scr)/2 : (debug? WidthOfScreen(scr) - 100 : WidthOfScreen(scr)))
3635 #define HEIGHT (inwindow? HeightOfScreen(scr)/2 : (debug? HeightOfScreen(scr) - 100 : HeightOfScreen(scr)))
3636 #if (defined( USE_GL ) && (!defined( MESA ) || defined( REALGLX ))) || !defined( COMPLIANT_COLORMAP )
3637 #define CWMASK (((debug||inwindow||inroot)? 0 : CWOverrideRedirect) | CWBackPixel | CWBorderPixel | CWEventMask | CWColormap)
3638 #else
3639 #define CWMASK (((debug||inwindow||inroot)? 0 : CWOverrideRedirect) | CWBackPixel | CWBorderPixel | CWEventMask)
3640 #endif
3641
3642 #if (defined( USE_GL ) && (!defined( MESA ) || defined( REALGLX ))) || !defined( COMPLIANT_COLORMAP )
3643 #define XLOCKWIN_DEPTH (Scr[screen].depth)
3644 #define XLOCKWIN_VISUAL (Scr[screen].visual)
3645 #else
3646 #define XLOCKWIN_DEPTH CopyFromParent
3647 #define XLOCKWIN_VISUAL CopyFromParent
3648 #endif
3649
3650 if (fullscreen) {
3651 Scr[screen].window = XCreateWindow(dsp, Scr[screen].root, 0, 0,
3652 (unsigned int) WIDTH, (unsigned int) HEIGHT, 0,
3653 XLOCKWIN_DEPTH, InputOutput, XLOCKWIN_VISUAL,
3654 CWMASK, &xswa);
3655 } else {
3656 sizeconfiguremask = CWX | CWY | CWWidth | CWHeight;
3657 Scr[screen].fullsizeconfigure.x = 0;
3658 Scr[screen].fullsizeconfigure.y = 0;
3659 Scr[screen].fullsizeconfigure.width = WIDTH;
3660 Scr[screen].fullsizeconfigure.height = HEIGHT;
3661 Scr[screen].window = XCreateWindow(dsp, Scr[screen].root,
3662 (int) minisizeconfigure.x,
3663 (int) minisizeconfigure.y,
3664 (unsigned int) minisizeconfigure.width,
3665 (unsigned int) minisizeconfigure.height,
3666 0, XLOCKWIN_DEPTH, InputOutput, XLOCKWIN_VISUAL,
3667 CWMASK, &xswa);
3668 }
3669 #ifdef USE_MB
3670 XmbSetWMProperties(dsp, Scr[screen].window,
3671 DEFAULT_NAME, DEFAULT_NAME, NULL, 0, NULL, NULL,
3672 &xclasshint);
3673 #endif
3674 }
3675 if (use3d) {
3676 XColor C;
3677
3678 #ifdef CALCULATE_BOTH
3679 XColor C2;
3680
3681 #endif
3682 unsigned long planemasks[10];
3683 unsigned long pixels[10];
3684
3685 if (!install || !XAllocColorCells(dsp, cmap, False, planemasks, 2, pixels,
3686 1)) {
3687 /* did not get the needed colours. Use normal 3d view without */
3688 /* color overlapping */
3689 Scr[screen].none_pixel = allocPixel(dsp, cmap,
3690 none3d, (char *)DEF_NONE3D);
3691 Scr[screen].right_pixel = allocPixel(dsp, cmap,
3692 right3d, (char *)DEF_RIGHT3D);
3693 Scr[screen].left_pixel = allocPixel(dsp, cmap,
3694 left3d, (char *)DEF_LEFT3D);
3695 Scr[screen].both_pixel = allocPixel(dsp, cmap,
3696 both3d, (char *)DEF_BOTH3D);
3697
3698 } else {
3699 /*
3700 * attention: the mixture of colours will only be guaranteed, if
3701 * the right black is used. The problems with BlackPixel would
3702 * be that BlackPixel | left_pixel need not be equal to left_pixel.
3703 * The same holds for rightcol (of course). That is why the right
3704 * black (black3dcol) must be used when GXor is used as put
3705 * function. I have allocated four colors above:
3706 * pixels[0], - 3d black
3707 * pixels[0] | planemasks[0], - 3d right eye color
3708 * pixels[0] | planemasks[1], - 3d left eye color
3709 * pixels[0] | planemasks[0] | planemasks[1] - 3d white
3710 */
3711
3712 if (!XParseColor(dsp, cmap, none3d, &C))
3713 (void) XParseColor(dsp, cmap, DEF_NONE3D, &C);
3714 Scr[screen].none_pixel = C.pixel = pixels[0];
3715 XStoreColor(dsp, cmap, &C);
3716
3717 if (!XParseColor(dsp, cmap, right3d, &C))
3718 (void) XParseColor(dsp, cmap, DEF_RIGHT3D, &C);
3719 Scr[screen].right_pixel = C.pixel = pixels[0] | planemasks[0];
3720 XStoreColor(dsp, cmap, &C);
3721
3722 #ifdef CALCULATE_BOTH
3723 C2.red = C.red;
3724 C2.green = C.green;
3725 C2.blue = C.blue;
3726 #else
3727 if (!XParseColor(dsp, cmap, left3d, &C))
3728 (void) XParseColor(dsp, cmap, DEF_LEFT3D, &C);
3729 #endif
3730 Scr[screen].left_pixel = C.pixel = pixels[0] | planemasks[1];
3731 XStoreColor(dsp, cmap, &C);
3732
3733 #ifdef CALCULATE_BOTH
3734 C.red |= C2.red; /* or them together... */
3735 C.green |= C2.green;
3736 C.blue |= C2.blue;
3737 #else
3738 if (!XParseColor(dsp, cmap, both3d, &C))
3739 (void) XParseColor(dsp, cmap, DEF_BOTH3D, &C);
3740 #endif
3741 Scr[screen].both_pixel = C.pixel =
3742 pixels[0] | planemasks[0] | planemasks[1];
3743 XStoreColor(dsp, cmap, &C);
3744 }
3745
3746 }
3747 fixColormap(mode_info(dsp, screen, Scr[screen].window, False), ncolors, saturation,
3748 mono, install, inroot, inwindow, verbose);
3749 if (debug || inwindow) {
3750 XWMHints xwmh;
3751
3752 xwmh.flags = InputHint;
3753 xwmh.input = True;
3754 XSetWMHints(dsp, Scr[screen].window, &xwmh);
3755 }
3756 if (debug) {
3757 Scr[screen].iconpos.x = (DisplayWidth(dsp, screen) - 100 -
3758 #ifdef HAVE_KRB5
3759 MAX(512, MAX(XTextWidth(font, text_info, strlen(text_info)), XTextWidth(font, text_krbinfo, strlen(text_krbinfo))))
3760 #else /* HAVE_KRB5 */
3761 MAX(512, XTextWidth(font, text_info, strlen(text_info)))
3762 #endif /* HAVE_KRB5 */
3763 ) / 2;
3764 Scr[screen].iconpos.y = (DisplayHeight(dsp, screen) - 100) / 6;
3765 #ifdef USE_XINERAMA
3766 } else if (xinerama_info) {
3767 Scr[screen].iconpos.x = (xinerama_info[0].width -
3768 #ifdef HAVE_KRB5
3769 MAX(512, MAX(XTextWidth(font, text_info, strlen(text_info)), XTextWidth(font, text_krbinfo, strlen(text_krbinfo))))
3770 #else /* HAVE_KRB5 */
3771 MAX(512, XTextWidth(font, text_info, strlen(text_info)))
3772 #endif /* HAVE_KRB5 */
3773 ) / 2 + xinerama_info[0].x_org;
3774 Scr[screen].iconpos.y = xinerama_info[0].y_org + xinerama_info[0].height / 6;
3775 #endif
3776 } else {
3777 Scr[screen].iconpos.x = (DisplayWidth(dsp, screen) -
3778 #ifdef HAVE_KRB5
3779 MAX(512, MAX(XTextWidth(font, text_info, strlen(text_info)), XTextWidth(font, text_krbinfo, strlen(text_krbinfo))))
3780 #else /* HAVE_KRB5 */
3781 MAX(512, XTextWidth(font, text_info, strlen(text_info)))
3782 #endif /* HAVE_KRB5 */
3783 ) / 2;
3784 Scr[screen].iconpos.y = DisplayHeight(dsp, screen) / 6;
3785 }
3786
3787 xswa.border_pixel = Scr[screen].white_pixel;
3788 xswa.background_pixel = Scr[screen].black_pixel;
3789 xswa.event_mask = ButtonPressMask;
3790 #if (defined( USE_GL ) && (!defined( MESA ) || defined( REALGLX ))) || !defined( COMPLIANT_COLORMAP )
3791 #define CIMASK CWBorderPixel | CWBackPixel | CWEventMask | CWColormap
3792 #else
3793 #define CIMASK CWBorderPixel | CWBackPixel | CWEventMask
3794 #endif
3795 if (nolock)
3796 Scr[screen].icon = None;
3797 else {
3798 Scr[screen].icon = XCreateWindow(dsp, Scr[screen].window,
3799 Scr[screen].iconpos.x, Scr[screen].iconpos.y,
3800 iconwidth, iconheight, 1, (int) CopyFromParent,
3801 InputOutput, CopyFromParent,
3802 CIMASK, &xswa);
3803 #ifdef USE_BUTTON_LOGOUT
3804 {
3805 char *buf;
3806 int w, h;
3807
3808 if ((buf = (char *) malloc(strlen(logoutButtonLabel) +
3809 3)) == NULL) {
3810 w = (strlen(logoutButtonLabel) + 5) * 8;
3811 } else {
3812 (void) sprintf(buf, " %s ", logoutButtonLabel);
3813 w = XTextWidth(font, buf, strlen(buf));
3814 free(buf);
3815 }
3816 h = fontHeight + 2;
3817 Scr[screen].button = XCreateWindow(dsp, Scr[screen].window,
3818 0, 0, w, h, 1, (int) CopyFromParent,
3819 InputOutput, CopyFromParent,
3820 CIMASK, &xswa);
3821 }
3822 #endif
3823 }
3824 XMapWindow(dsp, Scr[screen].window);
3825 XRaiseWindow(dsp, Scr[screen].window);
3826
3827 #if 0
3828 if (install && cmap != DefaultColormapOfScreen(scr))
3829 setColormap(dsp, Scr[screen].window, cmap, inwindow);
3830 #endif
3831
3832 xgcv.font = font->fid;
3833 xgcv.foreground = Scr[screen].white_pixel;
3834 xgcv.background = Scr[screen].black_pixel;
3835 Scr[screen].gc = XCreateGC(dsp, Scr[screen].window,
3836 GCFont | GCForeground | GCBackground, &xgcv);
3837
3838 xgcv.foreground = Scr[screen].fg_pixel;
3839 xgcv.background = Scr[screen].bg_pixel;
3840 Scr[screen].textgc = XCreateGC(dsp, Scr[screen].window,
3841 GCFont | GCForeground | GCBackground, &xgcv);
3842 xgcv.font = planfont->fid;
3843 Scr[screen].plantextgc = XCreateGC(dsp, Scr[screen].window,
3844 GCFont | GCForeground | GCBackground, &xgcv);
3845
3846 #ifdef ORIGINAL_XPM_PATCH
3847 if (mail_xpmimg) {
3848 XpmAttributes xpm_attr;
3849
3850 xpm_attr.valuemask = 0;
3851 XpmCreatePixmapFromXpmImage(dsp, Scr[screen].window,
3852 mail_xpmimg, &Scr[screen].mb.mail.pixmap,
3853 &Scr[screen].mb.mail.bitmap, &xpm_attr);
3854 }
3855 if (nomail_xpmimg) {
3856 XpmAttributes xpm_attr;
3857
3858 xpm_attr.valuemask = 0;
3859 XpmCreatePixmapFromXpmImage(dsp, Scr[screen].window, nomail_xpmimg,
3860 &Scr[screen].mb.nomail.pixmap,
3861 &Scr[screen].mb.nomail.bitmap, &xpm_attr);
3862 }
3863 if (mail_xpmimg || nomail_xpmimg) {
3864 Scr[screen].mb.mbgc = XCreateGC(dsp, Scr[screen].window,
3865 GCFont | GCForeground | GCBackground,
3866 &xgcv);
3867 }
3868 #else
3869 if (mailCmd && mailCmd[0]) {
3870 pickPixmap(dsp, Scr[screen].window, nomailIcon,
3871 NOMAIL_WIDTH, NOMAIL_HEIGHT, NOMAIL_BITS,
3872 &(Scr[screen].mb.nomail.width),
3873 &(Scr[screen].mb.nomail.height),
3874 &(Scr[screen].mb.nomail.pixmap),
3875 &(Scr[screen].mb.nomail.graphics_format));
3876 pickPixmap(dsp, Scr[screen].window, mailIcon,
3877 MAIL_WIDTH, MAIL_HEIGHT, MAIL_BITS,
3878 &(Scr[screen].mb.mail.width),
3879 &(Scr[screen].mb.mail.height),
3880 &(Scr[screen].mb.mail.pixmap),
3881 &(Scr[screen].mb.mail.graphics_format));
3882 Scr[screen].mb.mbgc = XCreateGC(dsp, Scr[screen].window,
3883 GCFont | GCForeground | GCBackground,
3884 &xgcv);
3885 }
3886 #endif
3887 }
3888 lockc = XCreateBitmapFromData(dsp, Scr[startscreen].root, no_bits, 1, 1);
3889 lockm = XCreateBitmapFromData(dsp, Scr[startscreen].root, no_bits, 1, 1);
3890 mycursor = XCreatePixmapCursor(dsp, lockc, lockm,
3891 &nullcolor, &nullcolor, 0, 0);
3892 XFreePixmap(dsp, lockc);
3893 XFreePixmap(dsp, lockm);
3894
3895 if (!grabmouse || inwindow || inroot) {
3896 nolock = 1;
3897 enablesaver = 1;
3898 } else if (!debug) {
3899 GrabKeyboardAndMouse(dsp, Scr[startscreen].window);
3900 }
3901 if (!nolock) {
3902 XGetScreenSaver(dsp, &sstimeout, &ssinterval,
3903 &ssblanking, &ssexposures);
3904 if (resetsaver)
3905 XResetScreenSaver(dsp); /* make sure not blank now */
3906 if (!enablesaver)
3907 XSetScreenSaver(dsp, 0, 0, 0, 0); /* disable screen saver */
3908 }
3909 #ifdef USE_DPMS
3910 if ((dpmsstandby >= 0) || (dpmssuspend >= 0) || (dpmsoff >= 0))
3911 SetDPMS(dsp, dpmsstandby, dpmssuspend, dpmsoff);
3912 #endif
3913 #ifdef HAVE_SETPRIORITY
3914 (void) setpriority(0, 0, nicelevel);
3915 #else /* !HAVE_SETPRIORITY */
3916 (void) nice(nicelevel);
3917 #endif /* HAVE_SETPRIORITY */
3918
3919 (void) XSetIOErrorHandler(xio_error);
3920
3921 /* start the command startcmd */
3922 if (startCmd && *startCmd) {
3923
3924 if ((cmd_pid = FORK()) == -1) {
3925 (void) fprintf(stderr, "Failed to launch \"%s\"\n", startCmd);
3926 perror(ProgramName);
3927 cmd_pid = 0;
3928 } else if (!cmd_pid) {
3929 #ifndef VMS
3930 (void) setpgid(0, 0);
3931 #endif
3932 #if 0
3933 #if (defined(sun) && defined(__svr4__)) || defined(sgi) || defined(__hpux) || defined(linux)
3934 setsid();
3935 #else
3936 setpgrp(getpid(), getpid());
3937 #endif
3938 #endif
3939 #if defined( SYSV ) || defined( SVR4 ) || ( __VMS_VER >= 70000000 ) || defined( __CYGWIN__ ) || defined( __linux__ )
3940 (void) sigprocmask(SIG_SETMASK, (sigset_t *)&old_sigmask, (sigset_t *)&old_sigmask);
3941 #else
3942 (void) sigsetmask(old_sigmask);
3943 #endif
3944 (void) system(startCmd);
3945 _exit(0);
3946 }
3947 }
3948 lock_delay = lockdelay;
3949 if (nolock) {
3950 (void) justDisplay(dsp);
3951 } else if (lock_delay) {
3952 if (justDisplay(dsp)) {
3953 lockDisplay(dsp, False);
3954 } else
3955 nolock = 1;
3956 } else {
3957 lockDisplay(dsp, True);
3958 }
3959 #if defined( HAVE_SYSLOG_H ) && defined( USE_SYSLOG )
3960 if (!nolock) {
3961 syslogStop(XDisplayString(dsp));
3962 closelog();
3963 }
3964 #endif
3965 #ifdef USE_DPMS
3966 SetDPMS(dsp, -1, -1, -1);
3967 #endif
3968 finish(dsp, True);
3969
3970 if (cmd_pid) {
3971 #if defined(NO_KILLPG) || defined(__svr4__) || defined(sgi) || defined(__hpux) || defined(VMS)
3972 kill(-cmd_pid, SIGTERM);
3973 #else
3974 (void) killpg(cmd_pid, SIGTERM);
3975 #endif
3976 }
3977 if (endCmd && *endCmd) {
3978 if ((cmd_pid = FORK()) == -1) {
3979 (void) fprintf(stderr, "Failed to launch \"%s\"\n", endCmd);
3980 perror(ProgramName);
3981 cmd_pid = 0;
3982 } else if (!cmd_pid) {
3983 (void) system(endCmd);
3984 _exit(0);
3985 }
3986 }
3987
3988 #if defined( USE_ESOUND )
3989 shutdown_sound();
3990 sound = 0;
3991 #endif
3992
3993 #ifdef VMS
3994 return 1;
3995 #else
3996 return 0;
3997 #endif
3998 }
3999 #endif
4000
4001
4002 #ifdef USE_PAM
4003 /* PAM_putText - method to have pam_converse functionality with in XLOCK */
PAM_putText(const struct pam_message * msg,struct pam_response * resp,Bool PAM_echokeys)4004 void PAM_putText( const struct pam_message *msg, struct pam_response *resp, Bool PAM_echokeys )
4005 {
4006 int x = 50, y = 50;
4007 int oldX, oldY;
4008 int left;
4009 char buffer[PASSLENGTH];
4010
4011 x = left = Scr[screen].iconpos.x;
4012 y = Scr[screen].iconpos.y + fontAscent + 200;
4013
4014 #ifdef DEBUG
4015 (void) printf( "PAM_putText: message of style %d received: (%s)\n", msg->msg_style, msg->msg );
4016 #endif
4017 if( ( msg->msg_style == PAM_PROMPT_ECHO_ON ) ||
4018 ( msg->msg_style == PAM_PROMPT_ECHO_OFF ) )
4019 {
4020 XFlush(dsp);
4021 XSync( dsp, True ); /* Flush Input Buffer */
4022
4023 putText(dsp, Scr[startscreen].window, Scr[startscreen].textgc, msg->msg, True, left, &x, &y);
4024 putText(dsp, Scr[startscreen].window, Scr[startscreen].textgc, " ", True, left, &x, &y);
4025
4026 unamex = x;
4027 unamey = y;
4028
4029 (void) ReadXString(buffer, PASSLENGTH, (Bool *) NULL
4030 #ifdef GLOBAL_UNLOCK
4031 , True
4032 #elif defined( USE_PAM )
4033 , PAM_echokeys
4034 #endif
4035 );
4036
4037 XSetForeground(dsp, Scr[screen].gc, Scr[screen].bg_pixel);
4038 resp->resp = strdup(buffer);
4039 resp->resp_retcode = PAM_SUCCESS;
4040
4041 #ifdef DEBUG
4042 (void) printf( "Received Username: (%s)\n", resp->resp );
4043 #endif
4044 }
4045 else
4046 {
4047 XFlush( dsp );
4048 /* Clears three lines of text before displaying the next message */
4049 oldX = x;
4050 oldY = y;
4051 XFillRectangle(dsp, Scr[startscreen].window, Scr[startscreen].gc,
4052 Scr[screen].iconpos.x, y - fontAscent,
4053 XTextWidth(font, msg->msg, strlen(msg->msg)),
4054 (fontHeight + 2) * 3);
4055 XSync( dsp, True );
4056 (void) sleep(1);
4057 /* display the message */
4058 putText(dsp, Scr[startscreen].window, Scr[startscreen].textgc, msg->msg, True, left, &x, &y);
4059 putText(dsp, Scr[startscreen].window, Scr[startscreen].textgc, " ", True, left, &x, &y);
4060
4061 x = oldX;
4062 y = oldY;
4063
4064 XSync( dsp, True );
4065 (void) sleep(3);
4066
4067 XFlush( dsp );
4068 /* Clears three lines of text before displaying the next message */
4069 XFillRectangle(dsp, Scr[startscreen].window, Scr[startscreen].gc,
4070 Scr[screen].iconpos.x, y - fontAscent,
4071 XTextWidth(font, msg->msg, strlen(msg->msg)),
4072 (fontHeight + 2) * 3);
4073 XSync( dsp, True );
4074 }
4075 }
4076 #endif
4077
4078 #if defined( __hpux ) || defined( __apollo )
4079 int
_main(int argc,char ** argv)4080 _main(int argc, char **argv)
4081 {
4082 main(argc, argv);
4083 }
4084 #endif
4085
4086 #ifdef HAVE_KRB5
4087 /* like putText, but takes a font argument */
4088 static void
putTextFont(Display * display,Window window,XFontStruct * pfont,GC gc,const char * string,int bold,int left,int * px,int * py)4089 putTextFont(Display * display, Window window, XFontStruct *pfont, GC gc,
4090 const char *string, int bold, int left, int *px, int *py)
4091 /* which window */
4092 /* font */
4093 /* gc */
4094 /* text to write */
4095 /* 1 = make it bold */
4096 /* left edge of text */
4097 /* current x and y, input & return */
4098 {
4099 #define PT_BUFSZ 2048
4100 char buf[PT_BUFSZ], *p, *s;
4101 int x = *px, y = *py, last, len;
4102
4103 (void) strncpy(buf, string, PT_BUFSZ);
4104 buf[PT_BUFSZ - 1] = 0;
4105
4106 p = buf;
4107 last = 0;
4108 for (;;) {
4109 s = p;
4110 for (; *p; ++p)
4111 if (*p == '\n')
4112 break;
4113 if (!*p)
4114 last = 1;
4115 *p = 0;
4116
4117 if ((len = strlen(s))) { /* yes, "=", not "==" */
4118 (void) XDrawImageString(display, window, gc, x, y, s, len);
4119 if (bold)
4120 (void) XDrawString(display, window, gc, x + 1, y, s, len);
4121 }
4122 if (!last) {
4123 y += pfont->ascent + pfont->descent + 2;
4124 x = left;
4125 } else {
4126 if (len)
4127 x += XTextWidth(pfont, s, len);
4128 break;
4129 }
4130 p++;
4131 }
4132 *px = x;
4133 *py = y;
4134 }
4135
4136 /*
4137 * Our Kerberos callback prompter. Note that the widgets aren't exactly
4138 * pretty ... but see if I care. We're assuming there won't be any embedded
4139 * newlines in the prompt strings (but we handle embedded newlines in
4140 * the banner string).
4141 */
4142
4143 krb5_error_code
xlock_prompter(krb5_context context,void * data,const char * name,const char * banner,int numprompts,krb5_prompt prompts[])4144 xlock_prompter(krb5_context context, void *data, const char *name,
4145 const char *banner, int numprompts, krb5_prompt prompts[])
4146 {
4147 Window parent = Scr[screen].window;
4148 Window win, button;
4149 GC gc;
4150 XGCValues xgcv;
4151 int lines = 0, max = 0, width, i, height, bwidth, bheight, x, y;
4152 int leave = 0, cp = 0, count;
4153 XWindowAttributes xgwa;
4154 XSetWindowAttributes xswa;
4155 XEvent event;
4156 KeySym keysym;
4157 char buffer[20];
4158 char *ok = "OK", *c;
4159 const char *b;
4160
4161 struct _promptinfo {
4162 int x;
4163 int y;
4164 int curx;
4165 int rp;
4166 } *pi = NULL;
4167
4168 if (numprompts > 0)
4169 if (!(pi = malloc(sizeof(*pi) * numprompts)))
4170 return ENOMEM;
4171
4172 /*
4173 * Let's see what our longest line is (handle embedded newlines,
4174 * but only in the banner)
4175 */
4176
4177 if (banner && banner[0] != NULL) {
4178 for (b = banner, c = index(banner, '\n'); c != NULL;
4179 b = c, c = index(c + 1, '\n')) {
4180 width = XTextWidth(planfont, b, c - b);
4181 if (width > max)
4182 max = width;
4183 lines++;
4184 }
4185 width = XTextWidth(planfont, b, strlen(b));
4186 if (width > max)
4187 max = width;
4188 lines++;
4189 }
4190
4191 for (i = 0; i < numprompts; i++) {
4192 /* 32 asterisks for entry should be enough */
4193 width = XTextWidth(planfont, prompts[i].prompt,
4194 strlen(prompts[i].prompt)) +
4195 XTextWidth(planfont,
4196 ": ********************************", 34);
4197 if (width > max)
4198 max = width;
4199 lines++;
4200 }
4201
4202 /*
4203 * we're saying a 10 pixel border around the text. We add in
4204 * 40 to the height because of the OK button
4205 */
4206
4207 height = (lines + 1) * (planFontHeight + 2) + 40;
4208 width = max + 20;
4209
4210 (void) XGetWindowAttributes(dsp, Scr[screen].window, &xgwa);
4211
4212 if (width > xgwa.width) {
4213 x = 0;
4214 width = xgwa.width;
4215 } else
4216 x = (xgwa.width - width) / 2;
4217
4218 if (height > xgwa.height) {
4219 y = 0;
4220 height = xgwa.height;
4221 } else
4222 y = (xgwa.height - height) / 2;
4223
4224 xswa.override_redirect = True;
4225 xswa.border_pixel = Scr[screen].white_pixel;
4226 xswa.background_pixel = Scr[screen].white_pixel;
4227 xswa.event_mask = KeyPressMask;
4228
4229 /*
4230 * Create the main dialog window
4231 */
4232
4233 win = XCreateWindow(dsp, parent, x, y, width, height, 2,
4234 CopyFromParent, CopyFromParent, Scr[screen].visual,
4235 CWOverrideRedirect | CWBackPixel | CWBorderPixel |
4236 CWEventMask, &xswa);
4237
4238 XMapWindow(dsp, win);
4239 XRaiseWindow(dsp, win);
4240
4241 /*
4242 * Create the OK button window
4243 */
4244
4245 bheight = planFontHeight + 10;
4246 bwidth = XTextWidth(planfont, ok, strlen(ok)) + 10;
4247
4248 xswa.border_pixel = Scr[screen].black_pixel;
4249 xswa.event_mask = ButtonPressMask;
4250
4251 button = XCreateWindow(dsp, win, (width - bwidth) / 2,
4252 height - bheight - 5, bwidth, bheight, 2,
4253 CopyFromParent, CopyFromParent,
4254 Scr[screen].visual, CWOverrideRedirect |
4255 CWBackPixel | CWBorderPixel | CWEventMask,
4256 &xswa);
4257
4258 XMapWindow(dsp, button);
4259 XRaiseWindow(dsp, button);
4260
4261 x = 10;
4262 y = 10 + planfont->ascent;
4263
4264 xgcv.font = planfont->fid;
4265 xgcv.foreground = Scr[screen].black_pixel;
4266 xgcv.background = Scr[screen].white_pixel;
4267 gc = XCreateGC(dsp, Scr[screen].window,
4268 GCFont | GCForeground | GCBackground, &xgcv);
4269
4270 if (banner && banner[0] != NULL)
4271 putTextFont(dsp, win, planfont, gc, banner, 1, x, &x, &y);
4272
4273 for (i = 0; i < numprompts; i++) {
4274 x = 10;
4275 y += planFontHeight + 2;
4276 putTextFont(dsp, win, planfont, gc, prompts[i].prompt, 1,
4277 x, &x, &y);
4278 putTextFont(dsp, win, planfont, gc, ": ", 1, x, &x, &y);
4279 pi[i].x = pi[i].curx = x;
4280 pi[i].y = y;
4281 pi[i].rp = 0;
4282 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
4283 }
4284
4285 x = 5;
4286 y = 5 + planfont->ascent;
4287
4288 putTextFont(dsp, button, planfont, gc, ok, 1, x, &x, &y);
4289
4290 while (leave == 0) {
4291 XNextEvent(dsp, &event);
4292
4293 switch (event.type) {
4294
4295 case ButtonPress:
4296 if (event.xbutton.window == button)
4297 leave = 1;
4298 break;
4299
4300 case KeyPress:
4301 count = XLookupString((XKeyEvent *) &event, buffer,
4302 sizeof(buffer), &keysym, NULL);
4303
4304 /*
4305 * Try to handle specific keysyms
4306 */
4307
4308 if (keysym == XK_Return || keysym == XK_KP_Enter ||
4309 keysym == XK_Linefeed) {
4310 if (++cp >= numprompts)
4311 leave = 1;
4312 break;
4313 }
4314
4315 /*
4316 * Ignore modifier keys
4317 */
4318
4319 if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
4320 break;
4321
4322 /*
4323 * If we don't do any prompts, then we only accept
4324 * Return/Enter/Linefeed
4325 */
4326
4327 if (numprompts == 0) {
4328 XBell(dsp, 100);
4329 break;
4330 }
4331
4332 /*
4333 * Handle Tab/Shift-Tab
4334 */
4335
4336 if (keysym == XK_Tab) {
4337 if (!(event.xkey.state & ShiftMask)) {
4338 if (++cp >= numprompts)
4339 cp = 0;
4340 } else {
4341 if (--cp < 0)
4342 cp = numprompts - 1;
4343 }
4344 break;
4345 }
4346
4347 /*
4348 * Handle BS/Delete
4349 */
4350
4351 if (keysym == XK_BackSpace || keysym == XK_Delete) {
4352 if (pi[cp].rp == 0) {
4353 XBell(dsp, 100);
4354 break;
4355 }
4356 prompts[cp].reply->data[--pi[cp].rp] = '\0';
4357 if (pi[cp].rp < 32) {
4358 pi[cp].curx -= XTextWidth(planfont,
4359 "*", 1);
4360 XClearArea(dsp, win, pi[cp].curx,
4361 pi[cp].y - planfont->ascent,
4362 0, planfont->ascent +
4363 planfont->descent, False);
4364 }
4365 break;
4366 }
4367
4368 /*
4369 * Handle keypresses
4370 */
4371
4372 for (i = 0; i < count; i++) {
4373 switch (buffer[i]) {
4374 case '\003':
4375 case '\025':
4376 XClearArea(dsp, win, pi[cp].x,
4377 pi[cp].y - planfont->ascent,
4378 0, planfont->ascent +
4379 planfont->descent, False);
4380 memset(prompts[cp].reply->data, 0,
4381 prompts[cp].reply->length);
4382 pi[cp].curx = pi[cp].x;
4383 pi[cp].rp = 0;
4384 break;
4385 default:
4386 if (pi[cp].rp + 1 >=
4387 prompts[cp].reply->length) {
4388 XBell(dsp, 100);
4389 break;
4390 }
4391 prompts[cp].reply->data[pi[cp].rp++] =
4392 buffer[i];
4393 if (pi[cp].rp <= 32) {
4394 putTextFont(dsp, win, planfont,
4395 gc, "*", 1,
4396 pi[cp].curx,
4397 &pi[cp].curx,
4398 &pi[cp].y);
4399 }
4400 break;
4401 }
4402 }
4403
4404 break;
4405
4406 default:
4407 /* Nothing */
4408 break;
4409
4410 }
4411
4412 }
4413
4414 if (pi)
4415 free(pi);
4416 XDestroyWindow(dsp, win);
4417 XFreeGC(dsp, gc);
4418
4419 for (i = 0; i < numprompts; i++)
4420 prompts[i].reply->length = strlen(prompts[i].reply->data);
4421
4422 return 0;
4423 }
4424 #endif /* HAVE_KRB5 */
4425
4426 #ifdef WIN32
4427 #define MAX_TIMES 10
4428 int showtext = 0;
4429
4430 void
4431 hsbramp(double h1, double s1, double b1, double h2, double s2, double b2,
4432 int count, unsigned char *red, unsigned char *green, unsigned char *blue);
4433
CalculateColors(int noofcolors,double saturation)4434 static void CalculateColors(int noofcolors, double saturation)
4435 {
4436
4437 /* free any previously allocated colormap */
4438 if (red != NULL)
4439 free(red);
4440 if (green != NULL)
4441 free(green);
4442 if (blue != NULL)
4443 free(blue);
4444
4445 /* create a new colormap */
4446 if ((red = calloc(noofcolors+2, sizeof(unsigned char))) == NULL)
4447 return;
4448 if ((green = calloc(noofcolors+2, sizeof(unsigned char))) == NULL)
4449 return;
4450 if ((blue = calloc(noofcolors+2, sizeof(unsigned char))) == NULL)
4451 return;
4452
4453 /* set the number of colors in the colormap */
4454 colorcount = noofcolors;
4455
4456 /* populate the colormap */
4457 hsbramp(0.0, saturation, 1.0, 1.0, saturation, 1.0, noofcolors,
4458 red, green, blue);
4459
4460 /* store white and black colormap entries */
4461 red[noofcolors] = green[noofcolors] = blue[noofcolors] = 255;
4462 red[noofcolors+1] = green[noofcolors+1] = blue[noofcolors+1] = 0;
4463 }
4464
get_random_mode(void)4465 static int get_random_mode(void)
4466 {
4467 extern char* xlock95_get_modelist(void); /* from xlock95.c */
4468 char *modelist, *p, *modestart;
4469 int nmodes, randommode, curmode, i;
4470
4471 /* Get a list of the selected modes */
4472 modelist = xlock95_get_modelist();
4473
4474 /* Determine how many modes are selected */
4475 nmodes = 0;
4476 p = modelist;
4477 while (*p) {
4478 if (*p == ',')
4479 nmodes++;
4480 p++;
4481 }
4482
4483 /* When the user deselected them all, ignore it */
4484 if (nmodes == 0)
4485 return NRAND(numprocs);
4486
4487 /* Get the random mode */
4488 randommode = NRAND(nmodes);
4489
4490 /* Get the name of this random mode */
4491 p = modelist;
4492 modestart = p;
4493 curmode = 0;
4494
4495 while (*p) {
4496 if (*p == ',') {
4497 if (randommode == curmode)
4498 break;
4499
4500 modestart = p + 1;
4501 curmode++;
4502 }
4503 p++;
4504 }
4505
4506 /* Get the mode number based upon the name */
4507 for (i = 0; i < numprocs; i++)
4508 if (strncmp(LockProcs[i].cmdline_arg,
4509 modestart, p - modestart) == 0)
4510 return(i);
4511
4512 /* Should never come here, just to prevent compile error */
4513 return NRAND(numprocs);
4514 }
4515
4516 void xlockmore_set_mode_options(ModeSpecOpt *ms);
4517
4518 /*-
4519 * xlockmore_create
4520 * called when WIN32 event handling issues a create window
4521 */
xlockmore_create(void)4522 unsigned int xlockmore_create(void)
4523 {
4524 int i;
4525 ModeInfo *mi; /* get mode info */
4526 ModeSpecOpt *ms;
4527 extern TCHAR szSaverName[_MAX_PATH];
4528
4529 /* seeds random number generation */
4530 SRAND((unsigned)time(NULL));
4531 /*#define _DEBUG*/
4532
4533 if (strlen(szSaverName) > 0) {
4534 randommode = NRAND(numprocs); /* Start with a random number */
4535 for (i = 0; i < numprocs; i++) {
4536 /* did the name on the command line match a savers name? */
4537 if (stricmp(LockProcs[i].cmdline_arg, szSaverName) == 0)
4538 {
4539 randommode = i;
4540 break;
4541 }
4542 }
4543 } else {
4544
4545 #ifdef RANDOMMODE
4546 randommode = numprocs - 1; /* random */
4547 #else
4548 randommode = get_random_mode();
4549 #endif
4550 }
4551
4552 /* set variables */
4553 delay = LockProcs[randommode].def_delay;
4554 count = LockProcs[randommode].def_count;
4555 cycles = LockProcs[randommode].def_cycles;
4556 size = LockProcs[randommode].def_size;
4557 saturation = LockProcs[randommode].def_saturation;
4558 bitmap = LockProcs[randommode].def_bitmap;
4559
4560 /* calculate new color map */
4561 CalculateColors(NUMCOLORS, saturation);
4562
4563 /* allocate mem to the ModeInfo & ScreenInfo structures */
4564 screens = ScreenCount(dsp);
4565 if (((modeinfo = (ModeInfo *) calloc(screens,
4566 sizeof (ModeInfo))) == NULL) ||
4567 ((Scr = (ScreenInfo *) calloc(screens,
4568 sizeof (ScreenInfo))) == NULL)) {
4569 error("low memory for info");
4570 }
4571
4572 /* set some WIN32 specific stuff */
4573 mi = mode_info(dsp, 0, (int)hwnd, 0);
4574 MI_COLORMAP_SIZE(mi) = ncolors = mi->screeninfo->npixels = colorcount;
4575 MI_GC(mi) = GCCreate();
4576 MI_NUM_SCREENS(mi) = screens;
4577
4578 for (screen = startscreen; screen < screens; screen++) {
4579 fixColormap(mode_info(dsp, screen, Scr[screen].window, False), ncolors, saturation,
4580 mono, install, inroot, inwindow, verbose);
4581 }
4582
4583 for (i=0; i<NUMCOLORS; i++)
4584 mi->screeninfo->pixels[i] = i;
4585
4586 /* set default options for mode */
4587 ms = LockProcs[randommode].msopt;
4588 xlockmore_set_mode_options(ms);
4589
4590 showtext = 0;
4591 return delay;
4592 }
4593
4594 /*-
4595 * xlockmore_init
4596 * called to initialise a mode
4597 */
xlockmore_init(void)4598 void xlockmore_init(void)
4599 {
4600 call_init_hook(&LockProcs[randommode], mode_info(dsp, 0, (int)hwnd, 0));
4601 }
4602
4603 /*-
4604 * xlockmore_destroy
4605 * called when WIN32 event handling issues a destroy window
4606 */
xlockmore_destroy(void)4607 void xlockmore_destroy(void)
4608 {
4609 call_release_hook(&LockProcs[randommode], mode_info(dsp, 0, (int)hwnd, 0));
4610 }
4611
4612 #ifdef _DEBUG
4613 static char debug_text[255] = { 0 };
4614 #endif
4615
4616 /*-
4617 * xlockmore_timer
4618 * called when WIN32 event handling issues a timer request
4619 */
xlockmore_timer(void)4620 unsigned int xlockmore_timer(void)
4621 {
4622 call_callback_hook(&LockProcs[randommode], mode_info(dsp, 0, (int)hwnd, 0));
4623
4624 /* This may cause more problems than worth. */
4625 #if 0
4626 #ifndef RANDOMMODE
4627 if (showtext < MAX_TIMES)
4628 {
4629 xlockmore_win32_text(10, 10, LockProcs[randommode].cmdline_arg);
4630 xlockmore_win32_text(10, 30, LockProcs[randommode].desc);
4631 showtext++;
4632 }
4633 #endif
4634 #endif
4635 #ifdef _DEBUG
4636 xlockmore_win32_text(10, 60, debug_text, 0);
4637 #endif
4638
4639 return (LockProcs[randommode].def_delay / 1000);
4640 }
4641
4642 /*-
4643 * xlockmore_set_mode_options
4644 * called from create. Sets any default options
4645 */
xlockmore_set_mode_options(ModeSpecOpt * ms)4646 void xlockmore_set_mode_options(ModeSpecOpt *ms)
4647 {
4648 int i;
4649 char **varChar;
4650 float *varFloat;
4651 int *varInt;
4652
4653 for (i=0; i < ms->numvarsdesc; i++)
4654 {
4655 switch (ms->vars[i].type)
4656 {
4657 case t_Bool:
4658 varInt = (int *)ms->vars[i].var;
4659 if (strcmp(ms->vars[i].def, "True") == 0)
4660 *varInt = TRUE;
4661 else
4662 *varInt = FALSE;
4663 break;
4664 case t_Float:
4665 varFloat = (float *)ms->vars[i].var;
4666 *varFloat = atof(ms->vars[i].def);
4667 break;
4668 case t_Int:
4669 varInt = (int *)ms->vars[i].var;
4670 *varInt = atoi(ms->vars[i].def);
4671 break;
4672 case t_String:
4673 varChar = (char **)ms->vars[i].var;
4674 *varChar = ms->vars[i].def;
4675 break;
4676 }
4677 }
4678 }
4679
xlockmore_win32_text(int xloc,int yloc,char * text)4680 void xlockmore_win32_text(int xloc, int yloc, char *text)
4681 {
4682 RECT rect;
4683 UINT nFlags = SetTextAlign(hdc, TA_RIGHT);
4684
4685 (void) GetClientRect(hwnd, &rect);
4686 TextOut(hdc, rect.right - xloc, yloc, text, strlen(text));
4687 SetTextAlign(hdc, nFlags);
4688 }
4689
4690 // FILE *fp = NULL;
xlockmore_set_debug(char * text)4691 void xlockmore_set_debug(char *text)
4692 {
4693 #ifdef _DEBUG
4694 static FILE *fp = NULL;
4695
4696 strcpy(debug_text, text);
4697
4698 #if 1
4699 if (fp == NULL)
4700 {
4701 fp = fopen("xlock_debug.log", "a");
4702 fprintf(fp, "\n");
4703 }
4704
4705 fprintf(fp, "%s\n", text);
4706 #endif
4707 #endif
4708 }
4709
4710 #endif /* WIN32 */
4711
4712 #endif /* STANDALONE */
4713