xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

sigio.c (8811B)


      1 /* sigio.c -- Support for SIGIO handler installation and removal
      2  * Created: Thu Jun  3 15:39:18 1999 by faith@precisioninsight.com
      3  *
      4  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the next
     15  * paragraph) shall be included in all copies or substantial portions of the
     16  * Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     24  * DEALINGS IN THE SOFTWARE.
     25  *
     26  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
     27  */
     28 /*
     29  * Copyright (c) 2002 by The XFree86 Project, Inc.
     30  *
     31  * Permission is hereby granted, free of charge, to any person obtaining a
     32  * copy of this software and associated documentation files (the "Software"),
     33  * to deal in the Software without restriction, including without limitation
     34  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     35  * and/or sell copies of the Software, and to permit persons to whom the
     36  * Software is furnished to do so, subject to the following conditions:
     37  *
     38  * The above copyright notice and this permission notice shall be included in
     39  * all copies or substantial portions of the Software.
     40  *
     41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     42  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     43  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     44  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     45  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     46  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     47  * OTHER DEALINGS IN THE SOFTWARE.
     48  *
     49  * Except as contained in this notice, the name of the copyright holder(s)
     50  * and author(s) shall not be used in advertising or otherwise to promote
     51  * the sale, use or other dealings in this Software without prior written
     52  * authorization from the copyright holder(s) and author(s).
     53  */
     54 
     55 #ifdef HAVE_XORG_CONFIG_H
     56 #include <xorg-config.h>
     57 #endif
     58 
     59 #include <X11/X.h>
     60 #include <xserver_poll.h>
     61 #include "xf86.h"
     62 #include "xf86Priv.h"
     63 #include "xf86_OSlib.h"
     64 #include "inputstr.h"
     65 
     66 #ifdef HAVE_STROPTS_H
     67 #include <stropts.h>
     68 #endif
     69 
     70 #ifdef MAXDEVICES
     71 /* MAXDEVICES represents the maximum number of input devices usable
     72  * at the same time plus one entry for DRM support.
     73  */
     74 #define MAX_FUNCS   (MAXDEVICES + 1)
     75 #else
     76 #define MAX_FUNCS 16
     77 #endif
     78 
     79 typedef struct _xf86SigIOFunc {
     80     void (*f) (int, void *);
     81     int fd;
     82     void *closure;
     83 } Xf86SigIOFunc;
     84 
     85 static Xf86SigIOFunc xf86SigIOFuncs[MAX_FUNCS];
     86 static int xf86SigIOMax;
     87 static struct pollfd *xf86SigIOFds;
     88 static int xf86SigIONum;
     89 
     90 static Bool
     91 xf86SigIOAdd(int fd)
     92 {
     93     struct pollfd *n;
     94 
     95     n = realloc(xf86SigIOFds, (xf86SigIONum + 1) * sizeof (struct pollfd));
     96     if (!n)
     97         return FALSE;
     98 
     99     n[xf86SigIONum].fd = fd;
    100     n[xf86SigIONum].events = POLLIN;
    101     xf86SigIONum++;
    102     xf86SigIOFds = n;
    103     return TRUE;
    104 }
    105 
    106 static void
    107 xf86SigIORemove(int fd)
    108 {
    109     int i;
    110     for (i = 0; i < xf86SigIONum; i++)
    111         if (xf86SigIOFds[i].fd == fd) {
    112             memmove(&xf86SigIOFds[i], &xf86SigIOFds[i+1], (xf86SigIONum - i - 1) * sizeof (struct pollfd));
    113             xf86SigIONum--;
    114             break;
    115         }
    116 }
    117 
    118 /*
    119  * SIGIO gives no way of discovering which fd signalled, select
    120  * to discover
    121  */
    122 static void
    123 xf86SIGIO(int sig)
    124 {
    125     int i, f;
    126     int save_errno = errno;     /* do not clobber the global errno */
    127     int r;
    128 
    129     inSignalContext = TRUE;
    130 
    131     SYSCALL(r = xserver_poll(xf86SigIOFds, xf86SigIONum, 0));
    132     for (f = 0; r > 0 && f < xf86SigIONum; f++) {
    133         if (xf86SigIOFds[f].revents & POLLIN) {
    134             for (i = 0; i < xf86SigIOMax; i++)
    135                 if (xf86SigIOFuncs[i].f && xf86SigIOFuncs[i].fd == xf86SigIOFds[f].fd)
    136                     (*xf86SigIOFuncs[i].f) (xf86SigIOFuncs[i].fd,
    137                                             xf86SigIOFuncs[i].closure);
    138             r--;
    139         }
    140     }
    141     if (r > 0) {
    142         xf86Msg(X_ERROR, "SIGIO %d descriptors not handled\n", r);
    143     }
    144     /* restore global errno */
    145     errno = save_errno;
    146 
    147     inSignalContext = FALSE;
    148 }
    149 
    150 static int
    151 xf86IsPipe(int fd)
    152 {
    153     struct stat buf;
    154 
    155     if (fstat(fd, &buf) < 0)
    156         return 0;
    157     return S_ISFIFO(buf.st_mode);
    158 }
    159 
    160 static void
    161 block_sigio(void)
    162 {
    163     sigset_t set;
    164 
    165     sigemptyset(&set);
    166     sigaddset(&set, SIGIO);
    167     xthread_sigmask(SIG_BLOCK, &set, NULL);
    168 }
    169 
    170 static void
    171 release_sigio(void)
    172 {
    173     sigset_t set;
    174 
    175     sigemptyset(&set);
    176     sigaddset(&set, SIGIO);
    177     xthread_sigmask(SIG_UNBLOCK, &set, NULL);
    178 }
    179 
    180 int
    181 xf86InstallSIGIOHandler(int fd, void (*f) (int, void *), void *closure)
    182 {
    183     struct sigaction sa;
    184     struct sigaction osa;
    185     int i;
    186     int installed = FALSE;
    187 
    188     for (i = 0; i < MAX_FUNCS; i++) {
    189         if (!xf86SigIOFuncs[i].f) {
    190             if (xf86IsPipe(fd))
    191                 return 0;
    192             block_sigio();
    193 #ifdef O_ASYNC
    194             if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC) == -1) {
    195                 xf86Msg(X_WARNING, "fcntl(%d, O_ASYNC): %s\n",
    196                         fd, strerror(errno));
    197             }
    198             else {
    199                 if (fcntl(fd, F_SETOWN, getpid()) == -1) {
    200                     xf86Msg(X_WARNING, "fcntl(%d, F_SETOWN): %s\n",
    201                             fd, strerror(errno));
    202                 }
    203                 else {
    204                     installed = TRUE;
    205                 }
    206             }
    207 #endif
    208 #if defined(I_SETSIG) && defined(HAVE_ISASTREAM)
    209             /* System V Streams - used on Solaris for input devices */
    210             if (!installed && isastream(fd)) {
    211                 if (ioctl(fd, I_SETSIG, S_INPUT | S_ERROR | S_HANGUP) == -1) {
    212                     xf86Msg(X_WARNING, "fcntl(%d, I_SETSIG): %s\n",
    213                             fd, strerror(errno));
    214                 }
    215                 else {
    216                     installed = TRUE;
    217                 }
    218             }
    219 #endif
    220             if (!installed) {
    221                 release_sigio();
    222                 return 0;
    223             }
    224             sigemptyset(&sa.sa_mask);
    225             sigaddset(&sa.sa_mask, SIGIO);
    226             sa.sa_flags = SA_RESTART;
    227             sa.sa_handler = xf86SIGIO;
    228             sigaction(SIGIO, &sa, &osa);
    229             xf86SigIOFuncs[i].fd = fd;
    230             xf86SigIOFuncs[i].closure = closure;
    231             xf86SigIOFuncs[i].f = f;
    232             if (i >= xf86SigIOMax)
    233                 xf86SigIOMax = i + 1;
    234             xf86SigIOAdd(fd);
    235             release_sigio();
    236             return 1;
    237         }
    238         /* Allow overwriting of the closure and callback */
    239         else if (xf86SigIOFuncs[i].fd == fd) {
    240             xf86SigIOFuncs[i].closure = closure;
    241             xf86SigIOFuncs[i].f = f;
    242             return 1;
    243         }
    244     }
    245     return 0;
    246 }
    247 
    248 int
    249 xf86RemoveSIGIOHandler(int fd)
    250 {
    251     struct sigaction sa;
    252     struct sigaction osa;
    253     int i;
    254     int max;
    255     int ret;
    256 
    257     max = 0;
    258     ret = 0;
    259     for (i = 0; i < MAX_FUNCS; i++) {
    260         if (xf86SigIOFuncs[i].f) {
    261             if (xf86SigIOFuncs[i].fd == fd) {
    262                 xf86SigIOFuncs[i].f = 0;
    263                 xf86SigIOFuncs[i].fd = 0;
    264                 xf86SigIOFuncs[i].closure = 0;
    265                 xf86SigIORemove(fd);
    266                 ret = 1;
    267             }
    268             else {
    269                 max = i + 1;
    270             }
    271         }
    272     }
    273     if (ret) {
    274 #ifdef O_ASYNC
    275         fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_ASYNC);
    276 #endif
    277 #if defined(I_SETSIG) && defined(HAVE_ISASTREAM)
    278         if (isastream(fd)) {
    279             if (ioctl(fd, I_SETSIG, 0) == -1) {
    280                 xf86Msg(X_WARNING, "fcntl(%d, I_SETSIG, 0): %s\n",
    281                         fd, strerror(errno));
    282             }
    283         }
    284 #endif
    285         xf86SigIOMax = max;
    286         if (!max) {
    287             sigemptyset(&sa.sa_mask);
    288             sigaddset(&sa.sa_mask, SIGIO);
    289             sa.sa_flags = 0;
    290             sa.sa_handler = SIG_IGN;
    291             sigaction(SIGIO, &sa, &osa);
    292         }
    293     }
    294     return ret;
    295 }