(_S_msg_report_wait): New stub function.
[kopensolaris-gnu/glibc.git] / hurd / hurdmsg.c
1 /* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 #include <hurd.h>
20 #include <hurd/msg_server.h>
21 #include <hurd/fd.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <string.h>
25
26
27 #define AUTHCHECK \
28   if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
29     return EPERM
30
31
32 /* Snarfing and frobbing the init ports.  */
33
34 kern_return_t
35   _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
36                         mach_port_t *result, mach_msg_type_name_t *result_type)
37 {
38   AUTHCHECK;
39   *result_type = MACH_MSG_TYPE_MOVE_SEND;
40   /* This function adds a new user reference for the *RESULT it gives back.
41      Our reply message uses a move-send right that consumes this reference.  */
42   return _hurd_ports_get (which, result);
43 }
44
45 kern_return_t
46 _S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
47                       int which, mach_port_t port)
48 {
49   error_t err;
50
51   AUTHCHECK;
52
53   err = _hurd_ports_set (which, port);
54   if (err == 0)
55     __mach_port_deallocate (__mach_task_self (), port);
56
57   return 0;
58 }
59
60 kern_return_t
61 _S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
62                        mach_port_t **ports,
63                        mach_msg_type_name_t *ports_type,
64                        mach_msg_type_number_t *nports)
65 {
66   mach_msg_type_number_t i;
67   error_t err;
68
69   AUTHCHECK;
70
71   if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
72                            _hurd_nports * sizeof (mach_port_t), 1))
73     return err;
74   *nports = _hurd_nports;
75
76   for (i = 0; i < _hurd_nports; ++i)
77     /* This function adds a new user ref for the *RESULT it gives back.
78        Our reply message uses move-send rights that consumes this ref.  */
79     if (err = _hurd_ports_get (i, &(*ports)[i]))
80       {
81         /* Died part way through.  Deallocate the ports already fetched.  */
82         while (i-- > 0)
83           __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
84         __vm_deallocate (__mach_task_self (),
85                          (vm_address_t) *ports,
86                          *nports * sizeof (mach_port_t));
87         return err;
88       }
89
90   *ports_type = MACH_MSG_TYPE_MOVE_SEND;
91   return 0;
92 }
93
94 kern_return_t
95 _S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
96                        mach_port_t *ports, mach_msg_type_number_t nports)
97 {
98   mach_msg_type_number_t i;
99   error_t err;
100
101   AUTHCHECK;
102
103   for (i = 0; i < _hurd_nports; ++i)
104     {
105       if (err = _hurd_ports_set (i, ports[i]))
106         return err;
107       else
108         __mach_port_deallocate (__mach_task_self (), ports[i]);
109     }
110
111   return 0;
112 }
113 \f
114 /* Snarfing and frobbing the init ints.  */
115
116 static kern_return_t
117 get_int (int which, int *value)
118 {
119   switch (which)
120     {
121     case INIT_UMASK:
122       *value = _hurd_umask;
123       return 0;
124     case INIT_SIGMASK:
125       {
126         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
127         __spin_lock (&ss->lock);
128         *value = ss->blocked;
129         __spin_unlock (&ss->lock);
130         return 0;
131       }
132     case INIT_SIGPENDING:
133       {
134         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
135         __spin_lock (&ss->lock);
136         *value = ss->pending;
137         __spin_unlock (&ss->lock);
138         return 0;
139       }
140     case INIT_SIGIGN:
141       {
142         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
143         sigset_t ign;
144         int sig;
145         __spin_lock (&ss->lock);
146         __sigemptyset (&ign);
147         for (sig = 1; sig < NSIG; ++sig)
148           if (ss->actions[sig].sa_handler == SIG_IGN)
149             __sigaddset (&ign, sig);
150         __spin_unlock (&ss->lock);
151         *value = ign;
152         return 0;
153       }
154     default:
155       return EINVAL;
156     }
157 }
158
159 kern_return_t
160 _S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
161                      int which, int *value)
162 {
163   AUTHCHECK;
164
165   return get_int (which, value);
166 }
167
168 kern_return_t
169 _S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
170                       int **values, mach_msg_type_number_t *nvalues)
171 {
172   error_t err;
173   mach_msg_type_number_t i;
174
175   AUTHCHECK;
176
177   if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
178                            INIT_INT_MAX * sizeof (int), 1))
179     return err;
180   *nvalues = INIT_INT_MAX;
181
182   for (i = 0; i < INIT_INT_MAX; ++i)
183     switch (err = get_int (i, &(*values)[i]))
184       {
185       case 0:                   /* Success.  */
186         break;
187       case EINVAL:              /* Unknown index.  */
188         (*values)[i] = 0;
189         break;
190       default:                  /* Lossage.  */
191         __vm_deallocate (__mach_task_self (),
192                          (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
193         return err;
194       }
195
196   return 0;
197 }
198
199
200 static kern_return_t
201 set_int (int which, int value)
202 {
203   switch (which)
204     {
205     case INIT_UMASK:
206       _hurd_umask = value;
207       return 0;
208
209       /* These are pretty odd things to do.  But you asked for it.  */
210     case INIT_SIGMASK:
211       {
212         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
213         __spin_lock (&ss->lock);
214         ss->blocked = value;
215         __spin_unlock (&ss->lock);
216         return 0;
217       }
218     case INIT_SIGPENDING:
219       {
220         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
221         __spin_lock (&ss->lock);
222         ss->pending = value;
223         __spin_unlock (&ss->lock);
224         return 0;
225       }
226     case INIT_SIGIGN:
227       {
228         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
229         int sig;
230         const sigset_t ign = value;
231         __spin_lock (&ss->lock);
232         for (sig = 1; sig < NSIG; ++sig)
233           {
234             if (__sigismember (&ign, sig))
235               ss->actions[sig].sa_handler = SIG_IGN;
236             else if (ss->actions[sig].sa_handler == SIG_IGN)
237               ss->actions[sig].sa_handler = SIG_DFL;
238           }
239         __spin_unlock (&ss->lock);
240         return 0;
241       }
242     default:
243       return EINVAL;
244     }
245 }
246
247 kern_return_t
248 _S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
249                      int which, int value)
250 {
251   AUTHCHECK;
252
253   return set_int (which, value);
254 }
255
256 kern_return_t
257 _S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
258                       int *values, mach_msg_type_number_t nvalues)
259 {
260   error_t err;
261   mach_msg_type_number_t i;
262
263   AUTHCHECK;
264
265   for (i = 0; i < INIT_INT_MAX; ++i)
266     switch (err = set_int (i, values[i]))
267       {
268       case 0:                   /* Success.  */
269         break;
270       case EINVAL:              /* Unknown index.  */
271         break;
272       default:                  /* Lossage.  */
273         return err;
274       }
275
276   return 0;
277 }
278 \f
279
280 kern_return_t
281 _S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
282                mach_port_t *result, mach_msg_type_name_t *result_type)
283 {
284   AUTHCHECK;
285
286   /* This creates a new user reference for the send right.
287      Our reply message will move that reference to the caller.  */
288   *result = __getdport (which);
289   if (*result == MACH_PORT_NULL)
290     return errno;
291   *result_type = MACH_MSG_TYPE_MOVE_SEND;
292
293   return 0;
294 }
295
296 kern_return_t
297 _S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
298                int which, mach_port_t port)
299 {
300   AUTHCHECK;
301
302   /* We consume the reference if successful.  */
303   return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
304 }
305 \f
306 /* Snarfing and frobbing environment variables.  */
307
308 kern_return_t
309 _S_msg_get_env_variable (mach_port_t msgport,
310                          char *variable,
311                          char **data, mach_msg_type_number_t *datalen)
312 {
313   const char *value = getenv (variable);
314
315   if (value == NULL)
316     return ENOENT;
317
318   /* XXX this pointer might become invalid */
319   *data = value;
320   *datalen = strlen (value);
321   return 0;
322 }
323
324
325 kern_return_t
326 _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
327                          char *variable,
328                          char *value,
329                          int replace)
330 {
331   AUTHCHECK;
332
333   if (setenv (variable, value, replace)) /* XXX name space */
334     return errno;
335   return 0;
336 }
337
338 kern_return_t
339 _S_msg_get_environment (mach_port_t msgport,
340                         char **data, mach_msg_type_number_t *datalen)
341 {
342   /* Pack the environment into an array with nulls separating elements.  */
343   if (__environ != NULL)
344     {
345       char *ap, **p;
346       size_t envlen = 0;
347
348       for (p = __environ; *p != NULL; ++p)
349         envlen += strlen (*p) + 1;
350
351       if (envlen > *datalen)
352         {
353           if (__vm_allocate (__mach_task_self (),
354                              (vm_address_t *) data, envlen, 1))
355             return ENOMEM;
356         }
357
358       ap = *data;
359       for (p = __environ; *p != NULL; ++p)
360         ap = __memccpy (ap, *p, '\0', ULONG_MAX);
361
362       *datalen = envlen;
363     }
364   else
365     *datalen = 0;
366
367   return 0;
368 }
369
370 kern_return_t
371 _S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
372                         char *data, mach_msg_type_number_t datalen)
373 {
374   int _hurd_split_args (char *, mach_msg_type_number_t, char **);
375   int envc;
376   char **envp;
377
378   AUTHCHECK;
379
380   envc = _hurd_split_args (data, datalen, NULL);
381   envp = malloc ((envc + 1) * sizeof (char *));
382   if (envp == NULL)
383     return errno;
384   _hurd_split_args (data, datalen, envp);
385   __environ = envp;             /* XXX cooperate with loadenv et al */
386   return 0;
387 }
388 \f
389 /* Get and frob the exec flags.  */
390
391 kern_return_t
392 _S_msg_get_exec_flags (mach_port_t process, mach_port_t auth,
393                        int *flags)
394 {
395   AUTHCHECK;
396
397   *flags = _hurd_exec_flags;
398   return 0;
399 }
400
401 kern_return_t
402 _S_msg_set_all_exec_flags (mach_port_t process, mach_port_t auth,
403                            int flags)
404 {
405   AUTHCHECK;
406
407   _hurd_exec_flags = flags;
408   return 0;
409 }
410
411 kern_return_t
412 _S_msg_set_some_exec_flags (mach_port_t process, mach_port_t auth,
413                             int flags)
414 {
415   AUTHCHECK;
416
417   _hurd_exec_flags |= flags;
418   return 0;
419 }
420
421 kern_return_t
422 _S_msg_clear_some_exec_flags (mach_port_t process, mach_port_t auth,
423                               int flags)
424 {
425   AUTHCHECK;
426
427   _hurd_exec_flags &= ~flags;
428   return 0;
429 }
430 \f
431
432 /* XXX */
433
434 kern_return_t
435 _S_msg_get_dtable (mach_port_t process,
436                    mach_port_t refport,
437                    portarray_t *dtable,
438                    mach_msg_type_name_t *dtablePoly,
439                    mach_msg_type_number_t *dtableCnt)
440 { return EOPNOTSUPP; }
441
442 kern_return_t
443 _S_msg_set_dtable (mach_port_t process,
444                    mach_port_t refport,
445                    portarray_t dtable,
446                    mach_msg_type_number_t dtableCnt)
447 { return EOPNOTSUPP; }
448
449 kern_return_t
450 _S_msg_startup_dosync (mach_port_t process)
451 { return EOPNOTSUPP; }
452
453 kern_return_t
454 _S_msg_report_wait (mach_port_t process,
455                     mach_port_t thread,
456                     string_t wait_desc,
457                     int *wait_rpc)
458 { return EOPNOTSUPP; }