xautolock-2.2/0000700000175100017500000000000010735227755011464 5ustar mcemcexautolock-2.2/src/0000700000175100017500000000000010735227755012253 5ustar mcemcexautolock-2.2/src/message.c0000600000175100017500000001703010700012602014015 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It implements * the program's IPC features. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #include "message.h" #include "state.h" #include "options.h" #include "miscutil.h" static Atom semaphore; /* semaphore property for locating an already running xautolock */ static Atom messageAtom; /* message property for talking to an already running xautolock */ #define SEM_PID "_SEMAPHORE_PID" #define MESSAGE "_MESSAGE" /* * Message handlers. */ static void disableByMessage (Display* d, Window root) { /* * The order in which things are done is rather important here. */ if (!secure) { setLockTrigger (lockTime); disableKillTrigger (); disabled = True; } } static void enableByMessage (Display* d, Window root) { if (!secure) { resetTriggers (); disabled = False; } } static void toggleByMessage (Display* d, Window root) { if (!secure) { if ((disabled = !disabled)) /* = intended */ { setLockTrigger (lockTime); disableKillTrigger (); } else { resetTriggers (); } } } static void exitByMessage (Display* d, Window root) { if (!secure) { error0 ("Exiting. Bye bye...\n"); exit (0); } } static void lockNowByMessage (Display* d, Window root) { if (!secure && !disabled) lockNow = True; } static void unlockNowByMessage (Display* d, Window root) { if (!secure && !disabled) unlockNow = True; } static void restartByMessage (Display* d, Window root) { if (!secure) { XDeleteProperty (d, root, semaphore); XFlush (d); execv (argArray[0], argArray); } } /* * Function for looking for messages from another xautolock. */ void lookForMessages (Display* d) { Window root; /* as it says */ Atom type; /* actual property type */ int format; /* dummy */ unsigned long nofItems; /* dummy */ unsigned long after; /* dummy */ int* contents; /* message property value */ static Bool first = True; /* is this the first call? */ /* * It would be cleaner (more X-like, using less cpu time and * network bandwith, ...) to implement this functionality by * keeping an eye open for PropertyNotify events on the root * window, or (even better) by using ClientMessage events. * Maybe I'll rewrite it one day to do just that, but the * current approach works just fine too. * * Note that we must clear the property before acting on it! * Otherwise funny things can happen on receipt of msg_exit. */ root = RootWindowOfScreen (ScreenOfDisplay (d, 0)); (void) XGetWindowProperty (d, root, messageAtom, 0L, 2L, False, AnyPropertyType, &type, &format, &nofItems, &after, (unsigned char**) &contents); XDeleteProperty (d, root, messageAtom); XFlush (d); /* * The very first time we get here, we ignore the message. Why? * Well, suppose some weirdo sends a SIGSTOP to a running xautolock, * then does an `xautolock -exit' and finally sends a SIGKILL to * the stopped xautolock. This would leave an unread message sitting * around. Unread that is, till the next xautolock is started. * * To solve this, we want any xautolock that enters the main event * loop to consume and ignore any message that may have been around * for a while and forgotten about. */ if (first) { first = False; } else if (type == XA_INTEGER) { switch (*contents) { case msg_disable: disableByMessage (d, root); break; case msg_enable: enableByMessage (d, root); break; case msg_toggle: toggleByMessage (d, root); break; case msg_lockNow: lockNowByMessage (d, root); break; case msg_unlockNow: unlockNowByMessage (d, root); break; case msg_restart: restartByMessage (d, root); break; case msg_exit: exitByMessage (d, root); break; default: /* unknown message, ignore silently */ break; } } (void) XFree ((char*) contents); } /* * Function for creating the communication atoms. */ void getAtoms (Display* d) { char* sem; /* semaphore property name */ char* mes; /* message property name */ char* ptr; /* iterator */ sem = newArray (char, strlen (progName) + strlen (SEM_PID) + 1); (void) sprintf (sem, "%s%s", progName, SEM_PID); for (ptr = sem; *ptr; ++ptr) *ptr = (char) toupper (*ptr); semaphore = XInternAtom (d, sem, False); free (sem); mes = newArray (char, strlen (progName) + strlen (MESSAGE) + 1); (void) sprintf (mes, "%s%s", progName, MESSAGE); for (ptr = mes; *ptr; ++ptr) *ptr = (char) toupper (*ptr); messageAtom = XInternAtom (d, mes, False); free (mes); } /* * Function for finding out whether another xautolock is already * running and for sending it a message if that's what the user * wanted. */ void checkConnectionAndSendMessage (Display* d) { pid_t pid; /* as it says */ Window root; /* as it says */ Atom type; /* actual property type */ int format; /* dummy */ unsigned long nofItems; /* dummy */ unsigned long after; /* dummy */ pid_t* contents; /* semaphore property value */ getAtoms (d); root = RootWindowOfScreen (ScreenOfDisplay (d, 0)); (void) XGetWindowProperty (d, root, semaphore, 0L, 2L, False, AnyPropertyType, &type, &format, &nofItems, &after, (unsigned char**) &contents); if (type == XA_INTEGER) { /* * This breaks if the other xautolock is not on the same machine. */ if (kill (*contents, 0)) { if (messageToSend) { error1 ("No process with PID %d, or the process " "is owned by another user.\n", *contents); exit (EXIT_FAILURE); } } else if (messageToSend) { (void) XChangeProperty (d, root, messageAtom, XA_INTEGER, 8, PropModeReplace, (unsigned char*) &messageToSend, (int) sizeof (messageToSend)); XFlush (d); exit (EXIT_SUCCESS); } else { #ifdef VMS error2 ("%s is already running (PID %x).\n", progName, *contents); #else /* VMS */ error2 ("%s is already running (PID %d).\n", progName, *contents); #endif /* VMS */ exit (EXIT_FAILURE); } } else if (messageToSend) { error1 ("Could not locate a running %s.\n", progName); exit (EXIT_FAILURE); } pid = getpid (); (void) XChangeProperty (d, root, semaphore, XA_INTEGER, 8, PropModeReplace, (unsigned char*) &pid, (int) sizeof (pid)); (void) XFree ((char*) contents); } xautolock-2.2/src/engine.c0000600000175100017500000003000310735227456013660 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It implements * the program's core functions. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #include "engine.h" #include "options.h" #include "state.h" #include "miscutil.h" /* * Function for querying the idle time from the server. * Only used if either the Xidle or the Xscreensaver * extension is present. */ void queryIdleTime (Display* d, Bool use_xidle) { Time idleTime = 0; /* millisecs since last input event */ #ifdef HasXidle if (use_xidle) { XGetIdleTime (d, &idleTime); } else #endif /* HasXIdle */ { #ifdef HasScreenSaver static XScreenSaverInfo* mitInfo = 0; if (!mitInfo) mitInfo = XScreenSaverAllocInfo (); XScreenSaverQueryInfo (d, DefaultRootWindow (d), mitInfo); idleTime = mitInfo->idle; #endif /* HasScreenSaver */ } if (idleTime < 1000) { resetTriggers (); } } /* * Function for monitoring pointer movements. This implements the * `corners' feature and as a side effect also tracks pointer * related user activity. The latter actually is only needed when * we're using the DIY mode of operations, but it's much simpler * to do it unconditionally. */ void queryPointer (Display* d) { Window dummyWin; /* as it says */ int dummyInt; /* as it says */ unsigned mask; /* modifier mask */ int rootX; /* as it says */ int rootY; /* as it says */ int corner; /* corner index */ time_t now; /* as it says */ time_t newTrigger; /* temporary storage */ int i; /* loop counter */ static Window root; /* root window the pointer is on */ static Screen* screen; /* screen the pointer is on */ static unsigned prevMask = 0; /* as it says */ static int prevRootX = -1; /* as it says */ static int prevRootY = -1; /* as it says */ static Bool firstCall = True; /* as it says */ /* * Have a guess... */ if (firstCall) { firstCall = False; root = DefaultRootWindow (d); screen = ScreenOfDisplay (d, DefaultScreen (d)); } /* * Find out whether the pointer has moved. Using XQueryPointer for this * is gross, but it also is the only way never to mess up propagation * of pointer events. */ if (!XQueryPointer (d, root, &root, &dummyWin, &rootX, &rootY, &dummyInt, &dummyInt, &mask)) { /* * Pointer has moved to another screen, so let's find out which one. */ for (i = -1; ++i < ScreenCount (d); ) { if (root == RootWindow (d, i)) { screen = ScreenOfDisplay (d, i); break; } } } if ( rootX == prevRootX && rootY == prevRootY && mask == prevMask) { /* * If the pointer has not moved since the previous call and * is inside one of the 4 corners, we act according to the * contents of the "corners" array. * * If rootX and rootY are less than zero, don't lock even if * ca_forceLock is set in the upper-left corner. Why? 'cause * on initial server startup, if (and only if) the pointer is * never moved, XQueryPointer() can return values less than * zero (only some servers, Openwindows 2.0 and 3.0 in * particular). */ if ( (corner = 0, rootX <= cornerSize && rootX >= 0 && rootY <= cornerSize && rootY >= 0) || (corner++, rootX >= WidthOfScreen (screen) - cornerSize - 1 && rootY <= cornerSize) || (corner++, rootX <= cornerSize && rootY >= HeightOfScreen (screen) - cornerSize - 1) || (corner++, rootX >= WidthOfScreen (screen) - cornerSize - 1 && rootY >= HeightOfScreen (screen) - cornerSize - 1)) { now = time (0); switch (corners[corner]) { case ca_forceLock: newTrigger = now + (useRedelay ? cornerRedelay : cornerDelay) - 1; if (newTrigger < lockTrigger) { setLockTrigger (newTrigger - now); } break; case ca_dontLock: resetTriggers (); #ifdef __GNUC__ default: break; /* Makes gcc -Wall shut up. */ #endif /* __GNUC__ */ } } } else { useRedelay = False; prevRootX = rootX; prevRootY = rootY; prevMask = mask; resetTriggers (); } } /* * Support for deciding whether to lock or kill. */ void evaluateTriggers (Display* d) { static time_t prevNotification = 0; time_t now = 0; /* * Obvious things first. * * The triggers are being moved all the time while in disabled * mode in order to make absolutely sure we cannot run into * trouble by an enable message coming in at an odd moment. * Otherwise we possibly might lock or kill too soon. */ if (disabled) { resetTriggers (); } /* * Next, wait for (or kill, if we were so told) the previous * locker (if any). Note that this must also be done while in * disabled mode. Not only to avoid a potential zombie proces * hanging around until we are re-enabled, but also to prevent * us from incorrectly setting a kill trigger at the moment * when we are finally re-enabled. */ #ifdef VMS if (vmsStatus == 0) { #else /* VMS */ if (lockerPid) { #if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) union wait status; /* childs process status */ #else /* !UTEKV && !SYSV && !SVR4 */ int status = 0; /* childs process status */ #endif /* !UTEKV && !SYSV && !SVR4 */ if (unlockNow && !disabled) { (void) kill (lockerPid, SIGTERM); } #if !defined (UTEKV) && !defined (SYSV) && !defined (SVR4) if (wait3 (&status, WNOHANG, 0)) #else /* !UTEKV && !SYSV && !SVR4 */ if (waitpid (-1, &status, WNOHANG)) #endif /* !UTEKV && !SYSV && !SVR4 */ { /* * If the locker exited normally, we disable any pending kill * trigger. Otherwise, we assume that it either has crashed or * was not able to lock the display because of an existing * locker (which may have been started manually). In both of * the later cases, disabling the kill trigger would open a * loop hole. */ if ( WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) { disableKillTrigger (); } useRedelay = True; lockerPid = 0; } #endif /* VMS */ setLockTrigger (lockTime); /* * No return here! The pointer may be sitting in a corner, while * parameter settings may be such that we need to start another * locker without further delay. If you think this cannot happen, * consider the case in which the locker simply crashed. */ } unlockNow = False; /* * Note that the above lot needs to be done even when we're in * disabled mode, since we may have entered said mode with an * active locker around. */ if (disabled) return; /* * Is it time to run the killer command? */ now = time (0); if (killTrigger && now >= killTrigger) { /* * There is a dirty trick here. On the one hand, we don't want * to block until the killer returns, but on the other one * we don't want to have it interfere with the wait() stuff we * do to keep track of the locker. To obtain both, the killer * command has already been patched by KillerChecker() so that * it gets backgrounded by the shell started by system(). * * For the time being, VMS users are out of luck: their xautolock * will indeed block until the killer returns. */ { int dummy; dummy = system (killer); } // Silly gcc... setKillTrigger (killTime); } /* * Now trigger the notifier if required. */ if ( notifyLock && now + notifyMargin >= lockTrigger && prevNotification < now - notifyMargin - 1) { if (notifierSpecified) { /* * Here we use the same dirty trick as for the killer command. */ { int dummy; dummy = system (notifier); } // Silly gcc... } else { (void) XBell (d, bellPercent); (void) XSync (d, 0); } prevNotification = now; } /* * Finally fire up the locker if time has somehow come. */ if ( lockNow || now >= lockTrigger) { #ifdef VMS if (vmsStatus != 0) #else /* VMS */ if (!lockerPid) #endif /* VMS */ { switch (lockerPid = vfork ()) { case -1: lockerPid = 0; break; case 0: (void) close (ConnectionNumber (d)); #ifdef VMS vmsStatus = 0; lockerPid = lib$spawn ((lockNow ? &nowLockerDescr : &lockerDescr), 0, 0, &1, 0, 0, &vmsStatus); if (!(lockerPid & 1)) exit (lockerPid); #ifdef SLOW_VMS (void) sleep (SLOW_VMS_DELAY); #endif /* SLOW_VMS */ #else /* VMS */ (void) execl ("/bin/sh", "/bin/sh", "-c", (lockNow ? nowLocker : locker), (void*) 0); #endif /* VMS */ _exit (EXIT_FAILURE); default: /* * In general xautolock should keep its fingers off the real * screensaver because no universally acceptable policy can * be defined. In no case should it decide to disable or enable * it all by itself. Setting the screensaver policy is something * the locker should take care of. After all, xautolock is not * supposed to know what the "locker" does and doesn't do. * People might be using xautolock for totally different * purposes (which, by the way, is why it will accept a * different set of X resources after being renamed). * * Nevertheless, simply resetting the screensaver is a * convenience action that aids many xlock users, and doesn't * harm anyone (*). The problem with older versions of xlock * is that they can be told to replace (= disable) the real * screensaver, but forget to reset that same screensaver if * it was already active at the time xlock starts. I guess * xlock initially wasn't designed to be run without a user * actually typing the comand ;-). * * (*) Well, at least it used not to harm anyone, but with the * advent of DPMS monitors, it now can mess up the power * saving setup. Hence we better make it optional. * * Also, some xlock versions also unconditionally call * XResetScreenSaver, yielding the same kind of problems * with DPMS that xautolock did. The latest and greatest * xlocks also have a -resetsaver option for this very * reason. You may want to upgrade. */ if (resetSaver) (void) XResetScreenSaver(d); setLockTrigger (lockTime); (void) XSync (d,0); } /* * Once the locker is running, all that needs to be done is to * set the killTrigger if needed. Notice that this must be done * even if we actually failed to start the locker. Otherwise * the error would "propagate" from one feature to another. */ if (killerSpecified) setKillTrigger (killTime); useRedelay = False; } lockNow = False; } } xautolock-2.2/src/state.c0000600000175100017500000000440310700012606013515 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It implements * everything needed to keep track of the program's state. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #include "state.h" #include "miscutil.h" const char* progName = 0; /* our own name */ char** argArray = 0; /* our command line arguments */ unsigned nofArgs = 0; /* number of command line arguments */ Bool disabled = False; /* whether to ignore all timeouts */ Bool lockNow = False; /* whether to lock immediately */ Bool unlockNow = False; /* whether to unlock immediately */ time_t lockTrigger = 0; /* time at which to invoke the locker */ time_t killTrigger = 0; /* time at which to invoke the killer */ pid_t lockerPid = 0; /* process id of the current locker */ /* * Please have a guess what this is for... :-) */ void initState (int argc, char* argv[]) { int i = 0; char* ptr; /* * Beautify argv[0] and remember it for later use. Also remember * the complete set of arguments just in case we're asked to * restart ourselves later on. */ argArray = newArray (char*, argc + 1); while (argv[i]) { argArray[i] = strdup (argv[i]); ++i; } argArray[i] = 0; #ifdef VMS if (ptr = strrchr (argv[0], ']')) { progName = ptr + 1; } else { progName = argv[0]; } if ((ptr = strchr (progName, '.'))) /* = intended */ { *ptr = '\0'; } #else /* VMS */ if ((ptr = strrchr (argv[0], '/'))) /* = intended */ { progName = ptr + 1; } else { progName = argv[0]; } #endif /* VMS */ } xautolock-2.2/src/diy.c0000600000175100017500000001454610700012576013201 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It implements * the stuff used when the program is not using a screen saver * extension and thus has to use the good old "do it yourself" * approach for detecting user activity. * * The basic idea is that we initially traverse the window tree, * selecting SubstructureNotify on all windows and adding each * window to a temporary list. About +- 30 seconds later, we * scan this list, now asking for KeyPress events. The delay * is needed in order to interfere as little as possible with * the event propagation mechanism. Whenever a new window is * created by an application, a similar process takes place. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #include "diy.h" #include "state.h" #include "options.h" #include "miscutil.h" static void selectEvents (Window window, Bool substructureOnly); /* * Window queue management. */ typedef struct item { Window window; time_t creationtime; struct item* next; } anItem, *item; static struct { Display* display; struct item* head; struct item* tail; } queue; static void addToQueue (Window window) { item newItem = newObj (anItem); newItem->window = window; newItem->creationtime = time (0); newItem->next = 0; if (!queue.head) queue.head = newItem; if ( queue.tail) queue.tail->next = newItem; queue.tail = newItem; } static void processQueue (time_t age) { if (queue.head) { time_t now = time (0); item current = queue.head; while (current && current->creationtime + age < now) { selectEvents (current->window, False); queue.head = current->next; free (current); current = queue.head; } if (!queue.head) queue.tail = 0; } } /* * Function for selecting all interesting events on a given * (tree of) window(s). */ static void selectEvents (Window window, Bool substructureOnly) { Window root; /* root window of the window */ Window parent; /* parent of the window */ Window* children; /* children of the window */ unsigned nofChildren = 0; /* number of children */ unsigned i; /* loop counter */ XWindowAttributes attribs; /* attributes of the window */ /* * Start by querying the server about the root and parent windows. */ if (!XQueryTree (queue.display, window, &root, &parent, &children, &nofChildren)) { return; } if (nofChildren) (void) XFree ((char*) children); /* * Build the appropriate event mask. The basic idea is that we don't * want to interfere with the normal event propagation mechanism if * we don't have to. * * On the root window, we need to ask for both substructureNotify * and KeyPress events. On all other windows, we always need * substructureNotify, but only need Keypress if some other client * also asked for them, or if they are not being propagated up the * window tree. */ if (substructureOnly) { (void) XSelectInput (queue.display, window, SubstructureNotifyMask); } else { if (parent == None) /* the *real* rootwindow */ { attribs.all_event_masks = attribs.do_not_propagate_mask = KeyPressMask; } else if (!XGetWindowAttributes (queue.display, window, &attribs)) { return; } (void) XSelectInput (queue.display, window, SubstructureNotifyMask | ( ( attribs.all_event_masks | attribs.do_not_propagate_mask) & KeyPressMask)); } /* * Now ask for the list of children again, since it might have changed * in between the last time and us selecting SubstructureNotifyMask. * * There is a (very small) chance that we might process a subtree twice: * child windows that have been created after our XSelectinput() has * been processed but before we get to the XQueryTree() bit will be * in this situation. This is harmless. It could be avoided by using * XGrabServer(), but that'd be an impolite thing to do, and since it * isn't required... */ if (!XQueryTree (queue.display, window, &root, &parent, &children, &nofChildren)) { return; } /* * Now do the same thing for all children. */ for (i = 0; i < nofChildren; ++i) { selectEvents (children[i], substructureOnly); } if (nofChildren) (void) XFree ((char*) children); } /* * Function for processing any events that have come in since * last time. It is crucial that this function does not block * in case nothing interesting happened. */ void processEvents (void) { while (XPending (queue.display)) { XEvent event; if (XCheckMaskEvent (queue.display, SubstructureNotifyMask, &event)) { if (event.type == CreateNotify) { addToQueue (event.xcreatewindow.window); } } else { (void) XNextEvent (queue.display, &event); } /* * Reset the triggers if and only if the event is a * KeyPress event *and* was not generated by XSendEvent(). */ if ( event.type == KeyPress && !event.xany.send_event) { resetTriggers (); } } /* * Check the window queue for entries that are older than * CREATION_DELAY seconds. */ processQueue ((time_t) CREATION_DELAY); } /* * Function for initialising the whole shebang. */ void initDiy (Display* d) { int s; queue.display = d; queue.tail = 0; queue.head = 0; for (s = -1; ++s < ScreenCount (d); ) { Window root = RootWindowOfScreen (ScreenOfDisplay (d, s)); addToQueue (root); selectEvents (root, True); } } xautolock-2.2/src/xautolock.c0000600000175100017500000001030610700012612014402 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) + Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It implements * the program's main() function as well as some boring X related * chit-chat. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #include "config.h" #include "options.h" #include "state.h" #include "miscutil.h" #include "diy.h" #include "message.h" #include "engine.h" /* * X error handler. We can safely ignore everything * here (mainly windows that die before we get even * see them). */ static int catchFalseAlarm (Display* d, XErrorEvent event) { return 0; } /* * X extension finding support. */ #if defined (HasXidle) || defined (HasScreenSaver) #ifndef DEBUG #define queryExtension(name,useIt) \ { \ int dummy; \ useIt = name##QueryExtension (d, &dummy, &dummy); \ } #endif /* DEBUG */ #endif /* HasXidle || HasScreenSaver */ /* * Window manager related stuff. */ static void wmSetup (Display* d) { /* * Get ourselves a dummy window in order to allow display and/or * session managers etc. to use XKillClient() on us (e.g. xdm when * not using XDMCP). * * I'm not sure whether the window needs to be mapped for xdm, but * the default setup Sun uses for OpenWindows and olwm definitely * requires it to be mapped. * * If we're doing all this anyway, we might as well set the correct * WM properties on the window as a convenience. */ Window ourWin; XTextProperty nameProp; XClassHint* classInfo; XSetWindowAttributes attribs; attribs.override_redirect = True; ourWin = XCreateWindow (d, DefaultRootWindow (d), -1, -1, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, CWOverrideRedirect, &attribs); classInfo = XAllocClassHint (); classInfo->res_class = APPLIC_CLASS; (void) XStringListToTextProperty (argArray, 1, &nameProp); XSetWMProperties (d, ourWin, &nameProp, (XTextProperty*) 0, argArray, nofArgs, (XSizeHints*) 0, (XWMHints*) 0, classInfo); (void) XFree (nameProp.value); (void) XFree (classInfo); (void) XMapWindow (d, ourWin); } /* * Combat control. */ int main (int argc, char* argv[]) { Display* d; time_t t0, t1; Bool useMit = False; Bool useXidle = False; /* * Find out whether there actually is a server on the other side... */ if (!(d = XOpenDisplay (0))) /* = intended */ { error1 ("Couldn't connect to %s\n", XDisplayName (0)); exit (EXIT_FAILURE); } /* * More initialisations. */ initState (argc, argv); processOpts (d, argc, argv); wmSetup (d); checkConnectionAndSendMessage (d); resetTriggers (); if (!noCloseOut) (void) fclose (stdout); if (!noCloseErr) (void) fclose (stderr); #ifdef HasXidle queryExtension (Xidle, useXidle) #endif /* HasXidle */ #ifdef HasScreenSaver if (!useXidle) queryExtension (XScreenSaver, useMit) #endif /* HasScreenSaver */ if (!useXidle && !useMit) initDiy (d); (void) XSetErrorHandler ((XErrorHandler) catchFalseAlarm); (void) XSync (d, 0); t0 = time (NULL); /* * Main event loop. */ for (;;) { lookForMessages (d); if (useXidle || useMit) { queryIdleTime (d, useXidle); } else { processEvents (); } queryPointer (d); evaluateTriggers (d); (void) sleep (1); if (detectSleep) { t1 = time (NULL); if ((unsigned long) t1 - (unsigned long) t0 > 3) resetLockTrigger (); t0 = t1; } } return 0; /* Never reached! */ } xautolock-2.2/src/options.c0000600000175100017500000006303410700012605014074 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) + Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It implements * all option and X resource processing support. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #include "options.h" #include "state.h" #include "miscutil.h" #include "version.h" /* * Global option settings. Do not modify outside this file. */ const char* locker = LOCKER; /* as it says */ const char* nowLocker = LOCKER; /* as it says */ const char* notifier = NOTIFIER; /* as it says */ const char* killer = KILLER; /* as it says */ time_t lockTime = LOCK_MINS; /* as it says */ time_t killTime = KILL_MINS; /* as it says */ time_t notifyMargin; /* as it says */ Bool secure = SECURE; /* as it says */ int bellPercent = BELL_PERCENT; /* as it says */ unsigned cornerSize = CORNER_SIZE; /* as it says */ time_t cornerDelay = CORNER_DELAY; /* as it says */ time_t cornerRedelay; /* as it says */ Bool notifyLock = False; /* whether to notify the user before locking */ Bool useRedelay = False; /* as it says */ cornerAction corners[4] = { ca_ignore, ca_ignore, ca_ignore, ca_ignore }; /* default cornerActions */ Bool resetSaver = False; /* whether to reset the X screensaver */ Bool noCloseOut = False; /* whether keep stdout open */ Bool noCloseErr = False; /* whether keep stderr open */ message messageToSend = msg_none; /* message to send to an already running xautolock */ Bool detectSleep = False; /* whether to reset the timers after a (laptop) sleep, i.e. after a big time jump */ #ifdef VMS struct dsc$descriptor lockerDescr; /* used to fire up the locker */ struct dsc$descriptor nowLockerDescr; /* used to fire up the locker */ int vmsStatus = 1; /* locker completion status */ #endif /* VMS */ Bool notifierSpecified = False; Bool killerSpecified = False; /* * Guess what, these are private. */ static Bool killTimeSpecified = False; static Bool redelaySpecified = False; static Bool bellSpecified = False; static Bool dummySpecified; static void usage (int exitCode); /* * Argument scanning support. */ static Bool getInteger (const char* arg, int* in) { char c; /* dummy */ return (sscanf (arg, "%d%c", in, &c) == 1); } static Bool getPositive (const char* arg, int* pos) { return getInteger (arg, pos) && *pos >= 0; } /* * Option action functions */ static Bool helpAction (Display* d, const char* arg) { usage (EXIT_SUCCESS); return True; /* keep gcc happy */ } static Bool versionAction (Display* d, const char* arg) { error2 ("%s : version %s\n", progName, VERSION); exit (EXIT_SUCCESS); return True; /* keep gcc happy */ } static Bool lockerAction (Display* d, const char* arg) { nowLocker = locker = arg; return True; } static Bool nowLockerAction (Display* d, const char* arg) { nowLocker = arg; return True; } static Bool killerAction (Display* d, const char* arg) { killerSpecified = True; killer = arg; return True; } static Bool notifierAction (Display* d, const char* arg) { notifierSpecified = True; notifier = arg; return True; } static Bool bellAction (Display* d, const char* arg) { bellSpecified = True; return getInteger (arg, &bellPercent); } static Bool cornerSizeAction (Display* d, const char* arg) { Bool retVal; int tmp; if ((retVal = getPositive (arg, &tmp))) /* = intended */ { cornerSize = tmp; } return retVal; } static Bool cornersAction (Display* d, const char* arg) { int c; if (strlen (arg) != 4) return False; for (c = -1; ++c < 4; ) { switch (arg[c]) { case '0': corners[c] = ca_ignore; continue; case '-': corners[c] = ca_dontLock; continue; case '+': corners[c] = ca_forceLock; continue; default: return False; } } return True; } #define TIME_ACTION(name,nameSpecified) \ static Bool \ name##Action (Display* d, const char* arg) \ { \ Bool retVal; \ int tmp = 0; \ \ if ((retVal = getPositive (arg, &tmp))) /* = intended */ \ { \ name = (time_t) tmp; \ } \ \ nameSpecified = True; \ return retVal; \ } \ TIME_ACTION (lockTime , dummySpecified ) TIME_ACTION (killTime , killTimeSpecified) TIME_ACTION (cornerDelay , dummySpecified ) TIME_ACTION (cornerRedelay, redelaySpecified ) TIME_ACTION (notifyMargin , notifyLock ) #define notifyAction notifyMarginAction #define MESSAGE_ACTION(name) \ static Bool \ name##Action (Display* d, const char* arg) \ { \ if (messageToSend) return False; \ messageToSend = msg_##name; \ return True; \ } MESSAGE_ACTION (disable ) MESSAGE_ACTION (enable ) MESSAGE_ACTION (toggle ) MESSAGE_ACTION (exit ) MESSAGE_ACTION (lockNow ) MESSAGE_ACTION (unlockNow) MESSAGE_ACTION (restart ) #define BOOL_ACTION(name) \ static Bool \ name##Action (Display* d, const char* arg) \ { \ return name = True; \ } BOOL_ACTION (secure ) BOOL_ACTION (resetSaver) BOOL_ACTION (noCloseOut) BOOL_ACTION (noCloseErr) BOOL_ACTION (detectSleep) static Bool noCloseAction (Display* d, const char* arg) { (void) noCloseOutAction (d, arg); (void) noCloseErrAction (d, arg); return True; } /* * Option checking logistics. */ #ifndef VMS static void addExecToCommand (const char** command) { /* * On UNIX systems, we dont want to have an extra shell process * hanging about all the time while the locker is running, so we * want to insert an `exec' in front of the command. But since * this obviuosly would fail to work correctly if the command * actually consists of multiple ones, we need to look for `;' * characters first. We can only err on the safe side here... */ if (!strchr (*command, ';')) { char* tmp; (void) sprintf (tmp = newArray (char, strlen (*command) + 6), "exec %s", *command); *command = tmp; } } #endif /* !VMS */ static void lockTimeChecker (Display* d) { if (lockTime < MIN_LOCK_MINS) { error1 ("Setting lock time to minimum value of %ld minute(s).\n", (long) (lockTime = MIN_LOCK_MINS)); } else if (lockTime > MAX_LOCK_MINS) { error1 ("Setting lock time to maximum value of %ld minute(s).\n", (long) (lockTime = MAX_LOCK_MINS)); } lockTime *= 60; /* convert to seconds */ } static void killTimeChecker (Display* d) { if (killTimeSpecified && !killerSpecified) { error0 ("Using -killtime without -killer makes no sense.\n"); return; } if (killTime < MIN_KILL_MINS) { error1 ("Setting kill time to minimum value of %ld minute(s).\n", (long) (killTime = MIN_KILL_MINS)); } else if (killTime > MAX_KILL_MINS) { error1 ("Setting kill time to maximum value of %ld minute(s).\n", (long) (killTime = MAX_KILL_MINS)); } killTime *= 60; /* convert to seconds */ } static void lockerChecker (Display* d) { #ifndef VMS addExecToCommand (&locker); #else /* VMS */ /* * Translate things to something that VMS knows how to handle. */ lockerDescr.dsc$w_length = (unsigned short) strlen (locker); lockerDescr.dsc$b_class = DSC$K_CLASS_S; lockerDescr.dsc$b_dtype = DSC$K_DTYPE_T; lockerDescr.dsc$a_pointer = (char*) locker; #endif /* VMS */ } static void nowLockerChecker (Display* d) { #ifndef VMS addExecToCommand (&nowLocker); #else /* VMS */ /* * Translate things to something that VMS knows how to handle. */ nowLockerDescr.dsc$w_length = (unsigned short) strlen (now_locker); nowLockerDescr.dsc$b_class = DSC$K_CLASS_S; nowLockerDescr.dsc$b_dtype = DSC$K_DTYPE_T; nowLockerDescr.dsc$a_pointer = (char*) nowLocker; #endif /* VMS */ } static void notifierChecker (Display* d) { if (strcmp (notifier, "")) { if (!notifyLock) { error0 ("Using -notifier without -notify makes no sense.\n"); } #ifndef VMS else { /* * Add an `&' to the notifier command, so that it always gets * run as a background process and things will work out properly * later. The rationale behind this hack is explained elsewhere. */ char* tmp; (void) sprintf (tmp = newArray (char, strlen (notifier) + 3), "%s &", notifier); notifier = tmp; } #endif /* !VMS */ } } static void killerChecker (Display* d) { #ifndef VMS if (strcmp (killer, "")) { /* * Add an `&' to the killer command, so that it always gets * run as a background process and things will work out properly * later. The rationale behind this hack is explained elsewhere. */ char* tmp; (void) sprintf (tmp = newArray (char, strlen (killer) + 3), "%s &", killer); killer = tmp; } #endif /* !VMS */ } static void notifyChecker (Display* d) { if ( notifyLock && ( corners[0] == ca_forceLock || corners[1] == ca_forceLock || corners[2] == ca_forceLock || corners[3] == ca_forceLock)) { time_t minDelay = MIN (cornerDelay, cornerRedelay); if (notifyMargin > minDelay) { error1 ("Notification time reset to %ld second(s).\n", (long) (notifyMargin = minDelay)); } if (notifyMargin > lockTime / 2) { error1 ("Notification time reset to %ld seconds.\n", (long) (notifyMargin = lockTime / 2)); } } } static void bellChecker (Display* d) { if (bellSpecified) { if (!notifyLock) { error0 ("Using -bell without -notify makes no sense.\n"); bellPercent = 0; } else if (notifierSpecified) { error0 ("Using both -bell and -notifier makes no sense.\n"); bellPercent = 0; } } if ( bellPercent < -100 || bellPercent > 100) { error1 ("Bell percentage reset to %d%%.\n", bellPercent = BELL_PERCENT); } } static void cornerSizeChecker (Display* d) { int s; Screen* scr; int maxCornerSize; for (maxCornerSize = 32000, s = -1; ++s < ScreenCount (d); ) { scr = ScreenOfDisplay (d, s); if ( maxCornerSize > WidthOfScreen (scr) / 4 || maxCornerSize > HeightOfScreen (scr) / 4) { maxCornerSize = MIN (WidthOfScreen (scr), HeightOfScreen (scr)) / 4; } } if (cornerSize > maxCornerSize) { error1 ("Corner size reset to %d pixels.\n", cornerSize = maxCornerSize); } } static void cornerReDelayChecker (Display* d) { if (!redelaySpecified) { cornerRedelay = cornerDelay; } } /* * The central option table. */ typedef Bool (*optAction) (Display*, const char*); typedef void (*optChecker) (Display*); static struct { const char* name; /* as it says */ XrmOptionKind kind; /* as it says */ caddr_t value; /* only for XrmOptionNoArg */ optAction action; /* as it says */ optChecker checker; /* as it says */ } options[] = { {"help" , XrmoptionNoArg , (caddr_t) "", helpAction , (optChecker) 0 }, {"version" , XrmoptionNoArg , (caddr_t) "", versionAction , (optChecker) 0 }, {"locker" , XrmoptionSepArg, (caddr_t) 0 , lockerAction , lockerChecker }, {"nowlocker" , XrmoptionSepArg, (caddr_t) 0 , nowLockerAction , nowLockerChecker }, {"killer" , XrmoptionSepArg, (caddr_t) 0 , killerAction , killerChecker }, {"notifier" , XrmoptionSepArg, (caddr_t) 0 , notifierAction , notifierChecker }, {"corners" , XrmoptionSepArg, (caddr_t) 0 , cornersAction , (optChecker) 0 }, {"cornersize" , XrmoptionSepArg, (caddr_t) 0 , cornerSizeAction , cornerSizeChecker }, {"cornerdelay" , XrmoptionSepArg, (caddr_t) 0 , cornerDelayAction , (optChecker) 0 }, {"cornerredelay" , XrmoptionSepArg, (caddr_t) 0 , cornerRedelayAction, cornerReDelayChecker }, {"killtime" , XrmoptionSepArg, (caddr_t) 0 , killTimeAction , killTimeChecker }, {"time" , XrmoptionSepArg, (caddr_t) 0 , lockTimeAction , lockTimeChecker }, {"notify" , XrmoptionSepArg, (caddr_t) 0 , notifyAction , notifyChecker }, {"bell" , XrmoptionSepArg, (caddr_t) 0 , bellAction , bellChecker }, {"secure" , XrmoptionNoArg , (caddr_t) "", secureAction , (optChecker) 0 }, {"enable" , XrmoptionNoArg , (caddr_t) "", enableAction , (optChecker) 0 }, {"disable" , XrmoptionNoArg , (caddr_t) "", disableAction , (optChecker) 0 }, {"toggle" , XrmoptionNoArg , (caddr_t) "", toggleAction , (optChecker) 0 }, {"exit" , XrmoptionNoArg , (caddr_t) "", exitAction , (optChecker) 0 }, {"locknow" , XrmoptionNoArg , (caddr_t) "", lockNowAction , (optChecker) 0 }, {"unlocknow" , XrmoptionNoArg , (caddr_t) "", unlockNowAction , (optChecker) 0 }, {"restart" , XrmoptionNoArg , (caddr_t) "", restartAction , (optChecker) 0 }, {"resetsaver" , XrmoptionNoArg , (caddr_t) "", resetSaverAction , (optChecker) 0 }, {"noclose" , XrmoptionNoArg , (caddr_t) "", noCloseAction , (optChecker) 0 }, {"nocloseout" , XrmoptionNoArg , (caddr_t) "", noCloseOutAction , (optChecker) 0 }, {"nocloseerr" , XrmoptionNoArg , (caddr_t) "", noCloseErrAction , (optChecker) 0 }, {"detectsleep" , XrmoptionNoArg , (caddr_t) "", detectSleepAction , (optChecker) 0 }, }; /* as it says, the order is important! */ /* * Have a guess... */ static void usage (int exitCode) { /* * The relative overhead is enormous here, but who cares. * I'm a perfectionist and usage() doesn't return anyway. */ char* blanks; /* string full of blanks */ size_t len; /* number of blanks */ len = strlen ("Usage : ") + strlen (progName); (void) memset (blanks = newArray (char, len + 1), ' ', len); blanks[len] = '\0'; /* * This is where the actual work gets done... */ error0 ("\n"); error1 ("Usage : %s ", progName); error0 ("[-help][-version][-time mins][-locker locker]\n"); error1 ("%s[-killtime mins][-killer killer]\n", blanks); error1 ("%s[-notify margin][-notifier notifier][-bell percent]\n", blanks); error1 ("%s[-corners xxxx][-cornerdelay secs]\n", blanks); error1 ("%s[-cornerredelay secs][-cornersize pixels]\n", blanks); error1 ("%s[-nocloseout][-nocloseerr][-noclose]\n", blanks); error1 ("%s[-enable][-disable][-toggle][-exit][-secure]\n", blanks); error1 ("%s[-locknow][-unlocknow][-nowlocker locker]\n", blanks); error1 ("%s[-restart][-resetsaver][-detectsleep]\n", blanks); error0 ("\n"); error0 (" -help : print this message and exit.\n"); error0 (" -version : print version number and exit.\n"); error0 (" -time mins : time before locking the screen"); error2 (" [%d <= mins <= %d].\n", MIN_LOCK_MINS, MAX_LOCK_MINS); error0 (" -locker locker : program used to lock.\n"); error0 (" -nowlocker locker : program used to lock immediately.\n"); error0 (" -killtime killmins : time after locking at which to run\n"); error2 (" the killer [%d <= killmins <= %d].\n", MIN_KILL_MINS, MAX_KILL_MINS); error0 (" -killer killer : program used to kill.\n"); error0 (" -notify margin : notify this many seconds before locking.\n"); error0 (" -notifier notifier : program used to notify.\n"); error0 (" -bell percent : loudness of notification beeps.\n"); error0 (" -corners xxxx : corner actions (0, +, -) in this order:\n"); error0 (" topleft topright bottomleft bottomright\n"); error0 (" -cornerdelay secs : time to lock screen in a `+' corner.\n"); error0 (" -cornerredelay secs : time to relock screen in a `+' corner.\n"); error0 (" -cornersize pixels : size of corner areas.\n"); error0 (" -nocloseout : do not close stdout.\n"); error0 (" -nocloseerr : do not close stderr.\n"); error0 (" -noclose : close neither stdout nor stderr.\n"); error0 (" -enable : enable a running xautolock.\n"); error0 (" -disable : disable a running xautolock.\n"); error0 (" -toggle : toggle a running xautolock.\n"); error0 (" -locknow : tell a running xautolock to lock.\n"); error0 (" -unlocknow : tell a running xautolock to unlock.\n"); error0 (" -restart : tell a running xautolock to restart.\n"); error0 (" -exit : kill a running xautolock.\n"); error0 (" -secure : ignore enable, disable, toggle, locknow\n"); error0 (" unlocknow, and restart messages.\n"); error0 (" -resetsaver : reset the screensaver when starting " "the locker.\n"); error0 (" -detectsleep : reset timers when awaking from sleep.\n"); error0 ("\n"); error0 ("Defaults :\n"); error0 ("\n"); error1 (" time : %d minutes\n" , LOCK_MINS ); error1 (" locker : %s\n" , LOCKER ); error1 (" nowlocker : %s\n" , LOCKER ); error1 (" killtime : %d minutes\n" , KILL_MINS ); error0 (" killer : none\n" ); error0 (" notify : don't notify\n" ); error0 (" notifier : none\n" ); error1 (" bell : %d%%\n" , BELL_PERCENT); error0 (" corners : 0000\n" ); error1 (" cornerdelay : %d seconds\n" , CORNER_DELAY); error1 (" cornerredelay : %d seconds\n" , CORNER_DELAY); error1 (" cornersize : %d pixels\n" , CORNER_SIZE ); error0 ("\n"); error1 ("Version : %s\n", VERSION); error0 ("\n"); exit (exitCode); } /* * Public interface to the above lot. */ void processOpts (Display* d, int argc, char* argv[]) { int nofOptions = sizeof (options) / sizeof (options[0]); /* number of supported options */ int j; /* loop counter */ unsigned l; /* temporary storage */ unsigned maxLen; /* temporary storage */ char* dummy; /* as it says */ char* fullname; /* full resource name */ char* str; /* temporary storage */ XrmValue value; /* resource value container */ XrmOptionDescList xoptions; /* optionslist in Xlib format */ XrmDatabase rescDb = (XrmDatabase) 0; /* resource file database */ XrmDatabase cmdlDb = (XrmDatabase) 0; /* command line options database */ /* * Collect defaults from various places except the command line into one * resource database, then parse the command line options into an other. * Both databases are not merged, because we want to know where exactly * each resource value came from. * * One day I might extend this stuff to fully cover *all* possible * resource value sources, but... One of the problems is that various * pieces of documentation make conflicting claims with respect to the * proper order in which resource value sources should be accessed. */ XrmInitialize (); if (XResourceManagerString (d)) { XrmMergeDatabases (XrmGetStringDatabase (XResourceManagerString (d)), &rescDb); } else if ((str = getenv ("XENVIRONMENT"))) /* = intended */ { XrmMergeDatabases (XrmGetFileDatabase (str), &rescDb); } #if defined (ReadXdefaultsFile) && !defined (VMS) else { /* * In general, the following is a not a good idea. Who is to say that * the user's .Xdefaults file matches the screen being used? And who * says we shouldn't run the file through cpp first? Using which * options, by the way? * * Fortunately, chances are pretty small that anyone will actually run * xautolock remotely. And even if someone does, the same .Xdefaults * file will most likely be involved on both sides of the link. Also, * we only do this of we failed to get our resources from the standard * places. People who have .Xdefaults files that need to be fed to cpp, * will run the appropriate xrdb command on login anyway, such that we * never get here. * * Having said that, I'm only keeping this stuff around because of the * desire to be backward compatible for those who originally convinced * me to include it, or who since became to depend on it. If I could * live my life over again, this wouldn't get added in the first place. */ XrmDatabase Xdefaults; struct passwd *passwd; const char* home; char* path; passwd = getpwuid (getuid ()); if (passwd) { home = passwd->pw_dir; } else { home = getenv ("HOME"); if (!home) home = "."; } path = newArray (char, strlen (home) + strlen ("/.Xdefaults") + 1); (void) sprintf (path, "%s/.Xdefaults", home); Xdefaults = XrmGetFileDatabase (path); if (Xdefaults) XrmMergeDatabases (Xdefaults, &rescDb); free (path); } #endif /* ReadXdefaultsFile && !VMS */ xoptions = newArray (XrmOptionDescRec, nofOptions); for (j = -1, maxLen = 0; ++j < nofOptions; ) { l = strlen (options[j].name) + 1; maxLen = MAX (maxLen, l); (void) sprintf (xoptions[j].option = newArray (char, l + 1), "-%s", options[j].name); (void) sprintf (xoptions[j].specifier = newArray (char, l + 1), ".%s", options[j].name); xoptions[j].argKind = options[j].kind; xoptions[j].value = options[j].value; } XrmParseCommand (&cmdlDb, xoptions, nofOptions, progName, &argc, argv); if (--argc) usage (EXIT_FAILURE); /* * Let's be perfect... */ { unsigned classLen = strlen (APPLIC_CLASS); unsigned progLen = strlen (progName); fullname = newArray (char, MAX (progLen, classLen) + maxLen + 1); } /* * Call the action functions. */ for (j = -1; ++j < nofOptions; ) { (void) sprintf (fullname, "%s%s", progName, xoptions[j].specifier); if ( XrmGetResource (cmdlDb, fullname, DUMMY_RES_CLASS, &dummy, &value) == True) { if (!(*(options[j].action)) (d, value.addr)) { usage (EXIT_FAILURE); } } else if ( XrmGetResource (rescDb, fullname, DUMMY_RES_CLASS, &dummy, &value) == True) { if (!(*(options[j].action)) (d, value.addr)) { error2 ("Can't interprete \"%s\" for \"%s\", using default.\n", value.addr, fullname); } } else { (void) sprintf (fullname, "%s%s", APPLIC_CLASS, xoptions[j].specifier); if ( ( XrmGetResource (rescDb, fullname, DUMMY_RES_CLASS, &dummy, &value) == True) && !(*(options[j].action)) (d, value.addr)) { error2 ("Can't interprete \"%s\" for \"%s\", using default.\n", value.addr, fullname); } } } /* * Call the consistency checkers. */ for (j = -1; ++j < nofOptions; ) { if (options[j].checker != (optChecker) NULL) { (*(options[j].checker)) (d); } } /* * General clean up. */ XrmDestroyDatabase (cmdlDb); XrmDestroyDatabase (rescDb); for (j = -1; ++j < nofOptions; ) { free (xoptions[j].option); free (xoptions[j].specifier); } free (xoptions); free (fullname); } xautolock-2.2/Todo0000600000175100017500000000164507275256671012330 0ustar mcemce The slowly but ever growing list of things to do and things not to ------------------------------------------------------------------ These will definitely be done: Someday in the future I'll look into these: - Add support for the -display option. - Add a killer notification to go with -killpid? - Get the resource management to work properly (no more dummy resource class and addition of a proper application defaults file). - Consider introducing the techniques used by XSpy. - Reintroduce (an updated version of) the idlefile patch that used to sit in the contrib directory during the final 1.x releases. Probably never: - Consider adding the -9to5 option suggested by Andrew Miller (amiller@equity.fbc.com) to not lock during working hours. It's a valid addition in some environments, but adding it to the "base system" would probably be a case of featuritis. - Allow logging duration of inactivity? xautolock-2.2/Readme0000600000175100017500000002132610735226752012606 0ustar mcemce PURPOSE ======= Xautolock monitors console activity under the X window system, and fires up a program of your choice if nothing happens during a user configurable period of time. You can use this to automatically start up a screen locker in case you tend to forget to do so manually before having a coffee break. Xautolock will typically be used to lock the screen but it really doesn't care what program you make it start. The only real assumption made by xautolock is that a new countdown starts as soon as the locker exits. WHAT'S NEW ========== Nearly 6 years after the release of version 2.1, version 2.2 fixes a few minor things, but most of all features freshly updated contact information, as I have left my previous employer in 2006. For more details on any of the changes, refre to the Changelog file. HOW TO USE IT ============= Just read the man page, it's really simple. If you're on VMS, you should also check out the VMS.notes file. HOW IT WORKS ============ If xautolock has been compiled to support either the Xidle, or the MIT ScreenSaver extensions (or both), it first tries to find out whether the X server also supports one of them. If it does, xautolock will periodically call it to determine the amount of time elapsed since the last input event, and will then base its actions upon that. In the absence of both extensions, xautolock starts by traversing the window tree, selecting SubstructureNotify on all windows and adding each window to a temporary list. About +- 30 seconds later, it scans this list, asking for KeyPress events. However, it takes care to interfere as little as possible with the event propagation mechanism. This is the reason for the delay between the moment xautolock learns about a new window (and consequently asks for SubstructureNotify events) and the moment it asks for KeyPress events. Whenever a new window is created by an application, a similar process takes place. In contradiction to what many people believe, this scheme does not cause a noticeable overhead. In addition, xautolock periodically issues a QueryPointer request in order to find out whether the pointer has moved and implement the "corners" feature as decribed in the man page. If nothing happens within a user-specified period of time, xautolock will fire up a program which is supposed to lock the screen. While this program is running, xautolock itself remains on the look-out for user interaction. COMPILING XAUTOLOCK =================== Xautolock should compile straight out of the box. Here's the recepy: 1. Edit the Imakefile to your likings. 2. Type: xmkmf make make install make install.man make clean 3. Have fun. If this procedure fails, the most likely reason is the absence of the MIT ScreenSaver extension on your system. If this is the case, simply edit the Imakefile accordingly and try again. If compilation fails because MIT ScreenSaver is not available, do the following: + Find out whether the X server supports it (use the xdpyinfo command for this). Quite often it will, even if the support for compiling programs with it is absent. If this applies to you, nag your sysadmin and/or vendor about it. MIT ScreenSaver is a pretty standard extension that IMHO should be provided with any X based system. + If you cannot find MIT ScreenSaver, repeat the same procedure with Xidle (except for the `nag your vendor' bit). If your server supports Xidle, but you do not have the development files and cannot find them on the web, just send me and e-mail and I will forward you a copy. + If you are still out of luck, use the good old backup mechanism. Xautolock wil be just as happy without server extensions. Nowadays, all modern X servers come with MIT ScreenSaver. However, some (or most/all?) of the HP ones apparently don't, so by default this feature is disabled on HP-UX. Simply edit the Imakefile if you disagree. KNOWN BUGS ========== Important notice: the first two bugs listed here are only present in case xautolock has been compiled with support for neither the Xidle nor the MIT ScreenSaver extensions, or in case the X server being used does not support them. They make up a good reason to get one of these extensions installed. 1. If, when creating a window, an application waits for more than 30 seconds before calling selecting KeyPress events on non-leaf windows, xautolock may interfere with the event propagation mechanism. This effect is theoretical and has never been observed in real life. 2. Xautolock can not properly handle the secure keyboard mode of xterm, since that will prevent any other process, including xautolock, from noticing the keyboard events aimed at the xterm. Consequently, xautolock sometimes will think that there is no keyboard activity while in reality there is. 3. Under some configurations, xautolock fails to exit upon logout. This problem can occur (but does not always do so) under the following combined circumstances: + Xautolock is started in background from within a .xinitrc. + Your are trusting your windowmanager to kill all X processes when quitting (which, by the way, is not a good idea). One well known source of problems in this area consists of olwm and its look-alikes. + The .xinitrc contains a "wait" statement to make it collect all background processes upon logout. The simplest workround for this problem is to start xautolock from within a subshell. I.e. use this: ( xautolock & ) On Solaris an alternative solution (which basically works in exactly the same way) is to use this: toolwait xautolock 4. The -disable, -enable, -toggle, -exit, -locknow, -unlocknow, and -restart options depend on access to the X server to do their work. This implies that they will be suspended in case some other application has grabbed the server all for itself. 5. Xautolock does not check whether the screen locker specified actually is available. 6. The xautolock resources have a dummy resource classes. If you can find others, please notify mce@scarlet.be. Note that, while I still scan most X related newsgroups, I do not actually read them on a regular basis anymore, as X no longer is a part of my job. I do still actively support xautolock on a daily basis, though. Hence you are much more likely to get quick help if you contact me directly. WARNING ======= It looks like there is a bug in the event management code of some X servers (amongst which both X11R4 and X11R5 on older versions of SunOS). If you are using version 1.7 of xautolock (previously known as patchlevel 7), it is best to reset the server before switching to version 1.8 or later. If you fail to do so, an old version 1.7 bug may still show up. (Some keyboard events were being hijacked by version 1.7 of xautolock, particularly when using tvtwm). CONTRIB DIRECTORY ================= The contrib directory may contain various patches that have been contributed over time. If a patch is in there, I have for some reason or another decided not to include it in xautolock proper, but still consider it to be sufficiently usefull to other people in order to add it to the distribution. Note that the contents of the contrib directory are *not* part of xautolock. Each of the contributions lives under its own copyright. In versions 2.1 and 2.2 of xautolock, the contrib directory is empty, since due to a lack of time I did not feel like porting the stuff that used to be in there prior to the 2.x versions. Maybe it'll be back in 2.3 or so. COPYRIGHT ========= Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and Michel Eyckmans. Versions 2.0 and above of xautolock are available under version 2 of the GNU GPL. Earlier versions are available under other conditions. For more information, see the License file. AUTHORS ======= Xautolock was conceived, written, and performed by: Michel Eyckmans (MCE) mce@scarlet.be Stefan De Troch Please send queries for help, feature suggestions, bug reports, etc. to mce@scarlet.be only. ACKNOWLEDGEMENTS ================ Special thanks to: Kris Croes croes@imec.be And the many people who submitted bug reports, patches, suggestions, kudos, etc. No thanks to a certain commercial X server provider who volunteered to beta test version 1.9 on many, *many* platforms but didn't live up to it. Also our apologies to the candidate beta testers who were not retained because of this candidate. xautolock-2.2/License0000600000175100017500000000177007415033320012760 0ustar mcemceXautolock licensing =================== Versions 2.0 and above of xautolock can be modified and/or redistributed under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. Note that this General Public License does not permit incorporating version 2.0 and above of xautolock into programs that are distributed under terms incompatible with those of the GNU General Public License. If this limitation is a problem for you, please consider using the earlier versions 1.7 to 1.15 of xautolock (previously known as "patchlevel 7" to "patchlevel 15"). These earlier versions can be redistributed and/or modified under a simple "for non-commercial use" license. On demand, these earlier versions can also be made available under other conditions on a case by case basis. This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. xautolock-2.2/Imakefile0000600000175100017500000000375407275261552013306 0ustar mcemce/************************************************************************/ /* Imakefile for xautolock. Edit to your likings. */ /************************************************************************/ /* * Tell it what extensions to use. */ #ifndef HPArchitecture #define HasScreenSaver 1 /* By default assume to have MIT ScreenSaver, */ #else #define HasScreenSaver 0 /* except on HP machines (sigh...) */ #endif #define HasXidle 0 /* By default assume not to have Xidle. */ /* * Uncomment the following if you want xautolock to read your * .Xdefaults file as a last resort for getting resource info. * This is not a good idea. For the reason why, see the comment * about it in src/options.c. This is not implemented on VMS. */ /*#define ReadXdefaultsFile */ /************************************************************************/ /* No modifications needed below this line if you're not using Xidle. */ /************************************************************************/ #if HasScreenSaver HASSAVER = -DHasScreenSaver SAVERLIB = $(XSSLIB) DEPSAVERLIB = $(DEPXSSLIB) #endif #if HasXidle HASXIDLE = -DHasXidle /* * Since Xidle is rather rare, I don't know of a generic way to * refer to the required libraries and include files. Users of * xidle will thus have to tweak things by hand here. */ #endif #if HasVFork VFORK = -DHasVFork #endif #ifdef OSF EXTRA_DEFINES = -DSYSV /* Solves wait() problems on DEC OSF/1. */ #endif SRCS = src/diy.c src/options.c src/message.c src/state.c \ src/engine.c src/xautolock.c OBJS = $(SRCS:.c=.o) INCLUDES = -Iinclude LOCAL_LIBRARIES = $(SAVERLIB) $(XLIB) DEPLIBS = $(DEPSAVERLIB) $(DEPXLIB) DEFINES = $(PROTOTYPES) $(VOIDSIGNAL) $(VFORK) \ $(HASXIDLE) $(HASSAVER) .c.o: $(CC) $(CFLAGS) -c $*.c -o $*.o ComplexProgramTarget(xautolock) clean:: $(RM) $(OBJS) distclean:: clean xautolock-2.2/contrib/0000700000175100017500000000000010735227755013124 5ustar mcemcexautolock-2.2/contrib/Readme0000600000175100017500000000134707266676674014270 0ustar mcemce Xautolock contrib directory --------------------------- The contrib directory contains various patches that other people have contributed to xautolock. If a patch is in there, I have for some reason or another decided not to include it in xautolock proper, but consider it to be sufficiently useful to other people in order to still add it to the distribution. Note that the contents of the contrib directory are *not* part of xautolock. Each contribution lives under its own copyright(s). Also note that I do *not* actively support the content of the contrib directory (in contrast to what is the case for xautolock itself). Use at your own risk. MCE --------------------------------------------------------------------- xautolock-2.2/Changelog0000600000175100017500000003760310735227563013306 0ustar mcemce xautolock ========= Authors : Michel Eyckmans (MCE) & Stefan De Troch (SDT) History : - Version 1.0 implemented on 22/07/1990 - Version 1.1 for private use only - Version 1.2 for private use only - Version 1.3 for private use only - Version 1.4 for private use only - Version 1.6 for private use only - Version 1.7 released on 07/04/1992 - Version 1.8 released on 15/05/1992 - Version 1.9 released on 24/01/1995 - Version 1.10 released on 22/02/1995 - Version 1.11 released on 03/11/1997 - Version 1.12 released on 09/08/1998 - Version 1.13 released on 13/08/1998 - Version 1.14 released on 18/11/1998 - Version 1.15 released on 13/03/1999 - Version 2.0 released on 06/05/2001 - Version 2.1 released on 16/01/2002 - Version 2.2 released on 28/12/2007 Review : - 28/12/2007 (MCE) : . Make `gcc -Wall' shut up about irrelevant stuff, even if it's gcc 4.0 we're talking about. - 30/09/2007 (MCE) : . Updated contact information to reflect some turbulent events of 2006. - 08/09/2004 (MCE) : . Make `gcc -Wall' shut up about irrelevant stuff, even if it's gcc 3.4 we're talking about (patch apparently by Pawel Worach ). - 20/04/2004 (MCE) : . Added the `-detectsleep' option (original patch by Cedric Pradalier .) - 12/12/2001 (MCE) : . Made the `-notify' option work again. (Bug reported by Matanya Elchanani .) - 10/09/2001 (MCE) : . Re-ported to OpenVMS. (Once more thanks to Jouk Jansen .) - 05/05/2001 (MCE) : . Disable the reading of $HOME/.Xdefaults files by default. It's a bad idea. Users should always use xrdb to process these. For more information, see the comment in src/options.c. . More general clean up. . Version 2.0 and above are GPL-ed. - 16/04/2001 (MCE) : . Finished the initial 2.0 work by recombining the pieces into a more understandable structure. - 23/03/2001 (MCE) : . Started work on the 2.0 version by finally cutting the big mess into little pieces and ANSIfying them. - 01/11/1999 (MCE) : . Added the "-restart" option. - 02/09/1999 (MCE) : . On UNIX, only prepend the locker commands with `exec' if they actually contain only a single command. (Bug reported by Guenther Grau .) . Removed some old and no longer used VMS cruft. - 01/06/1999 (MCE) : . Ignore any message found during the very first call to LookForMessages(). - 06/04/1999 (MCE) : . Minor improvements to the VMS port. (Again thanks to Jouk Jansen .) - 11/03/1999 (MCE) : . Fixed the communication code to always do the right thing when handling "-exit". - 16/02/1999 (MCE) : . Ripped out the use of signals to communicate with other xautolock processes. This removes the limit on the number of possible messages (yesterday's change was pushing that very hard) and makes things more portable as well. - 15/02/1999 (MCE) : . Added the "-locknow", "-unlocknow", and "-nowlocker" options. (Thanks to Timo J Rinne for the original patch (slightly modified by me).) . Some minor clean up. - 05/02/1999 (MCE) : . The VMS port should now actually work more or less. (Thanks to Jouk Jansen for taking the trouble to actually submit a patch.) . Fixed an include file conflict on AIX. (Also thanks to Jouk Jansen .) - 19/10/1998 (MCE) : . Added the "-exit" option. (Based on a patch by Yakov Yukhnovetsky .) - 11/08/1998 (MCE) : . Include pwd.h to make the $HOME/.Xdefaults stuff compile on more platforms. (Problem reported by Jens Schleusener .) - 09/08/1998 (MCE) : . Plugged a memory leak in the $HOME/.Xdefaults code. . Updated this changelog to always mention the full names of people. Provided I know them, that is... - 03/06/1998 (MCE) : . Extended the (unreleased) debugging code somewhat. - 08/04/1998 (MCE) : . Cleaned up some of the stuff that LCLint complained about (but definitely not all of it). - 14/11/1997 (MCE) : . Read resources from $HOME/.Xdefaults as a last resort. (Suggested by Marc Baudoin .) - 27/10/1997 (MCE) : . Added support for the MIT ScreenSaver extension. . Made gcc -Wall shut up on Linux and HP-UX 10. - 25/10/1997 (MCE) : . Merged in lots of VMS portability fixes taken from the latest VMS version. (Original code by Hunter Goatley .) Untested! . Replaced the "-killpid" option with the "-killer" one to allow for more flexibility. - 10/08/1997 (MCE) : . On VMS, use LIB$SPAWN rather than vfork to work around DECC/VAXC interoperability problems. (Taken from one of the many VMS branch versions.) Untested! . Added code to properly handle the -locker option to the VMS version. (Based on a patch by Erez Gur .) Untested! - 30/06/1997 (MCE) : . Added the "-resetsaver" option to aid people with DPMS monitors. (Triggered by Ian Rawlings .) - 03/04/1997 (MCE) : . Cleaned up the (unreleased) debugging code. . Fixed some minor bugs concerning "-killpid" and "-killtime". - 21/08/1996 (MCE) : . Do not free() the return value of getenv(). (Pointed out by Stefan Jais .) - 25/06/1996 (MCE) : . General clean up. - 23/06/1996 (MCE) : . Incorporated the "-secure", "-killtime" and "-killpid" options. (Based on a patch provided by Tony Mione .) - 07/05/1996 (MCE) : . Allow the user to exploit the entire range of bell_percent values supported by XBell(). (Suggested by Eddy De Greef .) - 29/04/1996 (MCE) : . Fixed a serious problem with the Xidle support. (Thanks to Lam N for attracting my attention to this one.) - 28/01/1996 (MCE) : . Minor stylistic editing. - 15/05/1995 (MCE) : . Removed the INITIAL_SLEEP stuff. - 08/05/1995 (MCE) : . Fixed a race condition in SelectEvents (). - 21/04/1995 (MCE) : . Better wording of the copyright notice (no fundamental change). - 28/02/1995 (MCE) : . Added correct setup of the standard WM properties. - 21/02/1995 (MCE) : . Initial cleaning up of the #ifdef and #include stuff. . Be less pedantic when validating the notification margin if the `corners' feature is not being used. . Fixed a horrificly stupid blooper that was sometimes causing the thing not to work at all. (Thanks to Don Lewis and Ben Suurmeijer for attracting my attention to this one.) - 01/02/1995 (MCE) : . Added a few unused intialisations because otherwise some compilers complain about them missing. - 23/01/1995 (MCE) : . Fixed various things ProLint complained about. . Fixed yet another minor oversight in option handling. - 20/01/1995 (MCE) : . Take the modifier mask into account when looking for pointer activity. (Idea taken from xscreensaver, which is by Jamie Zawinski .) . Fixed a minor oversight in option handling. . Fixed some uninitialised memory problems, a rare null pointer dereference and a small memory leak. (Purify sure is a great tool!) - 03/01/1995 (MCE) : . Finally solved the logout problems under OpenWinDows. (Thanks to the many people who reported this one in the past, and in particular to John Kent for putting me on the right track.) . Some minor cosmetic changes. - 21/11/1994 (MCE) : . Added "#ifdef"s as needed by Novell Unixware. (Thanks to Thanh Ma for reporting this.) . Plugged a minor memory leak in the resource management code. - 10/11/1994 (MCE) : . Added "-notifier" option. (Based on a suggestion by Steve Woodard .) . Made the "xxx_SEMAPHORE_PID" stuff honour the prog_name stuff. . Casting fixes related to use of time_t. - 06/11/1994 (MCE) : . Several minor corrections for VMS. . Added #define _HPUX_SOURCE for c89 on HP/UX. . Totally reworked time-keeping code to protect it against incorrect implementations of sleep (). - 01/11/1994 (MCE) : . Added SIGUSR1 and SIGUSR2 support, as well as "-enable", "-disable", "-toggle" options.(Thanks to Christopher Davis for the initial patch.) . Renamed some stuff for better maintainability. - 14/10/1994 (MCE) : . Finally added Xidle support. . Return value of waitpid () on SYSV was being used incorrectly. - 21/09/1994 (MCE) : . Several minor code embellishments. . Better wording of the copyright statement. . Ported to VMS. (Thanks to Brian D. Reed for providing the nitty-gritty details.) . Resources now have a (dummy) resource class. (Thanks to JF Bonhomme for pointing out that something had to be done here.) . Reworked resource processing. (Thanks to Joerg Lehrke for providing the original patch (stripped by me).) . Create a dummy window for proper XKillCLient () behaviour when using xdm without XDMCP or similar. . Added "-nocloseout" and "-nocloseerr". - 25/08/1994 (MCE) : . More accurate "usage" message. - 11/05/1994 (MCE) : . Corrected a "really stupid typo" ;-). - 23/12/1993 (MCE) : . Improved "#ifdef"s for SYSV. (Thanks to John Somerfield .) - 13/08/1993 (MCE) : . Added "-cornerredelay" for reasons described in the man page. - 22/06/1993 (MCE) : . Reset screensaver upon locking the screen. (Suggested by Paul Mossip .) . Improved resource usage. - 21/12/1992 (MCE) : . Added code to circumvent a server initialisation bug (OpenWindows 2.0 and 3.0) related to XQueryPointer (). (Thanks to Eric Engstrom for providing the patch.) - 08/07/1992 (MCE) : . Efficiency improvements and code embellishments . Improved conditional "#include"s etc. (Thanks to Jonathan I. Kamens and Fred J.R. Appelman .) . Moved a couple of premature calls to free (). (Purify sure is a great tool!) . Fixed a race condition related to the `corners' feature. . Fixed a minor initialization bug. - 11/05/1992 (MCE) : . Close stdout and stderr instead of using "2>&- 1>&-". (Suggested by Rainer Sinkwitz .) . Added "-noclose" for debugging. - 06/05/1992 (MCE) : . Fixed a few potential portability problems. (Thanks to Paul Smith again.) . CheckConnection () now works properly on multi-headed displays. (Thanks to Brian ? for testing the `multi-headed' support.) . Better version of Sleep (). . Recognize X resources for class "Xautolock". . Don't update timer while sighupped. . Switched to vfork () and execl (). . New copyright notice. - 28/04/1992 (MCE) : . Use the X resource manager. - 25/04/1992 (MCE) : . Added the `corners' feature. (Suggested by Neil I. Weisenfeld .) . Fixed a problem with pseudo-root windows. (Thnaks to Chris Sherman , Nathan Edwards , Dave Hayes , and Tom McConnell for pointing out the problem and testing the patch.) . Added `disable/enable on SIGHUP'. (Suggested by Paul Smith .) . Added support for multi-headed displays. - 20/04/1992 (MCE) : . Cut Main () into more managable pieces. . Periodically call XQueryPointer (). - 15/04/1992 (MCE) : . Changed the default locker to "xlock 2>&- 1>&-". . Fixed a couple of event mask bugs. (Thanks to Jamie Zawinski for running into these.) . Corrected a property type bug in CheckConnection (). - 24/03/1992 (MCE) : . Don't reset the timeout counter after receiving a synthetic or otherwise unexpected event. - 10/03/1992 (SDT & MCE) : . Added code to detect broken server connections. - 06/03/1992 (MCE) : . Re-arranged the event loop in order to detect defunct children as soon as possible. - 25/02/1992 (MCE) : . Added code to detect multiple invocations. - 24/02/1992 (MCE) : . Removed an initialization bug. - 21/02/1992 (MCE) : . Major rewrite. - 12/02/1992 (MCE) : . Hacked around a dxcalendar problem. --------------------------------------------------------------------------- Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and Michel Eyckmans. Versions 2.0 and above of xautolock are available under version 2 of the GNU GPL. Earlier versions are available under other conditions. For more information, see the License file. xautolock-2.2/include/0000700000175100017500000000000010735227755013107 5ustar mcemcexautolock-2.2/include/state.h0000600000175100017500000000311210700012567014360 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It declares * everything needed to keep track of the program's state. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __state_h #define __state_h #include "config.h" extern const char* progName; extern char** argArray; extern unsigned nofArgs; extern Bool disabled; extern Bool lockNow; extern Bool unlockNow; extern time_t lockTrigger; extern time_t killTrigger; extern pid_t lockerPid; #define setLockTrigger(delta) (lockTrigger = time ((time_t*) 0) + (delta)) #define setKillTrigger(delta) (killTrigger = time ((time_t*) 0) + (delta)) #define disableKillTrigger() (killTrigger = 0) #define resetLockTrigger() setLockTrigger (lockTime); #define resetTriggers() setLockTrigger (lockTime); \ if (killTrigger) setKillTrigger (killTime); \ extern void initState (int argc, char* argv[]); #endif /* __state_h */ xautolock-2.2/include/version.h0000600000175100017500000000002610041200446014717 0ustar mcemce#define VERSION "2.2" xautolock-2.2/include/message.h0000600000175100017500000000173510700012563014671 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It declares * the stuff used to implement the program's IPC features. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __message_h #define __message_h #include "config.h" extern void checkConnectionAndSendMessage (Display* d); extern void lookForMessages (Display* d); #endif /* __message_h */ xautolock-2.2/include/miscutil.h0000600000175100017500000000372510700012565015101 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It provides * general purpose logistic support. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __miscutil_h #define __miscutil_h #include #include #include #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif /* MIN */ #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif /* MAX */ #define error0(s) ((void) fprintf (stderr, (s))) #define error1(s,a1) ((void) fprintf (stderr, (s), (a1))) #define error2(s,a1,a2) ((void) fprintf (stderr, (s), (a1), (a2))) static caddr_t c_ptr = (caddr_t) &c_ptr; /* This is dirty! */ #define allocate(t,s) (c_ptr = (caddr_t) malloc ((unsigned) (s)), \ (c_ptr == (caddr_t) 0) \ ? (error0 ("Out of memory.\n"), \ exit (EXIT_FAILURE), \ /*NOTREACHED*/ (t*) 0 \ ) \ : (t*) c_ptr \ ) \ #define newObj(tp) allocate (tp, sizeof (tp)) #define newArray(tp,n) allocate (tp, sizeof (tp) * (unsigned) (n)) #endif /* __miscutil_h */ xautolock-2.2/include/engine.h0000600000175100017500000000174410700012542014507 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It declares * the program's core functions. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __engine_h #define __engine_h #include "config.h" extern void queryPointer (Display* d); extern void queryIdleTime (Display* d, Bool useXidle); extern void evaluateTriggers (Display* d); #endif /* engine_h */ xautolock-2.2/include/config.h0000600000175100017500000001056610700012325014510 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It takes care * of most OS dependencies, and defines the program's default * settings. * * Please send bug reports etc. to eyckmans@imec.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __config_h #define __config_h #if defined(hpux) || defined (__hpux) #ifndef _HPUX_SOURCE #define _HPUX_SOURCE #endif /* _HPUX_SOURCE */ #endif /* hpux || __hpux */ #include #include #include #include #include #include #include #ifndef VMS #include #include #endif /* VMS */ #ifdef VMS #define HasVFork #include #include #include #include #include #include #include /* Needed for close () */ #include /* Needed for getpid () */ #endif /* VMS */ #include #include #include #include #include #ifdef HasXidle #include "xidle.h" #endif /* HasXidle */ #ifdef HasScreenSaver #include #endif /* HasScreenSaver */ #ifndef HasVFork #define vfork fork #endif /* HasVFork */ #define SECURE False /* default -secure setting */ #define BELL_PERCENT 40 /* as is says */ #define MIN_LOCK_MINS 1 /* minimum number of minutes before firing up the locker */ #define LOCK_MINS 10 /* default ... */ #define MAX_LOCK_MINS 60 /* maximum ... */ #define MIN_KILL_MINS 10 /* minimum number of minutes before firing up the killer */ #define KILL_MINS 20 /* default ... */ #define MAX_KILL_MINS 120 /* maximum ... */ #define CREATION_DELAY 30 /* should be > 10 and < min(45,(MIN_LOCK_MINS*30)) */ #define CORNER_SIZE 10 /* size in pixels of the force-lock areas */ #define CORNER_DELAY 5 /* number of seconds to wait before forcing a lock */ #ifdef VMS #define SLOW_VMS_DELAY 15 /* explained in VMS.NOTES file */ #endif /* VMS */ #ifdef VMS #define LOCKER "mcr sys$system:decw$pausesession" /* default locker command */ #else /* VMS */ #define LOCKER "xlock" /* default locker command (avoid the -allowRoot option!) */ #endif /* VMS */ #define NOTIFIER "" /* default notifier command */ #define KILLER "" /* default killer command */ #define DUMMY_RES_CLASS "_xAx_" /* some X versions don't like a 0 class name, and implementing real classes isn't worth it */ #define APPLIC_CLASS "Xautolock" /* application class */ #ifdef VMS #if defined (VAX) && defined (vaxc) typedef long pid_t; #endif /* VAX && vaxc */ /* * Different versions of the DEC C compiler for OpenVMS Alpha define * pid_t in different ways. Later versions define either __PID_T (v5.2) * or __DEV_T (V5.0) when pid_t is already typedef'ed. DEC C V1.3 did * neither, so typedef if those aren't defined. */ #if defined (__DECC) && defined (__alpha) \ && !defined (____PID_T) && !defined (__DEV_T) typedef long pid_t; #endif /* __DECC && __alpha && !____PID_T && !__DEV_T */ #endif /* VMS */ #endif /* __config_h */ xautolock-2.2/include/options.h0000600000175100017500000000442010700012565014734 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It declares * all option and X resource processing support. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __options_h #define __options_h #include "config.h" typedef enum { ca_ignore, /* ignore corner */ ca_dontLock, /* prevent locking */ ca_forceLock /* lock immediately */ } cornerAction; typedef enum { msg_none, /* as it says */ msg_disable, /* disable a running xautolock */ msg_enable, /* enable a running xautolock */ msg_toggle, /* toggle a running xautolock */ msg_exit, /* kill a running xautolock */ msg_lockNow, /* tell running xautolock to lock now */ msg_unlockNow, /* tell running xautolock to unlock now */ msg_restart, /* tell running xautolock to restart */ } message; /* * Global option settings. Documented in options.c. * Do not modify any of these from outside that file. */ extern const char *locker, *nowLocker, *notifier, *killer; extern time_t lockTime, killTime, notifyMargin, cornerDelay, cornerRedelay; extern int bellPercent; extern unsigned cornerSize; extern Bool secure, notifyLock, useRedelay, resetSaver, noCloseOut, noCloseErr, detectSleep; extern cornerAction corners[4]; extern message messageToSend; extern Bool killerSpecified, notifierSpecified; #ifdef VMS extern struct dsc$descriptor lockerDescr, nowLockerDescr; extern int vmsStatus; #endif /* VMS */ extern void processOpts (Display* d, int argc, char* argv[]); #endif /* options.h */ xautolock-2.2/include/diy.h0000600000175100017500000000205510700012515014023 0ustar mcemce/***************************************************************************** * * Authors: Michel Eyckmans (MCE) & Stefan De Troch (SDT) * * Content: This file is part of version 2.x of xautolock. It declares * the stuff used when the program is not using a screen saver * extension and thus has to use the good old "do it yourself" * approach at detecting user activity. * * Please send bug reports etc. to mce@scarlet.be. * * -------------------------------------------------------------------------- * * Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and * Michel Eyckmans. * * Versions 2.0 and above of xautolock are available under version 2 of the * GNU GPL. Earlier versions are available under other conditions. For more * information, see the License file. * *****************************************************************************/ #ifndef __diy_h #define __diy_h #include "config.h" extern void initDiy (Display* d); extern void processEvents (void); #endif /* diy_h */ xautolock-2.2/VMS.notes0000600000175100017500000000376007275252370013207 0ustar mcemce This file contains special notes concerning VMS platforms. All information on how to fix the issues described below is welcome, provided it is complete, clean, and (most of all) working. We have no access to VMS, hence we cannot test anything ourselves! 1. The VMS port of xautolock is not complete. Some known functionality problems are: + Multi-headed displays may not be supported under VMS. + The -notifier option may either misbehave or even not work at all on VMS. + The -unlocknow option only works on some VMS versions (if it compiles, it should also work on the same machine). + The -killpid option might fail to work. 2. Due to some VMS quirks, the inner workings of which are a complete mystery to us, there seems to be something not quite right with the code used to detect the presence of the locker during the first few seconds of its existence. This sometimes manifests itself as follows (quoting from the original problem report): "One person reported that using the corners options, he had a problem. Apparently, if we guessed right, if it takes more than 5 seconds for the locker to start, the timer will time out again, and fire off a second locker screen." While this cannot ever occur on UNIX, even if the locker takes several hours to start, it does seem to be possible under VMS. As a workaround, the code contains a conditional sleep() call right after starting the locker, which can be compiled in be #define-ing SLOW_VMS. By default, this is not used. Obviously, defining SLOW_VMS will influence the timing behaviour of xautolock in ways which are incompatible with what is stated in the man page. Note for users of previous versions: xautolock is no longer sensitive to the sometimes serious mistimings caused by the braindead sleep() implementation of VMS. It may therefore be needed to modify your -time and -cornerdelay settings. xautolock-2.2/xautolock.man0000600000175100017500000004005410735226344014170 0ustar mcemce.TH xautolock l "December 28, 2007" .SH NAME xautolock \- fire up programs in case of user inactivity under X .SH VERSION This man page applies to xautolock version 2.2. .SH SYNOPSIS .TP 10 .B \fBxautolock\fR [\fB\-help\fR] [\fB\-version\fR] [\fB\-time\fR \fImins\fR] [\fB\-locker\fR \fIlocker\fR] [\fB\-killtime \fIkillmins\fR\fR] [\fB\-killer\fR \fIkiller\fR] [\fB\-notify \fImargin\fR] [\fB\-notifier \fInotifier\fR] [\fB\-bell \fIpercent\fR] [\fB\-corners\fR \fIxxxx\fR] [\fB\-cornerdelay\fR \fIsecs\fR] [\fB\-cornerredelay\fR \fIaltsecs\fR] [\fB\-cornersize\fR \fIpixels\fR] [\fB\-secure\fR] [\fB\-resetsaver\fR] [\fB\-nocloseout\fR] [\fB\-nocloseerr\fR] [\fB\-noclose\fR] [\fB\-disable\fR] [\fB\-enable\fR] [\fB\-toggle\fR] [\fB\-exit\fR] [\fB\-locknow\fR] [\fB\-unlocknow\fR] [\fB\-nowlocker\fR \fIlocker\fR] [\fB\-restart\fR] [\fB\-detectsleep\fR] .SH DESCRIPTION Xautolock monitors the user activity on an X Window display. If none is detected within \fImins\fR minutes, a program is started as specified by the \fB\-locker\fR option. Xautolock will typically be used to lock the screen (hence its primary name) but it really doesn't care what program you make it start. For this reason, xautolock does not interfere with the default X screen saver, unless the \fB\-resetsaver\fR option is used. This implies that it is the job of the \fIlocker\fR or the user to take the appropriate actions if the default screen saver is to be disabled. The only real assumption made by xautolock is that a new countdown starts as soon as the \fIlocker\fR exits. In the presence of the \fB\-notify\fR option, a warning signal will be issued \fImargin\fR seconds before starting the \fIlocker\fR. Warning signals come in two kinds: .TP 3 \(bu You can use the \fB\-notifier\fR option to specify the command to be issued to perform notification. .TP \(bu Alternatively, you can let xautolock ring the bell. In this case, the \fB\-bell\fR option specifies the loudness of the signal in \fIpercent\fR, as described in the \fIXBell\fR man page. .PP You can tell xautolock to take special actions when you move the mouse into one of the corners of the display and leave it there, by using the \fB\-corners\fR, \fB\-cornerdelay\fR, \fB\-cornerredelay\fR and \fB\-cornersize\fR options. This works as follows: The \fIxxxx\fR argument to the \fB\-corners\fR option must consist of exactly 4 characters from the following set: '0', '+', '-'. Each one of these specifies what xautolock should do when the mouse enters a small square area located in each of the corners of the screen. The corners are considered in the following order: top left, top right, bottom left, bottom right. A '0' indicates that xautolock should ignore the corner. A '+' indicates that xautolock should start the \fIlocker\fR after \fIsecs\fR or \fIaltsecs\fR seconds (see below for the difference between both), unless the mouse is moved or keyboard input is received. A '-' indicates that xautolock should not start the \fIlocker\fR at all. The \fIpixels\fR argument specifies the size in pixels of the corner areas. Most users of the \fB\-corners\fR option want the \fIlocker\fR to activate within a very short time interval after they move the mouse into a '+' corner. This can be achieved by specifying a small value for the \fB\-cornerdelay\fR option. However, if the mouse is subsequently left where it is, xautolock will almost immediately start a new \fIlocker\fR right after the user quits the current one. To prevent this from happening, the \fB\-cornerredelay\fR option can be used to specify the time-out interval to be used if and only if the mouse is sitting in a `+' corner and has not been moved since the previous \fIlocker\fR exited. A running xautolock process can be disabled (unless if the \fB\-secure\fR option has been specified), in which case it will not attempt to start the \fIlocker\fR. To disable an already running xautolock process, use the \fB\-disable\fR option. To re-enable it, use \fB\-enable\fR. To toggle it between both states, use \fB\-toggle\fR. Using this method is preferable to using sending it SIGSTOP and SIGCONT signals, because while disabled xautolock will still be emptying its event queue. A running xautolock process can also be told to exit (unless if the \fB\-secure\fR option has been specified). To do this, use the \fB\-exit\fR option. The \fB\-killtime\fR and \fB\-killer\fR options allow, amongst other things, to implement an additional automatic logout, on top of the automatic screen locking. In the presence of one or both of these options, a secondary timeout will be triggered \fIkillmins\fR after starting the \fIlocker\fR (unless user activity is detected in the mean time). Upon expiration of this secondary timer, the \fIkiller\fR program is run. Note that, despite the name of the options, xautolock really doesn't care what the \fIkiller\fR does in reality. If it doesn't (indirectly) cause xautolock to get killed, and assuming that no user activity is detected, the secondary trigger will periodically expire every \fIkillmins\fR minutes for as long as the \fIlocker\fR runs. In combination with \fB\-killtime\fR and \fB\-killer\fR, the \fB\-secure\fR option allows system administrators to enforce xautolock as a part of their security procedures, and to prevent people from locking shared displays for an excessive amount of time. One way to achieve this is to start xautolock (using \fB-secure\fR and optionally \fB\-killtime\fR and \fB\-killer\fR) from within XDM's Xsession file in such a way that the session automatically ends if xautolock itself is killed. By default xautolock closes stdout and stderr. This prevents the \fIlocker\fR from writing error messages to these files in case you manually lock your display. The \fB\-nocloseout\fR, \fB\-nocloseerr\fR and \fB\-noclose\fR options cause xautolock to not close stdout and/or stderr. On some platforms users of xnlock will need to use \fB\-nocloseout\fR, in order to make xnlock's witty sayings show up. These options can also be used for debugging cases in which \fIlocker\fR invocation is not successful. Xautolock is capable of managing multi-headed displays. .SH OPTIONS .TP 16 \fB\-help\fR Print a help message and exit. .TP \fB\-version\fR Print the version number and exit. .TP \fB\-time\fR Specifies the primary timeout interval. The default is 10 minutes, the minimum is 1 minute, and the maximum is 1 hour. .TP \fB\-locker\fR Specifies the \fIlocker\fR to be used. The default is xlock. Notice that if \fIlocker\fR contains multiple words, it must be specified between quotes. In order to use your PATH to locate the program, xautolock feeds the \fIlocker\fR command to /bin/sh, so it should be understandable for whatever shell your /bin/sh is. Because this typically is a Bourne shell, ~ expansion most likely will not work. .TP \fB\-killtime\fR Specifies the secondary timeout in minutes after starting the \fIlocker\fR. This timer is only active as long as the \fIlocker\fR is running, and is reset each time user activity is detected. If it expires before the \fIlocker\fR exits, the \fIkiller\fR command is run. The default is 20 minutes, the minimum is 10 minutes, and the maximum is 2 hours. This option is only useful in conjunction with \fB\-killer\fR. .TP \fB\-killer\fR Specifies the \fIkiller\fR to be used. The default is none. Notice that if \fIkiller\fR contains multiple words, it must be specified between quotes. In order to use your PATH to locate the program, xautolock feeds the \fIkillr\fR command to /bin/sh, so it should be understandable for whatever shell your /bin/sh is. Because this typically is a Bourne shell, ~ expansion most likely will not work. .TP \fB\-notify\fR Warn the user \fImargin\fR seconds before locking. The default is to not warn the user. If used in conjunction with \fB\-cornerdelay\fR or \fB\-cornerredelay\fR, the notification margin iused is the minimum of \fImargin\fR, \fIsecs\fR and/or \fIaltsecs\fR. .TP \fB\-notifier\fR Specifies the \fInotifier\fR to be used. The default is none. This option is only useful in conjunction with \fB\-notify\fR. Notice that if \fInotifier\fR contains multiple words, it must be specified between quotes. In order to use your PATH to locate the program, xautolock feeds the \fInotifier\fR command to /bin/sh, so it should be understandable for whatever shell your /bin/sh is. Because this typically is a Bourne shell, ~ expansion most likely will not work. .TP \fB\-bell\fR Specifies the loudness of the notification signal in the absence of the \fB\-notifier\fR option. The default is 40 percent. This option is only useful in conjunction with \fB\-notify\fR. .TP \fB\-corners\fR Define special actions to be taken when the mouse enters one of the corners of the display. The default is 0000, which means that no special action is taken. .TP \fB\-cornerdelay\fR Specifies the number of seconds to wait before reacting to the mouse entering a '+' corner. The default is 5 seconds. .TP \fB\-cornerredelay\fR Specifies the number of seconds to wait before reacting again if the current \fIlocker\fR exits while the mouse is sitting in a '+' corner. The default is for \fIaltsecs\fR to equal \fIsecs\fR. .TP \fB\-cornersize\fR Specifies the size in pixels of the corner areas. The default is 10 pixels. .TP \fB\-resetsaver\fR Causes xautolock to reset the X screen saver after successfully starting the \fIlocker\fR. This is typically used in case the locker is not really intended to lock the screen, but to replace the default X screen saver. Note that the default screen saver is not disabled, only reset. Also note that using \fB\-resetsaver\fR will inferfere with the DPMS monitors, as the power down time out will also be also reset. The default is not to reset the screen saver. See the \fIxset\fR man page for more information about managing the X screen saver. .TP \fB\-detectsleep\fR Instructs xautolock to detect that computer has been put to sleep. This is done by detecting that time has jumped by more than 3 seconds. When this occurs, the lock timer is reset and locker program is not launched even if primary timeout has been reached. This option is typically used to avoid locker program to be launched when awaking a laptop computer. .TP \fB\-secure\fR Instructs xautolock to run in secure mode. In this mode, xautolock becomes imune to the effects of \fB\-enable\fR, \fB\-disable\fR, \fB\-toggle\fR, and \fB\-exit\fR. The default is to honour these actions. .TP \fB\-nocloseout\fR Don't close stdout. .TP \fB\-nocloseerr\fR Don't close stderr. .TP \fB\-noclose\fR Close neither stdout nor stderr. .TP \fB\-disable\fR Disables an already running xautolock process (if there is one, and it does not have \fB\-secure\fR switched on). In any case, the current invocation of xautolock exits. .TP \fB\-enable\fR Enables an already running xautolock process (if there is one, and it does not have \fB\-secure\fR switched on). In any case, the current invocation of xautolock exits. .TP \fB\-toggle\fR Toggles an already running xautolock process (if there is one, and it does not have \fB\-secure\fR switched on) between its disabled and enabled modes of operation. In any case, the current invocation of xautolock exits. .TP \fB\-exit\fR Causes an already running xautolock process (if there is one, and it does not have \fB\-secure\fR switched on) to exit. In any case, the current invocation of xautolock also exits. .TP \fB\-locknow\fR Causes an already running xautolock process (if there is one, if it does not have \fB\-secure\fR switched on, and is not currently disabled) to lock the display immediately. In any case, the current invocation of xautolock exits. .TP \fB\-unlocknow\fR Causes an already running xautolock process (if there is one, if it does not have \fB\-secure\fR switched on, and is not currently disabled) to unlock the display immediately (if it's locked) by sending the \fIlocker\fR a SIGTERM signal. In any case, the current invocation of xautolock exits. .TP \fB\-nowlocker\fR Specifies the \fIlocker\fR to be used if the lock is initiated with \fB\-locknow\fR option. The default is to use the \fIlocker\fR program given with \fB\-locker\fR option, which defaults to xlock. .TP \fB\-restart\fR Causes an already running xautolock process (if there is one and it does not have \fB\-secure\fR switched on) to restart. In any case, the current invocation of xautolock exits. .SH RESOURCES .TP 16 .B time Specifies the primary timeout. Numerical. .TP .B locker Specifies the \fIlocker\fR. No quotes are needed, even if the \fIlocker\fR command contains multiple words. .TP .B killtime Specifies the secondary timeout. Numerical. .TP .B killer Specifies the \fIkiller\fR. No quotes are needed, even if the \fIkiller\fR command contains multiple words. .TP .B notify Specifies the notification margin. Numerical. .TP .B notifier Specifies the \fInotifier\fR. No quotes are needed, even if the \fInotifier\fR command contains multiple words. .TP .B bell Specifies the notification loudness. Numerical. .TP .B corners Specifies the corner behaviour, as explained above. .TP .B cornersize Specifies the size of the corner areas. Numerical. .TP .B cornerdelay Specifies the delay of a '+' corner. Numerical. .TP .B cornerredelay Specifies the alternative delay of a '+' corner. Numerical. .TP .B resetsaver Reset the default X screen saver. Boolean. .TP .B nocloseout Don't close stdout. Boolean. .TP .B nocloseerr Don't close stderr. Boolean. .TP .B noclose Close neither stdout nor stderr. Boolean. .PP Resources can be specified in your \fI~/.Xresources\fR or \fI~/.Xdefaults\fR file (whichever your system uses) and merged via the xrdb(1) command. They can be specified either for class \fIXautolock\fR, or for whatever name your xautolock program has been given. This can be useful in case xautolock is to be used for other purposes than simply locking the screen. For example: if you have two copies of xautolock, one called "xmonitor", and one called "xlogout", then both will honour the following: .IP \fBXautolock.corners: ++++\fR .PP In addition, "xmonitor" will honour: .IP \fBxmonitor.cornersize: 10\fR .PP while "xlogout" will honour: .IP \fBxlogout.cornersize: 5\fR .PP Each command line option takes precedence over the corresponding (default) resource specification. .SH KNOWN\ BUGS The \fB\-disable\fR, \fB\-enable\fR, \fB\-toggle\fR, \fB\-exit\fR, \fB\-locknow\fR, \fB\-unlocknow\fR, and \fB\-restart\fR options depend on access to the X server to do their work. This implies that they will be suspended in case some other application has grabbed the server all for itself. If, when creating a window, an application waits for more than 30 seconds before selecting KeyPress events on non-leaf windows, xautolock may interfere with the event propagation mechanism. This effect is theoretical and has never been observed in real life. It can only occur in case xautolock has been compiled without support for both the Xidle and the MIT ScreenSaver extensions, or in case the X server does not support these extensions. xautolock does not always properly handle the secure keyboard mode of terminal emulators like xterm, since that mode will prevent xautolock from noticing the keyboard events occurring on the terminal. Therefore, xautolock sometimes thinks that there is no keyboard activity while in reality there is. This can only occur in case xautolock has been compiled without support for both the Xidle and the MIT ScreenSaver extensions, or in case the X server does not support these extensions. xautolock does not check whether \fInotifier\fR and/or \fIlocker\fR are available. The xautolock resources have dummy resource classes. .SH SEE\ ALSO X(1), xset(1), xlock(1), xnlock(1), xscreensaver(1). .SH COPYRIGHT Copyright 1990, 1992-1999, 2001-2002, 2004, 2007 by Stefan De Troch and Michel Eyckmans. Versions 2.0 and above of xautolock are available under version 2 of the GNU GPL. Earlier versions are available under other conditions. For more information, see the License file. .SH AUTHORS Xautolock was conceived, written, and performed by: Michel Eyckmans (MCE) .br Stefan De Troch Please send queries for help, feature suggestions, bug reports, etc. to mce@scarlet.be. .SH SPECIAL\ THANKS\ TO Kris Croes