- Separate application calls to ShowOwnedPopups from Wine calls (in
[wine] / scheduler / client.c
1 /*
2  * Client part of the client/server communication
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <ctype.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <pwd.h>
14 #include <signal.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #ifdef HAVE_SYS_SOCKET_H
19 # include <sys/socket.h>
20 #endif
21 #ifdef HAVE_SYS_WAIT_H
22 #include <sys/wait.h>
23 #endif
24 #include <sys/un.h>
25 #ifdef HAVE_SYS_MMAN_H
26 #include <sys/mman.h>
27 #endif
28 #include <sys/stat.h>
29 #include <sys/uio.h>
30 #include <unistd.h>
31 #include <stdarg.h>
32
33 #include "process.h"
34 #include "thread.h"
35 #include "server.h"
36 #include "winerror.h"
37 #include "options.h"
38
39 /* Some versions of glibc don't define this */
40 #ifndef SCM_RIGHTS
41 #define SCM_RIGHTS 1
42 #endif
43
44 #define CONFDIR    "/.wine"        /* directory for Wine config relative to $HOME */
45 #define SERVERDIR  "/wineserver-"  /* server socket directory (hostname appended) */
46 #define SOCKETNAME "socket"        /* name of the socket file */
47
48 /* data structure used to pass an fd with sendmsg/recvmsg */
49 struct cmsg_fd
50 {
51     int len;   /* sizeof structure */
52     int level; /* SOL_SOCKET */
53     int type;  /* SCM_RIGHTS */
54     int fd;    /* fd to pass */
55 };
56
57 static void *boot_thread_id;
58
59
60 /* die on a fatal error; use only during initialization */
61 static void fatal_error( const char *err, ... ) WINE_NORETURN;
62 static void fatal_error( const char *err, ... )
63 {
64     va_list args;
65
66     va_start( args, err );
67     fprintf( stderr, "wine: " );
68     vfprintf( stderr, err, args );
69     va_end( args );
70     exit(1);
71 }
72
73 /* die on a fatal error; use only during initialization */
74 static void fatal_perror( const char *err, ... ) WINE_NORETURN;
75 static void fatal_perror( const char *err, ... )
76 {
77     va_list args;
78
79     va_start( args, err );
80     fprintf( stderr, "wine: " );
81     vfprintf( stderr, err, args );
82     perror( " " );
83     va_end( args );
84     exit(1);
85 }
86
87 /***********************************************************************
88  *           server_protocol_error
89  */
90 void server_protocol_error( const char *err, ... )
91 {
92     va_list args;
93
94     va_start( args, err );
95     fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
96     vfprintf( stderr, err, args );
97     va_end( args );
98     SYSDEPS_ExitThread(1);
99 }
100
101
102 /***********************************************************************
103  *           server_perror
104  */
105 static void server_perror( const char *err )
106 {
107     fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
108     perror( err );
109     SYSDEPS_ExitThread(1);
110 }
111
112
113 /***********************************************************************
114  *           send_request
115  *
116  * Send a request to the server.
117  */
118 static void send_request( enum request req )
119 {
120     int ret;
121     if ((ret = write( NtCurrentTeb()->socket, &req, sizeof(req) )) == sizeof(req))
122         return;
123     if (ret == -1)
124     {
125         if (errno == EPIPE) SYSDEPS_ExitThread(0);
126         server_perror( "sendmsg" );
127     }
128     server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
129 }
130
131 /***********************************************************************
132  *           send_request_fd
133  *
134  * Send a request to the server, passing a file descriptor.
135  */
136 static void send_request_fd( enum request req, int fd )
137 {
138     int ret;
139 #ifndef HAVE_MSGHDR_ACCRIGHTS
140     struct cmsg_fd cmsg;
141 #endif
142     struct msghdr msghdr;
143     struct iovec vec;
144
145     vec.iov_base = (void *)&req;
146     vec.iov_len  = sizeof(req);
147
148     msghdr.msg_name    = NULL;
149     msghdr.msg_namelen = 0;
150     msghdr.msg_iov     = &vec;
151     msghdr.msg_iovlen  = 1;
152
153 #ifdef HAVE_MSGHDR_ACCRIGHTS
154     msghdr.msg_accrights    = (void *)&fd;
155     msghdr.msg_accrightslen = sizeof(fd);
156 #else  /* HAVE_MSGHDR_ACCRIGHTS */
157     cmsg.len   = sizeof(cmsg);
158     cmsg.level = SOL_SOCKET;
159     cmsg.type  = SCM_RIGHTS;
160     cmsg.fd    = fd;
161     msghdr.msg_control    = &cmsg;
162     msghdr.msg_controllen = sizeof(cmsg);
163     msghdr.msg_flags      = 0;
164 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
165
166     if ((ret = sendmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(req)) return;
167     if (ret == -1)
168     {
169         if (errno == EPIPE) SYSDEPS_ExitThread(0);
170         server_perror( "sendmsg" );
171     }
172     server_protocol_error( "partial msg sent %d/%d\n", ret, sizeof(req) );
173 }
174
175 /***********************************************************************
176  *           wait_reply
177  *
178  * Wait for a reply from the server.
179  */
180 static unsigned int wait_reply(void)
181 {
182     int ret;
183     unsigned int res;
184
185     for (;;)
186     {
187         if ((ret = read( NtCurrentTeb()->socket, &res, sizeof(res) )) == sizeof(res))
188             return res;
189         if (!ret) break;
190         if (ret == -1)
191         {
192             if (errno == EINTR) continue;
193             if (errno == EPIPE) break;
194             server_perror("read");
195         }
196         server_protocol_error( "partial msg received %d/%d\n", ret, sizeof(res) );
197     }
198     /* the server closed the connection; time to die... */
199     SYSDEPS_ExitThread(0);
200 }
201
202
203 /***********************************************************************
204  *           wait_reply_fd
205  *
206  * Wait for a reply from the server, when a file descriptor is passed.
207  */
208 static unsigned int wait_reply_fd( int *fd )
209 {
210     struct iovec vec;
211     int ret;
212     unsigned int res;
213
214 #ifdef HAVE_MSGHDR_ACCRIGHTS
215     struct msghdr msghdr;
216
217     *fd = -1;
218     msghdr.msg_accrights    = (void *)fd;
219     msghdr.msg_accrightslen = sizeof(*fd);
220 #else  /* HAVE_MSGHDR_ACCRIGHTS */
221     struct msghdr msghdr;
222     struct cmsg_fd cmsg;
223
224     cmsg.len   = sizeof(cmsg);
225     cmsg.level = SOL_SOCKET;
226     cmsg.type  = SCM_RIGHTS;
227     cmsg.fd    = -1;
228     msghdr.msg_control    = &cmsg;
229     msghdr.msg_controllen = sizeof(cmsg);
230     msghdr.msg_flags      = 0;
231 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
232
233     msghdr.msg_name    = NULL;
234     msghdr.msg_namelen = 0;
235     msghdr.msg_iov     = &vec;
236     msghdr.msg_iovlen  = 1;
237     vec.iov_base = (void *)&res;
238     vec.iov_len  = sizeof(res);
239
240     for (;;)
241     {
242         if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) == sizeof(res))
243         {
244 #ifndef HAVE_MSGHDR_ACCRIGHTS
245             *fd = cmsg.fd;
246 #endif
247             return res;
248         }
249         if (!ret) break;
250         if (ret == -1)
251         {
252             if (errno == EINTR) continue;
253             if (errno == EPIPE) break;
254             server_perror("recvmsg");
255         }
256         server_protocol_error( "partial seq received %d/%d\n", ret, sizeof(res) );
257     }
258     /* the server closed the connection; time to die... */
259     SYSDEPS_ExitThread(0);
260 }
261
262
263 /***********************************************************************
264  *           server_call_noerr
265  *
266  * Perform a server call.
267  */
268 unsigned int server_call_noerr( enum request req )
269 {
270     send_request( req );
271     return wait_reply();
272 }
273
274
275 /***********************************************************************
276  *           server_call_fd
277  *
278  * Perform a server call, passing a file descriptor.
279  * If *fd is != -1, it will be passed to the server.
280  * If the server passes an fd, it will be stored into *fd.
281  */
282 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
283 {
284     unsigned int res;
285
286     if (fd_out == -1) send_request( req );
287     else send_request_fd( req, fd_out );
288
289     if (fd_in) res = wait_reply_fd( fd_in );
290     else res = wait_reply();
291     if (res) SetLastError( RtlNtStatusToDosError(res) );
292     return res;  /* error code */
293 }
294
295
296 /***********************************************************************
297  *           get_config_dir
298  *
299  * Return the configuration directory ($WINEPREFIX or $HOME/.wine)
300  */
301 const char *get_config_dir(void)
302 {
303     static char *confdir;
304     if (!confdir)
305     {
306         const char *prefix = getenv( "WINEPREFIX" );
307         if (prefix)
308         {
309             int len = strlen(prefix);
310             if (!(confdir = strdup( prefix ))) fatal_error( "out of memory\n" );
311             if (len > 1 && confdir[len-1] == '/') confdir[len-1] = 0;
312         }
313         else
314         {
315             const char *home = getenv( "HOME" );
316             if (!home)
317             {
318                 struct passwd *pwd = getpwuid( getuid() );
319                 if (!pwd) fatal_error( "could not find your home directory\n" );
320                 home = pwd->pw_dir;
321             }
322             if (!(confdir = malloc( strlen(home) + strlen(CONFDIR) + 1 )))
323                 fatal_error( "out of memory\n" );
324             strcpy( confdir, home );
325             strcat( confdir, CONFDIR );
326         }
327         mkdir( confdir, 0755 );  /* just in case */
328     }
329     return confdir;
330 }
331
332
333 /***********************************************************************
334  *           start_server
335  *
336  * Start a new wine server.
337  */
338 static void start_server( const char *oldcwd )
339 {
340     static int started;  /* we only try once */
341     char *path, *p;
342     if (!started)
343     {
344         int status;
345         int pid = fork();
346         if (pid == -1) fatal_perror( "fork" );
347         if (!pid)
348         {
349             /* first try the installation dir */
350             execl( BINDIR "/wineserver", "wineserver", NULL );
351
352             /* now try the dir we were launched from */
353             if (full_argv0)
354             {
355                 if (!(path = malloc( strlen(full_argv0) + 20 )))
356                     fatal_error( "out of memory\n" );
357                 if ((p = strrchr( strcpy( path, full_argv0 ), '/' )))
358                 {
359                     strcpy( p, "/wineserver" );
360                     execl( path, "wineserver", NULL );
361                     strcpy( p, "/server/wineserver" );
362                     execl( path, "wineserver", NULL );
363                 }
364                 free(path);
365             }
366
367             /* now try the path */
368             execlp( "wineserver", "wineserver", NULL );
369
370             /* and finally the current dir */
371             if (!(path = malloc( strlen(oldcwd) + 20 )))
372                 fatal_error( "out of memory\n" );
373             p = strcpy( path, oldcwd ) + strlen( oldcwd );
374             strcpy( p, "/wineserver" );
375             execl( path, "wineserver", NULL );
376             strcpy( p, "/server/wineserver" );
377             execl( path, "wineserver", NULL );
378             free(path);
379             fatal_error( "could not exec wineserver\n" );
380         }
381         started = 1;
382         waitpid( pid, &status, 0 );
383         status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
384         if (status) exit(status);  /* server failed */
385     }
386 }
387
388 /***********************************************************************
389  *           server_connect
390  *
391  * Attempt to connect to an existing server socket.
392  * We need to be in the server directory already.
393  */
394 static int server_connect( const char *oldcwd, const char *serverdir )
395 {
396     struct sockaddr_un addr;
397     struct stat st;
398     int s, slen, retry;
399
400     /* chdir to the server directory */
401     if (chdir( serverdir ) == -1)
402     {
403         if (errno != ENOENT) fatal_perror( "chdir to %s", serverdir );
404         start_server( "." );
405         if (chdir( serverdir ) == -1) fatal_perror( "chdir to %s", serverdir );
406     }
407
408     /* make sure we are at the right place */
409     if (stat( ".", &st ) == -1) fatal_perror( "stat %s", serverdir );
410     if (st.st_uid != getuid()) fatal_error( "'%s' is not owned by you\n", serverdir );
411     if (st.st_mode & 077) fatal_error( "'%s' must not be accessible by other users\n", serverdir );
412
413     for (retry = 0; retry < 3; retry++)
414     {
415         /* if not the first try, wait a bit to leave the server time to exit */
416         if (retry) usleep( 100000 * retry * retry );
417
418         /* check for an existing socket */
419         if (lstat( SOCKETNAME, &st ) == -1)
420         {
421             if (errno != ENOENT) fatal_perror( "lstat %s/%s", serverdir, SOCKETNAME );
422             start_server( oldcwd );
423             if (lstat( SOCKETNAME, &st ) == -1) fatal_perror( "lstat %s/%s", serverdir, SOCKETNAME );
424         }
425
426         /* make sure the socket is sane */
427         if (!S_ISSOCK(st.st_mode))
428             fatal_error( "'%s/%s' is not a socket\n", serverdir, SOCKETNAME );
429         if (st.st_uid != getuid())
430             fatal_error( "'%s/%s' is not owned by you\n", serverdir, SOCKETNAME );
431
432         /* try to connect to it */
433         addr.sun_family = AF_UNIX;
434         strcpy( addr.sun_path, SOCKETNAME );
435         slen = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path) + 1;
436 #ifdef HAVE_SOCKADDR_SUN_LEN
437         addr.sun_len = slen;
438 #endif
439         if ((s = socket( AF_UNIX, SOCK_STREAM, 0 )) == -1) fatal_perror( "socket" );
440         if (connect( s, (struct sockaddr *)&addr, slen ) != -1)
441         {
442             fcntl( s, F_SETFD, 1 ); /* set close on exec flag */
443             return s;
444         }
445         close( s );
446     }
447     fatal_error( "file '%s/%s' exists,\n"
448                  "   but I cannot connect to it; maybe the server has crashed?\n"
449                  "   If this is the case, you should remove this socket file and try again.\n",
450                  serverdir, SOCKETNAME );
451 }
452
453
454 /***********************************************************************
455  *           CLIENT_InitServer
456  *
457  * Start the server and create the initial socket pair.
458  */
459 int CLIENT_InitServer(void)
460 {
461     int fd, size;
462     char hostname[64];
463     char *oldcwd, *serverdir;
464     const char *configdir;
465
466     /* retrieve the current directory */
467     for (size = 512; ; size *= 2)
468     {
469         if (!(oldcwd = malloc( size ))) break;
470         if (getcwd( oldcwd, size )) break;
471         free( oldcwd );
472         if (errno == ERANGE) continue;
473         oldcwd = NULL;
474         break;
475     }
476
477     /* if argv[0] is a relative path, make it absolute */
478     full_argv0 = argv0;
479     if (oldcwd && argv0[0] != '/' && strchr( argv0, '/' ))
480     {
481         char *new_argv0 = malloc( strlen(oldcwd) + strlen(argv0) + 2 );
482         if (new_argv0)
483         {
484             strcpy( new_argv0, oldcwd );
485             strcat( new_argv0, "/" );
486             strcat( new_argv0, argv0 );
487             full_argv0 = new_argv0;
488         }
489     }
490
491     /* get the server directory name */
492     if (gethostname( hostname, sizeof(hostname) ) == -1) fatal_perror( "gethostname" );
493     configdir = get_config_dir();
494     serverdir = malloc( strlen(configdir) + strlen(SERVERDIR) + strlen(hostname) + 1 );
495     if (!serverdir) fatal_error( "out of memory\n" );
496     strcpy( serverdir, configdir );
497     strcat( serverdir, SERVERDIR );
498     strcat( serverdir, hostname );
499
500     /* connect to the server */
501     fd = server_connect( oldcwd, serverdir );
502
503     /* switch back to the starting directory */
504     if (oldcwd)
505     {
506         chdir( oldcwd );
507         free( oldcwd );
508     }
509     return fd;
510 }
511
512
513 /***********************************************************************
514  *           CLIENT_InitThread
515  *
516  * Send an init thread request. Return 0 if OK.
517  */
518 int CLIENT_InitThread(void)
519 {
520     struct get_thread_buffer_request *first_req;
521     struct init_thread_request *req;
522     TEB *teb = NtCurrentTeb();
523     int fd;
524
525     /* ignore SIGPIPE so that we get a EPIPE error instead  */
526     signal( SIGPIPE, SIG_IGN );
527
528     if (wait_reply_fd( &fd ) || (fd == -1))
529         server_protocol_error( "no fd passed on first request\n" );
530     if ((teb->buffer_size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
531     teb->buffer = mmap( 0, teb->buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
532     close( fd );
533     if (teb->buffer == (void*)-1) server_perror( "mmap" );
534     first_req = teb->buffer;
535     teb->pid = first_req->pid;
536     teb->tid = first_req->tid;
537     if (first_req->version != SERVER_PROTOCOL_VERSION)
538         server_protocol_error( "version mismatch %d/%d.\n"
539                                "Your %s binary was not upgraded correctly,\n"
540                                "or you have an older one somewhere in your PATH.\n",
541                                first_req->version, SERVER_PROTOCOL_VERSION,
542                                (first_req->version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
543     if (first_req->boot) boot_thread_id = teb->tid;
544     else if (boot_thread_id == teb->tid) boot_thread_id = 0;
545
546     req = teb->buffer;
547     req->unix_pid = getpid();
548     req->teb      = teb;
549     req->entry    = teb->entry_point;
550     return server_call_noerr( REQ_INIT_THREAD );
551 }
552
553 /***********************************************************************
554  *           CLIENT_BootDone
555  *
556  * Signal that we have finished booting, and set debug level.
557  */
558 int CLIENT_BootDone( int debug_level )
559 {
560     struct boot_done_request *req = get_req_buffer();
561     req->debug_level = debug_level;
562     return server_call( REQ_BOOT_DONE );
563 }
564
565
566 /***********************************************************************
567  *           CLIENT_IsBootThread
568  *
569  * Return TRUE if current thread is the boot thread.
570  */
571 int CLIENT_IsBootThread(void)
572 {
573     return (GetCurrentThreadId() == (DWORD)boot_thread_id);
574 }