1 /*
2  * Copyright © 2011-2014 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of the
9  * copyright holders not be used in advertising or publicity
10  * pertaining to distribution of the software without specific,
11  * written prior permission.  The copyright holders make no
12  * representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  */
25 
26 #include <xwayland-config.h>
27 
28 #if !defined(SYSV) && !defined(WIN32)
29 #include <sys/resource.h>
30 #endif
31 
32 #include <stdio.h>
33 #include <errno.h>
34 
35 #include <X11/Xatom.h>
36 #include <selection.h>
37 #include <micmap.h>
38 #include <misyncshm.h>
39 #include <compositeext.h>
40 #include <compint.h>
41 #include <glx_extinit.h>
42 #include <opaque.h>
43 #include <os.h>
44 #include <xserver_poll.h>
45 #include <propertyst.h>
46 #include <version-config.h>
47 
48 #include "xwayland-screen.h"
49 #include "xwayland-vidmode.h"
50 #include "xwayland-ext.h"
51 
52 #ifdef XF86VIDMODE
53 #include <X11/extensions/xf86vmproto.h>
54 extern _X_EXPORT Bool noXFree86VidModeExtension;
55 #endif
56 
57 _X_EXPORT Bool noXwaylandExtension;
58 
59 void
ddxGiveUp(enum ExitCode error)60 ddxGiveUp(enum ExitCode error)
61 {
62 }
63 
64 void
OsVendorInit(void)65 OsVendorInit(void)
66 {
67     if (serverGeneration == 1)
68         ForceClockId(CLOCK_MONOTONIC);
69 }
70 
71 void
OsVendorFatalError(const char * f,va_list args)72 OsVendorFatalError(const char *f, va_list args)
73 {
74 }
75 
76 #if defined(DDXBEFORERESET)
77 void
ddxBeforeReset(void)78 ddxBeforeReset(void)
79 {
80     return;
81 }
82 #endif
83 
84 #if INPUTTHREAD
85 /** This function is called in Xserver/os/inputthread.c when starting
86     the input thread. */
87 void
ddxInputThreadInit(void)88 ddxInputThreadInit(void)
89 {
90 }
91 #endif
92 
93 void
ddxUseMsg(void)94 ddxUseMsg(void)
95 {
96     ErrorF("-rootless              run rootless, requires wm support\n");
97     ErrorF("-wm fd                 create X client for wm on given fd\n");
98     ErrorF("-initfd fd             add given fd as a listen socket for initialization clients\n");
99     ErrorF("-listenfd fd           add given fd as a listen socket\n");
100     ErrorF("-listen fd             deprecated, use \"-listenfd\" instead\n");
101 #ifdef XWL_HAS_EGLSTREAM
102     ErrorF("-eglstream             use eglstream backend for nvidia GPUs\n");
103 #endif
104     ErrorF("-shm                   use shared memory for passing buffers\n");
105     ErrorF("-verbose [n]           verbose startup messages\n");
106     ErrorF("-version               show the server version and exit\n");
107     ErrorF("-noTouchPointerEmulation  disable touch pointer emulation\n");
108 }
109 
110 static int init_fd = -1;
111 static int wm_fd = -1;
112 static int listen_fds[5] = { -1, -1, -1, -1, -1 };
113 static int listen_fd_count = 0;
114 static int verbosity = 0;
115 
116 static void
xwl_show_version(void)117 xwl_show_version(void)
118 {
119     ErrorF("%s Xwayland %s (%d)\n", VENDOR_NAME, VENDOR_MAN_VERSION, VENDOR_RELEASE);
120     ErrorF("X Protocol Version %d, Revision %d\n", X_PROTOCOL, X_PROTOCOL_REVISION);
121 #if defined(BUILDERSTRING)
122     if (strlen(BUILDERSTRING))
123         ErrorF("%s\n", BUILDERSTRING);
124 #endif
125 }
126 
127 static void
try_raising_nofile_limit(void)128 try_raising_nofile_limit(void)
129 {
130 #ifdef RLIMIT_NOFILE
131     struct rlimit rlim;
132 
133     /* Only fiddle with the limit if not set explicitly from the command line */
134     if (limitNoFile >= 0)
135         return;
136 
137     if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
138         ErrorF("Failed to get the current nofile limit: %s\n", strerror(errno));
139         return;
140     }
141 
142     rlim.rlim_cur = rlim.rlim_max;
143 
144     if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
145         ErrorF("Failed to set the current nofile limit: %s\n", strerror(errno));
146         return;
147     }
148 
149     LogMessageVerb(X_INFO, 3, "Raising the file descriptors limit to %li\n",
150                    rlim.rlim_max);
151 #endif
152 }
153 
154 static void
xwl_add_listen_fd(int argc,char * argv[],int i)155 xwl_add_listen_fd(int argc, char *argv[], int i)
156 {
157     NoListenAll = TRUE;
158     if (listen_fd_count == ARRAY_SIZE(listen_fds))
159         FatalError("Too many -listen arguments given, max is %zu\n",
160                    ARRAY_SIZE(listen_fds));
161 
162     listen_fds[listen_fd_count++] = atoi(argv[i + 1]);
163 }
164 
165 int
ddxProcessArgument(int argc,char * argv[],int i)166 ddxProcessArgument(int argc, char *argv[], int i)
167 {
168     if (strcmp(argv[i], "-rootless") == 0) {
169         return 1;
170     }
171     else if (strcmp(argv[i], "-listen") == 0) {
172         CHECK_FOR_REQUIRED_ARGUMENTS(1);
173 
174         /* Not an FD */
175         if (!isdigit(*argv[i + 1]))
176             return 0;
177 
178         LogMessageVerb(X_WARNING, 0, "Option \"-listen\" for file descriptors is deprecated\n"
179                                      "Please use \"-listenfd\" instead.\n");
180 
181         xwl_add_listen_fd (argc, argv, i);
182         return 2;
183     }
184     else if (strcmp(argv[i], "-listenfd") == 0) {
185         CHECK_FOR_REQUIRED_ARGUMENTS(1);
186 
187         xwl_add_listen_fd (argc, argv, i);
188         return 2;
189     }
190     else if (strcmp(argv[i], "-wm") == 0) {
191         CHECK_FOR_REQUIRED_ARGUMENTS(1);
192         wm_fd = atoi(argv[i + 1]);
193         return 2;
194     }
195     else if (strcmp(argv[i], "-initfd") == 0) {
196         CHECK_FOR_REQUIRED_ARGUMENTS(1);
197         init_fd = atoi(argv[i + 1]);
198         return 2;
199     }
200     else if (strcmp(argv[i], "-shm") == 0) {
201         return 1;
202     }
203     else if (strcmp(argv[i], "-verbose") == 0) {
204         if (++i < argc && argv[i]) {
205             char *end;
206             long val;
207 
208             val = strtol(argv[i], &end, 0);
209             if (*end == '\0') {
210                 verbosity = val;
211                 LogSetParameter(XLOG_VERBOSITY, verbosity);
212                 return 2;
213             }
214         }
215         LogSetParameter(XLOG_VERBOSITY, ++verbosity);
216         return 1;
217     }
218     else if (strcmp(argv[i], "-eglstream") == 0) {
219         return 1;
220     }
221     else if (strcmp(argv[i], "-version") == 0) {
222         xwl_show_version();
223         exit(0);
224     }
225     else if (strcmp(argv[i], "-noTouchPointerEmulation") == 0) {
226         touchEmulatePointer = FALSE;
227         return 1;
228     }
229 
230     return 0;
231 }
232 
233 static CARD32
add_client_fd(OsTimerPtr timer,CARD32 time,void * arg)234 add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
235 {
236     if (!AddClientOnOpenFD(wm_fd))
237         FatalError("Failed to add wm client\n");
238 
239     TimerFree(timer);
240 
241     return 0;
242 }
243 
244 static void
listen_on_fds(void)245 listen_on_fds(void)
246 {
247     int i;
248 
249     for (i = 0; i < listen_fd_count; i++)
250         ListenOnOpenFD(listen_fds[i], FALSE);
251 }
252 
253 static void
wm_selection_callback(CallbackListPtr * p,void * data,void * arg)254 wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
255 {
256     SelectionInfoRec *info = arg;
257     struct xwl_screen *xwl_screen = data;
258     static const char atom_name[] = "WM_S0";
259     static Atom atom_wm_s0;
260 
261     if (atom_wm_s0 == None)
262         atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
263     if (info->selection->selection != atom_wm_s0 ||
264         info->kind != SelectionSetOwner)
265         return;
266 
267     listen_on_fds();
268 
269     DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
270 }
271 
272 _X_NORETURN
273 static void _X_ATTRIBUTE_PRINTF(1, 0)
xwl_log_handler(const char * format,va_list args)274 xwl_log_handler(const char *format, va_list args)
275 {
276     char msg[256];
277 
278     vsnprintf(msg, sizeof msg, format, args);
279     FatalError("%s", msg);
280 }
281 
282 static const ExtensionModule xwayland_extensions[] = {
283 #ifdef XF86VIDMODE
284     { xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
285     { xwlExtensionInit, XWAYLANDNAME, &noXwaylandExtension },
286 #endif
287 };
288 
289 void
InitOutput(ScreenInfo * screen_info,int argc,char ** argv)290 InitOutput(ScreenInfo * screen_info, int argc, char **argv)
291 {
292     int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
293     int bpp[] =    { 1, 8, 8, 16, 16, 32, 32 };
294     int i;
295 
296     for (i = 0; i < ARRAY_SIZE(depths); i++) {
297         screen_info->formats[i].depth = depths[i];
298         screen_info->formats[i].bitsPerPixel = bpp[i];
299         screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
300     }
301 
302     screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
303     screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
304     screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
305     screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
306     screen_info->numPixmapFormats = ARRAY_SIZE(depths);
307 
308     if (serverGeneration == 1) {
309         try_raising_nofile_limit();
310         LoadExtensionList(xwayland_extensions,
311                           ARRAY_SIZE(xwayland_extensions), FALSE);
312     }
313 
314     wl_log_set_handler_client(xwl_log_handler);
315 
316     if (AddScreen(xwl_screen_init, argc, argv) == -1) {
317         FatalError("Couldn't add screen\n");
318     }
319 
320     xorgGlxCreateVendor();
321 
322     LocalAccessScopeUser();
323 
324     if (wm_fd >= 0 || init_fd >= 0) {
325         if (wm_fd >= 0)
326             TimerSet(NULL, 0, 1, add_client_fd, NULL);
327         if (init_fd >= 0)
328             ListenOnOpenFD(init_fd, FALSE);
329         AddCallback(&SelectionCallback, wm_selection_callback, NULL);
330     }
331     else if (listen_fd_count > 0) {
332         listen_on_fds();
333     }
334 }
335