(_hurd_msgport_receive): Unlock self sigstate lock after getting it.
[kopensolaris-gnu/glibc.git] / hurd / hurdioctl.c
1 /* ioctl commands which must be done in the C library.
2 Copyright (C) 1994 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #include <hurd.h>
21 #include <hurd/fd.h>
22 #include <sys/ioctl.h>
23 #include <gnu-stabs.h>
24
25
26 /* Symbol set of ioctl handler lists.
27    This must be uninitialized for ld to use it for the set.  */
28 struct handler_set
29   {
30     size_t n;
31     struct ioctl_handler *v[0];
32   };
33 struct handler_set _hurd_ioctl_handler_lists;
34
35 /* This definition is here (and initialized!) so that when __ioctl refers
36    to it, we will link in fionread et al (below).  */
37 struct handler_set *const _hurd_ioctl_handlers = &_hurd_ioctl_handler_lists;
38 \f
39 #include <fcntl.h>
40
41 /* Find out how many bytes may be read from FD without blocking.  */
42
43 static int
44 fioctl (int fd,
45         int request,
46         int *arg)
47 {
48   error_t err;
49
50   *(volatile int *) arg = *arg;
51
52   switch (request)
53     {
54     default:
55       err = EGRATUITOUS;
56       break;
57
58     case FIONREAD:
59       err = HURD_DPORT_USE (fd, __io_readable (port, arg));
60       break;
61
62     case FIONBIO:
63       err = HURD_DPORT_USE (fd, (*arg ?
64                                  __io_set_some_openmodes :
65                                  __io_clear_some_openmodes)
66                             (port, O_NONBLOCK));
67       break;
68
69     case FIOASYNC:
70       err = HURD_DPORT_USE (fd, (*arg ?
71                                  __io_set_some_openmodes :
72                                  __io_clear_some_openmodes)
73                             (port, O_ASYNC));
74       break;
75
76     case FIOSETOWN:
77       err = HURD_DPORT_USE (fd, __io_mod_owner (port, *arg));
78       break;
79
80     case FIOGETOWN:
81       err = HURD_DPORT_USE (fd, __io_get_owner (port, arg));
82       break;
83     }
84
85   return err ? __hurd_fail (err) : 0;
86 }
87
88 _HURD_HANDLE_IOCTLS (fioctl, FIOGETOWN, FIONREAD);
89
90
91 static int
92 fioclex (int fd,
93          int request)
94 {
95   int flag;
96
97   switch (request)
98     {
99     default:
100       return __hurd_fail (EGRATUITOUS);
101     case FIOCLEX:
102       flag = FD_CLOEXEC;
103       break;
104     case FIONCLEX:
105       flag = 0;
106       break;
107     }
108
109   return __fcntl (fd, F_SETFD, flag);
110 }
111 _HURD_HANDLE_IOCTLS (fioclex, FIOCLEX, FIONCLEX);
112 \f
113 #include <hurd/term.h>
114
115 static void
116 rectty_dtable (mach_port_t cttyid)
117 {
118   int i;
119   
120   HURD_CRITICAL_BEGIN;
121   __mutex_lock (&_hurd_dtable_lock);
122
123   for (i = 0; i < _hurd_dtablesize; ++i)
124     {
125       struct hurd_fd *const d = _hurd_dtable[i];
126       mach_port_t newctty;
127
128       if (d == NULL)
129         /* Nothing to do for an unused descriptor cell.  */
130         continue;
131
132       if (cttyid == MACH_PORT_NULL)
133         /* We now have no controlling tty at all.  */
134         newctty = MACH_PORT_NULL;
135       else
136         HURD_PORT_USE (&d->port,
137                        ({ mach_port_t id;
138                           /* Get the io object's cttyid port.  */
139                           if (! __term_getctty (port, &id))
140                             {
141                               if (id == cttyid && /* Is it ours?  */
142                                   /* Get the ctty io port.  */
143                                   __term_open_ctty (port,
144                                                     _hurd_pid, _hurd_pgrp,
145                                                     &newctty))
146                                 /* XXX it is our ctty but the call failed? */
147                                 newctty = MACH_PORT_NULL;
148                               __mach_port_deallocate
149                                 (__mach_task_self (), (mach_port_t) id);
150                             }
151                           else
152                             newctty = MACH_PORT_NULL;
153                           0;
154                         }));
155
156       /* Install the new ctty port.  */
157       _hurd_port_set (&d->ctty, newctty);
158     }
159
160   __mutex_unlock (&_hurd_dtable_lock);
161   HURD_CRITICAL_END;
162 }
163
164
165 /* Called when we have received a message saying to use a new ctty ID port.  */
166
167 error_t
168 _hurd_setcttyid (mach_port_t cttyid)
169 {
170   error_t err;
171
172   if (cttyid != MACH_PORT_NULL)
173     {
174       /* Give the new send right a user reference.
175          This is a good way to check that it is valid.  */
176       if (err = __mach_port_mod_refs (__mach_task_self (), cttyid,
177                                       MACH_PORT_RIGHT_SEND, 1))
178         return err;
179     }
180
181   /* Install the port, consuming the reference we just created.  */
182   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid);
183
184   /* Reset all the ctty ports in all the descriptors.  */
185   __USEPORT (CTTYID, (rectty_dtable (cttyid), 0));
186
187   return 0;
188 }
189
190
191 /* Make FD be the controlling terminal.
192    This function is called for `ioctl (fd, TCIOSCTTY)'.  */
193
194 static int
195 tiocsctty (int fd,
196            int request)         /* Always TIOCSCTTY.  */
197 {
198   mach_port_t cttyid;
199   error_t err;
200
201   /* Get FD's cttyid port, unless it is already ours.  */
202   err = HURD_DPORT_USE (fd, ctty != MACH_PORT_NULL ? EADDRINUSE :
203                         __term_getctty (port, &cttyid));
204   if (err == EADDRINUSE)
205     /* FD is already the ctty.  Nothing to do.  */
206     return 0;
207   else if (err)
208     return __hurd_fail (err);
209
210   /* Make it our own.  */
211   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid);
212
213   /* Reset all the ctty ports in all the descriptors.  */
214   __USEPORT (CTTYID, (rectty_dtable (cttyid), 0));
215
216   return 0;
217 }
218 _HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
219
220 /* Dissociate from the controlling terminal.  */
221
222 static int
223 tiocnotty (int fd,
224            int request)         /* Always TIOCNOTTY.  */
225 {
226   mach_port_t fd_cttyid;
227   error_t err;
228
229   if (err = HURD_DPORT_USE (fd, __term_getctty (port, &fd_cttyid)))
230     return __hurd_fail (err);
231
232   if (__USEPORT (CTTYID, port != fd_cttyid))
233     err = EINVAL;
234
235   __mach_port_deallocate (__mach_task_self (), fd_cttyid);
236
237   if (err)
238     return __hurd_fail (err);
239
240   /* Clear our cttyid port cell.  */
241   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL);
242
243   /* Reset all the ctty ports in all the descriptors.  */
244                                 
245   __USEPORT (CTTYID, (rectty_dtable (MACH_PORT_NULL), 0));
246
247   return 0;
248 }
249 _HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);