File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / libntp / iosignal.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 5 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>