home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume5 / xlock / part01 / xlock.c < prev   
Encoding:
C/C++ Source or Header  |  1989-09-24  |  19.6 KB  |  770 lines

  1. #ifndef lint
  2. static char sccsid[] = "@(#)xlock.c 22.4 89/09/23";
  3. #endif
  4. /*-
  5.  * xlock.c - X11 client to lock a display and show a screen saver.
  6.  *
  7.  * Copyright (c) 1988-89 by Patrick Naughton and Sun Microsystems, Inc.
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and its
  10.  * documentation for any purpose and without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and that
  12.  * both that copyright notice and this permission notice appear in
  13.  * supporting documentation.
  14.  *
  15.  * This file is provided AS IS with no warranties of any kind.  The author
  16.  * shall have no liability with respect to the infringement of copyrights,
  17.  * trade secrets or any patents by this file or any part thereof.  In no
  18.  * event will the author be liable for any lost revenue or profits or
  19.  * other special, indirect and consequential damages.
  20.  *
  21.  * Comments and additions should be sent to the author:
  22.  *
  23.  *               naughton@sun.com
  24.  *
  25.  *               Patrick J. Naughton
  26.  *               Window Systems Group, MS 14-40
  27.  *               Sun Microsystems, Inc.
  28.  *               2550 Garcia Ave
  29.  *               Mountain View, CA  94043
  30.  *
  31.  * Revision History:
  32.  * 23-Sep-89: Added fix to allow local hostname:0 as a display.
  33.  *          Put empty case for Enter/Leave events.
  34.  *          Moved colormap installation later in startup.
  35.  * 20-Sep-89: Linted and made -saver mode grab the keyboard and mouse.
  36.  *          Replaced SunView code for life mode with Jim Graham's version,
  37.  *        so I could contrib it without legal problems.
  38.  *          Sent to expo for X11R4 contrib.
  39.  * 19-Sep-89: Added '?'s on input.
  40.  * 27-Mar-89: Added -qix mode.
  41.  *          Fixed GContext->GC.
  42.  * 20-Mar-89: Added backup font (fixed) if XQueryLoadFont() fails.
  43.  *          Changed default font to lucida-sans-24.
  44.  * 08-Mar-89: Added -nice, -mode and -display, built vector for life and hop.
  45.  * 24-Feb-89: Replaced hopalong display with life display from SunView1.
  46.  * 22-Feb-89: Added fix for color servers with n < 8 planes.
  47.  * 16-Feb-89: Updated calling conventions for XCreateHsbColormap();
  48.  *          Added -count for number of iterations per color.
  49.  *          Fixed defaulting mechanism.
  50.  *          Ripped out VMS hacks.
  51.  *          Sent to expo for X11R3 contrib.
  52.  * 15-Feb-89: Changed default font to pellucida-sans-18.
  53.  * 20-Jan-89: Added -verbose and fixed usage message.
  54.  * 19-Jan-89: Fixed monochrome gc bug.
  55.  * 16-Dec-88: Added SunView style password prompting.
  56.  * 19-Sep-88: Changed -color to -mono. (default is color on color displays).
  57.  *          Added -saver option. (just do display... don't lock.)
  58.  * 31-Aug-88: Added -time option.
  59.  *          Removed code for fractals to separate file for modularity.
  60.  *          Added signal handler to restore host access.
  61.  *          Installs dynamic colormap with a Hue Ramp.
  62.  *          If grabs fail then exit.
  63.  *          Added VMS Hacks. (password 'iwiwuu').
  64.  *          Sent to expo for X11R2 contrib.
  65.  * 08-Jun-88: Fixed root password pointer problem and changed PASSLENGTH to 20.
  66.  * 20-May-88: Added -root to allow root to unlock.
  67.  * 12-Apr-88: Added root password override.
  68.  *          Added screen saver override.
  69.  *          Removed XGrabServer/XUngrabServer.
  70.  *          Added access control handling instead.
  71.  * 01-Apr-88: Added XGrabServer/XUngrabServer for more security.
  72.  * 30-Mar-88: Removed startup password requirement.
  73.  *          Removed cursor to avoid phosphor burn.
  74.  * 27-Mar-88: Rotate fractal by 45 degrees clockwise.
  75.  * 24-Mar-88: Added color support. [-color]
  76.  *          wrote the man page.
  77.  * 23-Mar-88: Added HOPALONG routines from Scientific American Sept. 86 p. 14.
  78.  *          added password requirement for invokation
  79.  *          removed option for command line password
  80.  *          added requirement for display to be "unix:0".
  81.  * 22-Mar-88: Recieved Walter Milliken's comp.windows.x posting.
  82.  *
  83.  * Contributors:
  84.  *  milliken@heron.bbn.com
  85.  *  karlton@wsl.dec.com
  86.  *  dana@thumper.bellcore.com
  87.  *  vesper@3d.dec.com
  88.  */
  89.  
  90. #include <stdio.h>
  91. #include <signal.h>
  92. #include <sys/param.h>
  93. #include <string.h>
  94. #include <pwd.h>
  95. #include <X11/Xos.h>
  96. #include <X11/Xlib.h>
  97. #include <X11/Xutil.h>
  98. #include <X11/cursorfont.h>
  99.  
  100. extern char *crypt();
  101. extern char *getenv();
  102.  
  103. typedef struct {
  104.     char       *cmdline_arg;
  105.     int        (*lp_reinit) ();
  106.     void    (*lp_callback) ();
  107.     void    (*lp_init) ();
  108. }        lockProc;
  109.  
  110. /*
  111.  * Declare external interface routines for supported screen savers.
  112.  */
  113.  
  114. extern void randomInithop();
  115. extern int  hopdone();
  116. extern void hop();
  117.  
  118. extern void initlife();
  119. extern int  lifedone();
  120. extern void drawlife();
  121.  
  122. extern void initqix();
  123. extern int  qixdone();
  124. extern void drawqix();
  125.  
  126. lockProc    LockProcs[] = {
  127.     {"hop", hopdone, hop, randomInithop},
  128.     {"life", lifedone, drawlife, initlife},
  129.     {"qix", qixdone, drawqix, initqix}
  130. /*
  131.  * New screen savers may be added here.
  132.  * Refer to qix.c for simple sample screen saver.
  133.  */
  134.  
  135. };
  136. #define NUMPROCS (sizeof(LockProcs) / sizeof(lockProc))
  137.  
  138. int        (*reinit) () = NULL;
  139. void        (*callback) () = NULL;
  140. void        (*init) () = NULL;
  141.  
  142. char       *pname;        /* argv[0] */
  143. Display       *dsp = NULL;        /* server display connection */
  144. int        screen;        /* current screen */
  145. Window        w,            /* window used to cover screen */
  146.         icon,        /* window used during password typein */
  147.         root;        /* convenience pointer to the root window */
  148. GC        gc,            /* main graphics drawing graphics context */
  149.         textgc;        /* graphics context used for text rendering */
  150. XColor        black,        /* used for text rendering */
  151.         white;        /* background of text screen */
  152. Colormap    cmap;        /* colormap */
  153. Cursor        mycursor;        /* blank cursor */
  154. Pixmap        lockc,
  155.         lockm;        /* pixmaps for cursor and mask */
  156. char        no_bits[] = {0};    /* dummy array for the blank cursor */
  157. int        passx,        /* position of the ?'s */
  158.         passy;
  159. XFontStruct *font;
  160. char       *fontname = NULL;    /* the font used in the password screen */
  161. int        inittime = -1;    /* time to iterate before calling init */
  162. int        skipRoot;        /* skip root password check */
  163. int        color;        /* color or mono */
  164. int        count = -1;        /* number of pixels to draw in each color */
  165. int        nicelevel = -1;    /* system priority at which to run process */
  166. int        lock;        /* locked or just screensaver mode */
  167. int        verbose = False;    /* print configuration info to stderr? */
  168. char       *display = NULL;    /* X display variable */
  169. int        timeout,
  170.         interval,
  171.         blanking,
  172.         exposures;        /* screen saver parameters */
  173.  
  174. #define ICONX            300
  175. #define ICONY            150
  176. #define ICONW            64
  177. #define ICONH            64
  178. #define ICONLOOPS        600
  179. #define DEFAULT_FONTNAME    "LucidaSans-24"
  180. #define BACKUP_FONTNAME        "fixed"
  181. #define DEFAULT_INITTIME    60
  182. #define DEFAULT_SKIPROOT    True
  183. #define DEFAULT_COUNT        100
  184. #define DEFAULT_NICE        10
  185. #define DEFAULT_DISPLAY        ":0"
  186.  
  187. /* VARARGS1 */
  188. void
  189. error(s1, s2)
  190.     char       *s1,
  191.            *s2;
  192. {
  193.     fprintf(stderr, s1, pname, s2);
  194.     exit(1);
  195. }
  196.  
  197.  
  198. int        oldsigmask;
  199.  
  200. void
  201. block()
  202. {
  203.     oldsigmask = sigblock(sigmask(SIGINT)
  204.               | sigmask(SIGQUIT)
  205.               | sigmask(SIGFPE)
  206.               | sigmask(SIGSEGV));
  207. }
  208.  
  209. void
  210. unblock()
  211. {
  212.     sigsetmask(oldsigmask);
  213. }
  214.  
  215. void
  216. allowsig()
  217. {
  218.     unblock();
  219.     block();
  220. }
  221.  
  222.  
  223. XHostAddress *XHosts;
  224. int        HostAccessCount;
  225. Bool        HostAccessState;
  226.  
  227. void
  228. XGrabHosts(dsp)
  229.     Display    *dsp;
  230. {
  231.     XHosts = XListHosts(dsp, &HostAccessCount, &HostAccessState);
  232.     XRemoveHosts(dsp, XHosts, HostAccessCount);
  233.     XEnableAccessControl(dsp);
  234. }
  235.  
  236. void
  237. XUngrabHosts(dsp)
  238.     Display    *dsp;
  239. {
  240.     XAddHosts(dsp, XHosts, HostAccessCount);
  241.     XFree(XHosts);
  242.     if (HostAccessState == False)
  243.     XDisableAccessControl(dsp);
  244. }
  245.  
  246.  
  247. void
  248. GrabKeyboardAndMouse()
  249. {
  250.     Status    status;
  251.  
  252.     status = XGrabKeyboard(dsp, w, True,
  253.                GrabModeAsync, GrabModeAsync, CurrentTime);
  254.     if (status != GrabSuccess)
  255.     error("%s: couldn't grab keyboard! (%d)\n", status);
  256.     status = XGrabPointer(dsp, w, True, -1,
  257.               GrabModeAsync, GrabModeAsync, None, mycursor,
  258.               CurrentTime);
  259.     if (status != GrabSuccess)
  260.     error("%s: couldn't grab pointer! (%d)\n", status);
  261. }
  262.  
  263.  
  264. void
  265. XChangeGrabbedCursor(cursor)
  266.     Cursor    cursor;
  267. {
  268.     XGrabPointer(dsp, w, True, -1,
  269.          GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
  270. }
  271.  
  272. void
  273. finish()
  274. {
  275.     XSync(dsp, 0);
  276.     XUngrabHosts(dsp);
  277.     XUngrabPointer(dsp, CurrentTime);
  278.     XUngrabKeyboard(dsp, CurrentTime);
  279.     XSetScreenSaver(dsp, timeout, interval, blanking, exposures);
  280.     XDestroyWindow(dsp, w);
  281.     if (color)
  282.     XUninstallColormap(dsp, cmap);
  283.     XFlush(dsp);
  284.     XCloseDisplay(dsp);
  285. }
  286.  
  287. void
  288. sigcatch()
  289. {
  290.     finish();
  291.     error("%s: caught terminate signal.\nAccess control list restored.\n");
  292. }
  293.  
  294. int
  295. ReadXString(s, slen)
  296.     char       *s;
  297.     int        slen;
  298. {
  299.     XEvent    event;
  300.     char    keystr[20];
  301.     char    c;
  302.     int        i,
  303.         bp,
  304.         len,
  305.         loops;
  306.     char       *pwbuf = (char *) malloc(slen);
  307.  
  308.     XSetForeground(dsp, gc, BlackPixel(dsp, screen));
  309.     init(dsp, icon, gc, color, inittime, count);
  310.     bp = 0;
  311.     nice(-nicelevel);        /* make sure we can read the keystrokes... */
  312.     while (True) {
  313.     loops = 0;
  314.     while (!XPending(dsp)) {
  315.         allowsig();
  316.         callback();
  317.         if (reinit())
  318.         init(dsp, icon, gc, color, inittime, count);
  319.         if (++loops >= ICONLOOPS) {
  320.         nice(nicelevel);
  321.         free(pwbuf);
  322.         return 1;
  323.         }
  324.     }
  325.     XNextEvent(dsp, &event);
  326.     switch (event.type) {
  327.     case KeyPress:
  328.         len = XLookupString((XKeyEvent *) & event, keystr, 20, NULL, NULL);
  329.         for (i = 0; i < len; i++) {
  330.         c = keystr[i];
  331.         switch (c) {
  332.         case 8:    /* ^H */
  333.         case 127:    /* DEL */
  334.             if (bp > 0)
  335.             bp--;
  336.             break;
  337.         case 10:    /* ^J */
  338.         case 13:    /* ^M */
  339.             s[bp] = '\0';
  340.             nice(nicelevel);
  341.             free(pwbuf);
  342.             return 0;
  343.         case 21:    /* ^U */
  344.             bp = 0;
  345.             break;
  346.         default:
  347.             s[bp] = c;
  348.             if (bp < slen - 1)
  349.             bp++;
  350.         }
  351.         }
  352.         memset(pwbuf, '?', slen);
  353.         XSetForeground(dsp, gc, white.pixel);
  354.         XFillRectangle(dsp, w, gc, passx, passy - font->ascent,
  355.                XTextWidth(font, pwbuf, slen),
  356.                font->ascent + font->descent);
  357.         XDrawString(dsp, w, textgc, passx, passy, pwbuf, bp);
  358.         break;
  359.  
  360.     case ButtonPress:
  361.         if (((XButtonEvent *) & event)->window == icon) {
  362.         nice(nicelevel);
  363.         free(pwbuf);
  364.         return 1;
  365.         }
  366.         break;
  367.  
  368.     case KeyRelease:
  369.     case ButtonRelease:
  370.     case MotionNotify:
  371.     case LeaveNotify:
  372.     case EnterNotify:
  373.         break;
  374.  
  375.     default:
  376.         fprintf(stderr, "%s: unexpected event: %d\n", pname, event.type);
  377.         break;
  378.     }
  379.     }
  380. }
  381.  
  382. int
  383. getPassword()
  384. {
  385. #define PASSLENGTH 20
  386.     char    buffer[PASSLENGTH];
  387.     char    userpass[PASSLENGTH];
  388.     char    rootpass[PASSLENGTH];
  389.     struct passwd *pw;
  390.     XWindowAttributes xgwa;
  391.     char       *user = getenv("USER");
  392.     char       *name = "Name: ";
  393.     char       *pass = "Password: ";
  394.     char       *info = "Enter password to unlock; select icon to lock.";
  395.     char       *validate = "Validating login...";
  396.     char       *invalid = "Invalid login.";
  397.     int        y,
  398.         left,
  399.         done;
  400.  
  401.     XGetWindowAttributes(dsp, w, &xgwa);
  402.  
  403.     XChangeGrabbedCursor(XCreateFontCursor(dsp, XC_left_ptr));
  404.  
  405.     XSetForeground(dsp, gc, WhitePixel(dsp, screen));
  406.     XFillRectangle(dsp, w, gc, 0, 0, xgwa.width, xgwa.height);
  407.  
  408.     XMapWindow(dsp, icon);
  409.     XRaiseWindow(dsp, icon);
  410.  
  411.     left = ICONX + ICONW + font->max_bounds.width;
  412.     y = ICONY + font->ascent;
  413.  
  414.     XDrawString(dsp, w, textgc, left, y, name, strlen(name));
  415.     XDrawString(dsp, w, textgc, left + 1, y, name, strlen(name));
  416.     XDrawString(dsp, w, textgc,
  417.         left + XTextWidth(font, name, strlen(name)), y,
  418.         user, strlen(user));
  419.  
  420.     y += font->ascent + font->descent + 2;
  421.     XDrawString(dsp, w, textgc, left, y, pass, strlen(pass));
  422.     XDrawString(dsp, w, textgc, left + 1, y, pass, strlen(pass));
  423.  
  424.     passx = left + 1 + XTextWidth(font, pass, strlen(pass))
  425.     + XTextWidth(font, " ", 1);
  426.     passy = y;
  427.  
  428.     y = ICONY + ICONH + font->ascent + 2;
  429.     XDrawString(dsp, w, textgc, ICONX, y, info, strlen(info));
  430.  
  431.     XFlush(dsp);
  432.  
  433.     y += font->ascent + font->descent + 2;
  434.  
  435.     pw = getpwuid(0);
  436.     strcpy(rootpass, pw->pw_passwd);
  437.  
  438.     pw = getpwuid(getuid());
  439.     strcpy(userpass, pw->pw_passwd);
  440.  
  441.     done = False;
  442.     while (!done) {
  443.  
  444.     if (ReadXString(buffer, PASSLENGTH)) {
  445.         XChangeGrabbedCursor(mycursor);
  446.         XUnmapWindow(dsp, icon);
  447.         XSetForeground(dsp, gc, WhitePixel(dsp, screen));
  448.         return 1;
  449.     }
  450.     XSetForeground(dsp, gc, WhitePixel(dsp, screen));
  451.     XFillRectangle(dsp, w, gc, ICONX, y - font->ascent,
  452.                XTextWidth(font, validate, strlen(validate)),
  453.                font->ascent + font->descent + 2);
  454.  
  455.     XDrawString(dsp, w, textgc, ICONX, y, validate, strlen(validate));
  456.  
  457.     done = !((strcmp(crypt(buffer, userpass), userpass))
  458.          && (skipRoot || strcmp(crypt(buffer, rootpass), rootpass)));
  459.  
  460.     if (!done) {
  461.         XFlush(dsp);
  462.         sleep(1);
  463.         XFillRectangle(dsp, w, gc, ICONX, y - font->ascent,
  464.                XTextWidth(font, validate, strlen(validate)),
  465.                font->ascent + font->descent + 2);
  466.  
  467.         XDrawString(dsp, w, textgc, ICONX, y, invalid, strlen(invalid));
  468.     }
  469.     }
  470.     return 0;
  471. }
  472.  
  473. void
  474. justDisplay()
  475. {
  476.     XEvent    event;
  477.  
  478.     init(dsp, w, gc, color, inittime, count);
  479.     do {
  480.     while (!XPending(dsp)) {
  481.         callback();
  482.         if (reinit())
  483.         init(dsp, w, gc, color, inittime, count);
  484.     }
  485.     XNextEvent(dsp, &event);
  486.     } while (event.type != ButtonPress && event.type != KeyPress);
  487. }
  488.  
  489. void
  490. lockDisplay()
  491. {
  492.     do {
  493.     justDisplay();
  494.     } while (getPassword());
  495. }
  496.  
  497. void
  498. usage(s)
  499.     char       *s;
  500. {
  501.     int        i;
  502.  
  503.     fprintf(stderr, "%s\nusage: %s [-display dsp] [-mode %s",
  504.         s, pname, LockProcs[0].cmdline_arg);
  505.     for (i = 1; i < NUMPROCS; i++)
  506.     fprintf(stderr, " | %s", LockProcs[i].cmdline_arg);
  507.     fprintf(stderr, "]\n");
  508.     fprintf(stderr, "\t%s %s\n",
  509.         "[-time n] [-count n] [-nice n]",
  510.         "[-font f] [-mono] [-saver] [-root] [-v]");
  511.     exit(1);
  512. }
  513.  
  514. void
  515. BuildPointersFromString(s)
  516.     char       *s;
  517. {
  518.     int        i;
  519.  
  520.     for (i = 0; i < NUMPROCS; i++) {
  521.     if (!strncmp(LockProcs[i].cmdline_arg, s, strlen(s))) {
  522.         reinit = LockProcs[i].lp_reinit;
  523.         callback = LockProcs[i].lp_callback;
  524.         init = LockProcs[i].lp_init;
  525.         if (verbose)
  526.         fprintf(stderr, "Mode: %s\n", s);
  527.         return;
  528.     }
  529.     }
  530.     usage("Unknown Mode.");
  531. }
  532.  
  533. main(argc, argv)
  534.     int        argc;
  535.     char       *argv[];
  536. {
  537.     XSetWindowAttributes xswa;
  538.     XGCValues    xgcv;
  539.     int        i;
  540.     char       *s;
  541.     int        n;
  542.  
  543.     pname = argv[0];
  544.     color = True;
  545.     lock = True;
  546.     skipRoot = -1;
  547.  
  548.     for (i = 1; i < argc; i++) {
  549.     s = argv[i];
  550.     n = strlen(s);
  551.     if (!strncmp("-display", s, n)) {
  552.         if (++i >= argc)
  553.         usage(s);
  554.         display = argv[i];
  555.     } else if (!strncmp("-mono", s, n)) {
  556.         color = False;
  557.     } else if (!strncmp("-saver", s, n)) {
  558.         lock = False;
  559.     } else if (!strncmp("-root", s, n)) {
  560.         skipRoot = False;
  561.     } else if (!strncmp("-verbose", s, n)) {
  562.         verbose = True;
  563.     } else if (!strncmp("-time", s, n)) {
  564.         if (++i >= argc)
  565.         usage(s);
  566.         inittime = atoi(argv[i]);
  567.         if (inittime < 1)
  568.         usage("-time argument must be positive.");
  569.     } else if (!strncmp("-count", s, n)) {
  570.         if (++i >= argc)
  571.         usage(s);
  572.         count = atoi(argv[i]);
  573.         if (count < 1)
  574.         usage("-count argument must be positive.\n");
  575.     } else if (!strncmp("-nice", s, n)) {
  576.         if (++i >= argc)
  577.         usage(s);
  578.         nicelevel = atoi(argv[i]);
  579.     } else if (!strncmp("-font", s, n)) {
  580.         if (++i >= argc)
  581.         usage(s);
  582.         fontname = argv[i];
  583.     } else if (!strncmp("-mode", s, n)) {
  584.         if (++i >= argc)
  585.         usage(s);
  586.         BuildPointersFromString(argv[i]);
  587.     } else {
  588.         fprintf(stderr, "Bad switch: ");
  589.         usage(s);
  590.     }
  591.     }
  592.  
  593.     if (display == NULL)
  594.     display = getenv("DISPLAY");
  595.  
  596.     if (display != NULL) {
  597.     char       *colon = strchr(display, ':');
  598.     int        n = colon - display;
  599.     char        hostname[MAXHOSTNAMELEN];
  600.  
  601.     if (gethostname(hostname, MAXHOSTNAMELEN))
  602.         error("%s: Can't get local hostname.\n");
  603.  
  604.     if (colon == NULL)
  605.         error("%s: Malformed -display argument, \"%s\"\n", display);
  606.  
  607.     if (n) {
  608.         if (strncmp(display, "unix", n)
  609.          && strncmp(display, "localhost", n)
  610.          && strncmp(display, hostname, n)) {
  611.         *colon = (char) 0;
  612.         error("%s: can't lock %s's display\n", display);
  613.          }
  614.     }
  615.     } else
  616.     display = DEFAULT_DISPLAY;
  617.  
  618.     if (lock) {
  619.     block();
  620.     signal(SIGINT, sigcatch);
  621.     signal(SIGQUIT, sigcatch);
  622.     signal(SIGSEGV, sigcatch);
  623.     }
  624.     if (!(dsp = XOpenDisplay(display)))
  625.     error("%s: unable to open display %s.\n", display);
  626.  
  627.     if (fontname == NULL)
  628.     fontname = XGetDefault(dsp, pname, "font");
  629.     if (fontname == NULL)
  630.     fontname = DEFAULT_FONTNAME;
  631.  
  632.     if (count == -1) {
  633.     s = XGetDefault(dsp, pname, "count");
  634.     if (s != NULL)
  635.         count = atoi(s);
  636.     else
  637.         count = DEFAULT_COUNT;
  638.     }
  639.     if (nicelevel == -1) {
  640.     s = XGetDefault(dsp, pname, "nice");
  641.     if (s != NULL)
  642.         nicelevel = atoi(s);
  643.     else
  644.         nicelevel = DEFAULT_NICE;
  645.     }
  646.     if (inittime == -1) {
  647.     s = XGetDefault(dsp, pname, "time");
  648.     if (s != NULL)
  649.         inittime = atoi(s);
  650.     else
  651.         inittime = DEFAULT_INITTIME;
  652.     }
  653.     if (init == NULL) {
  654.     s = XGetDefault(dsp, pname, "mode");
  655.     if (s != NULL) {
  656.         BuildPointersFromString(s);
  657.     } else {
  658.         reinit = LockProcs[0].lp_reinit;
  659.         callback = LockProcs[0].lp_callback;
  660.         init = LockProcs[0].lp_init;
  661.         if (verbose)
  662.         fprintf(stderr, "Mode: %s\n", LockProcs[0].cmdline_arg);
  663.     }
  664.     }
  665.     if (skipRoot == -1) {
  666.     s = XGetDefault(dsp, pname, "root");
  667.     if (s != NULL)
  668.         skipRoot = !(strncmp("on", s, strlen(s)) == 0);
  669.     else
  670.         skipRoot = DEFAULT_SKIPROOT;
  671.     }
  672.     if (verbose) {
  673.     fprintf(stderr,
  674.         "%s: Font: %s, Time: %d, Root: %s, Nice: %d\n", pname,
  675.         fontname, inittime, skipRoot ? "False" : "True", nicelevel);
  676.     }
  677.     font = XLoadQueryFont(dsp, fontname);
  678.     if (font == NULL) {
  679.     fprintf(stderr, "%s: can't find font: %s, using %s...\n",
  680.         pname, fontname, BACKUP_FONTNAME);
  681.     font = XLoadQueryFont(dsp, BACKUP_FONTNAME);
  682.     if (font == NULL)
  683.         error("%s: can't even find %s!!!\n", BACKUP_FONTNAME);
  684.     }
  685.     screen = DefaultScreen(dsp);
  686.     if (color)
  687.     color = (DisplayCells(dsp, screen) > 2);
  688.     root = RootWindow(dsp, screen);
  689.  
  690.     if (color) {
  691.     if (XCreateHSBColormap(dsp, screen, &cmap, DisplayCells(dsp, screen),
  692.                    0.0, 1.0, 1.0, 1.0, 1.0, 1.0, True) != Success)
  693.         error("%s: couldn't create colormap.");
  694.     } else
  695.     cmap = DefaultColormap(dsp, screen);
  696.  
  697.     black.pixel = BlackPixel(dsp, screen);
  698.     XQueryColor(dsp, cmap, &black);
  699.  
  700.     white.pixel = WhitePixel(dsp, screen);
  701.     XQueryColor(dsp, cmap, &white);
  702.  
  703.     lockc = XCreateBitmapFromData(dsp, root, no_bits, 1, 1);
  704.     lockm = XCreateBitmapFromData(dsp, root, no_bits, 1, 1);
  705.     mycursor = XCreatePixmapCursor(dsp, lockc, lockm, &black, &black, 0, 0);
  706.     XFreePixmap(dsp, lockc);
  707.     XFreePixmap(dsp, lockm);
  708.  
  709.     xswa.cursor = mycursor;
  710.     xswa.override_redirect = True;
  711.     xswa.background_pixel = black.pixel;
  712.     xswa.event_mask = KeyPressMask | ButtonPressMask;
  713.  
  714.     w = XCreateWindow(dsp, root,
  715.               0, 0,
  716.               DisplayWidth(dsp, screen),
  717.               DisplayHeight(dsp, screen),
  718.               0, CopyFromParent, InputOutput, CopyFromParent,
  719.               CWCursor | CWOverrideRedirect |
  720.               CWBackPixel | CWEventMask, &xswa);
  721.  
  722.     xswa.cursor = XCreateFontCursor(dsp, XC_target);
  723.     xswa.background_pixel = white.pixel;
  724.     xswa.event_mask = ButtonPressMask;
  725.  
  726.     icon = XCreateWindow(dsp, w,
  727.              ICONX, ICONY,
  728.              ICONW, ICONH,
  729.              1, CopyFromParent, InputOutput, CopyFromParent,
  730.              CWCursor | CWBackPixel | CWEventMask, &xswa);
  731.  
  732.     XMapWindow(dsp, w);
  733.     XRaiseWindow(dsp, w);
  734.  
  735.     xgcv.foreground = white.pixel;
  736.     xgcv.background = black.pixel;
  737.     gc = XCreateGC(dsp, w, GCForeground | GCBackground, &xgcv);
  738.  
  739.     xgcv.foreground = black.pixel;
  740.     xgcv.background = white.pixel;
  741.     xgcv.font = font->fid;
  742.     textgc = XCreateGC(dsp, w, GCFont | GCForeground | GCBackground, &xgcv);
  743.  
  744.     XGetScreenSaver(dsp, &timeout, &interval, &blanking, &exposures);
  745.     XSetScreenSaver(dsp, 0, 0, 0, 0);    /* disable screen saver */
  746.     GrabKeyboardAndMouse();
  747.  
  748.     if (lock) {
  749.     XGrabHosts(dsp);
  750.     allowsig();
  751.     }
  752.     nice(nicelevel);
  753.     srandom(getpid());
  754.  
  755.     if (color)
  756.     XInstallColormap(dsp, cmap);
  757.  
  758.     if (lock)
  759.     lockDisplay();
  760.     else
  761.     justDisplay();
  762.  
  763.     finish();
  764.  
  765.     if (lock)
  766.     unblock();
  767.  
  768.     exit(0);
  769. }
  770.