Formerly ../hurd/hurdioctl.c.~4~
[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_become_ctty (port, _hurd_pid,
144                                                       _hurd_pgrp,
145                                                       _hurd_msgport,
146                                                       &newctty))
147                                 /* XXX it is our ctty but the call failed? */
148                                 newctty = MACH_PORT_NULL;
149                               __mach_port_deallocate
150                                 (__mach_task_self (), (mach_port_t) id);
151                             }
152                           else
153                             newctty = MACH_PORT_NULL;
154                           0;
155                         }));
156
157       /* Install the new ctty port.  */
158       _hurd_port_set (&d->ctty, newctty);
159     }
160
161   __mutex_unlock (&_hurd_dtable_lock);
162   HURD_CRITICAL_END;
163 }
164
165
166 /* Make FD be the controlling terminal.
167    This function is called for `ioctl (fd, TCIOSCTTY)'.  */
168
169 static int
170 tiocsctty (int fd,
171            int request)         /* Always TIOCSCTTY.  */
172 {
173   mach_port_t cttyid;
174   error_t err;
175
176   /* Get FD's cttyid port, unless it is already ours.  */
177   err = HURD_DPORT_USE (fd,
178                         ctty ? EADDRINUSE : __term_getctty (port, &cttyid));
179   if (err == EADDRINUSE)
180     /* FD is already the ctty.  Nothing to do.  */
181     return 0;
182   else if (err)
183     return __hurd_fail (err);
184
185   /* Make it our own.  */
186   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], cttyid); /* Consumes ref.  */
187
188   /* Reset all the ctty ports in all the descriptors.  */
189   __USEPORT (CTTYID, (rectty_dtable (port), 0));
190
191   return 0;
192 }
193 _HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
194
195 /* Dissociate from the controlling terminal.  */
196
197 static int
198 tiocnotty (int fd,
199            int request)         /* Always TIOCNOTTY.  */
200 {
201   mach_port_t fd_cttyid;
202   error_t err;
203
204   if (err = HURD_DPORT_USE (fd, __term_getctty (port, &fd_cttyid)))
205     return __hurd_fail (err);
206
207   if (__USEPORT (CTTYID, port != fd_cttyid))
208     err = EINVAL;
209
210   __mach_port_deallocate (__mach_task_self (), fd_cttyid);
211
212   if (err)
213     return __hurd_fail (err);
214
215   /* Clear our cttyid port cell.  */
216   _hurd_port_set (&_hurd_ports[INIT_PORT_CTTYID], MACH_PORT_NULL);
217
218   /* Reset all the ctty ports in all the descriptors.  */
219                                 
220   __USEPORT (CTTYID, (rectty_dtable (MACH_PORT_NULL), 0));
221
222   return 0;
223 }
224 _HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);