summaryrefslogtreecommitdiff
blob: 5b48b463b0aa1d9d07de12dd26ec3935fc45f449 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
From b9f261de75356be6e4ee94c0cc53f2edbd8fe4d2 Mon Sep 17 00:00:00 2001
From: Dan Nicholson <dbn.lists@gmail.com>
Date: Tue, 14 Oct 2008 07:06:21 -0700
Subject: [PATCH] Fork gdm-binary, except when -nodaemon is used

gdm-binary now forks and the parent terminates, except when the
-nodaemon or --nodaemon options are used. This provides compatibility
with xdm. Fixes bug #550170.
---
 daemon/main.c |   64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/daemon/main.c b/daemon/main.c
index 9d7ab5e..4a2f2a5 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -495,6 +495,56 @@ signal_cb (int      signo,
         return ret;
 }
 
+static void
+dup_dev_null (int fd, int flags)
+{
+        int nullfd;
+        int dupfd;
+
+        VE_IGNORE_EINTR (nullfd = open ("/dev/null", flags));
+        if (G_UNLIKELY (nullfd < 0)) {
+                gdm_fail (_("Cannot open /dev/null: %s!"),
+                          strerror (errno));
+                exit (EXIT_FAILURE);
+        }
+
+        VE_IGNORE_EINTR (dupfd = dup2 (nullfd, fd));
+        if (G_UNLIKELY (dupfd < 0)) {
+                gdm_fail (_("Cannot duplicate /dev/null: %s!"),
+                          strerror (errno));
+                exit (EXIT_FAILURE);
+        }
+
+        VE_IGNORE_EINTR (close (nullfd));
+}
+
+static void
+daemonify (void)
+{
+        pid_t pid;
+
+        pid = fork ();
+
+        /* terminate the parent */
+        if (pid > 0)
+                exit (EXIT_SUCCESS);
+
+        if (G_UNLIKELY (pid < 0)) {
+                gdm_fail (_("fork () failed: %s!"), strerror (errno));
+                exit (EXIT_FAILURE);
+        }
+
+        if (G_UNLIKELY (setsid () < 0)) {
+                gdm_fail (_("setsid () failed: %s!"), strerror (errno));
+                exit (EXIT_FAILURE);
+        }
+
+        /* reopen stdin, stdout, stderr with /dev/null */
+        dup_dev_null (STDIN_FILENO, O_RDONLY);
+        dup_dev_null (STDOUT_FILENO, O_RDWR);
+        dup_dev_null (STDERR_FILENO, O_RDWR);
+}
+
 int
 main (int    argc,
       char **argv)
@@ -505,6 +555,7 @@ main (int    argc,
         DBusGConnection    *connection;
         GError             *error;
         int                 ret;
+        int                 i;
         gboolean            res;
         gboolean            xdmcp_enabled;
         GdmSignalHandler   *signal_handler;
@@ -512,9 +563,11 @@ main (int    argc,
         static gboolean     do_timed_exit    = FALSE;
         static gboolean     print_version    = FALSE;
         static gboolean     fatal_warnings   = FALSE;
+        static gboolean     no_daemon        = FALSE;
         static GOptionEntry entries []   = {
                 { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL },
                 { "fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &fatal_warnings, N_("Make all warnings fatal"), NULL },
+                { "nodaemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_("Do not fork into the background"), NULL },
                 { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time - for debugging"), NULL },
                 { "version", 0, 0, G_OPTION_ARG_NONE, &print_version, N_("Print GDM version"), NULL },
 
@@ -531,6 +584,14 @@ main (int    argc,
 
         g_type_init ();
 
+        /* preprocess the arguments to support the xdm style
+         * -nodaemon option
+         */
+        for (i = 0; i < argc; i++) {
+                if (strcmp (argv[i], "-nodaemon") == 0)
+                        argv[i] = "--nodaemon";
+        }
+
         context = g_option_context_new (_("GNOME Display Manager"));
         g_option_context_add_main_entries (context, entries, NULL);
         g_option_context_set_ignore_unknown_options (context, TRUE);
@@ -596,6 +657,9 @@ main (int    argc,
                 exit (-1);
         }
 
+        if (no_daemon == FALSE)
+                daemonify ();
+
         /* pid file */
         delete_pid ();
         write_pid ();
-- 
1.5.6.5