commit 4952641328f28a541e3fdf2200df4e1e4b11d5dd
Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>
Date:   1328994151 -0600

    Commit the rest of 8d521d0b, not merged due to GIT glitch

diff --git a/kdesktop/lock/main.cc b/kdesktop/lock/main.cc
index 132ff30..4edd1b3 100644
--- a/kdesktop/lock/main.cc
+++ b/kdesktop/lock/main.cc
@@ -73,140 +73,241 @@ static KCmdLineOptions options[] =
    { "dontlock", I18N_NOOP("Only start screensaver"), 0 },
    { "securedialog", I18N_NOOP("Launch the secure dialog"), 0 },
    { "blank", I18N_NOOP("Only use the blank screensaver"), 0 },
+   { "internal <pid>", I18N_NOOP("TDE internal command for background process loading"), 0 },
    KCmdLineLastOption
 };
 
+static void sigusr1_handler(int)
+{
+    signalled_forcelock = TRUE;
+}
+
+static void sigusr2_handler(int)
+{
+    signalled_dontlock = TRUE;
+}
+
+static void sigusr3_handler(int)
+{
+    signalled_securedialog = TRUE;
+}
+
+static void sigusr4_handler(int)
+{
+    signalled_blank = TRUE;
+}
+
+static void sigusr5_handler(int)
+{
+    signalled_run = TRUE;
+}
+
 // -----------------------------------------------------------------------------
 
 int main( int argc, char **argv )
 {
     KLocale::setMainCatalogue("kdesktop");
 
-    KCmdLineArgs::init( argc, argv, "kdesktop_lock", I18N_NOOP("KDesktop Locker"), I18N_NOOP("Session Locker for KDesktop"), "2.0" );
+    KCmdLineArgs::init( argc, argv, "kdesktop_lock", I18N_NOOP("KDesktop Locker"), I18N_NOOP("Session Locker for KDesktop"), "2.1" );
     KCmdLineArgs::addCmdLineOptions( options );
     KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
 
-    if (args->isSet( "forcelock" ))
-        trinity_desktop_lock_forced = TRUE;
-
     putenv(strdup("SESSION_MANAGER="));
 
     KApplication::disableAutoDcopRegistration(); // not needed
 
-    int kdesktop_screen_number = 0;
-    int starting_screen = 0;
-
-    bool child = false;
-    int parent_connection = 0; // socket to the parent saver
-    TQValueList<int> child_sockets;
-
-    if (KGlobalSettings::isMultiHead())
-    {
-        Display *dpy = XOpenDisplay(NULL);
-        if (! dpy) {
-            fprintf(stderr,
-                    "%s: FATAL ERROR: couldn't open display '%s'\n",
-                    argv[0], XDisplayName(NULL));
-            exit(1);
-        }
+    while (1 == 1) {
+        signalled_forcelock = FALSE;
+        signalled_dontlock = FALSE;
+        signalled_securedialog = FALSE;
+        signalled_blank = FALSE;
+        signalled_run = FALSE;
 
-        int number_of_screens = ScreenCount(dpy);
-        starting_screen = kdesktop_screen_number = DefaultScreen(dpy);
-        int pos;
-        TQCString display_name = XDisplayString(dpy);
-        XCloseDisplay(dpy);
-        kdDebug() << "screen " << number_of_screens << " " << kdesktop_screen_number << " " << display_name << " " << starting_screen << endl;
-        dpy = 0;
-
-        if ((pos = display_name.findRev('.')) != -1)
-            display_name.remove(pos, 10);
-
-        TQCString env;
-        if (number_of_screens != 1) {
-            for (int i = 0; i < number_of_screens; i++) {
-                if (i != starting_screen) {
-                    int fd[2];
-                    if (pipe(fd)) {
-                        perror("pipe");
-                        break;
-                    }
-                    if (fork() == 0) {
-                        child = true;
-                        kdesktop_screen_number = i;
-                        parent_connection = fd[0];
-                        // break here because we are the child process, we don't
-                        // want to fork() anymore
-                        break;
-                    } else {
-                        child_sockets.append(fd[1]);
+        int kdesktop_screen_number = 0;
+        int starting_screen = 0;
+
+        bool child = false;
+        int parent_connection = 0; // socket to the parent saver
+        TQValueList<int> child_sockets;
+
+        if (KGlobalSettings::isMultiHead())
+        {
+            Display *dpy = XOpenDisplay(NULL);
+            if (! dpy) {
+                fprintf(stderr,
+                        "%s: FATAL ERROR: couldn't open display '%s'\n",
+                        argv[0], XDisplayName(NULL));
+                exit(1);
+            }
+
+            int number_of_screens = ScreenCount(dpy);
+            starting_screen = kdesktop_screen_number = DefaultScreen(dpy);
+            int pos;
+            TQCString display_name = XDisplayString(dpy);
+            XCloseDisplay(dpy);
+            kdDebug() << "screen " << number_of_screens << " " << kdesktop_screen_number << " " << display_name << " " << starting_screen << endl;
+            dpy = 0;
+
+            if ((pos = display_name.findRev('.')) != -1)
+                display_name.remove(pos, 10);
+
+            TQCString env;
+            if (number_of_screens != 1) {
+                for (int i = 0; i < number_of_screens; i++) {
+                    if (i != starting_screen) {
+                        int fd[2];
+                        if (pipe(fd)) {
+                            perror("pipe");
+                            break;
+                        }
+                        if (fork() == 0) {
+                            child = true;
+                            kdesktop_screen_number = i;
+                            parent_connection = fd[0];
+                            // break here because we are the child process, we don't
+                            // want to fork() anymore
+                            break;
+                        } else {
+                            child_sockets.append(fd[1]);
+                        }
                     }
                 }
-            }
 
-            env.sprintf("DISPLAY=%s.%d", display_name.data(),
-                        kdesktop_screen_number);
-            kdDebug() << "env " << env << endl;
+                env.sprintf("DISPLAY=%s.%d", display_name.data(),
+                            kdesktop_screen_number);
+                kdDebug() << "env " << env << endl;
 
-            if (putenv(strdup(env.data()))) {
-                fprintf(stderr,
-                        "%s: WARNING: unable to set DISPLAY environment variable\n",
-                        argv[0]);
-                perror("putenv()");
+                if (putenv(strdup(env.data()))) {
+                    fprintf(stderr,
+                            "%s: WARNING: unable to set DISPLAY environment variable\n",
+                            argv[0]);
+                    perror("putenv()");
+                }
             }
         }
-    }
 
-    MyApp app;
-    kdDebug() << "app " << kdesktop_screen_number << " " << starting_screen << " " << child << " " << child_sockets.count() << " " << parent_connection << endl;
-    app.disableSessionManagement();
-    KGlobal::locale()->insertCatalogue("libdmctl");
-
-    // we need to read from the right rc file - possibly taking screen number in account
-    KDesktopSettings::instance("kdesktoprc");
-
-    trinity_desktop_lock_use_system_modal_dialogs = !KDesktopSettings::useUnmanagedLockWindows();
-    trinity_desktop_lock_delay_screensaver_start = KDesktopSettings::delaySaverStart();
-    trinity_desktop_lock_use_sak = KDesktopSettings::useTDESAK();
-
-    LockProcess process(child, args->isSet( "blank" ));
-    if (!child)
-        process.setChildren(child_sockets);
-    else
-        process.setParent(parent_connection);
-
-    bool rt;
-    bool sig = false;
-    if( !child && args->isSet( "forcelock" ))
-    {
-        rt = process.lock();
-        sig = true;
-    }
-    else if( child || args->isSet( "dontlock" )) {
-        rt = process.dontLock();
-    }
-    else if( child || args->isSet( "securedialog" )) {
-        int retcode = tde_sak_verify_calling_process();
-        if (retcode == 0) {
-            rt = process.runSecureDialog();
+        MyApp app;
+        kdDebug() << "app " << kdesktop_screen_number << " " << starting_screen << " " << child << " " << child_sockets.count() << " " << parent_connection << endl;
+        app.disableSessionManagement();
+        KGlobal::locale()->insertCatalogue("libdmctl");
+
+        // we need to read from the right rc file - possibly taking screen number in account
+        KDesktopSettings::instance("kdesktoprc");
+
+        trinity_desktop_lock_use_system_modal_dialogs = !KDesktopSettings::useUnmanagedLockWindows();
+        trinity_desktop_lock_delay_screensaver_start = KDesktopSettings::delaySaverStart();
+        trinity_desktop_lock_use_sak = KDesktopSettings::useTDESAK();
+
+        if (args->isSet( "internal" )) {
+            while (signalled_run == FALSE) {
+                sigset_t new_mask;
+                struct sigaction act;
+
+                in_internal_mode = TRUE;
+
+                // handle SIGUSR1
+                act.sa_handler= sigusr1_handler;
+                sigemptyset(&(act.sa_mask));
+                sigaddset(&(act.sa_mask), SIGUSR1);
+                act.sa_flags = 0;
+                sigaction(SIGUSR1, &act, 0L);
+                // handle SIGUSR2
+                act.sa_handler= sigusr2_handler;
+                sigemptyset(&(act.sa_mask));
+                sigaddset(&(act.sa_mask), SIGUSR2);
+                act.sa_flags = 0;
+                sigaction(SIGUSR2, &act, 0L);
+                // handle SIGWINCH (an ersatz SIGUSR3)
+                act.sa_handler= sigusr3_handler;
+                sigemptyset(&(act.sa_mask));
+                sigaddset(&(act.sa_mask), SIGWINCH);
+                act.sa_flags = 0;
+                sigaction(SIGWINCH, &act, 0L);
+                // handle SIGTTIN (an ersatz SIGUSR4)
+                act.sa_handler= sigusr4_handler;
+                sigemptyset(&(act.sa_mask));
+                sigaddset(&(act.sa_mask), SIGTTIN);
+                act.sa_flags = 0;
+                sigaction(SIGTTIN, &act, 0L);
+                // handle SIGTTOU (an ersatz SIGUSR5)
+                act.sa_handler= sigusr5_handler;
+                sigemptyset(&(act.sa_mask));
+                sigaddset(&(act.sa_mask), SIGTTOU);
+                act.sa_flags = 0;
+                sigaction(SIGTTOU, &act, 0L);
+
+                // initialize the signal masks
+                sigfillset(&new_mask);
+                sigdelset(&new_mask,SIGUSR1);
+                sigdelset(&new_mask,SIGUSR2);
+                sigdelset(&new_mask,SIGWINCH);
+                sigdelset(&new_mask,SIGTTIN);
+                sigdelset(&new_mask,SIGTTOU);
+
+                // wait for SIGUSR1, SIGUSR2, SIGWINCH, SIGTTIN, or SIGTTOU
+                sigsuspend(&new_mask);
+            }
+        }
+
+        if (args->isSet( "forcelock" ) || (signalled_forcelock == TRUE))
+            trinity_desktop_lock_forced = TRUE;
+
+        LockProcess process(child, (args->isSet( "blank" ) || (signalled_blank == TRUE)));
+        if (!child)
+            process.setChildren(child_sockets);
+        else
+            process.setParent(parent_connection);
+
+        bool rt;
+        bool sig = false;
+        if( !child && (args->isSet( "forcelock" ) || (signalled_forcelock == TRUE)))
+        {
+            rt = process.lock();
+            sig = true;
+        }
+        else if( child || (args->isSet( "dontlock" ) || (signalled_dontlock == TRUE))) {
+            rt = process.dontLock();
+        }
+        else if( child || (args->isSet( "securedialog" ) || (signalled_securedialog == TRUE))) {
+            int retcode = tde_sak_verify_calling_process();
+            if (retcode == 0) {
+                rt = process.runSecureDialog();
+            }
+            else {
+                return 1;
+            }
         }
         else {
+            rt = process.defaultSave();
+        }
+        if (!rt) {
             return 0;
         }
-    }
-    else {
-        rt = process.defaultSave();
-    }
-    if (!rt) {
-        return 0;
-    }
 
-    if( sig )
-    {
-        DCOPRef ref( "kdesktop", "KScreensaverIface");
-        ref.send( "saverLockReady" );
-    }
+        if( sig )
+        {
+            DCOPRef ref( "kdesktop", "KScreensaverIface");
+            ref.send( "saverLockReady" );
+        }
+
+        if (in_internal_mode == FALSE) {
+            return app.exec();
+        }
+        else {
+            pid_t kdesktop_pid = atoi(args->getOption( "internal" ));
+            app.exec();
+            if (kill(kdesktop_pid, SIGUSR1) < 0) {
+                // The controlling kdesktop process probably died.  Commit suicide...
+                return 12;
+            }
 
-    return app.exec();
+            // FIXME
+            // We should not have to return (restart) at all,
+            // but it seems that some X11 connections are left active,
+            // preventing the lock process from restarting properly in the while() loop above.
+            return 0;
+        }
+    }
 }
 
 #include "main.moc"