home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / LIB / unix.zoo / ioctl.c < prev    next >
Text File  |  2009-11-06  |  18KB  |  508 lines

  1.  
  2. /***************************************************************************/
  3. /*                                                                         */
  4. /* ioctl() : Unix library (OS9/68000)                                      */
  5. /* =======                                                                 */
  6. /*                                                                         */
  7. /* Author:     K. Schmitt                                                  */
  8. /* Compiler:   Microware C Vers. 3.0                                       */
  9. /* OS:         OS9/68000 Vers. 2.2                                         */
  10. /*                                                                         */
  11. /* Edition History                                                         */
  12. /* ===============                                                         */
  13. /*                                                                         */
  14. /* Ed. 0.00  Date 11/11/88                                                 */
  15. /*           First version                                                 */
  16. /*                                                                         */
  17. /***************************************************************************/
  18. /*                                                                         */
  19. /* Description                                                             */
  20. /*
  21.  
  22.      NAME
  23.           ioctl - control device
  24.  
  25.      SYNOPSIS
  26.           #include <UNIX/ioctl.h>
  27.  
  28.           ioctl (fildes, request, arg)
  29.           int fildes, request;
  30.  
  31.      DESCRIPTION
  32.           Ioctl performs a variety of functions on character special
  33.           files (devices).
  34.  
  35.           Ioctl will fail if one or more of the following are true:
  36.  
  37.           [EBADF]        Fildes is not a valid open file descriptor.
  38.  
  39.           [ENOTTY]       Fildes is not associated with a character
  40.                          special device.
  41.  
  42.           [EINVAL]       Request or arg is not valid.
  43.  
  44.           [EINTR]        A signal was caught during the ioctl system
  45.                          call.
  46.  
  47.      RETURN VALUE
  48.           If an error has occurred, a value of -1 is returned and
  49.           errno is set to indicate the error.
  50.  
  51. */
  52.  
  53. #include <stdio.h>
  54. #include <UNIX/errno.h>
  55. #include <UNIX/ioctl.h>
  56. #include <UNIX/termio.h>
  57. #include <sgstat.h>
  58.  
  59. # ifndef TRUE
  60. #define TRUE   1
  61. #define FALSE  0
  62. #define ERROR -1
  63. # endif
  64.  
  65. typedef unsigned char FLAG;
  66.  
  67. extern int errno;
  68. extern struct sgbuf _tty_opt_; /* defined in 'isatty()' */
  69.  
  70. /* external functions */
  71. extern int fclose(), close(), open(), munlink(), tsleep(), _gs_opt(), _ss_opt();
  72. extern int fflush(), _gs_devn(), _gs_rdy(), isatty();
  73. extern FILE *fopen();
  74. extern char *modlink();
  75.  
  76.  
  77. int ioctl (fildes, request, arg)
  78.           register int fildes;
  79.           int request;
  80.           struct termio *arg; /* CAUTION: in some calls 'arg' is of type int */
  81.           {
  82.           register struct sgbuf *tty_options;
  83.           register int i;
  84.           register long *l;
  85.  
  86.  
  87.           if (i=isatty(fildes))                /* is 'fildes' a tty path ? */
  88.                {
  89.                if (i == ERROR) return (EBADF); /* bad fildes    */
  90.                }
  91.           else
  92.                {
  93.                return (ENOTTY);                /* no tty fildes */
  94.                }
  95.  
  96.           tty_options = &_tty_opt_;
  97.           switch (request)
  98.                {
  99.                /****************************/
  100.                /* 'arg' is of type 'int'   */
  101.                /****************************/
  102.  
  103.                case TIOCFLUSH:
  104.                case TCFLSH:   /* if arg is 0, flush the input queue, if 1, */
  105.                               /* flush the output queue, if 2, flush both  */
  106.                               i = (int) arg;
  107.                               if ((i < 0) || (i > 2)) return (EINVAL);
  108.                               /* buffered file ? If not => return */
  109.                               if ((_iob[fildes]._flag & _INIT) &&
  110.                                   (_iob[fildes]._fd == fildes))
  111.                                    {
  112.                                    fflush((FILE *) &_iob[fildes]);
  113.                                    }
  114.                               break;
  115.  
  116.                case TCSBRK:   /* wait for the output to drain. If arg is 0,*/
  117.                               /* then send a break (zero bits for 0.25 sec */
  118.                               tsleep(10); /* nothing to do (no I$ call)    */
  119.                               break;
  120.  
  121.                case TCXONC:   /* start/stop control. If arg is 0, suspend  */
  122.                               /* output; if arg is 1, restart suspended    */
  123.                               /* output                                    */
  124.                               break; /* nothing to do */
  125.  
  126.                /************************************/
  127.                /* 'arg' is of type 'struct termio' */
  128.                /************************************/
  129.  
  130.                case TCGETA:   /* get the parameters associated with the    */
  131.                               /* terminal and store in the termio structure*/
  132.                               /* referenced by arg                         */
  133.                               arg->c_iflag = 0;
  134.                               arg->c_oflag = (tty_options->sg_case ?
  135.                                                   OLCUC : 0) |
  136.                                              (tty_options->sg_alf  ?
  137.                                                   ONLCR : 0);
  138.                               arg->c_cflag = get_baud(tty_options->sg_baud) |
  139.                                              get_csize(tty_options->sg_parity) |
  140.                                              get_stopb(tty_options->sg_parity) |
  141.                                              get_parity(tty_options->sg_parity);
  142.                               arg->c_lflag = get_echo(tty_options);
  143.                               arg->c_cc[VINTR]  = tty_options->sg_kbich;
  144.                               arg->c_cc[VQUIT]  = tty_options->sg_kbach;
  145.                               arg->c_cc[VERASE] = tty_options->sg_bspch;
  146.                               arg->c_cc[VKILL]  = tty_options->sg_dlnch;
  147.                               arg->c_cc[VEOF]   = tty_options->sg_eofch;
  148.                               arg->c_cc[VEOL]   = tty_options->sg_eorch;
  149.                               arg->c_cc[VSUSP]  = tty_options->sg_pause;
  150.                               break;
  151.  
  152.                case TCSETA:   /* Set the parameters associated with the    */
  153.                               /* terminal from the structure arg           */
  154.                               tty_options->sg_echo = (arg->c_lflag & ECHO)
  155.                                                      ? TRUE : FALSE;
  156.                               tty_options->sg_backsp = (arg->c_lflag & ECHOE)
  157.                                                      ? TRUE : FALSE;
  158.                               tty_options->sg_case = (arg->c_iflag & IUCLC)
  159.                                                      ? 1 : 0;
  160.                               tty_options->sg_kbich = arg->c_cc[VINTR];
  161.                               tty_options->sg_kbach = arg->c_cc[VQUIT];
  162.                               tty_options->sg_bspch = arg->c_cc[VERASE];
  163.                               tty_options->sg_dlnch = arg->c_cc[VKILL];
  164.                               tty_options->sg_eofch = arg->c_cc[VEOF];
  165.                               tty_options->sg_eorch = arg->c_cc[VEOL];
  166.                               tty_options->sg_pause = arg->c_cc[VSUSP];
  167.                               if (set_mode_bits(arg->c_cflag))
  168.                                    {
  169.                                    /* baud rate, character size, parity...
  170.                                     * have changed!! We have NO function
  171.                                     * calls to change one of the above
  172.                                     * on an open path under OS9.
  173.                                     * So we must
  174.                                     *  a) close the path
  175.                                     *  b) modify the device descriptor
  176.                                     *  c) re-open the device
  177.                                     */
  178.                                    if (change_device_mode(fildes))
  179.                                         {
  180.                                         /* something failed!!! */
  181.                                         return (ERROR);
  182.                                         }
  183.                                    }
  184.  
  185.                              /* set the new terminal mode */
  186.  
  187.                              if (_ss_opt(fildes,tty_options) == ERROR)
  188.                                   {
  189.                                   return (ERROR);
  190.                                   }
  191.                              break;
  192.  
  193.                /****************************/
  194.                /* 'arg' is of type 'long'  */
  195.                /****************************/
  196.  
  197.                case FIONREAD:/* get # of bytes in the read buffer */
  198.                              l = (long *) arg;
  199.                              if ((i=_gs_rdy(fildes)) == ERROR)
  200.                                   {
  201.                                   errno = 0;
  202.                                   *l = 0L;
  203.                                   }
  204.                              else
  205.                                   {
  206.                                   *l = (long) i;
  207.                                   }
  208.                              break;
  209.  
  210.                default:      /* invalid request */
  211. #ifdef DEBUG
  212.                              fprintf(stderr,
  213.                                   "\nioctl: invalid request (%d)\n",
  214.                                   request);
  215. #endif
  216.                              return (EINVAL);
  217.  
  218.                } /* end switch (request) */
  219.  
  220.           return (0);
  221.  
  222.           } /* end of ioctl */
  223.  
  224.  
  225. #ifdef STATIC
  226. static
  227. #endif
  228. int get_baud(rate)
  229.           int rate;
  230.           {
  231.           register int baudrate;
  232.  
  233.           switch (rate & 0xFF)
  234.                {
  235.                case 0:   baudrate = B50;
  236.                          break;
  237.                case 1:   baudrate = B75;
  238.                          break;
  239.                case 2:   baudrate = B110;
  240.                          break;
  241.                case 3:   baudrate = B134;
  242.                          break;
  243.                case 4:   baudrate = B150;
  244.                          break;
  245.                case 5:   baudrate = B300;
  246.                          break;
  247.                case 6:   baudrate = B600;
  248.                          break;
  249.                case 7:   baudrate = B1200;
  250.                          break;
  251.                case 8:   baudrate = B1800;
  252.                          break;
  253.                case 10:  baudrate = B2400;
  254.                          break;
  255.                case 12:  baudrate = B4800;
  256.                          break;
  257.                case 14:  baudrate = B9600;
  258.                          break;
  259.                case 15:  baudrate = B19200;
  260.                          break;
  261.                case 256: baudrate = EXTB;
  262.                          break;
  263.                default:  baudrate = B0;
  264.                }
  265.  
  266.           return (baudrate);
  267.  
  268.           } /* end of get_baud */
  269.  
  270. #ifdef STATIC
  271. static
  272. #endif
  273. int get_csize(size)
  274.           int size;
  275.           {
  276.           register int csize;
  277.           
  278.           switch ((size >> 2) & 0x03)
  279.                {
  280.                case 0:   csize = CS8;
  281.                          break;
  282.                case 1:   csize = CS7;
  283.                          break;
  284.                case 2:   csize = CS6;
  285.                          break;
  286.                case 3:   csize = CS5;
  287.                }
  288.  
  289.           return (csize);
  290.  
  291.           } /* end of get_csize */
  292.  
  293. #ifdef STATIC
  294. static
  295. #endif
  296. int get_stopb(stopbits)
  297.           register int stopbits;
  298.           {
  299.  
  300.           if (((stopbits >> 4) & 0x03) == 2) stopbits = CSTOPB;
  301.           else                               stopbits = 0;
  302.  
  303.           return (stopbits);
  304.  
  305.           } /* end of get_stopb */
  306.  
  307. #ifdef STATIC
  308. static
  309. #endif
  310. int get_parity(parity)
  311.           register int parity;
  312.           {
  313.  
  314.           switch (parity & 3)
  315.                {
  316.                case 2:
  317.                case 0:   parity = 0; /* no parity */
  318.                          break;
  319.                case 1:   parity = PARENB | PARODD;
  320.                          break;
  321.                case 3:   parity = PARENB;
  322.                }
  323.  
  324.           return (parity);
  325.  
  326.           } /* end of get_parity */
  327.  
  328.  
  329. #ifdef STATIC
  330. static
  331. #endif
  332. int get_echo(options)
  333.           register struct sgbuf *options;
  334.           {
  335.           register int echo = 0;
  336.  
  337.           if (options->sg_echo) echo = ECHO; /* echo input */
  338.           if (options->sg_backsp) echo |= ECHOE; /* echo BS-SP-BS */
  339.  
  340.           return (echo);
  341.  
  342.           } /* end of get_echo */
  343.  
  344. #ifdef STATIC
  345. static
  346. #endif
  347. int set_mode_bits(mode)
  348.           unsigned short mode;
  349.           {
  350.           register FLAG modified = FALSE;
  351.           register int  old_value, i;
  352.           register struct sgbuf *tty_options;
  353.  
  354.           tty_options = &_tty_opt_;
  355.           old_value = (int) tty_options->sg_baud;
  356.           tty_options->sg_baud = 0;
  357.  
  358.           switch ((int) (mode & CBAUD))
  359.                {
  360.                case B50:      i = 0;
  361.                               break;
  362.                case B75:      i = 1;
  363.                               break;
  364.                case B110:     i = 2;
  365.                               break;
  366.                case B134:     i = 3;
  367.                               break;
  368.                case B150:     i = 4;
  369.                               break;
  370.                case B300:     i = 5;
  371.                               break;
  372.                case B600:     i = 6;
  373.                               break;
  374.                case B1200:    i = 7;
  375.                               break;
  376.                case B1800:    i = 8;
  377.                               break;
  378.                case B2400:    i = 10;
  379.                               break;
  380.                case B4800:    i = 12;
  381.                               break;
  382.                default:
  383.                case B9600:    i = 14;
  384.                               break;
  385.                case B19200:   i = 15;
  386.                               break;
  387.                case EXTB:     i = 0xFF;
  388.                }
  389.  
  390.           tty_options->sg_baud = i;
  391.           if (i != old_value) modified = TRUE;
  392.  
  393.           /* get character size */
  394.  
  395.           old_value = (int) (tty_options->sg_parity & 0x3F);
  396.  
  397.           i = (int) (mode & (CS8|CS7|CS6));
  398.           if      (i == CS8) i = 0x00;
  399.           else if (i == CS7) i = 0x04;
  400.           else if (i == CS6) i = 0x08;
  401.           else if (i == CS5) i = 0x0C;
  402.           else               i = 0x00;
  403.  
  404.           tty_options->sg_parity = i;
  405.  
  406.           /* get stop bits */
  407.  
  408.           if (mode & CSTOPB) tty_options->sg_parity |= 0x20;
  409.  
  410.           /* get parity */
  411.  
  412.           i = (int) (mode & (PARENB|PARODD));
  413.           if      (i == (PARENB|PARODD)) i = 0x01; /* odd parity  */
  414.           else if (i == PARENB)          i = 0x03; /* even parity */
  415.           else                           i = 0x00; /* no parity   */
  416.           tty_options->sg_parity |= i;
  417.  
  418.           if ((int) tty_options->sg_parity != old_value) modified = TRUE;
  419.           
  420.           return (modified);
  421.  
  422.           } /* end of set_mode_bits */
  423.  
  424.  
  425. #ifdef STATIC
  426. static
  427. #endif
  428. int change_device_mode(fildes)
  429.           int fildes;
  430.           {
  431.           char device_name[34];
  432.           register int i;
  433.           register FLAG buffered = FALSE;
  434.           register struct sgbuf *tty_options;
  435.           register char *module;
  436.  
  437.           if (_gs_devn(fildes,&device_name[1]) == ERROR) return (ERROR);
  438.  
  439.           if (_iob[fildes]._flag & _INIT)
  440.                {
  441.                buffered = TRUE;
  442.                if (fclose((FILE *) &_iob[fildes]) == ERROR) return (ERROR);
  443.                }
  444.           else
  445.                {
  446.                if (close(fildes) == ERROR) return (ERROR);
  447.                }
  448.  
  449.           /* link the device descriptor */
  450.           
  451.           if ((module=modlink(&device_name[1],0)) == (char *) ERROR)
  452.                return (ERROR);
  453.  
  454.           tty_options = &_tty_opt_;
  455.           *(module+0x5C) = tty_options->sg_parity;
  456.           *(module+0x5D) = tty_options->sg_baud;
  457.           munlink(module);
  458.           device_name[0] = '/';
  459.           if (buffered)
  460.                {
  461.                FILE *files[_NFILE];
  462.                FILE *f;
  463.                for (i=0 ; i < _NFILE ; i++) files[i] = (FILE *) 0;
  464.                i = 0;
  465.                do
  466.                     {
  467.                     if ((f = fopen(device_name,"w+")) == (FILE *) 0)
  468.                          return (ERROR);
  469.                     if (fileno(f) == fildes) break;
  470.                     files[fileno(f)] = f;
  471.                     i++;
  472.                     } while (i < _NFILE) ;
  473.                for (i=0 ; i < _NFILE ; i++)
  474.                     {
  475.                     if (files[i])
  476.                          {
  477.                          if (fclose(files[i]) == ERROR) return (ERROR);
  478.                          }
  479.                     }
  480.                }
  481.           else
  482.                { /* unbuffered */
  483.                int files[_NFILE];
  484.                int f;
  485.                for (i=0 ; i < _NFILE ; i++) files[i] = -1;
  486.                i = 0;
  487.                do
  488.                     {
  489.                     if ((f = open(device_name,_READ|_WRITE)) == ERROR)
  490.                          return (ERROR);
  491.                     if (f == fildes) break;
  492.                     files[f] = f;
  493.                     i++;
  494.                     } while (i < _NFILE) ;
  495.                for (i=0 ; i < _NFILE ; i++)
  496.                     {
  497.                     if (files[i] != -1)
  498.                          {
  499.                          if (close(files[i]) == ERROR) return (ERROR);
  500.                          }
  501.                     }
  502.                }
  503.  
  504.           return (0);
  505.  
  506.           } /* end of change_device_mode */
  507.  
  508.