Fix PrintDlg collate icons. Add orientation icons.
[wine.git] / scheduler / client.c
blobe6720c24b5a6d33d47e4a0a2d747b41541a92b56
1 /*
2 * Client part of the client/server communication
4 * Copyright (C) 1998 Alexandre Julliard
5 */
7 #include "config.h"
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>
33 #include "process.h"
34 #include "thread.h"
35 #include "server.h"
36 #include "winerror.h"
37 #include "options.h"
39 /* Some versions of glibc don't define this */
40 #ifndef SCM_RIGHTS
41 #define SCM_RIGHTS 1
42 #endif
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 */
48 /* data structure used to pass an fd with sendmsg/recvmsg */
49 struct cmsg_fd
51 int len; /* sizeof structure */
52 int level; /* SOL_SOCKET */
53 int type; /* SCM_RIGHTS */
54 int fd; /* fd to pass */
57 static void *boot_thread_id;
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, ... )
64 va_list args;
66 va_start( args, err );
67 fprintf( stderr, "wine: " );
68 vfprintf( stderr, err, args );
69 va_end( args );
70 exit(1);
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, ... )
77 va_list args;
79 va_start( args, err );
80 fprintf( stderr, "wine: " );
81 vfprintf( stderr, err, args );
82 perror( " " );
83 va_end( args );
84 exit(1);
87 /***********************************************************************
88 * server_protocol_error
90 void server_protocol_error( const char *err, ... )
92 va_list args;
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);
102 /***********************************************************************
103 * server_perror
105 static void server_perror( const char *err )
107 fprintf( stderr, "Client protocol error:%p: ", NtCurrentTeb()->tid );
108 perror( err );
109 SYSDEPS_ExitThread(1);
113 /***********************************************************************
114 * server_exception_handler
116 DWORD server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
117 CONTEXT *context, EXCEPTION_FRAME **pdispatcher )
119 struct __server_exception_frame *server_frame = (struct __server_exception_frame *)frame;
120 if ((record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
121 *NtCurrentTeb()->buffer_info = server_frame->info;
122 return ExceptionContinueSearch;
126 /***********************************************************************
127 * server_alloc_req
129 void *server_alloc_req( size_t fixed_size, size_t var_size )
131 unsigned int pos = NtCurrentTeb()->buffer_info->cur_pos;
132 union generic_request *req = (union generic_request *)((char *)NtCurrentTeb()->buffer + pos);
133 size_t size = sizeof(*req) + var_size;
135 assert( fixed_size <= sizeof(*req) );
136 assert( var_size <= REQUEST_MAX_VAR_SIZE );
138 if ((char *)req + size > (char *)NtCurrentTeb()->buffer_info)
139 server_protocol_error( "buffer overflow %d bytes\n",
140 (char *)req + size - (char *)NtCurrentTeb()->buffer_info );
141 NtCurrentTeb()->buffer_info->cur_pos = pos + size;
142 req->header.fixed_size = fixed_size;
143 req->header.var_size = var_size;
144 return req;
148 /***********************************************************************
149 * send_request
151 * Send a request to the server.
153 static void send_request( enum request req, struct request_header *header )
155 header->req = req;
156 NtCurrentTeb()->buffer_info->cur_req = (char *)header - (char *)NtCurrentTeb()->buffer;
157 /* write a single byte; the value is ignored anyway */
158 if (write( NtCurrentTeb()->socket, header, 1 ) == -1)
160 if (errno == EPIPE) SYSDEPS_ExitThread(0);
161 server_perror( "sendmsg" );
165 /***********************************************************************
166 * send_request_fd
168 * Send a request to the server, passing a file descriptor.
170 static void send_request_fd( enum request req, struct request_header *header, int fd )
172 #ifndef HAVE_MSGHDR_ACCRIGHTS
173 struct cmsg_fd cmsg;
174 #endif
175 struct msghdr msghdr;
176 struct iovec vec;
178 /* write a single byte; the value is ignored anyway */
179 vec.iov_base = (void *)header;
180 vec.iov_len = 1;
182 msghdr.msg_name = NULL;
183 msghdr.msg_namelen = 0;
184 msghdr.msg_iov = &vec;
185 msghdr.msg_iovlen = 1;
187 #ifdef HAVE_MSGHDR_ACCRIGHTS
188 msghdr.msg_accrights = (void *)&fd;
189 msghdr.msg_accrightslen = sizeof(fd);
190 #else /* HAVE_MSGHDR_ACCRIGHTS */
191 cmsg.len = sizeof(cmsg);
192 cmsg.level = SOL_SOCKET;
193 cmsg.type = SCM_RIGHTS;
194 cmsg.fd = fd;
195 msghdr.msg_control = &cmsg;
196 msghdr.msg_controllen = sizeof(cmsg);
197 msghdr.msg_flags = 0;
198 #endif /* HAVE_MSGHDR_ACCRIGHTS */
200 header->req = req;
202 if (sendmsg( NtCurrentTeb()->socket, &msghdr, 0 ) == -1)
204 if (errno == EPIPE) SYSDEPS_ExitThread(0);
205 server_perror( "sendmsg" );
209 /***********************************************************************
210 * wait_reply
212 * Wait for a reply from the server.
214 static void wait_reply(void)
216 int ret;
217 char dummy[1];
219 for (;;)
221 if ((ret = read( NtCurrentTeb()->socket, dummy, 1 )) > 0) return;
222 if (!ret) break;
223 if (errno == EINTR) continue;
224 if (errno == EPIPE) break;
225 server_perror("read");
227 /* the server closed the connection; time to die... */
228 SYSDEPS_ExitThread(0);
232 /***********************************************************************
233 * wait_reply_fd
235 * Wait for a reply from the server, when a file descriptor is passed.
237 static void wait_reply_fd( int *fd )
239 struct iovec vec;
240 int ret;
241 char dummy[1];
243 #ifdef HAVE_MSGHDR_ACCRIGHTS
244 struct msghdr msghdr;
246 *fd = -1;
247 msghdr.msg_accrights = (void *)fd;
248 msghdr.msg_accrightslen = sizeof(*fd);
249 #else /* HAVE_MSGHDR_ACCRIGHTS */
250 struct msghdr msghdr;
251 struct cmsg_fd cmsg;
253 cmsg.len = sizeof(cmsg);
254 cmsg.level = SOL_SOCKET;
255 cmsg.type = SCM_RIGHTS;
256 cmsg.fd = -1;
257 msghdr.msg_control = &cmsg;
258 msghdr.msg_controllen = sizeof(cmsg);
259 msghdr.msg_flags = 0;
260 #endif /* HAVE_MSGHDR_ACCRIGHTS */
262 msghdr.msg_name = NULL;
263 msghdr.msg_namelen = 0;
264 msghdr.msg_iov = &vec;
265 msghdr.msg_iovlen = 1;
266 vec.iov_base = (void *)dummy;
267 vec.iov_len = 1;
269 for (;;)
271 if ((ret = recvmsg( NtCurrentTeb()->socket, &msghdr, 0 )) > 0)
273 #ifndef HAVE_MSGHDR_ACCRIGHTS
274 *fd = cmsg.fd;
275 #endif
276 return;
278 if (!ret) break;
279 if (errno == EINTR) continue;
280 if (errno == EPIPE) break;
281 server_perror("recvmsg");
283 /* the server closed the connection; time to die... */
284 SYSDEPS_ExitThread(0);
288 /***********************************************************************
289 * server_call_noerr
291 * Perform a server call.
293 unsigned int server_call_noerr( enum request req )
295 void *req_ptr = get_req_buffer();
296 send_request( req, req_ptr );
297 wait_reply();
298 return ((struct request_header *)req_ptr)->error;
302 /***********************************************************************
303 * server_call_fd
305 * Perform a server call, passing a file descriptor.
306 * If *fd is != -1, it will be passed to the server.
307 * If the server passes an fd, it will be stored into *fd.
309 unsigned int server_call_fd( enum request req, int fd_out, int *fd_in )
311 unsigned int res;
312 void *req_ptr = get_req_buffer();
314 if (fd_out == -1) send_request( req, req_ptr );
315 else send_request_fd( req, req_ptr, fd_out );
317 if (fd_in) wait_reply_fd( fd_in );
318 else wait_reply();
320 if ((res = ((struct request_header *)req_ptr)->error))
321 SetLastError( RtlNtStatusToDosError(res) );
322 return res; /* error code */
326 /***********************************************************************
327 * get_config_dir
329 * Return the configuration directory ($WINEPREFIX or $HOME/.wine)
331 const char *get_config_dir(void)
333 static char *confdir;
334 if (!confdir)
336 const char *prefix = getenv( "WINEPREFIX" );
337 if (prefix)
339 int len = strlen(prefix);
340 if (!(confdir = strdup( prefix ))) fatal_error( "out of memory\n" );
341 if (len > 1 && confdir[len-1] == '/') confdir[len-1] = 0;
343 else
345 const char *home = getenv( "HOME" );
346 if (!home)
348 struct passwd *pwd = getpwuid( getuid() );
349 if (!pwd) fatal_error( "could not find your home directory\n" );
350 home = pwd->pw_dir;
352 if (!(confdir = malloc( strlen(home) + strlen(CONFDIR) + 1 )))
353 fatal_error( "out of memory\n" );
354 strcpy( confdir, home );
355 strcat( confdir, CONFDIR );
357 mkdir( confdir, 0755 ); /* just in case */
359 return confdir;
363 /***********************************************************************
364 * start_server
366 * Start a new wine server.
368 static void start_server( const char *oldcwd )
370 static int started; /* we only try once */
371 char *path, *p;
372 if (!started)
374 int status;
375 int pid = fork();
376 if (pid == -1) fatal_perror( "fork" );
377 if (!pid)
379 /* if server is explicitly specified, use this */
380 if ((p = getenv("WINESERVER")))
382 execl( p, "wineserver", NULL );
383 fatal_perror( "could not exec the server '%s'\n"
384 " specified in the WINESERVER environment variable", p );
387 /* first try the installation dir */
388 execl( BINDIR "/wineserver", "wineserver", NULL );
390 /* now try the dir we were launched from */
391 if (full_argv0)
393 if (!(path = malloc( strlen(full_argv0) + 20 )))
394 fatal_error( "out of memory\n" );
395 if ((p = strrchr( strcpy( path, full_argv0 ), '/' )))
397 strcpy( p, "/wineserver" );
398 execl( path, "wineserver", NULL );
399 strcpy( p, "/server/wineserver" );
400 execl( path, "wineserver", NULL );
402 free(path);
405 /* now try the path */
406 execlp( "wineserver", "wineserver", NULL );
408 /* and finally the current dir */
409 if (!(path = malloc( strlen(oldcwd) + 20 )))
410 fatal_error( "out of memory\n" );
411 p = strcpy( path, oldcwd ) + strlen( oldcwd );
412 strcpy( p, "/wineserver" );
413 execl( path, "wineserver", NULL );
414 strcpy( p, "/server/wineserver" );
415 execl( path, "wineserver", NULL );
416 free(path);
417 fatal_error( "could not exec wineserver\n" );
419 started = 1;
420 waitpid( pid, &status, 0 );
421 status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
422 if (status) exit(status); /* server failed */
426 /***********************************************************************
427 * server_connect
429 * Attempt to connect to an existing server socket.
430 * We need to be in the server directory already.
432 static int server_connect( const char *oldcwd, const char *serverdir )
434 struct sockaddr_un addr;
435 struct stat st;
436 int s, slen, retry;
438 /* chdir to the server directory */
439 if (chdir( serverdir ) == -1)
441 if (errno != ENOENT) fatal_perror( "chdir to %s", serverdir );
442 start_server( "." );
443 if (chdir( serverdir ) == -1) fatal_perror( "chdir to %s", serverdir );
446 /* make sure we are at the right place */
447 if (stat( ".", &st ) == -1) fatal_perror( "stat %s", serverdir );
448 if (st.st_uid != getuid()) fatal_error( "'%s' is not owned by you\n", serverdir );
449 if (st.st_mode & 077) fatal_error( "'%s' must not be accessible by other users\n", serverdir );
451 for (retry = 0; retry < 3; retry++)
453 /* if not the first try, wait a bit to leave the server time to exit */
454 if (retry) usleep( 100000 * retry * retry );
456 /* check for an existing socket */
457 if (lstat( SOCKETNAME, &st ) == -1)
459 if (errno != ENOENT) fatal_perror( "lstat %s/%s", serverdir, SOCKETNAME );
460 start_server( oldcwd );
461 if (lstat( SOCKETNAME, &st ) == -1) fatal_perror( "lstat %s/%s", serverdir, SOCKETNAME );
464 /* make sure the socket is sane */
465 if (!S_ISSOCK(st.st_mode))
466 fatal_error( "'%s/%s' is not a socket\n", serverdir, SOCKETNAME );
467 if (st.st_uid != getuid())
468 fatal_error( "'%s/%s' is not owned by you\n", serverdir, SOCKETNAME );
470 /* try to connect to it */
471 addr.sun_family = AF_UNIX;
472 strcpy( addr.sun_path, SOCKETNAME );
473 slen = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path) + 1;
474 #ifdef HAVE_SOCKADDR_SUN_LEN
475 addr.sun_len = slen;
476 #endif
477 if ((s = socket( AF_UNIX, SOCK_STREAM, 0 )) == -1) fatal_perror( "socket" );
478 if (connect( s, (struct sockaddr *)&addr, slen ) != -1)
480 fcntl( s, F_SETFD, 1 ); /* set close on exec flag */
481 return s;
483 close( s );
485 fatal_error( "file '%s/%s' exists,\n"
486 " but I cannot connect to it; maybe the server has crashed?\n"
487 " If this is the case, you should remove this socket file and try again.\n",
488 serverdir, SOCKETNAME );
492 /***********************************************************************
493 * CLIENT_InitServer
495 * Start the server and create the initial socket pair.
497 int CLIENT_InitServer(void)
499 int fd, size;
500 char hostname[64];
501 char *oldcwd, *serverdir;
502 const char *configdir;
504 /* retrieve the current directory */
505 for (size = 512; ; size *= 2)
507 if (!(oldcwd = malloc( size ))) break;
508 if (getcwd( oldcwd, size )) break;
509 free( oldcwd );
510 if (errno == ERANGE) continue;
511 oldcwd = NULL;
512 break;
515 /* if argv[0] is a relative path, make it absolute */
516 full_argv0 = argv0;
517 if (oldcwd && argv0[0] != '/' && strchr( argv0, '/' ))
519 char *new_argv0 = malloc( strlen(oldcwd) + strlen(argv0) + 2 );
520 if (new_argv0)
522 strcpy( new_argv0, oldcwd );
523 strcat( new_argv0, "/" );
524 strcat( new_argv0, argv0 );
525 full_argv0 = new_argv0;
529 /* get the server directory name */
530 if (gethostname( hostname, sizeof(hostname) ) == -1) fatal_perror( "gethostname" );
531 configdir = get_config_dir();
532 serverdir = malloc( strlen(configdir) + strlen(SERVERDIR) + strlen(hostname) + 1 );
533 if (!serverdir) fatal_error( "out of memory\n" );
534 strcpy( serverdir, configdir );
535 strcat( serverdir, SERVERDIR );
536 strcat( serverdir, hostname );
538 /* connect to the server */
539 fd = server_connect( oldcwd, serverdir );
541 /* switch back to the starting directory */
542 if (oldcwd)
544 chdir( oldcwd );
545 free( oldcwd );
547 return fd;
551 /***********************************************************************
552 * CLIENT_InitThread
554 * Send an init thread request. Return 0 if OK.
556 int CLIENT_InitThread(void)
558 struct get_thread_buffer_request *req;
559 TEB *teb = NtCurrentTeb();
560 int fd, ret, size;
562 /* ignore SIGPIPE so that we get a EPIPE error instead */
563 signal( SIGPIPE, SIG_IGN );
565 wait_reply_fd( &fd );
566 if (fd == -1) server_protocol_error( "no fd passed on first request\n" );
568 if ((size = lseek( fd, 0, SEEK_END )) == -1) server_perror( "lseek" );
569 teb->buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
570 close( fd );
571 if (teb->buffer == (void*)-1) server_perror( "mmap" );
572 teb->buffer_info = (struct server_buffer_info *)((char *)teb->buffer + size) - 1;
574 req = (struct get_thread_buffer_request *)teb->buffer;
575 teb->pid = req->pid;
576 teb->tid = req->tid;
577 if (req->version != SERVER_PROTOCOL_VERSION)
578 server_protocol_error( "version mismatch %d/%d.\n"
579 "Your %s binary was not upgraded correctly,\n"
580 "or you have an older one somewhere in your PATH.\n",
581 req->version, SERVER_PROTOCOL_VERSION,
582 (req->version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
583 if (req->boot) boot_thread_id = teb->tid;
584 else if (boot_thread_id == teb->tid) boot_thread_id = 0;
586 SERVER_START_REQ
588 struct init_thread_request *req = server_alloc_req( sizeof(*req), 0 );
589 req->unix_pid = getpid();
590 req->teb = teb;
591 req->entry = teb->entry_point;
592 ret = server_call_noerr( REQ_INIT_THREAD );
594 SERVER_END_REQ;
595 return ret;
598 /***********************************************************************
599 * CLIENT_BootDone
601 * Signal that we have finished booting, and set debug level.
603 int CLIENT_BootDone( int debug_level )
605 int ret;
606 SERVER_START_REQ
608 struct boot_done_request *req = server_alloc_req( sizeof(*req), 0 );
609 req->debug_level = debug_level;
610 ret = server_call( REQ_BOOT_DONE );
612 SERVER_END_REQ;
613 return ret;
617 /***********************************************************************
618 * CLIENT_IsBootThread
620 * Return TRUE if current thread is the boot thread.
622 int CLIENT_IsBootThread(void)
624 return (GetCurrentThreadId() == (DWORD)boot_thread_id);