summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dix/globals.c1
-rw-r--r--include/opaque.h1
-rw-r--r--man/Xserver.man7
-rw-r--r--os/connection.c68
-rw-r--r--os/utils.c9
5 files changed, 66 insertions, 20 deletions
diff --git a/dix/globals.c b/dix/globals.c
index a564575f3..332b91f5c 100644
--- a/dix/globals.c
+++ b/dix/globals.c
@@ -128,6 +128,7 @@ int defaultColorVisualClass = -1;
int monitorResolution = 0;
char *display;
+int displayfd;
char *ConnectionInfo;
CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
diff --git a/include/opaque.h b/include/opaque.h
index 9ca408ae1..b76ab6e6b 100644
--- a/include/opaque.h
+++ b/include/opaque.h
@@ -50,6 +50,7 @@ extern _X_EXPORT int ScreenSaverAllowExposures;
extern _X_EXPORT int defaultScreenSaverBlanking;
extern _X_EXPORT int defaultScreenSaverAllowExposures;
extern _X_EXPORT char *display;
+extern _X_EXPORT int displayfd;
extern _X_EXPORT int defaultBackingStore;
extern _X_EXPORT Bool disableBackingStore;
diff --git a/man/Xserver.man b/man/Xserver.man
index 0cd9b941c..8d243d6b7 100644
--- a/man/Xserver.man
+++ b/man/Xserver.man
@@ -127,6 +127,13 @@ Not obeyed by all servers.
.B \-core
causes the server to generate a core dump on fatal errors.
.TP 8
+.B \-displayfd \fIfd\fP
+specifies a file descriptor in the launching process. Rather than specify
+a display number, the X server will attempt to listen on successively higher
+display numbers, and upon finding a free one, will write the port number back
+on this file descriptor as a newline-terminated string. The \-pn option is
+ignored when using \-displayfd.
+.TP 8
.B \-deferglyphs \fIwhichfonts\fP
specifies the types of fonts for which the server should attempt to use
deferred glyph loading. \fIwhichfonts\fP can be all (all fonts),
diff --git a/os/connection.c b/os/connection.c
index 1099752e4..039942f91 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -142,6 +142,7 @@ Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
Bool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or
equivalent) will send SIGCONT back. */
+static char dynamic_display[7]; /* display name */
Bool PartialNetwork; /* continue even if unable to bind all addrs */
static Pid_t ParentProcess;
@@ -350,6 +351,10 @@ void
NotifyParentProcess(void)
{
#if !defined(WIN32)
+ if (dynamic_display[0]) {
+ write(displayfd, dynamic_display, strlen(dynamic_display));
+ close(displayfd);
+ }
if (RunFromSmartParent) {
if (ParentProcess > 1) {
kill(ParentProcess, SIGUSR1);
@@ -360,6 +365,18 @@ NotifyParentProcess(void)
#endif
}
+static Bool
+TryCreateSocket(int num, int *partial)
+{
+ char port[20];
+
+ snprintf(port, sizeof(port), "%d", num);
+
+ return (_XSERVTransMakeAllCOTSServerListeners(port, partial,
+ &ListenTransCount,
+ &ListenTransConns) >= 0);
+}
+
/*****************
* CreateWellKnownSockets
* At initialization, create the sockets to listen on for new clients.
@@ -370,7 +387,6 @@ CreateWellKnownSockets(void)
{
int i;
int partial;
- char port[20];
FD_ZERO(&AllSockets);
FD_ZERO(&AllClients);
@@ -386,29 +402,41 @@ CreateWellKnownSockets(void)
FD_ZERO(&WellKnownConnections);
- snprintf(port, sizeof(port), "%d", atoi(display));
-
- if ((_XSERVTransMakeAllCOTSServerListeners(port, &partial,
- &ListenTransCount,
- &ListenTransConns) >= 0) &&
- (ListenTransCount >= 1)) {
- if (!PartialNetwork && partial) {
- FatalError("Failed to establish all listening sockets");
+ /* display is initialized to "0" by main(). It is then set to the display
+ * number if specified on the command line, or to NULL when the -displayfd
+ * option is used. */
+ if (display) {
+ if (TryCreateSocket(atoi(display), &partial) &&
+ ListenTransCount >= 1)
+ if (!PartialNetwork && partial)
+ FatalError ("Failed to establish all listening sockets");
+ }
+ else { /* -displayfd */
+ Bool found = 0;
+ for (i = 0; i < 65535 - X_TCP_PORT; i++) {
+ if (TryCreateSocket(i, &partial) && !partial) {
+ found = 1;
+ break;
+ }
+ else
+ CloseWellKnownConnections();
}
- else {
- ListenTransFds = malloc(ListenTransCount * sizeof(int));
+ if (!found)
+ FatalError("Failed to find a socket to listen on");
+ snprintf(dynamic_display, sizeof(dynamic_display), "%d", i);
+ display = dynamic_display;
+ }
- for (i = 0; i < ListenTransCount; i++) {
- int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]);
+ ListenTransFds = malloc(ListenTransCount * sizeof (int));
- ListenTransFds[i] = fd;
- FD_SET(fd, &WellKnownConnections);
+ for (i = 0; i < ListenTransCount; i++) {
+ int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]);
- if (!_XSERVTransIsLocal(ListenTransConns[i])) {
- DefineSelf(fd);
- }
- }
- }
+ ListenTransFds[i] = fd;
+ FD_SET(fd, &WellKnownConnections);
+
+ if (!_XSERVTransIsLocal(ListenTransConns[i]))
+ DefineSelf (fd);
}
if (!XFD_ANYSET(&WellKnownConnections))
diff --git a/os/utils.c b/os/utils.c
index 30592d2cc..3a1ef9303 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -659,6 +659,15 @@ ProcessCommandLine(int argc, char *argv[])
else
UseMsg();
}
+ else if (strcmp(argv[i], "-displayfd") == 0) {
+ if (++i < argc) {
+ displayfd = atoi(argv[i]);
+ display = NULL;
+ nolock = TRUE;
+ }
+ else
+ UseMsg();
+ }
#ifdef DPMSExtension
else if (strcmp(argv[i], "dpms") == 0)
/* ignored for compatibility */ ;