Annotation of embedaddon/ntp/libntp/iosignal.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * iosignal.c - input/output routines for ntpd.        The socket-opening code
                      3:  *                was shamelessly stolen from ntpd.
                      4:  */
                      5: 
                      6: /*
                      7:  * [Bug 158]
                      8:  * Do the #includes differently, as under some versions of Linux
                      9:  * sys/param.h has a #undef CONFIG_PHONE line in it.
                     10:  *
                     11:  * As we have ~40 CONFIG_ variables, I don't feel like renaming them
                     12:  * every time somebody adds a new macro to some system header.
                     13:  */
                     14: 
                     15: #ifdef HAVE_CONFIG_H
                     16: # include <config.h>
                     17: #endif
                     18: 
                     19: #include <stdio.h>
                     20: #include <signal.h>
                     21: #ifdef HAVE_SYS_PARAM_H
                     22: # include <sys/param.h>
                     23: #endif /* HAVE_SYS_PARAM_H */
                     24: #ifdef HAVE_SYS_IOCTL_H
                     25: # include <sys/ioctl.h>
                     26: #endif
                     27: 
                     28: #include <arpa/inet.h>
                     29: 
                     30: #if _BSDI_VERSION >= 199510
                     31: # include <ifaddrs.h>
                     32: #endif
                     33: 
                     34: # ifdef __QNXNTO__
                     35: #  include <fcntl.h>
                     36: #  include <unix.h>
                     37: #  define FNDELAY O_NDELAY
                     38: # endif
                     39: 
                     40: #include "ntp_machine.h"
                     41: #include "ntpd.h"
                     42: #include "ntp_io.h"
                     43: #include "ntp_if.h"
                     44: #include "ntp_stdlib.h"
                     45: #include "iosignal.h"
                     46: 
                     47: #if defined(HAVE_SIGNALED_IO)
                     48: static int sigio_block_count = 0;
                     49: # if defined(HAVE_SIGACTION)
                     50: /*
                     51:  * If sigaction() is used for signal handling and a signal is
                     52:  * pending then the kernel blocks the signal before it calls
                     53:  * the signal handler.
                     54:  *
                     55:  * The variable below is used to take care that the SIGIO signal
                     56:  * is not unintentionally unblocked inside the sigio_handler()
                     57:  * if the handler executes a piece of code that is normally
                     58:  * bracketed by BLOCKIO()/UNBLOCKIO() calls.
                     59:  */
                     60: static int sigio_handler_active = 0;
                     61: # endif
                     62: extern void    input_handler   (l_fp *);
                     63: 
                     64: /*
                     65:  * SIGPOLL and SIGIO ROUTINES.
                     66:  */
                     67: 
                     68:  /*
                     69:  * Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and
                     70:  * a few have separate SIGIO and SIGPOLL signals.  This code checks for the
                     71:  * SIGIO == SIGPOLL case at compile time.
                     72:  * Do not define USE_SIGPOLL or USE_SIGIO.
                     73:  * these are interal only to iosignal.c!
                     74:  */
                     75: # if defined(USE_SIGPOLL)
                     76: #  undef USE_SIGPOLL
                     77: # endif
                     78: # if defined(USE_SIGIO)
                     79: #  undef USE_SIGIO
                     80: # endif
                     81: 
                     82: # if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
                     83: #  define USE_SIGPOLL
                     84: # endif
                     85: 
                     86: # if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL)
                     87: #  define USE_SIGIO
                     88: # endif
                     89: 
                     90: # if defined(USE_SIGIO) && defined(USE_SIGPOLL)
                     91: #  if SIGIO == SIGPOLL
                     92: #      define USE_SIGIO
                     93: #      undef USE_SIGPOLL
                     94: #  endif /* SIGIO == SIGPOLL */
                     95: # endif /* USE_SIGIO && USE_SIGIO */
                     96: 
                     97: 
                     98: /*
                     99:  * TTY initialization routines.
                    100:  */
                    101: int
                    102: init_clock_sig(
                    103:        struct refclockio *rio
                    104:        )
                    105: {
                    106: # ifdef USE_TTY_SIGPOLL
                    107:        {
                    108:                /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
                    109:                if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0)
                    110:                {
                    111:                        msyslog(LOG_ERR,
                    112:                                "init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
                    113:                        return 1;
                    114:                }
                    115:                return 0;
                    116:        }
                    117: # else
                    118:        /*
                    119:         * Special cases first!
                    120:         */
                    121:        /* Was: defined(SYS_HPUX) */
                    122: #  if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
                    123: #define CLOCK_DONE
                    124:        {
                    125:                int pgrp, on = 1;
                    126: 
                    127:                /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
                    128:                pgrp = getpid();
                    129:                if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1)
                    130:                {
                    131:                        msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m");
                    132:                        exit(1);
                    133:                        /*NOTREACHED*/
                    134:                }
                    135: 
                    136:                /*
                    137:                 * set non-blocking, async I/O on the descriptor
                    138:                 */
                    139:                if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1)
                    140:                {
                    141:                        msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m");
                    142:                        exit(1);
                    143:                        /*NOTREACHED*/
                    144:                }
                    145: 
                    146:                if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1)
                    147:                {
                    148:                        msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m");
                    149:                        exit(1);
                    150:                        /*NOTREACHED*/
                    151:                }
                    152:                return 0;
                    153:        }
                    154: #  endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
                    155:        /* Was: defined(SYS_AIX) && !defined(_BSD) */
                    156: #  if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN)
                    157:        /*
                    158:         * SYSV compatibility mode under AIX.
                    159:         */
                    160: #define CLOCK_DONE
                    161:        {
                    162:                int pgrp, on = 1;
                    163: 
                    164:                /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
                    165:                if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1)
                    166:                {
                    167:                        msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m");
                    168:                        return 1;
                    169:                }
                    170:                pgrp = -getpid();
                    171:                if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1)
                    172:                {
                    173:                        msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m");
                    174:                        return 1;
                    175:                }
                    176: 
                    177:                if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
                    178:                {
                    179:                        msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
                    180:                        return 1;
                    181:                }
                    182:                return 0;
                    183:        }
                    184: #  endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
                    185: #  ifndef  CLOCK_DONE
                    186:        {
                    187:                /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
                    188: #      if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
                    189:                /*
                    190:                 * there are, however, always exceptions to the rules
                    191:                 * one is, that OSF accepts SETOWN on TTY fd's only, iff they are
                    192:                 * CTTYs. SunOS and HPUX do not semm to have this restriction.
                    193:                 * another question is: how can you do multiple SIGIO from several
                    194:                 * ttys (as they all should be CTTYs), wondering...
                    195:                 *
                    196:                 * kd 95-07-16
                    197:                 */
                    198:                if (ioctl(rio->fd, TIOCSCTTY, 0) == -1)
                    199:                {
                    200:                        msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
                    201:                        return 1;
                    202:                }
                    203: #      endif /* TIOCSCTTY && USE_FSETOWNCTTY */
                    204: 
                    205:                if (fcntl(rio->fd, F_SETOWN, getpid()) == -1)
                    206:                {
                    207:                        msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m");
                    208:                        return 1;
                    209:                }
                    210: 
                    211:                if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
                    212:                {
                    213:                        msyslog(LOG_ERR,
                    214:                                "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
                    215:                        return 1;
                    216:                }
                    217:                return 0;
                    218:        }
                    219: #  endif /* CLOCK_DONE */
                    220: # endif /* !USE_TTY_SIGPOLL  */
                    221: }
                    222: 
                    223: 
                    224: 
                    225: void
                    226: init_socket_sig(
                    227:        int fd
                    228:        )
                    229: {
                    230: # ifdef USE_UDP_SIGPOLL
                    231:        {
                    232:                if (ioctl(fd, I_SETSIG, S_INPUT) < 0)
                    233:                {
                    234:                        msyslog(LOG_ERR,
                    235:                                "init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
                    236:                        exit(1);
                    237:                }
                    238:        }
                    239: # else /* USE_UDP_SIGPOLL */
                    240:        {
                    241:                int pgrp;
                    242: # ifdef FIOASYNC
                    243:                int on = 1;
                    244: # endif
                    245: 
                    246: #  if defined(FIOASYNC)
                    247:                if (ioctl(fd, FIOASYNC, (char *)&on) == -1)
                    248:                {
                    249:                        msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m");
                    250:                        exit(1);
                    251:                        /*NOTREACHED*/
                    252:                }
                    253: #  elif defined(FASYNC)
                    254:                {
                    255:                        int flags;
                    256: 
                    257:                        if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
                    258:                        {
                    259:                                msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m");
                    260:                                exit(1);
                    261:                                /*NOTREACHED*/
                    262:                        }
                    263:                        if (fcntl(fd, F_SETFL, flags|FASYNC) < 0)
                    264:                        {
                    265:                                msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m");
                    266:                                exit(1);
                    267:                                /*NOTREACHED*/
                    268:                        }
                    269:                }
                    270: #  else
                    271: #      include "Bletch: Need asynchronous I/O!"
                    272: #  endif
                    273: 
                    274: #  ifdef UDP_BACKWARDS_SETOWN
                    275:                pgrp = -getpid();
                    276: #  else
                    277:                pgrp = getpid();
                    278: #  endif
                    279: 
                    280: #  if defined(SIOCSPGRP)
                    281:                if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1)
                    282:                {
                    283:                        msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m");
                    284:                        exit(1);
                    285:                        /*NOTREACHED*/
                    286:                }
                    287: #  elif defined(FIOSETOWN)
                    288:                if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1)
                    289:                {
                    290:                        msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m");
                    291:                        exit(1);
                    292:                        /*NOTREACHED*/
                    293:                }
                    294: #  elif defined(F_SETOWN)
                    295:                if (fcntl(fd, F_SETOWN, pgrp) == -1)
                    296:                {
                    297:                        msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m");
                    298:                        exit(1);
                    299:                        /*NOTREACHED*/
                    300:                }
                    301: #  else
                    302: #      include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
                    303: #  endif
                    304:        }
                    305: # endif /* USE_UDP_SIGPOLL */
                    306: }
                    307: 
                    308: RETSIGTYPE
                    309: sigio_handler(
                    310:        int sig
                    311:        )
                    312: {
                    313:        int saved_errno = errno;
                    314:        l_fp ts;
                    315: 
                    316:        get_systime(&ts);
                    317: 
                    318: # if defined(HAVE_SIGACTION)
                    319:        sigio_handler_active++;
                    320:        if (sigio_handler_active != 1)  /* This should never happen! */
                    321:            msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1");
                    322: # endif
                    323: 
                    324:        (void)input_handler(&ts);
                    325: 
                    326: # if defined(HAVE_SIGACTION)
                    327:        sigio_handler_active--;
                    328:        if (sigio_handler_active != 0)  /* This should never happen! */
                    329:            msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0");
                    330: # endif
                    331: 
                    332:        errno = saved_errno;
                    333: }
                    334: 
                    335: /*
                    336:  * Signal support routines.
                    337:  */
                    338: # ifdef HAVE_SIGACTION
                    339: void
                    340: set_signal(void)
                    341: {
                    342: #  ifdef USE_SIGIO
                    343:        (void) signal_no_reset(SIGIO, sigio_handler);
                    344: # endif
                    345: #  ifdef USE_SIGPOLL
                    346:        (void) signal_no_reset(SIGPOLL, sigio_handler);
                    347: # endif
                    348: }
                    349: 
                    350: void
                    351: block_io_and_alarm(void)
                    352: {
                    353:        sigset_t set;
                    354: 
                    355:        if (sigemptyset(&set))
                    356:            msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m");
                    357: #  if defined(USE_SIGIO)
                    358:        if (sigaddset(&set, SIGIO))
                    359:            msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
                    360: #  endif
                    361: #  if defined(USE_SIGPOLL)
                    362:        if (sigaddset(&set, SIGPOLL))
                    363:            msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
                    364: #  endif
                    365:        if (sigaddset(&set, SIGALRM))
                    366:            msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
                    367: 
                    368:        if (sigprocmask(SIG_BLOCK, &set, NULL))
                    369:            msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m");
                    370: }
                    371: 
                    372: void
                    373: block_sigio(void)
                    374: {
                    375:        if ( sigio_handler_active == 0 )  /* not called from within signal handler */
                    376:        {
                    377:                sigset_t set;
                    378: 
                    379:                ++sigio_block_count;
                    380:                if (sigio_block_count > 1)
                    381:                    msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
                    382:                if (sigio_block_count < 1)
                    383:                    msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
                    384: 
                    385:                if (sigemptyset(&set))
                    386:                    msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m");
                    387: #      if defined(USE_SIGIO)
                    388:                if (sigaddset(&set, SIGIO))
                    389:                    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m");
                    390: #      endif
                    391: #      if defined(USE_SIGPOLL)
                    392:                if (sigaddset(&set, SIGPOLL))
                    393:                    msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m");
                    394: #      endif
                    395: 
                    396:                if (sigprocmask(SIG_BLOCK, &set, NULL))
                    397:                    msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m");
                    398:        }
                    399: }
                    400: 
                    401: void
                    402: unblock_io_and_alarm(void)
                    403: {
                    404:        sigset_t unset;
                    405: 
                    406:        if (sigemptyset(&unset))
                    407:            msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m");
                    408: 
                    409: #  if defined(USE_SIGIO)
                    410:        if (sigaddset(&unset, SIGIO))
                    411:            msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
                    412: #  endif
                    413: #  if defined(USE_SIGPOLL)
                    414:        if (sigaddset(&unset, SIGPOLL))
                    415:            msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
                    416: #  endif
                    417:        if (sigaddset(&unset, SIGALRM))
                    418:            msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
                    419: 
                    420:        if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
                    421:            msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m");
                    422: }
                    423: 
                    424: void
                    425: unblock_sigio(void)
                    426: {
                    427:        if ( sigio_handler_active == 0 )  /* not called from within signal handler */
                    428:        {
                    429:                sigset_t unset;
                    430: 
                    431:                --sigio_block_count;
                    432:                if (sigio_block_count > 0)
                    433:                    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
                    434:                if (sigio_block_count < 0)
                    435:                    msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
                    436: 
                    437:                if (sigemptyset(&unset))
                    438:                    msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m");
                    439: 
                    440: #      if defined(USE_SIGIO)
                    441:                if (sigaddset(&unset, SIGIO))
                    442:                    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m");
                    443: #      endif
                    444: #      if defined(USE_SIGPOLL)
                    445:                if (sigaddset(&unset, SIGPOLL))
                    446:                    msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
                    447: #      endif
                    448: 
                    449:                if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
                    450:                    msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m");
                    451:        }
                    452: }
                    453: 
                    454: void
                    455: wait_for_signal(void)
                    456: {
                    457:        sigset_t old;
                    458: 
                    459:        if (sigprocmask(SIG_UNBLOCK, NULL, &old))
                    460:            msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m");
                    461: 
                    462: #  if defined(USE_SIGIO)
                    463:        if (sigdelset(&old, SIGIO))
                    464:            msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m");
                    465: #  endif
                    466: #  if defined(USE_SIGPOLL)
                    467:        if (sigdelset(&old, SIGPOLL))
                    468:            msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
                    469: #  endif
                    470:        if (sigdelset(&old, SIGALRM))
                    471:            msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
                    472: 
                    473:        if (sigsuspend(&old) && (errno != EINTR))
                    474:            msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m");
                    475: }
                    476: 
                    477: # else /* !HAVE_SIGACTION */
                    478: /*
                    479:  * Must be an old bsd system.
                    480:  * We assume there is no SIGPOLL.
                    481:  */
                    482: 
                    483: void
                    484: block_io_and_alarm(void)
                    485: {
                    486:        int mask;
                    487: 
                    488:        mask = sigmask(SIGIO) | sigmask(SIGALRM);
                    489:        if (sigblock(mask))
                    490:            msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m");
                    491: }
                    492: 
                    493: void
                    494: block_sigio(void)
                    495: {
                    496:        int mask;
                    497: 
                    498:        ++sigio_block_count;
                    499:        if (sigio_block_count > 1)
                    500:            msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
                    501:        if (sigio_block_count < 1)
                    502:            msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
                    503: 
                    504:        mask = sigmask(SIGIO);
                    505:        if (sigblock(mask))
                    506:            msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m");
                    507: }
                    508: 
                    509: void
                    510: set_signal(void)
                    511: {
                    512:        (void) signal_no_reset(SIGIO, sigio_handler);
                    513: }
                    514: 
                    515: void
                    516: unblock_io_and_alarm(void)
                    517: {
                    518:        int mask, omask;
                    519: 
                    520:        mask = sigmask(SIGIO) | sigmask(SIGALRM);
                    521:        omask = sigblock(0);
                    522:        omask &= ~mask;
                    523:        (void) sigsetmask(omask);
                    524: }
                    525: 
                    526: void
                    527: unblock_sigio(void)
                    528: {
                    529:        int mask, omask;
                    530: 
                    531:        --sigio_block_count;
                    532:        if (sigio_block_count > 0)
                    533:            msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
                    534:        if (sigio_block_count < 0)
                    535:            msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
                    536:        mask = sigmask(SIGIO);
                    537:        omask = sigblock(0);
                    538:        omask &= ~mask;
                    539:        (void) sigsetmask(omask);
                    540: }
                    541: 
                    542: void
                    543: wait_for_signal(void)
                    544: {
                    545:        int mask, omask;
                    546: 
                    547:        mask = sigmask(SIGIO) | sigmask(SIGALRM);
                    548:        omask = sigblock(0);
                    549:        omask &= ~mask;
                    550:        if (sigpause(omask) && (errno != EINTR))
                    551:            msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m");
                    552: }
                    553: 
                    554: # endif /* HAVE_SIGACTION */
                    555: #else
                    556: int  NotAnEmptyCompilationUnit;
                    557: #endif 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>