wine/server/console.c
Alexandre Julliard 0562539d18 Implemented file sharing checks in the server.
Added set file time server request.
Overall clean up of the file handling (DOS device handling is now
broken, should be redone).
1999-01-03 11:55:56 +00:00

214 lines
5.6 KiB
C

/*
* Server-side console management
*
* Copyright (C) 1998 Alexandre Julliard
*
* FIXME: all this stuff is a hack to avoid breaking
* the client-side console support.
*/
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "winerror.h"
#include "winnt.h"
#include "server/thread.h"
struct console
{
struct object obj; /* object header */
int fd; /* Unix file descriptor */
int is_read; /* is this the read or write part? */
};
static void console_dump( struct object *obj, int verbose );
static int console_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int console_signaled( struct object *obj, struct thread *thread );
static int console_get_read_fd( struct object *obj );
static int console_get_write_fd( struct object *obj );
static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
static void console_destroy( struct object *obj );
static const struct object_ops console_ops =
{
console_dump,
console_add_queue,
console_remove_queue,
console_signaled,
no_satisfied,
console_get_read_fd,
console_get_write_fd,
no_flush,
console_get_info,
console_destroy
};
static const struct select_ops select_ops =
{
default_select_event,
NULL /* we never set a timeout on a console */
};
int create_console( int fd, struct object *obj[2] )
{
struct console *console_read, *console_write;
int read_fd, write_fd;
if ((read_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
{
file_set_error();
return 0;
}
if ((write_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
{
file_set_error();
close( read_fd );
return 0;
}
if (!(console_read = mem_alloc( sizeof(struct console) )))
{
close( read_fd );
close( write_fd );
return 0;
}
if (!(console_write = mem_alloc( sizeof(struct console) )))
{
close( read_fd );
close( write_fd );
free( console_read );
return 0;
}
init_object( &console_read->obj, &console_ops, NULL );
init_object( &console_write->obj, &console_ops, NULL );
console_read->fd = read_fd;
console_read->is_read = 1;
console_write->fd = write_fd;
console_write->is_read = 0;
CLEAR_ERROR();
obj[0] = &console_read->obj;
obj[1] = &console_write->obj;
return 1;
}
int set_console_fd( int handle, int fd )
{
struct console *console;
if (!(console = (struct console *)get_handle_obj( current->process, handle,
0, &console_ops )))
return 0;
if ((fd = dup(fd)) == -1)
{
file_set_error();
release_object( console );
return 0;
}
close( console->fd );
console->fd = fd;
release_object( console );
return 1;
}
static void console_dump( struct object *obj, int verbose )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
fprintf( stderr, "Console %s fd=%d\n",
console->is_read ? "input" : "output", console->fd );
}
static int console_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (!obj->head) /* first on the queue */
{
if (!add_select_user( console->fd,
console->is_read ? READ_EVENT : WRITE_EVENT,
&select_ops, console ))
{
SET_ERROR( ERROR_OUTOFMEMORY );
return 0;
}
}
add_queue( obj, entry );
return 1;
}
static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct console *console = (struct console *)grab_object(obj);
assert( obj->ops == &console_ops );
remove_queue( obj, entry );
if (!obj->head) /* last on the queue is gone */
remove_select_user( console->fd );
release_object( obj );
}
static int console_signaled( struct object *obj, struct thread *thread )
{
fd_set fds;
struct timeval tv = { 0, 0 };
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
FD_ZERO( &fds );
FD_SET( console->fd, &fds );
if (console->is_read)
return select( console->fd + 1, &fds, NULL, NULL, &tv ) > 0;
else
return select( console->fd + 1, NULL, &fds, NULL, &tv ) > 0;
}
static int console_get_read_fd( struct object *obj )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (!console->is_read)
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( console->fd );
}
static int console_get_write_fd( struct object *obj )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (console->is_read)
{
SET_ERROR( ERROR_ACCESS_DENIED );
return -1;
}
return dup( console->fd );
}
static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
{
memset( reply, 0, sizeof(*reply) );
reply->type = FILE_TYPE_CHAR;
return 1;
}
static void console_destroy( struct object *obj )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
close( console->fd );
free( console );
}