user32: Remove duplicated code.
[wine] / server / procfs.c
1 /*
2  * Server-side /proc support for Solaris
3  *
4  * Copyright (C) 2007 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <signal.h>
28 #include <stdarg.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "winternl.h"
35
36 #include "file.h"
37 #include "process.h"
38 #include "thread.h"
39
40 #ifdef USE_PROCFS
41
42 #include <procfs.h>
43
44 static int open_proc_as( struct process *process, int flags )
45 {
46     char buffer[32];
47     int fd;
48
49     sprintf( buffer, "/proc/%u/as", process->unix_pid );
50     if ((fd = open( buffer, flags )) == -1) file_set_error();
51     return fd;
52 }
53
54 static int open_proc_lwpctl( struct thread *thread )
55 {
56     char buffer[48];
57     int fd;
58
59     sprintf( buffer, "/proc/%u/lwp/%u/lwpctl", thread->unix_pid, thread->unix_tid );
60     if ((fd = open( buffer, O_WRONLY )) == -1) file_set_error();
61     return fd;
62 }
63
64
65 /* handle a SIGCHLD signal */
66 void sigchld_callback(void)
67 {
68     assert( 0 );  /* should only be called when using ptrace */
69 }
70
71 /* initialize the process tracing mechanism */
72 void init_tracing_mechanism(void)
73 {
74     /* no initialization needed */
75 }
76
77 /* initialize the per-process tracing mechanism */
78 void init_process_tracing( struct process *process )
79 {
80     /* setup is done on-demand */
81 }
82
83 /* terminate the per-process tracing mechanism */
84 void finish_process_tracing( struct process *process )
85 {
86 }
87
88 /* send a Unix signal to a specific thread */
89 int send_thread_signal( struct thread *thread, int sig )
90 {
91     int fd = open_proc_lwpctl( thread );
92     long kill[2];
93     ssize_t ret;
94
95     if (fd == -1) return 0;
96
97     kill[0] = PCKILL;
98     kill[1] = sig;
99     ret = write( fd, kill, sizeof(kill) );
100     close( fd );
101     return (ret == sizeof(kill));
102 }
103
104 /* read data from a process memory space */
105 int read_process_memory( struct process *process, const void *ptr, size_t size, char *dest )
106 {
107     ssize_t ret;
108     int fd = open_proc_as( process, O_RDONLY );
109
110     if (fd == -1) return 0;
111
112     ret = pread( fd, dest, size, (off_t)ptr );
113     close( fd );
114     if (ret == size) return 1;
115
116     if (ret == -1) file_set_error();
117     else set_error( STATUS_ACCESS_VIOLATION );
118     return 0;
119 }
120
121 /* write data to a process memory space */
122 int write_process_memory( struct process *process, void *ptr, size_t size, const char *src )
123 {
124     ssize_t ret;
125     int fd = open_proc_as( process, O_WRONLY );
126
127     if (fd == -1) return 0;
128
129     ret = pwrite( fd, src, size, (off_t)ptr );
130     close( fd );
131     if (ret == size) return 1;
132
133     if (ret == -1) file_set_error();
134     else set_error( STATUS_ACCESS_VIOLATION );
135     return 0;
136 }
137
138 /* retrieve an LDT selector entry */
139 void get_selector_entry( struct thread *thread, int entry, unsigned int *base,
140                          unsigned int *limit, unsigned char *flags )
141 {
142     ssize_t ret;
143     off_t pos = (off_t)thread->process->ldt_copy;
144     int fd = open_proc_as( thread->process, O_RDONLY );
145
146     if (fd == -1) return;
147
148     ret = pread( fd, base, sizeof(*base), pos + entry*sizeof(int) );
149     if (ret != sizeof(*base)) goto error;
150     ret = pread( fd, limit, sizeof(*limit), pos + (8192 + entry)*sizeof(int) );
151     if (ret != sizeof(*limit)) goto error;
152     ret = pread( fd, flags, sizeof(*flags), pos + 2*8192*sizeof(int) + entry );
153     if (ret != sizeof(*flags)) goto error;
154     close( fd );
155     return;
156
157 error:
158     if (ret == -1) file_set_error();
159     else set_error( STATUS_ACCESS_VIOLATION );
160     close( fd );
161 }
162
163 /* retrieve the thread registers */
164 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
165 {
166     /* all other regs are handled on the client side */
167     assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
168
169     /* FIXME: get debug registers */
170 }
171
172 /* set the thread registers */
173 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
174 {
175     /* all other regs are handled on the client side */
176     assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
177
178     /* FIXME: set debug registers */
179 }
180
181 #endif /* USE_PROCFS */