home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / xntpd / ntpd.c < prev    next >
C/C++ Source or Header  |  1992-08-29  |  8KB  |  393 lines

  1. /*
  2.  * ntpd.c - main program for the fixed point NTP daemon
  3.  */
  4. #include <stdio.h>
  5. #include <signal.h>
  6. #include <errno.h>
  7. #include <sys/param.h>
  8. #include <sys/signal.h>
  9. #include <sys/ioctl.h>
  10. #include <sys/socket.h>
  11. #include <sys/time.h>
  12. #include <sys/resource.h>
  13. #include <netinet/in.h>
  14.  
  15. #include "ntp_syslog.h"
  16. #include "ntp_fp.h"
  17. #include "ntp.h"
  18.  
  19. #if defined(ULT_2_0_SUCKS)
  20. #ifndef sigmask
  21. #define    sigmask(m)    (1<<(m))
  22. #endif
  23. #endif
  24.  
  25. /*
  26.  * Mask for blocking SIGIO and SIGALRM
  27.  */
  28. #define    BLOCKSIGMASK    (sigmask(SIGIO)|sigmask(SIGALRM))
  29.  
  30. /*
  31.  * Signals we catch for debugging.  If not debugging we ignore them.
  32.  */
  33. #define    MOREDEBUGSIG    SIGUSR1
  34. #define    LESSDEBUGSIG    SIGUSR2
  35.  
  36. /*
  37.  * Signals which terminate us gracefully.
  38.  */
  39. #define    SIGDIE1        SIGHUP
  40. #define    SIGDIE2        SIGINT
  41. #define    SIGDIE3        SIGQUIT
  42. #define    SIGDIE4        SIGTERM
  43.  
  44. /*
  45.  * Scheduling priority we run at
  46.  */
  47. #define    NTPD_PRIO    (-12)
  48.  
  49. /*
  50.  * Debugging flag
  51.  */
  52. int debug;
  53.  
  54. /*
  55.  * Initializing flag.  All async routines watch this and only do their
  56.  * thing when it is clear.
  57.  */
  58. int initializing;
  59.  
  60. /*
  61.  * Version declaration
  62.  */
  63. extern char *Version;
  64.  
  65. /*
  66.  * Alarm flag.  Imported from timer module
  67.  */
  68. extern int alarm_flag;
  69.  
  70.  
  71. /*
  72.  * Main program.  Initialize us, disconnect us from the tty if necessary,
  73.  * and loop waiting for I/O and/or timer expiries.
  74.  */
  75. main(argc, argv)
  76.     int argc;
  77.     char *argv[];
  78. {
  79.     char *cp;
  80.     int was_alarmed;
  81.     struct recvbuf *rbuflist;
  82.     struct recvbuf *rbuf;
  83.     extern struct recvbuf *getrecvbufs();
  84.     extern void getstartup();
  85.     extern char *rindex();
  86. #ifdef DEBUG
  87.     void moredebug(), lessdebug();
  88. #endif
  89. #ifdef SIGDIE1
  90.     void finish();
  91. #endif    /* SIGDIE1 */
  92.  
  93.     initializing = 1;    /* mark that we are initializing */
  94.     debug = 0;        /* no debugging by default */
  95.  
  96.     getstartup(argc, argv);    /* startup configuration, may set debug */
  97.  
  98. #ifndef NODETACH
  99.     /*
  100.      * Detach us from the terminal.  May need an #ifndef GIZMO.
  101.      */
  102. #ifdef    DEBUG
  103.     if (!debug) {
  104. #endif
  105. #if BSD >= 199006
  106.         daemon(0, 0);
  107. #else
  108.         if (fork())
  109.             exit(0);
  110.  
  111.         {
  112.             int s;
  113.             for (s = getdtablesize(); s >= 0; s--)
  114.                 (void) close(s);
  115.             (void) open("/", 0);
  116.             (void) dup2(0, 1);
  117.             (void) dup2(0, 2);
  118. #if defined(HPUX)
  119.             (void) setsid();
  120. #else
  121.             (void) setpgrp(0, getpid());
  122. #endif
  123. #if defined(HPUX)
  124.             if (fork())
  125.                 exit(0);
  126. #else
  127. #ifdef apollo
  128. /*
  129.  * This breaks... the program fails to listen to any packets coming
  130.  * in on the UDP socket.  So how do you break terminal affiliation?
  131.  */
  132. #else
  133.             s = open("/dev/tty", 2);
  134.             if (s >= 0) {
  135.                 (void) ioctl(s, (u_long) TIOCNOTTY, (char *) 0);
  136.                 (void) close(s);
  137.             }
  138. #endif
  139. #endif
  140.         }
  141. #endif
  142. #ifdef    DEBUG
  143.     }
  144. #endif
  145. #endif /* NODETACH */
  146.  
  147.     /*
  148.      * Logging.  This may actually work on the gizmo board.  Find a name
  149.      * to log with by using the basename of argv[0]
  150.      */
  151.     cp = rindex(argv[0], '/');
  152.     if (cp == 0)
  153.         cp = argv[0];
  154.     else
  155.         cp++;
  156.  
  157. #ifndef    LOG_DAEMON
  158.     openlog(cp, LOG_PID);
  159. #else
  160.  
  161. #ifndef    LOG_NTP
  162. #define    LOG_NTP    LOG_DAEMON
  163. #endif
  164.     openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
  165. #ifdef    DEBUG
  166.     if (debug)
  167.         setlogmask(LOG_UPTO(LOG_DEBUG));
  168.     else
  169. #endif    /* DEBUG */
  170.         setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
  171. #endif    /* LOG_DAEMON */
  172.  
  173.     syslog(LOG_INFO, Version);
  174.  
  175.  
  176.     /*
  177.      * Set the priority.
  178.      */
  179. #if !defined(HPUX)
  180. #if defined(NTPD_PRIO) && NTPD_PRIO != 0
  181.     (void) setpriority(PRIO_PROCESS, 0, NTPD_PRIO);
  182. #endif    /* ... */
  183. #endif
  184.  
  185.     /*
  186.      * Set up signals we pay attention to locally.
  187.      */
  188. #ifdef SIGDIE1
  189.     (void) signal(SIGDIE1, finish);
  190. #endif    /* SIGDIE1 */
  191. #ifdef SIGDIE2
  192.     (void) signal(SIGDIE2, finish);
  193. #endif    /* SIGDIE2 */
  194. #ifdef SIGDIE3
  195.     (void) signal(SIGDIE3, finish);
  196. #endif    /* SIGDIE3 */
  197. #ifdef SIGDIE4
  198.     (void) signal(SIGDIE4, finish);
  199. #endif    /* SIGDIE4 */
  200.  
  201. #ifdef DEBUG
  202.     (void) signal(MOREDEBUGSIG, moredebug);
  203.     (void) signal(LESSDEBUGSIG, lessdebug);
  204. #else
  205.     (void) signal(MOREDEBUGSIG, SIG_IGN);
  206.     (void) signal(LESSDEBUGSIG, SIG_IGN);
  207. #endif     /* DEBUG */
  208.  
  209.     /*
  210.      * Call the init_ routines to initialize the data structures.
  211.      * Note that init_systime() may run a protocol to get a crude
  212.      * estimate of the time as an NTP client when running on the
  213.      * gizmo board.  It is important that this be run before
  214.      * init_subs() since the latter uses the time of day to seed
  215.      * the random number generator.  That is not the only
  216.      * dependency between these, either, be real careful about
  217.      * reordering.
  218.      */
  219.     init_auth();
  220.     init_util();
  221.     init_restrict();
  222.     init_mon();
  223.     init_systime();
  224.     init_timer();
  225.     init_lib();
  226.     init_random();
  227.     init_request();
  228.     init_control();
  229.     init_leap();
  230.     init_peer();
  231. #ifdef REFCLOCK
  232.     init_refclock();
  233. #endif
  234.     init_proto();
  235.     init_io();
  236.     init_loopfilter();
  237.  
  238.     /*
  239.      * Get configuration.  This (including argument list parsing) is
  240.      * done in a separate module since this will definitely be different
  241.      * for the gizmo board.
  242.      */
  243.     getconfig(argc, argv);
  244.     initializing = 0;
  245.  
  246.     /*
  247.      * Report that we're up to any trappers
  248.      */
  249.     report_event(EVNT_SYSRESTART, (struct peer *)0);
  250.  
  251.     /*
  252.      * Done all the preparation stuff, now the real thing.  We block
  253.      * SIGIO and SIGALRM and check to see if either has occured.
  254.      * If not, we pause until one or the other does.  We then call
  255.      * the timer processing routine and/or feed the incoming packets
  256.      * to the protocol module.  Then around again.
  257.      */
  258.     was_alarmed = 0;
  259.     rbuflist = (struct recvbuf *)0;
  260.     for (;;) {
  261.         int omask;
  262.  
  263.         omask = sigblock(BLOCKSIGMASK);
  264.         if (alarm_flag) {        /* alarmed? */
  265.             was_alarmed = 1;
  266.             alarm_flag = 0;
  267.         }
  268.         rbuflist = getrecvbufs();    /* get received buffers */
  269.  
  270.         if (!was_alarmed && rbuflist == (struct recvbuf *)0) {
  271.             /*
  272.              * Nothing to do.  Wait for something.
  273.              */
  274. #ifdef USESELECT
  275.                 {
  276.               /*
  277.                * Unfortunately the Sequent doesn't give us
  278.                * a SIGIO ig the input file descriptors
  279.                * therefore we cheat and do a select()
  280.                * on all input fs's for unlimited time.
  281.                * select() will terminate on SIGALARM, SIGIO
  282.                * (maybe there was as TTY in the file descriptors)
  283.                * or on the reception of input (let's hope
  284.                * Sequents select() works for file descriptors)
  285.                */
  286.               extern fd_set activefds;
  287.               extern int maxactivefd;
  288.               extern void input_handler();
  289.               
  290.               fd_set rdfdes;
  291.               int nfound;
  292.               
  293.               rdfdes = activefds;
  294.               nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
  295.                     (fd_set *)0, (struct timeval *)0);
  296.               if (nfound > 0)
  297.                 input_handler();
  298.               else
  299.                 if (nfound == -1 && errno != EINTR)
  300.                   {
  301.                 syslog(LOG_ERR, "select() error: %m");
  302.                   }
  303.             }
  304.             
  305. #else              
  306.             sigpause(omask);
  307. #endif
  308.             if (alarm_flag) {        /* alarmed? */
  309.                 was_alarmed = 1;
  310.                 alarm_flag = 0;
  311.             }
  312.             rbuflist = getrecvbufs();  /* get received buffers */
  313.         }
  314.         (void)sigsetmask(omask);
  315.  
  316.         /*
  317.          * Out here, signals are unblocked.  Call timer routine
  318.          * to process expiry.
  319.          */
  320.         if (was_alarmed) {
  321.             timer();
  322.             was_alarmed = 0;
  323.         }
  324.  
  325.         /*
  326.          * Call the data procedure to handle each received
  327.          * packet.
  328.          */
  329.         while (rbuflist != (struct recvbuf *)0) {
  330.             rbuf = rbuflist;
  331.             rbuflist = rbuf->next;
  332.             (rbuf->receiver)(rbuf);
  333.             freerecvbuf(rbuf);
  334.         }
  335.         /*
  336.          * Go around again
  337.          */
  338.     }
  339. }
  340.  
  341.  
  342. #ifdef SIGDIE1
  343. /*
  344.  * finish - exit gracefully
  345.  */
  346. void
  347. finish()
  348. {
  349.     struct timeval tv;
  350.  
  351.     /*
  352.      * The only thing we really want to do here is make sure
  353.      * any pending time adjustment is terminated, as a bug
  354.      * preventative.  Also log any useful info before exiting.
  355.      */
  356.     tv.tv_sec = tv.tv_usec = 0;
  357.     (void) adjtime(&tv, (struct timeval *)0);
  358.  
  359. #ifdef notdef
  360.     log_exit_stats();
  361. #endif
  362.     exit(0);
  363. }
  364. #endif    /* SIGDIE1 */
  365.  
  366.  
  367. #ifdef DEBUG
  368. /*
  369.  * moredebug - increase debugging verbosity
  370.  */
  371. void
  372. moredebug()
  373. {
  374.     if (debug < 255) {
  375.         debug++;
  376.         syslog(LOG_DEBUG, "debug raised to %d", debug);
  377.     }
  378. }
  379.  
  380.  
  381. /*
  382.  * lessdebug - decrease debugging verbosity
  383.  */
  384. void
  385. lessdebug()
  386. {
  387.     if (debug > 0) {
  388.         debug--;
  389.         syslog(LOG_DEBUG, "debug lowered to %d", debug);
  390.     }
  391. }
  392. #endif    /* DEBUG */
  393.