server.c 27.5 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
/*
2
 * Wine server communication
Alexandre Julliard's avatar
Alexandre Julliard committed
3 4
 *
 * Copyright (C) 1998 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Alexandre Julliard's avatar
Alexandre Julliard committed
19 20
 */

21
#include "config.h"
22
#include "wine/port.h"
23

Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <assert.h>
25
#include <ctype.h>
26
#include <dirent.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27
#include <errno.h>
28
#include <fcntl.h>
29
#include <signal.h>
30
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
31 32
#include <stdio.h>
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
33
#include <sys/types.h>
34 35 36
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
37 38 39
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
Steven Edwards's avatar
Steven Edwards committed
40
#ifdef HAVE_SYS_UN_H
41
#include <sys/un.h>
Steven Edwards's avatar
Steven Edwards committed
42
#endif
43
#ifdef HAVE_SYS_MMAN_H
44
#include <sys/mman.h>
45
#endif
46 47 48
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
Steven Edwards's avatar
Steven Edwards committed
49
#ifdef HAVE_SYS_UIO_H
Alexandre Julliard's avatar
Alexandre Julliard committed
50
#include <sys/uio.h>
Steven Edwards's avatar
Steven Edwards committed
51
#endif
52 53 54
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
55

56
#include "ntstatus.h"
57
#define WIN32_NO_STATUS
58
#include "wine/library.h"
59
#include "wine/pthread.h"
60
#include "wine/server.h"
61
#include "wine/debug.h"
62
#include "ntdll_misc.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
63

64 65
WINE_DEFAULT_DEBUG_CHANNEL(server);

Alexandre Julliard's avatar
Alexandre Julliard committed
66 67 68 69
/* Some versions of glibc don't define this */
#ifndef SCM_RIGHTS
#define SCM_RIGHTS 1
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
70

71
#define SOCKETNAME "socket"        /* name of the socket file */
72
#define LOCKNAME   "lock"          /* name of the lock file */
73

74
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
75 76 77
/* data structure used to pass an fd with sendmsg/recvmsg */
struct cmsg_fd
{
78 79 80 81 82 83 84
    struct
    {
        size_t len;   /* size of structure */
        int    level; /* SOL_SOCKET */
        int    type;  /* SCM_RIGHTS */
    } header;
    int fd;          /* fd to pass */
85
};
86
#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
Alexandre Julliard's avatar
Alexandre Julliard committed
87

88 89
time_t server_start_time = 0;  /* time of server startup */

90 91
extern struct wine_pthread_functions pthread_functions;

92
static sigset_t block_set;  /* signals to block during server calls */
93
static int fd_socket = -1;  /* socket to exchange file descriptors with the server */
94

95 96 97 98 99 100 101 102 103 104
static RTL_CRITICAL_SECTION fd_cache_section;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
{
    0, 0, &fd_cache_section,
    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
      0, 0, { (DWORD_PTR)(__FILE__ ": fd_cache_section") }
};
static RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 };


105 106 107 108 109 110
#ifdef __GNUC__
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
static void fatal_perror( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
static void server_connect_error( const char *serverdir ) __attribute__((noreturn));
#endif

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/* die on a fatal error; use only during initialization */
static void fatal_error( const char *err, ... )
{
    va_list args;

    va_start( args, err );
    fprintf( stderr, "wine: " );
    vfprintf( stderr, err, args );
    va_end( args );
    exit(1);
}

/* die on a fatal error; use only during initialization */
static void fatal_perror( const char *err, ... )
{
    va_list args;

    va_start( args, err );
    fprintf( stderr, "wine: " );
    vfprintf( stderr, err, args );
    perror( " " );
    va_end( args );
    exit(1);
}

136

137
/***********************************************************************
138
 *           server_exit_thread
139
 */
140
void server_exit_thread( int status )
141 142
{
    struct wine_pthread_thread_info info;
143
    SIZE_T size;
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

    RtlAcquirePebLock();
    RemoveEntryList( &NtCurrentTeb()->TlsLinks );
    RtlReleasePebLock();

    info.stack_base  = NtCurrentTeb()->DeallocationStack;
    info.teb_base    = NtCurrentTeb();
    info.teb_sel     = wine_get_fs();
    info.exit_status = status;

    size = 0;
    NtFreeVirtualMemory( GetCurrentProcess(), &info.stack_base, &size, MEM_RELEASE | MEM_SYSTEM );
    info.stack_size = size;

    size = 0;
    NtFreeVirtualMemory( GetCurrentProcess(), &info.teb_base, &size, MEM_RELEASE | MEM_SYSTEM );
    info.teb_size = size;

    sigprocmask( SIG_BLOCK, &block_set, NULL );
163 164 165 166
    close( ntdll_get_thread_data()->wait_fd[0] );
    close( ntdll_get_thread_data()->wait_fd[1] );
    close( ntdll_get_thread_data()->reply_fd );
    close( ntdll_get_thread_data()->request_fd );
167
    pthread_functions.exit_thread( &info );
168 169 170
}


171 172 173 174 175 176
/***********************************************************************
 *           server_abort_thread
 */
void server_abort_thread( int status )
{
    sigprocmask( SIG_BLOCK, &block_set, NULL );
177 178 179 180
    close( ntdll_get_thread_data()->wait_fd[0] );
    close( ntdll_get_thread_data()->wait_fd[1] );
    close( ntdll_get_thread_data()->reply_fd );
    close( ntdll_get_thread_data()->request_fd );
181
    pthread_functions.abort_thread( status );
182 183 184
}


Alexandre Julliard's avatar
Alexandre Julliard committed
185
/***********************************************************************
186
 *           server_protocol_error
Alexandre Julliard's avatar
Alexandre Julliard committed
187
 */
188
void server_protocol_error( const char *err, ... )
Alexandre Julliard's avatar
Alexandre Julliard committed
189 190 191 192
{
    va_list args;

    va_start( args, err );
193
    fprintf( stderr, "wine client error:%lx: ", GetCurrentThreadId() );
Alexandre Julliard's avatar
Alexandre Julliard committed
194 195
    vfprintf( stderr, err, args );
    va_end( args );
196
    server_abort_thread(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
197 198 199
}


Alexandre Julliard's avatar
Alexandre Julliard committed
200
/***********************************************************************
201
 *           server_protocol_perror
202
 */
203
void server_protocol_perror( const char *err )
204
{
205
    fprintf( stderr, "wine client error:%lx: ", GetCurrentThreadId() );
206
    perror( err );
207
    server_abort_thread(1);
208 209 210 211 212
}


/***********************************************************************
 *           send_request
Alexandre Julliard's avatar
Alexandre Julliard committed
213 214 215
 *
 * Send a request to the server.
 */
216
static void send_request( const struct __server_request_info *req )
217
{
218 219
    unsigned int i;
    int ret;
220 221 222

    if (!req->u.req.request_header.request_size)
    {
223
        if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req,
224 225 226 227 228 229 230 231 232 233 234 235 236 237
                          sizeof(req->u.req) )) == sizeof(req->u.req)) return;

    }
    else
    {
        struct iovec vec[__SERVER_MAX_DATA+1];

        vec[0].iov_base = (void *)&req->u.req;
        vec[0].iov_len = sizeof(req->u.req);
        for (i = 0; i < req->data_count; i++)
        {
            vec[i+1].iov_base = (void *)req->data[i].ptr;
            vec[i+1].iov_len = req->data[i].size;
        }
238
        if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) ==
239 240
            req->u.req.request_header.request_size + sizeof(req->u.req)) return;
    }
241 242

    if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
243
    if (errno == EPIPE) server_abort_thread(0);
244
    server_protocol_perror( "write" );
245 246
}

247

Alexandre Julliard's avatar
Alexandre Julliard committed
248
/***********************************************************************
249
 *           read_reply_data
Alexandre Julliard's avatar
Alexandre Julliard committed
250
 *
251
 * Read data from the reply buffer; helper for wait_reply.
Alexandre Julliard's avatar
Alexandre Julliard committed
252
 */
253
static void read_reply_data( void *buffer, size_t size )
Alexandre Julliard's avatar
Alexandre Julliard committed
254
{
255
    int ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
256

257
    for (;;)
Alexandre Julliard's avatar
Alexandre Julliard committed
258
    {
259
        if ((ret = read( ntdll_get_thread_data()->reply_fd, buffer, size )) > 0)
260 261 262 263 264
        {
            if (!(size -= ret)) return;
            buffer = (char *)buffer + ret;
            continue;
        }
265
        if (!ret) break;
266 267
        if (errno == EINTR) continue;
        if (errno == EPIPE) break;
268
        server_protocol_perror("read");
Alexandre Julliard's avatar
Alexandre Julliard committed
269
    }
270
    /* the server closed the connection; time to die... */
271
    server_abort_thread(0);
Alexandre Julliard's avatar
Alexandre Julliard committed
272 273 274
}


275 276 277 278 279 280 281 282 283 284 285 286 287
/***********************************************************************
 *           wait_reply
 *
 * Wait for a reply from the server.
 */
inline static void wait_reply( struct __server_request_info *req )
{
    read_reply_data( &req->u.reply, sizeof(req->u.reply) );
    if (req->u.reply.reply_header.reply_size)
        read_reply_data( req->reply_data, req->u.reply.reply_header.reply_size );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
288
/***********************************************************************
289
 *           wine_server_call (NTDLL.@)
290 291
 *
 * Perform a server call.
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
 *
 * PARAMS
 *     req_ptr [I/O] Function dependent data
 *
 * RETURNS
 *     Depends on server function being called, but usually an NTSTATUS code.
 *
 * NOTES
 *     Use the SERVER_START_REQ and SERVER_END_REQ to help you fill out the
 *     server request structure for the particular call. E.g:
 *|     SERVER_START_REQ( event_op )
 *|     {
 *|         req->handle = handle;
 *|         req->op     = SET_EVENT;
 *|         ret = wine_server_call( req );
 *|     }
 *|     SERVER_END_REQ;
309
 */
310
unsigned int wine_server_call( void *req_ptr )
311
{
312
    struct __server_request_info * const req = req_ptr;
313 314 315
    sigset_t old_set;

    sigprocmask( SIG_BLOCK, &block_set, &old_set );
316 317
    send_request( req );
    wait_reply( req );
318
    sigprocmask( SIG_SETMASK, &old_set, NULL );
319
    return req->u.reply.reply_header.error;
320 321 322 323
}


/***********************************************************************
324
 *           wine_server_send_fd   (NTDLL.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
325
 *
326
 * Send a file descriptor to the server.
327 328 329 330 331 332
 *
 * PARAMS
 *     fd [I] file descriptor to send
 *
 * RETURNS
 *     nothing
Alexandre Julliard's avatar
Alexandre Julliard committed
333
 */
334
void wine_server_send_fd( int fd )
335
{
336
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
    struct cmsg_fd cmsg;
#endif
    struct send_fd data;
    struct msghdr msghdr;
    struct iovec vec;
    int ret;

    vec.iov_base = (void *)&data;
    vec.iov_len  = sizeof(data);

    msghdr.msg_name    = NULL;
    msghdr.msg_namelen = 0;
    msghdr.msg_iov     = &vec;
    msghdr.msg_iovlen  = 1;

352
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
353 354
    msghdr.msg_accrights    = (void *)&fd;
    msghdr.msg_accrightslen = sizeof(fd);
355
#else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
356 357 358 359
    cmsg.header.len   = sizeof(cmsg.header) + sizeof(fd);
    cmsg.header.level = SOL_SOCKET;
    cmsg.header.type  = SCM_RIGHTS;
    cmsg.fd           = fd;
360
    msghdr.msg_control    = &cmsg;
361
    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
362
    msghdr.msg_flags      = 0;
363
#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
364

365
    data.tid = GetCurrentThreadId();
366 367 368 369 370 371 372
    data.fd  = fd;

    for (;;)
    {
        if ((ret = sendmsg( fd_socket, &msghdr, 0 )) == sizeof(data)) return;
        if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
        if (errno == EINTR) continue;
373
        if (errno == EPIPE) server_abort_thread(0);
374 375
        server_protocol_perror( "sendmsg" );
    }
376 377 378 379
}


/***********************************************************************
380
 *           receive_fd
381 382 383
 *
 * Receive a file descriptor passed from the server.
 */
384
static int receive_fd( obj_handle_t *handle )
Alexandre Julliard's avatar
Alexandre Julliard committed
385
{
386
    struct iovec vec;
387
    int ret, fd;
Alexandre Julliard's avatar
Alexandre Julliard committed
388

389
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
Patrik Stridvall's avatar
Patrik Stridvall committed
390 391
    struct msghdr msghdr;

392 393 394
    fd = -1;
    msghdr.msg_accrights    = (void *)&fd;
    msghdr.msg_accrightslen = sizeof(fd);
395
#else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
Patrik Stridvall's avatar
Patrik Stridvall committed
396 397 398
    struct msghdr msghdr;
    struct cmsg_fd cmsg;

399 400 401 402
    cmsg.header.len   = sizeof(cmsg.header) + sizeof(fd);
    cmsg.header.level = SOL_SOCKET;
    cmsg.header.type  = SCM_RIGHTS;
    cmsg.fd           = -1;
Patrik Stridvall's avatar
Patrik Stridvall committed
403
    msghdr.msg_control    = &cmsg;
404
    msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
Patrik Stridvall's avatar
Patrik Stridvall committed
405
    msghdr.msg_flags      = 0;
406
#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
Patrik Stridvall's avatar
Patrik Stridvall committed
407 408 409

    msghdr.msg_name    = NULL;
    msghdr.msg_namelen = 0;
410 411
    msghdr.msg_iov     = &vec;
    msghdr.msg_iovlen  = 1;
412 413
    vec.iov_base = (void *)handle;
    vec.iov_len  = sizeof(*handle);
Patrik Stridvall's avatar
Patrik Stridvall committed
414

415
    for (;;)
Alexandre Julliard's avatar
Alexandre Julliard committed
416
    {
417
        if ((ret = recvmsg( fd_socket, &msghdr, 0 )) > 0)
418
        {
419
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
420
            fd = cmsg.fd;
421
#endif
422
            if (fd != -1) fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
423
            return fd;
424
        }
425
        if (!ret) break;
426 427
        if (errno == EINTR) continue;
        if (errno == EPIPE) break;
428
        server_protocol_perror("recvmsg");
Alexandre Julliard's avatar
Alexandre Julliard committed
429
    }
430
    /* the server closed the connection; time to die... */
431
    server_abort_thread(0);
432
}
Alexandre Julliard's avatar
Alexandre Julliard committed
433 434


435 436 437
/***********************************************************************
 *           wine_server_fd_to_handle   (NTDLL.@)
 *
438 439 440 441 442
 * Allocate a file handle for a Unix file descriptor.
 *
 * PARAMS
 *     fd      [I] Unix file descriptor.
 *     access  [I] Win32 access flags.
443
 *     attributes [I] Object attributes.
444 445 446 447
 *     handle  [O] Address where Wine file handle will be stored.
 *
 * RETURNS
 *     NTSTATUS code
448
 */
449
int wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, obj_handle_t *handle )
450 451 452 453 454 455 456 457
{
    int ret;

    *handle = 0;
    wine_server_send_fd( fd );

    SERVER_START_REQ( alloc_file_handle )
    {
458
        req->access     = access;
459
        req->attributes = attributes;
460
        req->fd         = fd;
461 462 463 464 465 466 467
        if (!(ret = wine_server_call( req ))) *handle = reply->handle;
    }
    SERVER_END_REQ;
    return ret;
}


468 469 470
/***********************************************************************
 *           wine_server_handle_to_fd   (NTDLL.@)
 *
471 472 473 474 475 476 477 478 479 480
 * Retrieve the file descriptor corresponding to a file handle.
 *
 * PARAMS
 *     handle  [I] Wine file handle.
 *     access  [I] Win32 file access rights requested.
 *     unix_fd [O] Address where Unix file descriptor will be stored.
 *     flags   [O] Address where the Unix flags associated with file will be stored. Optional.
 *
 * RETURNS
 *     NTSTATUS code
481
 */
482
int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd, int *flags )
483
{
484
    obj_handle_t fd_handle;
485
    int ret, removable = -1, fd = -1;
486

487 488
    RtlEnterCriticalSection( &fd_cache_section );

489 490 491 492 493 494 495
    *unix_fd = -1;
    for (;;)
    {
        SERVER_START_REQ( get_handle_fd )
        {
            req->handle = handle;
            req->access = access;
496 497 498 499 500 501
            if (!(ret = wine_server_call( req )))
            {
                fd = reply->fd;
                removable = reply->removable;
                if (flags) *flags = reply->flags;
            }
502 503
        }
        SERVER_END_REQ;
504
        if (ret) break;
505

506 507
        if (fd != -1)
        {
508
            if ((fd = dup(fd)) == -1) ret = FILE_GetNtStatus();
509 510
            break;
        }
511 512 513

        /* it wasn't in the cache, get it from the server */
        fd = receive_fd( &fd_handle );
514 515 516 517 518
        if (fd == -1)
        {
            ret = STATUS_TOO_MANY_OPENED_FILES;
            break;
        }
519 520 521 522 523 524 525 526
        if (fd_handle != handle) removable = -1;

        if (removable == -1)
        {
            FILE_FS_DEVICE_INFORMATION info;
            if (FILE_GetDeviceInfo( fd, &info ) == STATUS_SUCCESS)
                removable = (info.Characteristics & FILE_REMOVABLE_MEDIA) != 0;
        }
527
        else if (removable) break;  /* don't cache it */
528

529
        /* and store it back into the cache */
530 531
        SERVER_START_REQ( set_handle_fd )
        {
532
            req->handle    = fd_handle;
533 534 535 536
            req->fd        = fd;
            req->removable = removable;
            if (!(ret = wine_server_call( req )))
            {
537
                if (reply->cur_fd != -1) /* it has been cached */
538
                {
539 540
                    if (reply->cur_fd != fd) close( fd );  /* someone was here before us */
                    if ((fd = dup(reply->cur_fd)) == -1) ret = FILE_GetNtStatus();
541 542 543 544 545 546 547 548 549
                }
            }
            else
            {
                close( fd );
                fd = -1;
            }
        }
        SERVER_END_REQ;
550
        if (ret) break;
551 552 553 554 555 556

        if (fd_handle == handle) break;
        /* if we received a different handle this means there was
         * a race with another thread; we restart everything from
         * scratch in this case.
         */
557
        close( fd );
558 559
    }

560 561 562
    RtlLeaveCriticalSection( &fd_cache_section );
    if (!ret) *unix_fd = fd;
    return ret;
563 564 565
}


566 567 568
/***********************************************************************
 *           wine_server_release_fd   (NTDLL.@)
 *
569 570 571 572 573 574 575 576
 * Release the Unix file descriptor returned by wine_server_handle_to_fd.
 *
 * PARAMS
 *     handle  [I] Wine file handle.
 *     unix_fd [I] Unix file descriptor to release.
 *
 * RETURNS
 *     nothing
577 578 579 580 581 582 583
 */
void wine_server_release_fd( obj_handle_t handle, int unix_fd )
{
    close( unix_fd );
}


584 585 586 587 588
/***********************************************************************
 *           start_server
 *
 * Start a new wine server.
 */
589
static void start_server(void)
590 591
{
    static int started;  /* we only try once */
592
    char *argv[3];
593

594 595
    if (!started)
    {
596
        int status;
597 598 599 600
        int pid = fork();
        if (pid == -1) fatal_perror( "fork" );
        if (!pid)
        {
601
            argv[0] = "server/wineserver";
602 603
            argv[1] = TRACE_ON(server) ? "-d" : NULL;
            argv[2] = NULL;
604
            wine_exec_wine_binary( argv[0], argv, getenv("WINESERVER") );
605 606
            fatal_error( "could not exec wineserver\n" );
        }
607 608
        waitpid( pid, &status, 0 );
        status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
609
        if (status == 2) return;  /* server lock held by someone else, will retry later */
610
        if (status) exit(status);  /* server failed */
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
        started = 1;
    }
}


/***********************************************************************
 *           server_connect_error
 *
 * Try to display a meaningful explanation of why we couldn't connect
 * to the server.
 */
static void server_connect_error( const char *serverdir )
{
    int fd;
    struct flock fl;

    if ((fd = open( LOCKNAME, O_WRONLY )) == -1)
        fatal_error( "for some mysterious reason, the wine server never started.\n" );

    fl.l_type   = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start  = 0;
    fl.l_len    = 1;
    if (fcntl( fd, F_GETLK, &fl ) != -1)
    {
        if (fl.l_type == F_WRLCK)  /* the file is locked */
            fatal_error( "a wine server seems to be running, but I cannot connect to it.\n"
                         "   You probably need to kill that process (it might be pid %d).\n",
                         (int)fl.l_pid );
        fatal_error( "for some mysterious reason, the wine server failed to run.\n" );
641
    }
642 643 644 645
    fatal_error( "the file system of '%s' doesn't support locks,\n"
          "   and there is a 'socket' file in that directory that prevents wine from starting.\n"
          "   You should make sure no wine server is running, remove that file and try again.\n",
                 serverdir );
646 647
}

648

649 650 651 652 653 654
/***********************************************************************
 *           server_connect
 *
 * Attempt to connect to an existing server socket.
 * We need to be in the server directory already.
 */
655
static int server_connect( const char *serverdir )
656 657 658
{
    struct sockaddr_un addr;
    struct stat st;
659 660 661 662 663
    int s, slen, retry, fd_cwd;

    /* retrieve the current directory */
    fd_cwd = open( ".", O_RDONLY );
    if (fd_cwd != -1) fcntl( fd_cwd, F_SETFD, 1 ); /* set close on exec flag */
664

665
    /* chdir to the server directory */
666 667 668
    if (chdir( serverdir ) == -1)
    {
        if (errno != ENOENT) fatal_perror( "chdir to %s", serverdir );
669
        start_server();
670
        if (chdir( serverdir ) == -1) fatal_perror( "chdir to %s", serverdir );
671
    }
672 673

    /* make sure we are at the right place */
674 675 676 677
    if (stat( ".", &st ) == -1) fatal_perror( "stat %s", serverdir );
    if (st.st_uid != getuid()) fatal_error( "'%s' is not owned by you\n", serverdir );
    if (st.st_mode & 077) fatal_error( "'%s' must not be accessible by other users\n", serverdir );

678
    for (retry = 0; retry < 6; retry++)
679
    {
680 681 682 683
        /* if not the first try, wait a bit to leave the previous server time to exit */
        if (retry)
        {
            usleep( 100000 * retry * retry );
684
            start_server();
685 686 687
            if (lstat( SOCKETNAME, &st ) == -1) continue;  /* still no socket, wait a bit more */
        }
        else if (lstat( SOCKETNAME, &st ) == -1) /* check for an already existing socket */
688 689
        {
            if (errno != ENOENT) fatal_perror( "lstat %s/%s", serverdir, SOCKETNAME );
690
            start_server();
691
            if (lstat( SOCKETNAME, &st ) == -1) continue;  /* still no socket, wait a bit more */
692
        }
693

694 695
        /* make sure the socket is sane (ISFIFO needed for Solaris) */
        if (!S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode))
696 697 698
            fatal_error( "'%s/%s' is not a socket\n", serverdir, SOCKETNAME );
        if (st.st_uid != getuid())
            fatal_error( "'%s/%s' is not owned by you\n", serverdir, SOCKETNAME );
699

700 701 702 703
        /* try to connect to it */
        addr.sun_family = AF_UNIX;
        strcpy( addr.sun_path, SOCKETNAME );
        slen = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path) + 1;
704
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
705
        addr.sun_len = slen;
706
#endif
707
        if ((s = socket( AF_UNIX, SOCK_STREAM, 0 )) == -1) fatal_perror( "socket" );
708 709
        if (connect( s, (struct sockaddr *)&addr, slen ) != -1)
        {
710 711 712 713 714 715
            /* switch back to the starting directory */
            if (fd_cwd != -1)
            {
                fchdir( fd_cwd );
                close( fd_cwd );
            }
716 717 718 719
            fcntl( s, F_SETFD, 1 ); /* set close on exec flag */
            return s;
        }
        close( s );
720
    }
721
    server_connect_error( serverdir );
722 723 724
}


725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
/***********************************************************************
 *           rm_rf
 *
 * Remove a directory and all its contents; helper for create_config_dir.
 */
static void rm_rf( const char *path )
{
    int err = errno;  /* preserve errno */
    DIR *dir;
    char *buffer, *p;
    struct stat st;
    struct dirent *de;

    if (!(buffer = malloc( strlen(path) + 256 + 1 ))) goto done;
    strcpy( buffer, path );
    p = buffer + strlen(buffer);
    *p++ = '/';

    if ((dir = opendir( path )))
    {
        while ((de = readdir( dir )))
        {
            if (!strcmp( de->d_name, "." ) || !strcmp( de->d_name, ".." )) continue;
            strcpy( p, de->d_name );
            if (unlink( buffer ) != -1) continue;
            if (errno == EISDIR ||
                (errno == EPERM && !lstat( buffer, &st ) && S_ISDIR(st.st_mode)))
            {
                /* recurse in the sub-directory */
                rm_rf( buffer );
            }
        }
        closedir( dir );
    }
    free( buffer );
    rmdir( path );
done:
    errno = err;
}


/***********************************************************************
 *           create_config_dir
 *
 * Create the wine configuration dir (~/.wine).
 */
static void create_config_dir(void)
{
    const char *config_dir = wine_get_config_dir();
    char *tmp_dir;
    int fd;
    pid_t pid, wret;

    if (!(tmp_dir = malloc( strlen(config_dir) + sizeof("-XXXXXX") )))
        fatal_error( "out of memory\n" );
    strcpy( tmp_dir, config_dir );
    strcat( tmp_dir, "-XXXXXX" );
    if ((fd = mkstemps( tmp_dir, 0 )) == -1)
        fatal_perror( "can't get temp file name for %s", config_dir );
    close( fd );
    unlink( tmp_dir );
    if (mkdir( tmp_dir, 0777 ) == -1)
        fatal_perror( "cannot create temp dir %s", tmp_dir );

    MESSAGE( "wine: creating configuration directory '%s'...\n", config_dir );
    pid = fork();
    if (pid == -1)
    {
        rmdir( tmp_dir );
        fatal_perror( "fork" );
    }
    if (!pid)
    {
798
        const char *argv[6];
799

800
        argv[0] = "tools/wineprefixcreate";
801
        argv[1] = "--quiet";
802 803 804 805
        argv[2] = "--wait";
        argv[3] = "--prefix";
        argv[4] = tmp_dir;
        argv[5] = NULL;
806
        wine_exec_wine_binary( argv[0], (char **)argv, NULL );
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
        rmdir( tmp_dir );
        fatal_perror( "could not exec wineprefixcreate" );
    }
    else
    {
        int status;

        while ((wret = waitpid( pid, &status, 0 )) != pid)
        {
            if (wret == -1 && errno != EINTR) fatal_perror( "wait4" );
        }
        if (!WIFEXITED(status) || WEXITSTATUS(status))
        {
            rm_rf( tmp_dir );
            fatal_error( "wineprefixcreate failed while creating '%s'.\n", config_dir );
        }
    }
    if (rename( tmp_dir, config_dir ) == -1)
    {
        rm_rf( tmp_dir );
        if (errno != EEXIST && errno != ENOTEMPTY)
            fatal_perror( "rename '%s' to '%s'", tmp_dir, config_dir );
        /* else it was probably created by a concurrent wine process */
    }
    free( tmp_dir );
    MESSAGE( "wine: '%s' created successfully.\n", config_dir );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
836
/***********************************************************************
837
 *           server_init_process
Alexandre Julliard's avatar
Alexandre Julliard committed
838
 *
839
 * Start the server and create the initial socket pair.
Alexandre Julliard's avatar
Alexandre Julliard committed
840
 */
841
void server_init_process(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
842
{
843
    obj_handle_t dummy_handle;
844 845 846 847 848 849 850
    const char *server_dir = wine_get_server_dir();

    if (!server_dir)  /* this means the config dir doesn't exist */
    {
        create_config_dir();
        server_dir = wine_get_server_dir();
    }
851

852
    /* connect to the server */
853
    fd_socket = server_connect( server_dir );
854 855 856 857 858 859 860

    /* setup the signal mask */
    sigemptyset( &block_set );
    sigaddset( &block_set, SIGALRM );
    sigaddset( &block_set, SIGIO );
    sigaddset( &block_set, SIGINT );
    sigaddset( &block_set, SIGHUP );
861 862
    sigaddset( &block_set, SIGUSR1 );
    sigaddset( &block_set, SIGUSR2 );
863
    sigaddset( &block_set, SIGCHLD );
864

865
    /* receive the first thread request fd on the main socket */
866
    ntdll_get_thread_data()->request_fd = receive_fd( &dummy_handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
867 868 869
}


870
/***********************************************************************
871
 *           server_init_thread
872 873 874
 *
 * Send an init thread request. Return 0 if OK.
 */
875
size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point )
876 877
{
    int version, ret;
878
    int reply_pipe[2];
879
    struct sigaction sig_act;
880
    size_t info_size;
881 882 883 884

    sig_act.sa_handler = SIG_IGN;
    sig_act.sa_flags   = 0;
    sigemptyset( &sig_act.sa_mask );
885

886
    /* ignore SIGPIPE so that we get an EPIPE error instead  */
887
    sigaction( SIGPIPE, &sig_act, NULL );
888
    /* automatic child reaping to avoid zombies */
889 890 891 892
#ifdef SA_NOCLDWAIT
    sig_act.sa_flags |= SA_NOCLDWAIT;
#endif
    sigaction( SIGCHLD, &sig_act, NULL );
893 894 895

    /* create the server->client communication pipes */
    if (pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
896
    if (pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
897
    wine_server_send_fd( reply_pipe[1] );
898 899
    wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
    ntdll_get_thread_data()->reply_fd = reply_pipe[0];
900
    close( reply_pipe[1] );
901 902

    /* set close on exec flag */
903 904 905
    fcntl( ntdll_get_thread_data()->reply_fd, F_SETFD, 1 );
    fcntl( ntdll_get_thread_data()->wait_fd[0], F_SETFD, 1 );
    fcntl( ntdll_get_thread_data()->wait_fd[1], F_SETFD, 1 );
906

907
    SERVER_START_REQ( init_thread )
908
    {
909 910
        req->unix_pid    = unix_pid;
        req->unix_tid    = unix_tid;
911
        req->teb         = NtCurrentTeb();
912
        req->peb         = NtCurrentTeb()->Peb;
913
        req->entry       = entry_point;
914
        req->ldt_copy    = &wine_ldt_copy;
915
        req->reply_fd    = reply_pipe[1];
916
        req->wait_fd     = ntdll_get_thread_data()->wait_fd[1];
917
        req->debug_level = (TRACE_ON(server) != 0);
918
        ret = wine_server_call( req );
919 920
        NtCurrentTeb()->ClientId.UniqueProcess = (HANDLE)reply->pid;
        NtCurrentTeb()->ClientId.UniqueThread  = (HANDLE)reply->tid;
921 922 923
        info_size         = reply->info_size;
        version           = reply->version;
        server_start_time = reply->server_start;
924 925
    }
    SERVER_END_REQ;
926 927 928 929 930 931 932 933 934

    if (ret) server_protocol_error( "init_thread failed with status %x\n", ret );
    if (version != SERVER_PROTOCOL_VERSION)
        server_protocol_error( "version mismatch %d/%d.\n"
                               "Your %s binary was not upgraded correctly,\n"
                               "or you have an older one somewhere in your PATH.\n"
                               "Or maybe the wrong wineserver is still running?\n",
                               version, SERVER_PROTOCOL_VERSION,
                               (version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
935
    return info_size;
Alexandre Julliard's avatar
Alexandre Julliard committed
936
}