root/compat/sunos/sunos_ioctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stios2btios
  2. btios2stios
  3. stios2stio
  4. stio2stios
  5. sunos_sys_ioctl
  6. bsd_to_sunos_flock
  7. sunos_to_bsd_flock
  8. sunos_sys_fcntl

    1 /*      $OpenBSD: sunos_ioctl.c,v 1.16 2004/09/19 21:34:43 mickey Exp $ */
    2 /*      $NetBSD: sunos_ioctl.c,v 1.23 1996/03/14 19:33:46 christos Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1993 Markus Wild.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/proc.h>
   32 #include <sys/systm.h>
   33 #include <sys/file.h>
   34 #include <sys/filedesc.h>
   35 #include <sys/ioctl.h>
   36 #include <sys/termios.h>
   37 #include <sys/tty.h>
   38 #include <sys/socket.h>
   39 #include <sys/audioio.h>
   40 #include <sys/vnode.h>
   41 #include <net/if.h>
   42 
   43 #include <sys/mount.h>
   44 
   45 #include <miscfs/specfs/specdev.h>
   46 
   47 #include <sys/syscallargs.h>
   48 #include <compat/sunos/sunos.h>
   49 #include <compat/sunos/sunos_syscallargs.h>
   50 #include <compat/sunos/sunos_util.h>
   51 
   52 /*
   53  * SunOS ioctl calls.
   54  * This file is something of a hodge-podge.
   55  * Support gets added as things turn up....
   56  */
   57 
   58 static const struct speedtab sptab[] = {
   59         { 0, 0 },
   60         { 50, 1 },
   61         { 75, 2 },
   62         { 110, 3 },
   63         { 134, 4 },
   64         { 135, 4 },
   65         { 150, 5 },
   66         { 200, 6 },
   67         { 300, 7 },
   68         { 600, 8 },
   69         { 1200, 9 },
   70         { 1800, 10 },
   71         { 2400, 11 },
   72         { 4800, 12 },
   73         { 9600, 13 },
   74         { 19200, 14 },
   75         { 38400, 15 },
   76         { -1, -1 }
   77 };
   78 
   79 static const u_long s2btab[] = {
   80         0,
   81         50,
   82         75,
   83         110,
   84         134,
   85         150,
   86         200,
   87         300,
   88         600,
   89         1200,
   90         1800,
   91         2400,
   92         4800,
   93         9600,
   94         19200,
   95         38400,
   96 };
   97 
   98 static void stios2btios(struct sunos_termios *, struct termios *);
   99 static void btios2stios(struct termios *, struct sunos_termios *);
  100 static void stios2stio(struct sunos_termios *, struct sunos_termio *);
  101 static void stio2stios(struct sunos_termio *, struct sunos_termios *);
  102 
  103 /*
  104  * These two conversion functions have mostly been done
  105  * with some perl cut&paste, then hand-edited to comment
  106  * out what doesn't exist under NetBSD.
  107  * A note from Markus's code:
  108  *      (l & BITMASK1) / BITMASK1 * BITMASK2  is translated
  109  *      optimally by gcc m68k, much better than any ?: stuff.
  110  *      Code may vary with different architectures of course.
  111  *
  112  * I don't know what optimizer you used, but seeing divu's and
  113  * bfextu's in the m68k assembly output did not encourage me...
  114  * as well, gcc on the sparc definitely generates much better
  115  * code with `?:'.
  116  */
  117 
  118 static void
  119 stios2btios(st, bt)
  120         struct sunos_termios *st;
  121         struct termios *bt;
  122 {
  123         register u_long l, r;
  124 
  125         l = st->c_iflag;
  126         r =     ((l & 0x00000001) ? IGNBRK      : 0);
  127         r |=    ((l & 0x00000002) ? BRKINT      : 0);
  128         r |=    ((l & 0x00000004) ? IGNPAR      : 0);
  129         r |=    ((l & 0x00000008) ? PARMRK      : 0);
  130         r |=    ((l & 0x00000010) ? INPCK       : 0);
  131         r |=    ((l & 0x00000020) ? ISTRIP      : 0);
  132         r |=    ((l & 0x00000040) ? INLCR       : 0);
  133         r |=    ((l & 0x00000080) ? IGNCR       : 0);
  134         r |=    ((l & 0x00000100) ? ICRNL       : 0);
  135         /*      ((l & 0x00000200) ? IUCLC       : 0) */
  136         r |=    ((l & 0x00000400) ? IXON        : 0);
  137         r |=    ((l & 0x00000800) ? IXANY       : 0);
  138         r |=    ((l & 0x00001000) ? IXOFF       : 0);
  139         r |=    ((l & 0x00002000) ? IMAXBEL     : 0);
  140         bt->c_iflag = r;
  141 
  142         l = st->c_oflag;
  143         r =     ((l & 0x00000001) ? OPOST       : 0);
  144         /*      ((l & 0x00000002) ? OLCUC       : 0) */
  145         r |=    ((l & 0x00000004) ? ONLCR       : 0);
  146         /*      ((l & 0x00000008) ? OCRNL       : 0) */
  147         /*      ((l & 0x00000010) ? ONOCR       : 0) */
  148         /*      ((l & 0x00000020) ? ONLRET      : 0) */
  149         /*      ((l & 0x00000040) ? OFILL       : 0) */
  150         /*      ((l & 0x00000080) ? OFDEL       : 0) */
  151         /*      ((l & 0x00000100) ? NLDLY       : 0) */
  152         /*      ((l & 0x00000100) ? NL1         : 0) */
  153         /*      ((l & 0x00000600) ? CRDLY       : 0) */
  154         /*      ((l & 0x00000200) ? CR1         : 0) */
  155         /*      ((l & 0x00000400) ? CR2         : 0) */
  156         /*      ((l & 0x00000600) ? CR3         : 0) */
  157         /*      ((l & 0x00001800) ? TABDLY      : 0) */
  158         /*      ((l & 0x00000800) ? TAB1        : 0) */
  159         /*      ((l & 0x00001000) ? TAB2        : 0) */
  160         r |=    ((l & 0x00001800) ? OXTABS      : 0);
  161         /*      ((l & 0x00002000) ? BSDLY       : 0) */
  162         /*      ((l & 0x00002000) ? BS1         : 0) */
  163         /*      ((l & 0x00004000) ? VTDLY       : 0) */
  164         /*      ((l & 0x00004000) ? VT1         : 0) */
  165         /*      ((l & 0x00008000) ? FFDLY       : 0) */
  166         /*      ((l & 0x00008000) ? FF1         : 0) */
  167         /*      ((l & 0x00010000) ? PAGEOUT     : 0) */
  168         /*      ((l & 0x00020000) ? WRAP        : 0) */
  169         bt->c_oflag = r;
  170 
  171         l = st->c_cflag;
  172         switch (l & 0x00000030) {
  173         case 0:
  174                 r = CS5;
  175                 break;
  176         case 0x00000010:
  177                 r = CS6;
  178                 break;
  179         case 0x00000020:
  180                 r = CS7;
  181                 break;
  182         case 0x00000030:
  183                 r = CS8;
  184                 break;
  185         }
  186         r |=    ((l & 0x00000040) ? CSTOPB      : 0);
  187         r |=    ((l & 0x00000080) ? CREAD       : 0);
  188         r |=    ((l & 0x00000100) ? PARENB      : 0);
  189         r |=    ((l & 0x00000200) ? PARODD      : 0);
  190         r |=    ((l & 0x00000400) ? HUPCL       : 0);
  191         r |=    ((l & 0x00000800) ? CLOCAL      : 0);
  192         /*      ((l & 0x00001000) ? LOBLK       : 0) */
  193         r |=    ((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
  194         bt->c_cflag = r;
  195 
  196         bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
  197 
  198         l = st->c_lflag;
  199         r =     ((l & 0x00000001) ? ISIG        : 0);
  200         r |=    ((l & 0x00000002) ? ICANON      : 0);
  201         /*      ((l & 0x00000004) ? XCASE       : 0) */
  202         r |=    ((l & 0x00000008) ? ECHO        : 0);
  203         r |=    ((l & 0x00000010) ? ECHOE       : 0);
  204         r |=    ((l & 0x00000020) ? ECHOK       : 0);
  205         r |=    ((l & 0x00000040) ? ECHONL      : 0);
  206         r |=    ((l & 0x00000080) ? NOFLSH      : 0);
  207         r |=    ((l & 0x00000100) ? TOSTOP      : 0);
  208         r |=    ((l & 0x00000200) ? ECHOCTL     : 0);
  209         r |=    ((l & 0x00000400) ? ECHOPRT     : 0);
  210         r |=    ((l & 0x00000800) ? ECHOKE      : 0);
  211         /*      ((l & 0x00001000) ? DEFECHO     : 0) */
  212         r |=    ((l & 0x00002000) ? FLUSHO      : 0);
  213         r |=    ((l & 0x00004000) ? PENDIN      : 0);
  214         bt->c_lflag = r;
  215 
  216         bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
  217         bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
  218         bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
  219         bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
  220         bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
  221         bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
  222         bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
  223     /*  bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
  224         bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
  225         bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
  226         bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
  227         bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
  228         bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
  229         bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
  230         bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
  231         bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
  232         bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
  233 
  234         /* if `raw mode', create native VMIN/VTIME from SunOS VEOF/VEOL */
  235         bt->c_cc[VMIN]     = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOF];
  236         bt->c_cc[VTIME]    = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOL];
  237 }
  238 
  239 
  240 static void
  241 btios2stios(bt, st)
  242         struct termios *bt;
  243         struct sunos_termios *st;
  244 {
  245         register u_long l, r;
  246         int s;
  247 
  248         l = bt->c_iflag;
  249         r =     ((l &  IGNBRK) ? 0x00000001     : 0);
  250         r |=    ((l &  BRKINT) ? 0x00000002     : 0);
  251         r |=    ((l &  IGNPAR) ? 0x00000004     : 0);
  252         r |=    ((l &  PARMRK) ? 0x00000008     : 0);
  253         r |=    ((l &   INPCK) ? 0x00000010     : 0);
  254         r |=    ((l &  ISTRIP) ? 0x00000020     : 0);
  255         r |=    ((l &   INLCR) ? 0x00000040     : 0);
  256         r |=    ((l &   IGNCR) ? 0x00000080     : 0);
  257         r |=    ((l &   ICRNL) ? 0x00000100     : 0);
  258         /*      ((l &   IUCLC) ? 0x00000200     : 0) */
  259         r |=    ((l &    IXON) ? 0x00000400     : 0);
  260         r |=    ((l &   IXANY) ? 0x00000800     : 0);
  261         r |=    ((l &   IXOFF) ? 0x00001000     : 0);
  262         r |=    ((l & IMAXBEL) ? 0x00002000     : 0);
  263         st->c_iflag = r;
  264 
  265         l = bt->c_oflag;
  266         r =     ((l &   OPOST) ? 0x00000001     : 0);
  267         /*      ((l &   OLCUC) ? 0x00000002     : 0) */
  268         r |=    ((l &   ONLCR) ? 0x00000004     : 0);
  269         /*      ((l &   OCRNL) ? 0x00000008     : 0) */
  270         /*      ((l &   ONOCR) ? 0x00000010     : 0) */
  271         /*      ((l &  ONLRET) ? 0x00000020     : 0) */
  272         /*      ((l &   OFILL) ? 0x00000040     : 0) */
  273         /*      ((l &   OFDEL) ? 0x00000080     : 0) */
  274         /*      ((l &   NLDLY) ? 0x00000100     : 0) */
  275         /*      ((l &     NL1) ? 0x00000100     : 0) */
  276         /*      ((l &   CRDLY) ? 0x00000600     : 0) */
  277         /*      ((l &     CR1) ? 0x00000200     : 0) */
  278         /*      ((l &     CR2) ? 0x00000400     : 0) */
  279         /*      ((l &     CR3) ? 0x00000600     : 0) */
  280         /*      ((l &  TABDLY) ? 0x00001800     : 0) */
  281         /*      ((l &    TAB1) ? 0x00000800     : 0) */
  282         /*      ((l &    TAB2) ? 0x00001000     : 0) */
  283         r |=    ((l &  OXTABS) ? 0x00001800     : 0);
  284         /*      ((l &   BSDLY) ? 0x00002000     : 0) */
  285         /*      ((l &     BS1) ? 0x00002000     : 0) */
  286         /*      ((l &   VTDLY) ? 0x00004000     : 0) */
  287         /*      ((l &     VT1) ? 0x00004000     : 0) */
  288         /*      ((l &   FFDLY) ? 0x00008000     : 0) */
  289         /*      ((l &     FF1) ? 0x00008000     : 0) */
  290         /*      ((l & PAGEOUT) ? 0x00010000     : 0) */
  291         /*      ((l &    WRAP) ? 0x00020000     : 0) */
  292         st->c_oflag = r;
  293 
  294         l = bt->c_cflag;
  295         switch (l & CSIZE) {
  296         case CS5:
  297                 r = 0;
  298                 break;
  299         case CS6:
  300                 r = 0x00000010;
  301                 break;
  302         case CS7:
  303                 r = 0x00000020;
  304                 break;
  305         case CS8:
  306                 r = 0x00000030;
  307                 break;
  308         }
  309         r |=    ((l &  CSTOPB) ? 0x00000040     : 0);
  310         r |=    ((l &   CREAD) ? 0x00000080     : 0);
  311         r |=    ((l &  PARENB) ? 0x00000100     : 0);
  312         r |=    ((l &  PARODD) ? 0x00000200     : 0);
  313         r |=    ((l &   HUPCL) ? 0x00000400     : 0);
  314         r |=    ((l &  CLOCAL) ? 0x00000800     : 0);
  315         /*      ((l &   LOBLK) ? 0x00001000     : 0) */
  316         r |=    ((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
  317         st->c_cflag = r;
  318 
  319         l = bt->c_lflag;
  320         r =     ((l &    ISIG) ? 0x00000001     : 0);
  321         r |=    ((l &  ICANON) ? 0x00000002     : 0);
  322         /*      ((l &   XCASE) ? 0x00000004     : 0) */
  323         r |=    ((l &    ECHO) ? 0x00000008     : 0);
  324         r |=    ((l &   ECHOE) ? 0x00000010     : 0);
  325         r |=    ((l &   ECHOK) ? 0x00000020     : 0);
  326         r |=    ((l &  ECHONL) ? 0x00000040     : 0);
  327         r |=    ((l &  NOFLSH) ? 0x00000080     : 0);
  328         r |=    ((l &  TOSTOP) ? 0x00000100     : 0);
  329         r |=    ((l & ECHOCTL) ? 0x00000200     : 0);
  330         r |=    ((l & ECHOPRT) ? 0x00000400     : 0);
  331         r |=    ((l &  ECHOKE) ? 0x00000800     : 0);
  332         /*      ((l & DEFECHO) ? 0x00001000     : 0) */
  333         r |=    ((l &  FLUSHO) ? 0x00002000     : 0);
  334         r |=    ((l &  PENDIN) ? 0x00004000     : 0);
  335         st->c_lflag = r;
  336 
  337         s = ttspeedtab(bt->c_ospeed, sptab);
  338         if (s >= 0)
  339                 st->c_cflag |= s;
  340 
  341         st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
  342         st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
  343         st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
  344         st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
  345         st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
  346         st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
  347         st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
  348         st->c_cc[7] = 0;
  349                 /*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
  350         st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
  351         st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
  352         st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
  353         st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
  354         st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
  355         st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
  356         st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
  357         st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
  358         st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
  359 
  360         if (!(bt->c_lflag & ICANON)) {
  361                 /* SunOS stores VMIN/VTIME in VEOF/VEOL (if ICANON is off) */
  362                 st->c_cc[4] = bt->c_cc[VMIN];
  363                 st->c_cc[5] = bt->c_cc[VTIME];
  364         }
  365 
  366         st->c_line = 0;
  367 }
  368 
  369 static void
  370 stios2stio(ts, t)
  371         struct sunos_termios *ts;
  372         struct sunos_termio *t;
  373 {
  374         t->c_iflag = ts->c_iflag;
  375         t->c_oflag = ts->c_oflag;
  376         t->c_cflag = ts->c_cflag;
  377         t->c_lflag = ts->c_lflag;
  378         t->c_line  = ts->c_line;
  379         bcopy(ts->c_cc, t->c_cc, 8);
  380 }
  381 
  382 static void
  383 stio2stios(t, ts)
  384         struct sunos_termio *t;
  385         struct sunos_termios *ts;
  386 {
  387         ts->c_iflag = t->c_iflag;
  388         ts->c_oflag = t->c_oflag;
  389         ts->c_cflag = t->c_cflag;
  390         ts->c_lflag = t->c_lflag;
  391         ts->c_line  = t->c_line;
  392         bcopy(t->c_cc, ts->c_cc, 8); /* don't touch the upper fields! */
  393 }
  394 
  395 int
  396 sunos_sys_ioctl(p, v, retval)
  397         register struct proc *p;
  398         void *v;
  399         register_t *retval;
  400 {
  401         struct sunos_sys_ioctl_args *uap = v;
  402         struct filedesc *fdp = p->p_fd;
  403         struct file *fp;
  404         int (*ctl)(struct file *, u_long, caddr_t, struct proc *);
  405         int error;
  406 
  407         if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
  408                 return EBADF;
  409         FREF(fp);
  410 
  411         if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
  412                 error = EBADF;
  413                 goto out;
  414         }
  415 
  416         ctl = fp->f_ops->fo_ioctl;
  417 
  418         switch (SCARG(uap, com)) {
  419         case _IOR('t', 0, int):
  420                 SCARG(uap, com) = TIOCGETD;
  421                 break;
  422         case _IOW('t', 1, int):
  423             {
  424                 int disc;
  425 
  426                 if ((error = copyin(SCARG(uap, data), (caddr_t)&disc,
  427                     sizeof disc)) != 0)
  428                         goto out;
  429 
  430                 /* map SunOS NTTYDISC into our termios discipline */
  431                 if (disc == 2)
  432                         disc = 0;
  433                 /* all other disciplines are not supported by NetBSD */
  434                 if (disc) {
  435                         error = ENXIO;
  436                         goto out;
  437                 }
  438 
  439                 error = (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
  440                 goto out;
  441             }
  442         case _IOW('t', 101, int):       /* sun SUNOS_TIOCSSOFTCAR */
  443             {
  444                 int x;  /* unused */
  445 
  446                 error = copyin((caddr_t)&x, SCARG(uap, data), sizeof x);
  447                 goto out;
  448             }
  449         case _IOR('t', 100, int):       /* sun SUNOS_TIOCGSOFTCAR */
  450             {
  451                 int x = 0;
  452 
  453                 error = copyout((caddr_t)&x, SCARG(uap, data), sizeof x);
  454                 goto out;
  455             }
  456         case _IO('t', 36):              /* sun TIOCCONS, no parameters */
  457             {
  458                 int on = 1;
  459                 error = (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
  460                 goto out;
  461             }
  462         case _IOW('t', 37, struct sunos_ttysize):
  463             {
  464                 struct winsize ws;
  465                 struct sunos_ttysize ss;
  466 
  467                 if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
  468                         goto out;
  469 
  470                 if ((error = copyin (SCARG(uap, data), &ss, sizeof (ss))) != 0)
  471                         goto out;
  472 
  473                 ws.ws_row = ss.ts_row;
  474                 ws.ws_col = ss.ts_col;
  475 
  476                 error = ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
  477                 goto out;
  478             }
  479         case _IOW('t', 38, struct sunos_ttysize):
  480             {
  481                 struct winsize ws;
  482                 struct sunos_ttysize ss;
  483 
  484                 if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
  485                         goto out;
  486 
  487                 ss.ts_row = ws.ws_row;
  488                 ss.ts_col = ws.ws_col;
  489 
  490                 error = copyout ((caddr_t)&ss, SCARG(uap, data), sizeof (ss));
  491                 goto out;
  492             }
  493         case _IOW('t', 130, int):       /* TIOCSETPGRP: posix variant */
  494                 SCARG(uap, com) = TIOCSPGRP;
  495                 break;
  496         case _IOR('t', 131, int):       /* TIOCGETPGRP: posix variant */
  497             {
  498                 /*
  499                  * sigh, must do error translation on pty devices
  500                  * (see also kern/tty_pty.c)
  501                  */
  502                 int pgrp;
  503                 struct vnode *vp;
  504                 error = (*ctl)(fp, TIOCGPGRP, (caddr_t)&pgrp, p);
  505                 if (error) {
  506                         vp = (struct vnode *)fp->f_data;
  507                         if (error == EIO && vp != NULL &&
  508                             vp->v_type == VCHR && major(vp->v_rdev) == 21)
  509                                 error = ENOTTY;
  510                         goto out;
  511                 }
  512                 error = copyout((caddr_t)&pgrp, SCARG(uap, data), sizeof(pgrp));
  513                 goto out;
  514             }
  515         case _IO('t', 132):
  516                 SCARG(uap, com) = TIOCSCTTY;
  517                 break;
  518         case SUNOS_TCFLSH:
  519                 /* XXX: fixme */
  520                 error = 0;
  521                 goto out;
  522         case SUNOS_TCGETA:
  523         case SUNOS_TCGETS:
  524             {
  525                 struct termios bts;
  526                 struct sunos_termios sts;
  527                 struct sunos_termio st;
  528 
  529                 if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
  530                         goto out;
  531 
  532                 btios2stios (&bts, &sts);
  533                 if (SCARG(uap, com) == SUNOS_TCGETA) {
  534                         stios2stio (&sts, &st);
  535                         error = copyout((caddr_t)&st, SCARG(uap, data),
  536                             sizeof (st));
  537                         goto out;
  538                 } else {
  539                         error = copyout((caddr_t)&sts, SCARG(uap, data),
  540                             sizeof (sts));
  541                         goto out;
  542                 }
  543                 /*NOTREACHED*/
  544             }
  545         case SUNOS_TCSETA:
  546         case SUNOS_TCSETAW:
  547         case SUNOS_TCSETAF:
  548             {
  549                 struct termios bts;
  550                 struct sunos_termios sts;
  551                 struct sunos_termio st;
  552 
  553                 if ((error = copyin(SCARG(uap, data), (caddr_t)&st,
  554                     sizeof (st))) != 0)
  555                         goto out;
  556 
  557                 /* get full BSD termios so we don't lose information */
  558                 if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
  559                         goto out;
  560 
  561                 /*
  562                  * convert to sun termios, copy in information from
  563                  * termio, and convert back, then set new values.
  564                  */
  565                 btios2stios(&bts, &sts);
  566                 stio2stios(&st, &sts);
  567                 stios2btios(&sts, &bts);
  568 
  569                 error = (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
  570                     (caddr_t)&bts, p);
  571                 goto out;
  572             }
  573         case SUNOS_TCSETS:
  574         case SUNOS_TCSETSW:
  575         case SUNOS_TCSETSF:
  576             {
  577                 struct termios bts;
  578                 struct sunos_termios sts;
  579 
  580                 if ((error = copyin (SCARG(uap, data), (caddr_t)&sts,
  581                     sizeof (sts))) != 0)
  582                         goto out;
  583                 stios2btios (&sts, &bts);
  584                 error = (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
  585                     (caddr_t)&bts, p);
  586                 goto out;
  587             }
  588 /*
  589  * Pseudo-tty ioctl translations.
  590  */
  591         case _IOW('t', 32, int): {      /* TIOCTCNTL */
  592                 int error, on;
  593 
  594                 error = copyin (SCARG(uap, data), (caddr_t)&on, sizeof (on));
  595                 if (error)
  596                         goto out;
  597                 error = (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
  598                 goto out;
  599         }
  600         case _IOW('t', 33, int): {      /* TIOCSIGNAL */
  601                 int error, sig;
  602 
  603                 error = copyin (SCARG(uap, data), (caddr_t)&sig, sizeof (sig));
  604                 if (error)
  605                         goto out;
  606                 error = (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
  607                 goto out;
  608         }
  609 
  610 /*
  611  * Socket ioctl translations.
  612  */
  613 #define IFREQ_IN(a) { \
  614         struct ifreq ifreq; \
  615         error = copyin (SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
  616         if (error) \
  617                 goto out; \
  618         error = (*ctl)(fp, a, (caddr_t)&ifreq, p); \
  619         goto out; \
  620 }
  621 #define IFREQ_INOUT(a) { \
  622         struct ifreq ifreq; \
  623         error = copyin (SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
  624         if (error) \
  625                 goto out; \
  626         if ((error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) != 0) \
  627                 goto out; \
  628         error = copyout ((caddr_t)&ifreq, SCARG(uap, data), sizeof (ifreq)); \
  629         goto out; \
  630 }
  631 
  632         case _IOW('i', 12, struct ifreq):
  633                 /* SIOCSIFADDR */
  634                 break;
  635 
  636         case _IOWR('i', 13, struct ifreq):
  637                 IFREQ_INOUT(OSIOCGIFADDR);
  638 
  639         case _IOW('i', 14, struct ifreq):
  640                 /* SIOCSIFDSTADDR */
  641                 break;
  642 
  643         case _IOWR('i', 15, struct ifreq):
  644                 IFREQ_INOUT(OSIOCGIFDSTADDR);
  645 
  646         case _IOW('i', 16, struct ifreq):
  647                 /* SIOCSIFFLAGS */
  648                 break;
  649 
  650         case _IOWR('i', 17, struct ifreq):
  651                 /* SIOCGIFFLAGS */
  652                 break;
  653 
  654         case _IOW('i', 21, struct ifreq):
  655                 IFREQ_IN(SIOCSIFMTU);
  656 
  657         case _IOWR('i', 22, struct ifreq):
  658                 IFREQ_INOUT(SIOCGIFMTU);
  659 
  660         case _IOWR('i', 23, struct ifreq):
  661                 IFREQ_INOUT(SIOCGIFBRDADDR);
  662 
  663         case _IOW('i', 24, struct ifreq):
  664                 IFREQ_IN(SIOCSIFBRDADDR);
  665 
  666         case _IOWR('i', 25, struct ifreq):
  667                 IFREQ_INOUT(OSIOCGIFNETMASK);
  668 
  669         case _IOW('i', 26, struct ifreq):
  670                 IFREQ_IN(SIOCSIFNETMASK);
  671 
  672         case _IOWR('i', 27, struct ifreq):
  673                 IFREQ_INOUT(SIOCGIFMETRIC);
  674 
  675         case _IOWR('i', 28, struct ifreq):
  676                 IFREQ_IN(SIOCSIFMETRIC);
  677 
  678         case _IOW('i', 30, struct arpreq):
  679                 /* SIOCSARP */
  680                 break;
  681 
  682         case _IOWR('i', 31, struct arpreq):
  683                 /* SIOCGARP */
  684                 break;
  685 
  686         case _IOW('i', 32, struct arpreq):
  687                 /* SIOCDARP */
  688                 break;
  689 
  690         case _IOW('i', 18, struct ifreq):       /* SIOCSIFMEM */
  691         case _IOWR('i', 19, struct ifreq):      /* SIOCGIFMEM */
  692         case _IOW('i', 40, struct ifreq):       /* SIOCUPPER */
  693         case _IOW('i', 41, struct ifreq):       /* SIOCLOWER */
  694         case _IOW('i', 44, struct ifreq):       /* SIOCSETSYNC */
  695         case _IOWR('i', 45, struct ifreq):      /* SIOCGETSYNC */
  696         case _IOWR('i', 46, struct ifreq):      /* SIOCSDSTATS */
  697         case _IOWR('i', 47, struct ifreq):      /* SIOCSESTATS */
  698         case _IOW('i', 48, int):                /* SIOCSPROMISC */
  699         case _IOW('i', 49, struct ifreq):       /* SIOCADDMULTI */
  700         case _IOW('i', 50, struct ifreq):       /* SIOCDELMULTI */
  701                 error = EOPNOTSUPP;
  702                 goto out;
  703 
  704         case _IOWR('i', 20, struct ifconf):     /* SIOCGIFCONF */
  705             {
  706                 struct ifconf ifconf;
  707 
  708                 /*
  709                  * XXX: two more problems
  710                  * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
  711                  * 2. this returns a name per protocol, ie. it returns two "lo0"'s
  712                  */
  713                 error = copyin (SCARG(uap, data), (caddr_t)&ifconf,
  714                     sizeof (ifconf));
  715                 if (error)
  716                         goto out;
  717                 error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p);
  718                 if (error)
  719                         goto out;
  720                 error = copyout ((caddr_t)&ifconf, SCARG(uap, data),
  721                     sizeof (ifconf));
  722                 goto out;
  723             }
  724 
  725 /*
  726  * Audio ioctl translations.
  727  */
  728         case _IOR('A', 1, struct sunos_audio_info):     /* AUDIO_GETINFO */
  729         sunos_au_getinfo:
  730             {
  731                 struct audio_info aui;
  732                 struct sunos_audio_info sunos_aui;
  733 
  734                 error = (*ctl)(fp, AUDIO_GETINFO, (caddr_t)&aui, p);
  735                 if (error)
  736                         goto out;
  737 
  738                 sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
  739                 sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
  740 
  741                 /* `avail_ports' is `seek' in BSD */
  742                 sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
  743                 sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
  744 
  745                 sunos_aui.play.waiting = 0;
  746                 sunos_aui.record.waiting = 0;
  747                 sunos_aui.play.eof = 0;
  748                 sunos_aui.record.eof = 0;
  749                 sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
  750                 /*XXXsunos_aui.output_muted = 0;*/
  751                 /*XXX*/sunos_aui.reserved[0] = 0;
  752                 /*XXX*/sunos_aui.reserved[1] = 0;
  753                 /*XXX*/sunos_aui.reserved[2] = 0;
  754                 /*XXX*/sunos_aui.reserved[3] = 0;
  755 
  756                 error = copyout ((caddr_t)&sunos_aui, SCARG(uap, data),
  757                                 sizeof (sunos_aui));
  758                 goto out;
  759             }
  760 
  761         case _IOWR('A', 2, struct sunos_audio_info):    /* AUDIO_SETINFO */
  762             {
  763                 struct audio_info aui;
  764                 struct sunos_audio_info sunos_aui;
  765 
  766                 error = copyin (SCARG(uap, data), (caddr_t)&sunos_aui,
  767                     sizeof (sunos_aui));
  768                 if (error)
  769                         goto out;
  770 
  771                 aui.play = *(struct audio_prinfo *)&sunos_aui.play;
  772                 aui.record = *(struct audio_prinfo *)&sunos_aui.record;
  773                 /* aui.__spare = sunos_aui.monitor_gain; */
  774                 aui.blocksize = ~0;
  775                 aui.hiwat = ~0;
  776                 aui.lowat = ~0;
  777                 /* XXX somebody check this please. - is: aui.backlog = ~0; */
  778                 aui.mode = ~0;
  779                 /*
  780                  * The bsd driver does not distinguish between paused and
  781                  * active. (In the sun driver, not active means samples are
  782                  * not output at all, but paused means the last streams buffer
  783                  * is drained and then output stops.)  If either are 0, then
  784                  * when stop output. Otherwise, if either are non-zero,
  785                  * we resume.
  786                  */
  787                 if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
  788                         aui.play.pause = 0;
  789                 else if (sunos_aui.play.pause != (u_char)~0 ||
  790                          sunos_aui.play.active != (u_char)~0)
  791                         aui.play.pause = 1;
  792                 if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
  793                         aui.record.pause = 0;
  794                 else if (sunos_aui.record.pause != (u_char)~0 ||
  795                          sunos_aui.record.active != (u_char)~0)
  796                         aui.record.pause = 1;
  797 
  798                 error = (*ctl)(fp, AUDIO_SETINFO, (caddr_t)&aui, p);
  799                 if (error)
  800                         goto out;
  801                 /* Return new state */
  802                 goto sunos_au_getinfo;
  803             }
  804         case _IO('A', 3):       /* AUDIO_DRAIN */
  805                 error = (*ctl)(fp, AUDIO_DRAIN, (void *)0, p);
  806                 goto out;
  807         case _IOR('A', 4, int): /* AUDIO_GETDEV */
  808             {
  809                 int devtype = SUNOS_AUDIO_DEV_AMD;
  810                 error = copyout ((caddr_t)&devtype, SCARG(uap, data),
  811                                 sizeof (devtype));
  812                 goto out;
  813             }
  814 
  815 /*
  816  * Selected streams ioctls.
  817  */
  818 #define SUNOS_S_FLUSHR          1
  819 #define SUNOS_S_FLUSHW          2
  820 #define SUNOS_S_FLUSHRW         3
  821 
  822 #define SUNOS_S_INPUT           1
  823 #define SUNOS_S_HIPRI           2
  824 #define SUNOS_S_OUTPUT          4
  825 #define SUNOS_S_MSG             8
  826 
  827         case _IO('S', 5):       /* I_FLUSH */
  828             {
  829                 int tmp = 0;
  830                 switch ((int)SCARG(uap, data)) {
  831                 case SUNOS_S_FLUSHR:
  832                         tmp = FREAD;
  833                         break;
  834                 case SUNOS_S_FLUSHW:
  835                         tmp = FWRITE;
  836                         break;
  837                 case SUNOS_S_FLUSHRW:
  838                         tmp = FREAD|FWRITE;
  839                         break;
  840                 }
  841                 error = (*ctl)(fp, TIOCFLUSH, (caddr_t)&tmp, p);
  842                 goto out;
  843             }
  844         case _IO('S', 9):       /* I_SETSIG */
  845             {
  846                 int on = 1;
  847 
  848                 if (((int)SCARG(uap, data) & (SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
  849                     SUNOS_S_HIPRI) {
  850                         error = EOPNOTSUPP;
  851                         goto out;
  852                 }
  853                 error = (*ctl)(fp, FIOASYNC, (caddr_t)&on, p);
  854                 goto out;
  855             }
  856         }
  857         error = (sys_ioctl(p, uap, retval));
  858 out:
  859         FRELE(fp);
  860         return (error);
  861 }
  862 
  863 /* SunOS fcntl(2) cmds not implemented */
  864 #define SUN_F_RGETLK    10
  865 #define SUN_F_RSETLK    11
  866 #define SUN_F_CNVT      12
  867 #define SUN_F_RSETLKW   13
  868 
  869 /* SunOS flock translation */
  870 struct sunos_flock {
  871         short   l_type;
  872         short   l_whence;
  873         long    l_start;
  874         long    l_len;
  875         short   l_pid;
  876         short   l_xxx;
  877 };
  878 
  879 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
  880 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
  881 
  882 #define SUNOS_F_RDLCK   1
  883 #define SUNOS_F_WRLCK   2
  884 #define SUNOS_F_UNLCK   3
  885 
  886 static void
  887 bsd_to_sunos_flock(iflp, oflp)
  888         struct flock            *iflp;
  889         struct sunos_flock      *oflp;
  890 {
  891         switch (iflp->l_type) {
  892         case F_RDLCK:
  893                 oflp->l_type = SUNOS_F_RDLCK;
  894                 break;
  895         case F_WRLCK:
  896                 oflp->l_type = SUNOS_F_WRLCK;
  897                 break;
  898         case F_UNLCK:
  899                 oflp->l_type = SUNOS_F_UNLCK;
  900                 break;
  901         default:
  902                 oflp->l_type = -1;
  903                 break;
  904         }
  905 
  906         oflp->l_whence = (short) iflp->l_whence;
  907         oflp->l_start = (long) iflp->l_start;
  908         oflp->l_len = (long) iflp->l_len;
  909         oflp->l_pid = (short) iflp->l_pid;
  910         oflp->l_xxx = 0;
  911 }
  912 
  913 
  914 static void
  915 sunos_to_bsd_flock(iflp, oflp)
  916         struct sunos_flock      *iflp;
  917         struct flock            *oflp;
  918 {
  919         switch (iflp->l_type) {
  920         case SUNOS_F_RDLCK:
  921                 oflp->l_type = F_RDLCK;
  922                 break;
  923         case SUNOS_F_WRLCK:
  924                 oflp->l_type = F_WRLCK;
  925                 break;
  926         case SUNOS_F_UNLCK:
  927                 oflp->l_type = F_UNLCK;
  928                 break;
  929         default:
  930                 oflp->l_type = -1;
  931                 break;
  932         }
  933 
  934         oflp->l_whence = iflp->l_whence;
  935         oflp->l_start = (off_t) iflp->l_start;
  936         oflp->l_len = (off_t) iflp->l_len;
  937         oflp->l_pid = (pid_t) iflp->l_pid;
  938 
  939 }
  940 static struct {
  941         long    sun_flg;
  942         long    bsd_flg;
  943 } sunfcntl_flgtab[] = {
  944         /* F_[GS]ETFLags that differ: */
  945 #define SUN_FSETBLK     0x0010
  946 #define SUN_SHLOCK      0x0080
  947 #define SUN_EXLOCK      0x0100
  948 #define SUN_FNBIO       0x1000
  949 #define SUN_FSYNC       0x2000
  950 #define SUN_NONBLOCK    0x4000
  951 #define SUN_FNOCTTY     0x8000
  952         { SUN_NONBLOCK, O_NONBLOCK },
  953         { SUN_FNBIO, O_NONBLOCK },
  954         { SUN_SHLOCK, O_SHLOCK },
  955         { SUN_EXLOCK, O_EXLOCK },
  956         { SUN_FSYNC, O_SYNC },
  957         { SUN_FSETBLK, 0 },
  958         { SUN_FNOCTTY, 0 }
  959 };
  960 
  961 int
  962 sunos_sys_fcntl(p, v, retval)
  963         register struct proc *p;
  964         void *v;
  965         register_t *retval;
  966 {
  967         struct sunos_sys_fcntl_args *uap = v;
  968         long flg;
  969         int n, ret;
  970 
  971 
  972         switch (SCARG(uap, cmd)) {
  973         case F_SETFL:
  974                 flg = (long)SCARG(uap, arg);
  975                 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
  976                 while (--n >= 0) {
  977                         if (flg & sunfcntl_flgtab[n].sun_flg) {
  978                                 flg &= ~sunfcntl_flgtab[n].sun_flg;
  979                                 flg |= sunfcntl_flgtab[n].bsd_flg;
  980                         }
  981                 }
  982                 SCARG(uap, arg) = (void *)flg;
  983                 break;
  984 
  985         case F_GETLK:
  986         case F_SETLK:
  987         case F_SETLKW:
  988                 {
  989                         int error;
  990                         struct sunos_flock       ifl;
  991                         struct flock            *flp, fl;
  992                         caddr_t sg = stackgap_init(p->p_emul);
  993                         struct sys_fcntl_args           fa;
  994 
  995                         SCARG(&fa, fd) = SCARG(uap, fd);
  996                         SCARG(&fa, cmd) = SCARG(uap, cmd);
  997 
  998                         flp = stackgap_alloc(&sg, sizeof(struct flock));
  999                         SCARG(&fa, arg) = (void *) flp;
 1000 
 1001                         error = copyin(SCARG(uap, arg), &ifl, sizeof ifl);
 1002                         if (error)
 1003                                 return error;
 1004 
 1005                         sunos_to_bsd_flock(&ifl, &fl);
 1006 
 1007                         error = copyout(&fl, flp, sizeof fl);
 1008                         if (error)
 1009                                 return error;
 1010 
 1011                         error = sys_fcntl(p, &fa, retval);
 1012                         if (error || SCARG(&fa, cmd) != F_GETLK)
 1013                                 return error;
 1014 
 1015                         error = copyin(flp, &fl, sizeof fl);
 1016                         if (error)
 1017                                 return error;
 1018 
 1019                         bsd_to_sunos_flock(&fl, &ifl);
 1020 
 1021                         return copyout(&ifl, SCARG(uap, arg), sizeof ifl);
 1022                 }
 1023                 break;
 1024         case SUN_F_RGETLK:
 1025         case SUN_F_RSETLK:
 1026         case SUN_F_CNVT:
 1027         case SUN_F_RSETLKW:
 1028                 return (EOPNOTSUPP);
 1029 
 1030         default:
 1031                 break;
 1032         }
 1033 
 1034         ret = sys_fcntl(p, uap, retval);
 1035 
 1036         switch (SCARG(uap, cmd)) {
 1037         case F_GETFL:
 1038                 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
 1039                 while (--n >= 0) {
 1040                         if (ret & sunfcntl_flgtab[n].bsd_flg) {
 1041                                 ret &= ~sunfcntl_flgtab[n].bsd_flg;
 1042                                 ret |= sunfcntl_flgtab[n].sun_flg;
 1043                         }
 1044                 }
 1045                 break;
 1046         default:
 1047                 break;
 1048         }
 1049 
 1050         return (ret);
 1051 }

/* [<][>][^][v][top][bottom][index][help] */