Use mach_msg_type_number_t in place of unsigned int.
[kopensolaris-gnu/glibc.git] / hurd / hurdmsg.c
1 /* Copyright (C) 1992, 1994 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_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_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_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_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         *value = ss->blocked;
128         __mutex_unlock (&ss->lock);
129         return 0;
130       }
131     case INIT_SIGPENDING:
132       {
133         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
134         *value = ss->pending;
135         __mutex_unlock (&ss->lock);
136         return 0;
137       }
138     case INIT_SIGIGN:
139       {
140         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
141         sigset_t ign;
142         int sig;
143         __sigemptyset (&ign);
144         for (sig = 1; sig < NSIG; ++sig)
145           if (ss->actions[sig].sa_handler == SIG_IGN)
146             __sigaddset (&ign, sig);
147         __mutex_unlock (&ss->lock);
148         *value = ign;
149         return 0;
150       }
151     default:
152       return EINVAL;
153     }
154 }
155
156 kern_return_t
157 _S_get_init_int (mach_port_t msgport, mach_port_t auth,
158                  int which, int *value)
159 {
160   AUTHCHECK;
161
162   return get_int (which, value);
163 }
164
165 kern_return_t
166 _S_get_init_ints (mach_port_t msgport, mach_port_t auth,
167                   int **values, mach_msg_type_number_t *nvalues)
168 {
169   error_t err;
170   mach_msg_type_number_t i;
171
172   AUTHCHECK;
173
174   if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
175                            INIT_INT_MAX * sizeof (int), 1))
176     return err;
177   *nvalues = INIT_INT_MAX;
178
179   for (i = 0; i < INIT_INT_MAX; ++i)
180     switch (err = get_int (i, &(*values)[i]))
181       {
182       case 0:                   /* Success.  */
183         break;
184       case EINVAL:              /* Unknown index.  */
185         (*values)[i] = 0;
186         break;
187       default:                  /* Lossage.  */
188         __vm_deallocate (__mach_task_self (),
189                          (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
190         return err;
191       }
192
193   return 0;
194 }
195
196
197 static kern_return_t
198 set_int (int which, int value)
199 {
200   switch (which)
201     {
202     case INIT_UMASK:
203       _hurd_umask = value;
204       return 0;
205
206       /* These are pretty odd things to do.  But you asked for it.  */
207     case INIT_SIGMASK:
208       {
209         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
210         ss->blocked = value;
211         __mutex_unlock (&ss->lock);
212         return 0;
213       }
214     case INIT_SIGPENDING:
215       {
216         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
217         ss->pending = value;
218         __mutex_unlock (&ss->lock);
219         return 0;
220       }
221     case INIT_SIGIGN:
222       {
223         struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
224         int sig;
225         const sigset_t ign = value;
226         for (sig = 1; sig < NSIG; ++sig)
227           {
228             if (__sigismember (&ign, sig))
229               ss->actions[sig].sa_handler = SIG_IGN;
230             else if (ss->actions[sig].sa_handler == SIG_IGN)
231               ss->actions[sig].sa_handler = SIG_DFL;
232           }
233         __mutex_unlock (&ss->lock);
234         return 0;
235       }
236     default:
237       return EINVAL;
238     }
239 }
240
241 kern_return_t
242 _S_set_init_int (mach_port_t msgport, mach_port_t auth,
243                  int which, int value)
244 {
245   AUTHCHECK;
246
247   return set_int (which, value);
248 }
249
250 kern_return_t
251 _S_set_init_ints (mach_port_t msgport, mach_port_t auth,
252                   int *values, mach_msg_type_number_t nvalues)
253 {
254   error_t err;
255   mach_msg_type_number_t i;
256
257   AUTHCHECK;
258
259   for (i = 0; i < INIT_INT_MAX; ++i)
260     switch (err = set_int (i, values[i]))
261       {
262       case 0:                   /* Success.  */
263         break;
264       case EINVAL:              /* Unknown index.  */
265         break;
266       default:                  /* Lossage.  */
267         return err;
268       }
269
270   return 0;
271 }
272 \f
273
274 kern_return_t
275 _S_get_fd (mach_port_t msgport, mach_port_t auth,
276            int which, mach_port_t *result, mach_msg_type_name_t *result_type)
277 {
278   AUTHCHECK;
279
280   /* This creates a new user reference for the send right.
281      Our reply message will move that reference to the caller.  */
282   *result = __getdport (which);
283   if (*result == MACH_PORT_NULL)
284     return errno;
285   *result_type = MACH_MSG_TYPE_MOVE_SEND;
286
287   return 0;
288 }
289
290 kern_return_t
291 _S_set_fd (mach_port_t msgport, mach_port_t auth,
292            int which, mach_port_t port)
293 {
294   AUTHCHECK;
295
296   /* We consume the reference if successful.  */
297   return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
298 }
299 \f
300 /* Snarfing and frobbing environment variables.  */
301
302 kern_return_t
303 _S_get_env_variable (mach_port_t msgport,
304                      char *variable,
305                      char **data, mach_msg_type_number_t *datalen)
306 {
307   const char *value = getenv (variable);
308
309   if (value == NULL)
310     return ENOENT;
311
312   /* XXX this pointer might become invalid */
313   *data = value;
314   *datalen = strlen (value);
315   return 0;
316 }
317
318
319 kern_return_t
320 _S_set_env_variable (mach_port_t msgport, mach_port_t auth,
321                      char *variable,
322                      char *value,
323                      int replace)
324 {
325   AUTHCHECK;
326
327   if (setenv (variable, value, replace)) /* XXX name space */
328     return errno;
329   return 0;
330 }
331
332 kern_return_t
333 _S_get_environment (mach_port_t msgport,
334                     char **data, mach_msg_type_number_t *datalen)
335 {
336   /* Pack the environment into an array with nulls separating elements.  */
337   if (__environ != NULL)
338     {
339       char *ap, **p;
340       size_t envlen = 0;
341
342       for (p = __environ; *p != NULL; ++p)
343         envlen += strlen (*p) + 1;
344
345       if (envlen > *datalen)
346         {
347           if (__vm_allocate (__mach_task_self (),
348                              (vm_address_t *) data, envlen, 1))
349             return ENOMEM;
350         }
351
352       ap = *data;
353       for (p = __environ; *p != NULL; ++p)
354         ap = __memccpy (ap, *p, '\0', ULONG_MAX);
355
356       *datalen = envlen;
357     }
358   else
359     *datalen = 0;
360
361   return 0;
362 }
363
364 kern_return_t
365 _S_set_environment (mach_port_t msgport, mach_port_t auth,
366                     char *data, mach_msg_type_number_t datalen)
367 {
368   int _hurd_split_args (char *, mach_msg_type_number_t, char **);
369   int envc;
370   char **envp;
371
372   AUTHCHECK;
373
374   envc = _hurd_split_args (data, datalen, NULL);
375   envp = malloc ((envc + 1) * sizeof (char *));
376   if (envp == NULL)
377     return errno;
378   _hurd_split_args (data, datalen, envp);
379   __environ = envp;             /* XXX cooperate with loadenv et al */
380   return 0;
381 }
382
383 \f
384
385 /* XXX */
386
387 kern_return_t
388 _S_get_dtable (mach_port_t process,
389                mach_port_t refport,
390                portarray_t *dtable,
391                mach_msg_type_name_t *dtablePoly,
392                mach_msg_type_number_t *dtableCnt)
393 { return EOPNOTSUPP; }
394
395 kern_return_t
396 _S_set_dtable (mach_port_t process,
397                mach_port_t refport,
398                portarray_t dtable,
399                mach_msg_type_number_t dtableCnt)
400 { return EOPNOTSUPP; }
401
402 kern_return_t
403 _S_io_select_done (mach_port_t notify_port,
404                    mach_msg_type_name_t notify_port_type,
405                    int select_result,
406                    int id_tag)
407 { return EOPNOTSUPP; }
408
409 kern_return_t
410 _S_startup_dosync (mach_port_t process)
411 { return EOPNOTSUPP; }
412
413 kern_return_t
414 _S_dir_changed (mach_port_t notify_port,
415                 dir_changed_type_t change,
416                 string_t name)
417 { return EOPNOTSUPP; }
418
419 kern_return_t
420 _S_file_changed (mach_port_t notify_port,
421                  file_changed_type_t change,
422                  off_t start,
423                  off_t end)
424 { return EOPNOTSUPP; }