(linenum→info "unix/slp.c:2238")

glibc/2.7/hurd/hurdioctl.c

    1: /* ioctl commands which must be done in the C library.
    2:    Copyright (C) 1994,95,96,97,99,2001,02 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 Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the 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:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <hurd.h>
   21: #include <hurd/fd.h>
   22: #include <sys/ioctl.h>
   23: #include <hurd/ioctl.h>
   24: #include <string.h>
   25: 
   26: 
   27: /* Symbol set of ioctl handler lists.  If there are user-registered
   28:    handlers, one of these lists will contain them.  The other lists are
   29:    handlers built into the library.  */
   30: symbol_set_define (_hurd_ioctl_handler_lists)
   31: 
   32: /* Look up REQUEST in the set of handlers.  */
   33: ioctl_handler_t
   34: _hurd_lookup_ioctl_handler (int request)
   35: {
   36:   void *const *ptr;
   37:   const struct ioctl_handler *h;
   38: 
   39:   /* Mask off the type bits, so that we see requests in a single group as a
   40:      contiguous block of values.  */
   41:   request = _IOC_NOTYPE (request);
   42: 
   43:   for (ptr = symbol_set_first_element (_hurd_ioctl_handler_lists);
   44:        !symbol_set_end_p (_hurd_ioctl_handler_lists, ptr);
   45:        ++ptr)
   46:     for (h = *ptr; h != NULL; h = h->next)
   47:       if (request >= h->first_request && request <= h->last_request)
   48:         return h->handler;
   49: 
   50:   return NULL;
   51: }
   52: ^L
   53: #include <fcntl.h>
   54: 
   55: /* Find out how many bytes may be read from FD without blocking.  */
   56: 
   57: static int
   58: fioctl (int fd,
   59:         int request,
   60:         int *arg)
   61: {
   62:   error_t err;
   63: 
   64:   *(volatile int *) arg = *arg;
   65: 
   66:   switch (request)
   67:     {
   68:     default:
   69:       err = ENOTTY;
   70:       break;
   71: 
   72:     case FIONREAD:
   73:       {
   74:         mach_msg_type_number_t navail;
   75:         err = HURD_DPORT_USE (fd, __io_readable (port, &navail));
   76:         if (!err)
   77:           *arg = (int) navail;
   78:       }
   79:       break;
   80: 
   81:     case FIONBIO:
   82:       err = HURD_DPORT_USE (fd, (*arg ?
   83:                                  __io_set_some_openmodes :
   84:                                  __io_clear_some_openmodes)
   85:                             (port, O_NONBLOCK));
   86:       break;
   87: 
   88:     case FIOASYNC:
   89:       err = HURD_DPORT_USE (fd, (*arg ?
   90:                                  __io_set_some_openmodes :
   91:                                  __io_clear_some_openmodes)
   92:                             (port, O_ASYNC));
   93:       break;
   94: 
   95:     case FIOSETOWN:
   96:       err = HURD_DPORT_USE (fd, __io_mod_owner (port, *arg));
   97:       break;
   98: 
   99:     case FIOGETOWN:
  100:       err = HURD_DPORT_USE (fd, __io_get_owner (port, arg));
  101:       break;
  102:     }
  103: 
  104:   return err ? __hurd_dfail (fd, err) : 0;
  105: }
  106: 
  107: _HURD_HANDLE_IOCTLS (fioctl, FIOGETOWN, FIONREAD);
  108: 
  109: 
  110: static int
  111: fioclex (int fd,
  112:          int request)
  113: {
  114:   int flag;
  115: 
  116:   switch (request)
  117:     {
  118:     default:
  119:       return __hurd_fail (ENOTTY);
  120:     case FIOCLEX:
  121:       flag = FD_CLOEXEC;
  122:       break;
  123:     case FIONCLEX:
  124:       flag = 0;
  125:       break;
  126:     }
  127: 
  128:   return __fcntl (fd, F_SETFD, flag);
  129: }
  130: _HURD_HANDLE_IOCTLS (fioclex, FIOCLEX, FIONCLEX);
  131: ^L
  132: #include <hurd/term.h>
  133: #include <hurd/tioctl.h>
  134: 
  135: /* Install a new CTTYID port, atomically updating the dtable appropriately.
  136:    This consumes the send right passed in.  */
  137: 
  138: void
  139: _hurd_locked_install_cttyid (mach_port_t cttyid)
  140: {
  141:   mach_port_t old;
  142:   struct hurd_port *const port = &_hurd_ports[INIT_PORT_CTTYID];
  143:   struct hurd_userlink ulink;
  144:   int i;
  145: 
  146:   /* Install the new cttyid port, and preserve it with a ulink.
  147:      We unroll the _hurd_port_set + _hurd_port_get here so that
  148:      there is no window where the cell is unlocked and CTTYID could
  149:      be changed by another thread.  (We also delay the deallocation
  150:      of the old port until the end, to minimize the duration of the
  151:      critical section.)
  152: 
  153:      It is important that changing the cttyid port is only ever done by
  154:      holding the dtable lock continuously while updating the port cell and
  155:      re-ctty'ing the dtable; dtable.c assumes we do this.  Otherwise, the
  156:      pgrp-change notification code in dtable.c has to worry about racing
  157:      against us here in odd situations.  The one exception to this is
  158:      setsid, which holds the dtable lock while changing the pgrp and
  159:      clearing the cttyid port, and then unlocks the dtable lock to allow
  160: 
  161: 
  162:   */
  163: 
  164:   __spin_lock (&port->lock);
  165:   old = _hurd_userlink_clear (&port->users) ? port->port : MACH_PORT_NULL;
  166:   port->port = cttyid;
  167:   cttyid = _hurd_port_locked_get (port, &ulink);
  168: 
  169:   for (i = 0; i < _hurd_dtablesize; ++i)
  170:     {
  171:       struct hurd_fd *const d = _hurd_dtable[i];
  172:       mach_port_t newctty;
  173: 
  174:       if (d == NULL)
  175:         /* Nothing to do for an unused descriptor cell.  */
  176:         continue;
  177: 
  178:       if (cttyid == MACH_PORT_NULL)
  179:         /* We now have no controlling tty at all.  */
  180:         newctty = MACH_PORT_NULL;
  181:       else
  182:         HURD_PORT_USE (&d->port,
  183:                        ({ mach_port_t id;
  184:                           /* Get the io object's cttyid port.  */
  185:                           if (! __term_getctty (port, &id))
  186:                             {
  187:                               if (id == cttyid && /* Is it ours?  */
  188:                                   /* Get the ctty io port.  */
  189:                                   __term_open_ctty (port,
  190:                                                     _hurd_pid, _hurd_pgrp,
  191:                                                     &newctty))
  192:                                 /* XXX it is our ctty but the call failed? */
  193:                                 newctty = MACH_PORT_NULL;
  194:                               __mach_port_deallocate
  195:                                 (__mach_task_self (), (mach_port_t) id);
  196:                             }
  197:                           else
  198:                             newctty = MACH_PORT_NULL;
  199:                           0;
  200:                         }));
  201: 
  202:       /* Install the new ctty port.  */
  203:       _hurd_port_set (&d->ctty, newctty);
  204:     }
  205: 
  206:   __mutex_unlock (&_hurd_dtable_lock);
  207: 
  208:   if (old != MACH_PORT_NULL)
  209:     __mach_port_deallocate (__mach_task_self (), old);
  210:   _hurd_port_free (port, &ulink, cttyid);
  211: }
  212: 
  213: static void
  214: install_ctty (mach_port_t cttyid)
  215: {
  216:   HURD_CRITICAL_BEGIN;
  217:   __mutex_lock (&_hurd_dtable_lock);
  218:   _hurd_locked_install_cttyid (cttyid);
  219:   HURD_CRITICAL_END;
  220: }
  221: 
  222: 
  223: /* Called when we have received a message saying to use a new ctty ID port.  */
  224: 
  225: error_t
  226: _hurd_setcttyid (mach_port_t cttyid)
  227: {
  228:   error_t err;
  229: 
  230:   if (cttyid != MACH_PORT_NULL)
  231:     {
  232:       /* Give the new send right a user reference.
  233:          This is a good way to check that it is valid.  */
  234:       if (err = __mach_port_mod_refs (__mach_task_self (), cttyid,
  235:                                       MACH_PORT_RIGHT_SEND, 1))
  236:         return err;
  237:     }
  238: 
  239:   /* Install the port, consuming the reference we just created.  */
  240:   install_ctty (cttyid);
  241: 
  242:   return 0;
  243: }
  244: 
  245: 
  246: /* Make FD be the controlling terminal.
  247:    This function is called for `ioctl (fd, TCIOSCTTY)'.  */
  248: 
  249: static int
  250: tiocsctty (int fd,
  251:            int request)                /* Always TIOCSCTTY.  */
  252: {
  253:   mach_port_t cttyid;
  254:   error_t err;
  255: 
  256:   /* Get FD's cttyid port, unless it is already ours.  */
  257:   err = HURD_DPORT_USE (fd, ctty != MACH_PORT_NULL ? EADDRINUSE :
  258:                         __term_getctty (port, &cttyid));
  259:   if (err == EADDRINUSE)
  260:     /* FD is already the ctty.  Nothing to do.  */
  261:     return 0;
  262:   else if (err)
  263:     return __hurd_fail (err);
  264: 
  265:   /* Change the terminal's pgrp to ours.  */
  266:   err = HURD_DPORT_USE (fd, __tioctl_tiocspgrp (port, _hurd_pgrp));
  267:   if (err)
  268:     return __hurd_fail (err);
  269: 
  270:   /* Make it our own.  */
  271:   install_ctty (cttyid);
  272: 
  273:   return 0;
  274: }
  275: _HURD_HANDLE_IOCTL (tiocsctty, TIOCSCTTY);
  276: 
  277: /* Dissociate from the controlling terminal.  */
  278: 
  279: static int
  280: tiocnotty (int fd,
  281:            int request)                /* Always TIOCNOTTY.  */
  282: {
  283:   mach_port_t fd_cttyid;
  284:   error_t err;
  285: 
  286:   if (err = HURD_DPORT_USE (fd, __term_getctty (port, &fd_cttyid)))
  287:     return __hurd_fail (err);
  288: 
  289:   if (__USEPORT (CTTYID, port != fd_cttyid))
  290:     err = EINVAL;
  291: 
  292:   __mach_port_deallocate (__mach_task_self (), fd_cttyid);
  293: 
  294:   if (err)
  295:     return __hurd_fail (err);
  296: 
  297:   /* Clear our cttyid port.  */
  298:   install_ctty (MACH_PORT_NULL);
  299: 
  300:   return 0;
  301: }
  302: _HURD_HANDLE_IOCTL (tiocnotty, TIOCNOTTY);
  303: ^L
  304: #include <hurd/pfinet.h>
  305: #include <net/if.h>
  306: #include <netinet/in.h>
  307: 
  308: /* Fill in the buffer IFC->IFC_BUF of length IFC->IFC_LEN with a list
  309:    of ifr structures, one for each network interface.  */
  310: static int
  311: siocgifconf (int fd, int request, struct ifconf *ifc)
  312: {
  313:   error_t err;
  314:   size_t data_len = ifc->ifc_len;
  315:   char *data = ifc->ifc_buf;
  316: 
  317:   if (data_len <= 0)
  318:     return 0;
  319: 
  320:   err = HURD_DPORT_USE (fd, __pfinet_siocgifconf (port, ifc->ifc_len,
  321:                                                   &data, &data_len));
  322:   if (data_len < ifc->ifc_len)
  323:     ifc->ifc_len = data_len;
  324:   if (data != ifc->ifc_buf)
  325:     {
  326:       memcpy (ifc->ifc_buf, data, ifc->ifc_len);
  327:       __vm_deallocate (__mach_task_self (), (vm_address_t) data, data_len);
  328:     }
  329:   return err ? __hurd_dfail (fd, err) : 0;
  330: }
  331: _HURD_HANDLE_IOCTL (siocgifconf, SIOCGIFCONF);
Syntax (Markdown)