2b1ac3de052673cbac24c6f31e0cf3a478ae0198
[kopensolaris-gnu/glibc.git] / hurd / hurd.h
1 /* Copyright (C) 1993 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 #ifndef _HURD_H
20
21 #define _HURD_H 1
22
23 /* #define      _GNU_SOURCE             XXX why did I want this here? */
24 #include <features.h>
25
26
27 /* Get types, macros, constants and function declarations
28    for all Mach microkernel interaction.  */
29 #include <mach.h>
30
31 /* Get types and constants necessary for Hurd interfaces.  */
32 #include <hurd/hurd_types.h>
33
34 /* Get MiG stub declarations for commonly used Hurd interfaces.  */
35 #include <hurd/auth.h>
36 #include <hurd/process.h>
37 #include <hurd/fs.h>
38 #include <hurd/io.h>
39 #include <hurd/msg.h>
40
41 #include <errno.h>
42 #define __hurd_fail(err)        (errno = (err), -1)
43
44 #define __spin_lock(lockaddr) /* no-op XXX */
45 #define __spin_unlock(lockaddr) /* no-op XXX */
46
47 #define __mutex_lock(lockaddr) /* no-op XXX */
48 #define __mutex_unlock(lockaddr) /* no-op XXX */
49
50 \f
51 /* Lightweight user references for ports.  */
52
53 /* Structure describing a cell containing a port.
54    With the lock held, a user extracts PORT, and sets USER_DEALLOC to point
55    to a word in his local storage.  PORT can then safely be used.  When
56    PORT is no longer needed, with the lock held, the user examines
57    USER_DEALLOC.  If it is the same address that user stored there, he
58    extracts *USER_DEALLOC, clears USER_DEALLOC to NULL, and releases the
59    lock.  If *USER_DEALLOC is set, the user deallocates the port he used.  */
60 struct _hurd_port
61   {
62 #ifdef noteven
63     spin_lock_t lock;           /* Locks rest.  */
64 #endif
65     int *user_dealloc;          /* If not NULL, points to user's flag word.  */
66     mach_port_t port;           /* Port. */
67   };
68
69 /* Evaluate EXPR with the variable `port' bound to the port in PORTCELL.  */
70 #define _HURD_PORT_USE(portcell, expr)                                        \
71   ({ struct _hurd_port *const __p = (portcell);                               \
72      int __dealloc;                                                           \
73      const mach_port_t port = _hurd_port_get (__p, &__dealloc);               \
74      __typeof(expr) __result = (expr);                                        \
75      _hurd_port_free (__p, &__dealloc, port);                                 \
76      __result; })
77
78 /* Initialize *PORT to INIT.  */
79 static inline void
80 _hurd_port_init (struct _hurd_port *port, mach_port_t init)
81 {
82 #ifdef noteven
83   __spin_lock_init (&port->lock);
84 #endif
85   port->user_dealloc = NULL;
86   port->port = init;
87 }
88
89 /* Get a reference to *PORT, which is locked.
90    Pass return value and MYFLAG to _hurd_port_free when done.  */
91 static inline mach_port_t
92 _hurd_port_locked_get (struct _hurd_port *port, int *myflag)
93 {
94   mach_port_t result;
95   result = port->port;
96   if (result != MACH_PORT_NULL)
97     {
98       port->user_dealloc = myflag;
99       *myflag = 0;
100     }
101   __spin_unlock (&port->lock);
102   return result;
103 }
104
105 /* Same, but locks PORT first.  */
106 static inline mach_port_t
107 _hurd_port_get (struct _hurd_port *port, int *myflag)
108 {
109   __spin_lock (&port->lock);
110   return _hurd_port_locked_get (port, myflag);
111 }
112
113 /* Free a reference gotten with
114    `USED_PORT = _hurd_port_get (PORT, MYFLAG);' */
115 static inline void
116 _hurd_port_free (struct _hurd_port *port,
117                  int *myflag, mach_port_t used_port)
118 {
119   __spin_lock (&port->lock);
120   if (port->user_dealloc == myflag)
121     port->user_dealloc = NULL;
122   __spin_unlock (&port->lock);
123   if (*myflag)
124     __mach_port_deallocate (__mach_task_self (), used_port);
125 }
126
127 /* Set *PORT's port to NEWPORT.  NEWPORT's reference is consumed by PORT->port.
128    PORT->lock is locked.  */
129 static inline void
130 _hurd_port_locked_set (struct _hurd_port *port, mach_port_t newport)
131 {
132   mach_port_t old;
133   if (port->user_dealloc == NULL)
134     old = port->port;
135   else
136     {
137       old = MACH_PORT_NULL;
138       *port->user_dealloc = 1;
139     }
140   port->port = newport;
141   __spin_unlock (&port->lock);
142   if (old != MACH_PORT_NULL)
143     __mach_port_deallocate (__mach_task_self (), old);
144 }
145
146 /* Same, but locks PORT first.  */
147 static inline void
148 _hurd_port_set (struct _hurd_port *port, mach_port_t newport)
149 {
150   __spin_lock (&port->lock);
151   return _hurd_port_locked_set (port, newport);
152 }
153 \f
154 /* Basic ports and info, initialized by startup.  */
155 extern struct _hurd_port *_hurd_ports;
156 extern unsigned int _hurd_nports;
157 extern volatile mode_t _hurd_umask;
158
159 /* Shorthand macro for referencing _hurd_ports.  */
160 #define __USEPORT(which, expr) \
161   _HURD_PORT_USE (&_hurd_ports[INIT_PORT_##which], (expr))
162
163 /* Base address and size of the initial stack set up by the exec server.
164    If using cthreads, this stack is deallocated in startup.
165    Not locked.  */
166 extern vm_address_t _hurd_stack_base;
167 extern vm_size_t _hurd_stack_size;
168
169 extern thread_t _hurd_msgport_thread;
170 extern mach_port_t _hurd_msgport; /* Locked by _hurd_siglock.  */
171
172 /* Not locked.  If we are using a real dtable, these are turned into that
173    and then cleared at startup.  If not, these are never changed after
174    startup.  */
175 extern mach_port_t *_hurd_init_dtable;
176 extern mach_msg_type_number_t _hurd_init_dtablesize;
177 \f
178 /* File descriptor table.  */
179
180
181 /* File descriptor structure.  */
182 struct _hurd_fd
183   {
184     struct _hurd_port port;     /* io server port.  */
185     int flags;                  /* fcntl flags; locked by port.lock.  */
186
187     /* Normal port to the ctty.  When `port' is our ctty, this is a port to
188        the same io object but which never returns EBACKGROUND; when not,
189        this is nil.  */
190     struct _hurd_port ctty;
191   };
192
193 /* Set up *FD to have PORT its server port, doing appropriate ctty magic.
194    Does no locking or unlocking.  */
195 extern void _hurd_port2fd (struct _hurd_fd *fd, io_t port, int flags);
196
197 /* Allocate a new file descriptor and install PORT in it (doing any
198    appropriate ctty magic); consumes a user reference on PORT.  FLAGS are
199    as for `open'; only O_NOCTTY is meaningful, but all are saved.
200
201    If the descriptor table is full, set errno, and return -1.
202    If DEALLOC is nonzero, deallocate PORT first.  */
203 extern int _hurd_intern_fd (io_t port, int flags, int dealloc);
204
205 /* Allocate a new file descriptor and return it, locked.
206    The new descriptor will not be less than FIRST_FD.  */
207 extern struct _hurd_fd *_hurd_alloc_fd (int *fd_ptr, int first_fd);
208
209
210 struct _hurd_dtable
211   {
212     int size;                   /* Number of elts in `d' array.  */
213
214     /* Uses of individual descriptors are not locked.  It is up to the user
215        to synchronize descriptor operations on a single descriptor.  */
216
217     struct _hurd_fd *d;
218   };
219
220 #ifdef noteven
221 extern struct mutex _hurd_dtable_lock; /* Locks next two.  */
222 #endif
223 extern struct _hurd_dtable _hurd_dtable;
224 extern int _hurd_dtable_rlimit; /* RLIM_OFILES: number of file descriptors.  */
225
226 /* If not NULL, pointed-to word is set when _hurd_dtable.d changes.
227    User who set `user_dealloc' should free the _hurd_dtable.d value
228    he used if his word is set when he is finished.
229    If NULL, the old value of _hurd_dtable.d is freed by the setter.  */
230 int *_hurd_dtable_user_dealloc;
231
232 static inline struct _hurd_dtable
233 _hurd_dtable_use (int *dealloc)
234 {
235   struct _hurd_dtable dtable;
236   __mutex_lock (&_hurd_dtable_lock);
237   _hurd_dtable_user_dealloc = dealloc;
238   dtable = _hurd_dtable;
239   __mutex_unlock (&_hurd_dtable_lock);
240   return dtable;
241 }
242
243 struct _hurd_dtable_resizes
244   {
245     size_t n;
246     void (*free) (void *);
247     void *terminator;
248   };
249 extern const struct _hurd_dtable_resizes _hurd_dtable_resizes;
250
251 static inline void
252 _hurd_dtable_done (struct _hurd_dtable dtable, int *dealloc)
253 {
254   __mutex_lock (&_hurd_dtable_lock);
255   if (_hurd_dtable_user_dealloc == dealloc)
256     _hurd_dtable_user_dealloc = NULL;
257   __mutex_unlock (&_hurd_dtable_lock);
258   if (*dealloc)
259     /* _hurd_dtable_resizes is a symbol set.
260        setrlimit.c gives it one element: free.
261        If setrlimit is not linked in, *DEALLOC
262        will never get set, so we will never get here.
263        This hair avoids linking in free if we don't need it.  */
264     (*_hurd_dtable_resizes.free) (dtable.d);
265 }
266
267 /* Return the descriptor cell for FD in DTABLE, locked.  */
268 static inline struct _hurd_fd *
269 _hurd_dtable_fd (int fd, struct _hurd_dtable dtable)
270 {
271   if (fd < 0 || fd >= dtable.size)
272     return NULL;
273   else
274     {
275       struct _hurd_fd *cell = &dtable.d[fd];
276       __spin_lock (&cell->port.lock);
277       if (cell->port.port == MACH_PORT_NULL)
278         {
279           __spin_unlock (&cell->port.lock);
280           return NULL;
281         }
282       return cell;
283     }
284 }
285
286 struct _hurd_fd_user
287   {
288     struct _hurd_dtable dtable;
289     struct _hurd_fd *d;
290   };
291
292 /* Returns the descriptor cell for FD, locked.  The passed DEALLOC word and
293    returned structure hold onto the descriptor table to it doesn't move
294    while you might be using a pointer into it.  */
295 static inline struct _hurd_fd_user
296 _hurd_fd (int fd, int *dealloc)
297 {
298   struct _hurd_fd_user d;
299   d.dtable = _hurd_dtable_use (dealloc);
300   d.d = _hurd_dtable_fd (fd, d.dtable);
301   if (d.d == NULL)
302     _hurd_dtable_done (d.dtable, dealloc);
303   return d;
304 }
305
306 static inline void
307 _hurd_fd_done (struct _hurd_fd_user d, int *dealloc)
308 {
309   _hurd_dtable_done (d.dtable, dealloc);
310 }
311
312 /* Evaluate EXPR with the variable `port' bound to the port to FD,
313    and `ctty' bound to the ctty port.  */
314    
315 #define _HURD_DPORT_USE(fd, expr)                                             \
316   ({ int __dealloc_dt;                                                        \
317      error_t __result;                                                        \
318      struct _hurd_fd_user __d = _hurd_fd (fd, &__dealloc_dt);                 \
319      if (__d.d == NULL)                                                       \
320        __result = EBADF;                                                      \
321      else                                                                     \
322        {                                                                      \
323          int __dealloc, __dealloc_ctty;                                       \
324          io_t port = _hurd_port_locked_get (&__d.d->port, &__dealloc);        \
325          io_t ctty = _hurd_port_locked_get (&__d.d->ctty, &__dealloc_ctty);   \
326          __result = (expr);                                                   \
327          _hurd_port_free (&__d.d->port, &__dealloc, port);                    \
328          if (ctty != MACH_PORT_NULL)                                          \
329            _hurd_port_free (&__d.d->ctty, &__dealloc_ctty, ctty);             \
330          _hurd_fd_done (__d, &__dealloc_dt);                                  \
331        }                                                                      \
332       __result;                                                               \
333    })                                                                         \
334
335 static inline int
336 __hurd_dfail (int fd, error_t err)
337 {
338   switch (err)
339     {
340     case MACH_SEND_INVALID_DEST: /* The server has disappeared!  */
341 #ifdef notyet
342       _hurd_raise_signal (NULL, SIGLOST, fd);
343 #else
344       abort ();
345 #endif
346       break;
347     case EPIPE:
348 #ifdef notyet
349       _hurd_raise_signal (NULL, SIGPIPE, fd);
350 #else
351       abort ();
352 #endif
353       break;
354     default:
355       return __hurd_fail (err);
356     }
357 }
358 \f
359 /* Return the socket server for sockaddr domain DOMAIN.  */
360 extern socket_t _hurd_socket_server (int domain);
361
362 /* Return a receive right which will not be sent to.  */
363 extern mach_port_t _hurd_dead_recv (void);
364
365
366 /* Current process IDs.  */
367 extern pid_t _hurd_pid, _hurd_ppid, _hurd_pgrp;
368 extern int _hurd_orphaned;
369 #ifdef noteven
370 extern struct mutex _hurd_pid_lock; /* Locks above.  */
371 #endif
372
373
374 /* User and group IDs.  */
375 struct _hurd_id_data
376   {
377 #ifdef noteven
378     mutex_t lock;
379 #endif
380
381     int valid;                  /* If following data are up to date.  */
382
383     struct
384       {
385         uid_t *uids;
386         gid_t *gids;
387         unsigned int nuids, ngids;
388       } gen, aux;
389
390     auth_t rid_auth;            /* Cache used by access.  */
391   };
392 extern struct _hurd_id_data _hurd_id;
393 /* Update _hurd_id (caller should be holding the lock).  */
394 extern error_t _hurd_check_ids (void);
395
396
397 /* Unix `data break', for brk and sbrk.
398    If brk and sbrk are not used, this info will not be initialized or used.  */
399 extern vm_address_t _hurd_brk;  /* Data break.  */
400 extern vm_address_t _hurd_data_end; /* End of allocated space.  */
401 #ifdef noteven
402 extern struct mutex _hurd_brk_lock; /* Locks brk and data_end.  */
403 #endif
404 extern int _hurd_set_data_limit (const struct rlimit *);
405
406 /* Set the data break; the brk lock must
407    be held, and is released on return.  */
408 extern int _hurd_set_brk (vm_address_t newbrk);
409
410 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
411 extern int _hurd_core_limit;
412 \f
413 #ifdef notyet
414
415 #include <signal.h>
416
417 /* Per-thread signal state.  */
418 struct _hurd_sigstate
419   {
420     thread_t thread;
421     struct _hurd_sigstate *next; /* Linked-list of thread sigstates.  */
422
423     struct mutex lock;          /* Locks the rest of this structure.  */
424     sigset_t blocked;
425     sigset_t pending;
426     struct sigaction actions[NSIG];
427     struct sigaltstack sigaltstack;
428     int sigcodes[NSIG];         /* Codes for pending signals.  */
429
430     int suspended;              /* If nonzero, sig_post signals `arrived'.  */
431     struct condition arrived;
432
433 #if 0
434     int vforked;                /* Nonzero if this thread is a vfork child.  */
435     struct
436       {
437         process_t proc;
438         file_t ccdir, cwdir, crdir, auth;
439         mode_t umask;
440         int ctty_fstype;
441         fsid_t ctty_fsid;
442         ino_t ctty_fileid;
443         struct _hurd_dtable *dtable;
444         jmp_buf continuation;
445       } *vfork_saved;
446 #endif
447
448     /* Not locked.  Used only by this thread,
449        or by signal thread with this thread suspended.  */
450     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
451     volatile int intr_restart;  /* If nonzero, restart interrupted RPC.  */
452   };
453 /* Linked list of states of all threads
454    whose state has been inquired about.  */
455 extern struct _hurd_sigstate *_hurd_sigstates;
456 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
457 /* Get the sigstate of a given thread, taking its lock.  */
458 extern struct _hurd_sigstate *_hurd_thread_sigstate (thread_t);
459
460 /* Thread to receive process-global signals.  */
461 extern thread_t _hurd_sigthread;
462
463 /* Called by the machine-dependent exception handler.  */
464 extern void _hurd_exc_post_signal (thread_t, int sig, int code);
465
466 /* SS->lock is held on entry, and released before return.  */
467 extern void _hurd_internal_post_signal (struct _hurd_sigstate *ss,
468                                         int signo, int sigcode,
469                                         sigset_t *restore_blocked);
470
471 /* Function run by the signal thread to receive from the signal port.  */
472 extern void _hurd_msgport_receive (void);
473
474
475 /* Perform interruptible RPC CALL on PORT.
476    The args in CALL should be constant or local variable refs.
477    They may be evaluated many times, and must not change.
478    PORT must not be deallocated before this RPC is finished.  */
479 #define HURD_EINTR_RPC(port, call) \
480   ({
481     error_t __err;
482     struct _hurd_sigstate *__ss
483       = _hurd_thread_sigstate (__mach_thread_self ());
484     __mutex_unlock (&__ss->lock); /* Lock not needed.  */
485     /* If we get a signal and should return EINTR, the signal thread will
486        clear this.  The RPC might return EINTR when some other thread gets
487        a signal, in which case we want to restart our call.  */
488     __ss->intr_restart = 1;
489     /* This one needs to be last.  A signal can arrive before here,
490        and if intr_port were set before intr_restart is
491        initialized, the signal thread would get confused.  */
492     __ss->intr_port = (port);
493     /* A signal may arrive here, after intr_port is set,
494        but before the mach_msg system call.  The signal handler might do an
495        interruptible RPC, and clobber intr_port; then it would not be set
496        properly when we actually did send the RPC, and a later signal
497        wouldn't interrupt that RPC.  So, _hurd_run_sighandler saves
498        intr_port in the sigcontext, and sigreturn restores it.  */
499   __do_call:
500     switch (__err = (call))
501       {
502       case EINTR:               /* RPC went out and was interrupted.  */
503       case MACH_SEND_INTERRUPTED: /* RPC didn't get out.  */
504         if (__ss->intr_restart)
505           /* Restart the interrupted call.  */
506           goto __do_call;
507         /* FALLTHROUGH */
508       case MACH_RCV_PORT_DIED:
509         /* Server didn't respond to interrupt_operation,
510            so the signal thread destroyed the reply port.  */
511         __err = EINTR;
512         break;
513       }
514     __ss->intr_port = MACH_PORT_NULL;
515     __err;
516   })
517
518 #endif /* notyet */
519
520 /* Mask of signals that cannot be caught, blocked, or ignored.  */
521 #define _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
522
523 \f
524
525 /* Calls to get and set basic ports.  */
526 extern process_t getproc (void);
527 extern file_t getccdir (void), getcwdir (void), getcrdir (void);
528 extern auth_t getauth (void);
529 extern int setproc (process_t);
530 extern int setcwdir (file_t), setcrdir (file_t);
531
532 /* Does reauth with the proc server and fd io servers.  */
533 extern int __setauth (auth_t), setauth (auth_t);
534
535
536 extern error_t __hurd_path_split (file_t crdir, file_t cwdir,
537                                   const char *file,
538                                   file_t *dir, char **name);
539 extern error_t hurd_path_split (file_t crdir, file_t cwdir,
540                                 const char *file,
541                                 file_t *dir, char **name);
542 extern error_t __hurd_path_lookup (file_t crdir, file_t cwdir,
543                                    const char *file,
544                                    int flags, mode_t mode,
545                                    file_t *port);
546 extern error_t hurd_path_lookup (file_t crdir, file_t cwdir,
547                                  const char *filename,
548                                  int flags, mode_t mode,
549                                  file_t *port);
550
551 /* Returns a port to the directory, and sets *NAME to the file name.  */
552 extern file_t __path_split (const char *file, char **name);
553 extern file_t path_split (const char *file, char **name);
554
555 /* Looks up FILE with the given FLAGS and MODE (as for dir_pathtrans).  */
556 extern file_t __path_lookup (const char *file, int flags, mode_t mode);
557 extern file_t path_lookup (const char *file, int flags, mode_t mode);
558
559 /* Open a file descriptor on a port.  */
560 extern int openport (io_t port, int flags);
561
562 /* Inform the proc server we have exitted with STATUS, and kill the
563    task thoroughly.  This function never returns, no matter what.  */
564 extern volatile void _hurd_exit (int status);
565
566 /* Initialize the library data structures from the
567    ints and ports passed to us by the exec server.
568    Then vm_deallocate PORTARRAY and INTARRAY.  */
569 extern void _hurd_init (int flags, char **argv,
570                         mach_port_t *portarray, size_t portarraysize,
571                         int *intarray, size_t intarraysize);
572
573 /* Do startup handshaking with the proc server.  */
574 extern void _hurd_proc_init (char **argv);
575 \f
576 /* User-registered handlers for specific `ioctl' requests.  */
577
578 struct ioctl_handler
579   {
580     int first_request, last_request; /* Range of handled request values.  */
581
582     int (*handler) (int fd, int request, void *arg);
583
584     struct ioctl_handler *next; /* Next handler.  */
585   };
586
587 /* Define a library-internal handler for ioctl commands
588    between FIRST and LAST inclusive.  */
589
590 #define _HURD_HANDLE_IOCTLS(handler, first, last)                             \
591   static const struct ioctl_handler handler##_ioctl_handler =                 \
592     { first, last, handler, NULL };                                           \
593   text_set_element (_hurd_ioctl_handler_lists, ##handler##_ioctl_handler)
594
595 /* Define a library-internal handler for a single ioctl command.  */
596 #define _HURD_HANDLE_IOCTL(handler, ioctl) \
597   _HURD_HANDLE_IOCTLS (handler, (ioctl), (ioctl))
598
599 #endif  /* hurd.h */