home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / xinetd21 / part22 < prev    next >
Encoding:
Text File  |  1993-06-26  |  27.3 KB  |  1,103 lines

  1. Newsgroups: comp.sources.unix
  2. From: panos@cs.colorado.edu (Panos Tsirigotis)
  3. Subject: v26i266: xinetd-2.1.1 - inetd replacement with access control and logging, Part22/31
  4. Sender: unix-sources-moderator@gw.home.vix.com
  5. Approved: vixie@gw.home.vix.com
  6.  
  7. Submitted-By: panos@cs.colorado.edu (Panos Tsirigotis)
  8. Posting-Number: Volume 26, Issue 266
  9. Archive-Name: xinetd-2.1.1/part22
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 22 (of 31)."
  18. # Contents:  xinetd/internals.c xinetd/signals.c
  19. # Wrapped by panos@mystique on Mon Jun 21 14:51:26 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'xinetd/internals.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'xinetd/internals.c'\"
  23. else
  24. echo shar: Extracting \"'xinetd/internals.c'\" \(12327 characters\)
  25. sed "s/^X//" >'xinetd/internals.c' <<'END_OF_FILE'
  26. X/*
  27. X * (c) Copyright 1992 by Panagiotis Tsirigotis
  28. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  29. X * and conditions for redistribution.
  30. X */
  31. X
  32. Xstatic char RCSid[] = "$Id: internals.c,v 6.5 1993/06/06 00:13:50 panos Exp $" ;
  33. X
  34. X#include <sys/types.h>
  35. X#include <sys/stat.h>
  36. X#include <signal.h>
  37. X#include <time.h>
  38. X#include <fcntl.h>
  39. X#include <syslog.h>
  40. X
  41. X#include "sio.h"
  42. X
  43. X#include "config.h"
  44. X#include "service.h"
  45. X#include "server.h"
  46. X#include "state.h"
  47. X#include "flags.h"
  48. X
  49. Xextern char program_version[] ;
  50. X
  51. Xvoid msg() ;
  52. X
  53. Xtime_t time() ;
  54. X
  55. X
  56. XPRIVATE void dump_services( fd )
  57. X    int fd ;
  58. X{
  59. X    register unsigned u ;
  60. X
  61. X    /*
  62. X     * Dump the current configuration (services + defaults)
  63. X     */
  64. X    Sprint( fd, "Services + defaults:\n" ) ;
  65. X    sc_dump( DEFAULTS( ps ), fd, 0, TRUE ) ;
  66. X
  67. X    for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
  68. X        svc_dump( SP( pset_pointer( SERVICES( ps ), u ) ), fd ) ;
  69. X}
  70. X
  71. X
  72. Xvoid dump_internal_state()
  73. X{
  74. X    int dump_fd ;
  75. X    char *dump_file = DUMP_FILE ;
  76. X    time_t current_time ;
  77. X    register int fd ;
  78. X    register unsigned u ;
  79. X    char *func = "dump_internal_state" ;
  80. X
  81. X    dump_fd = open( dump_file, O_WRONLY + O_CREAT + O_APPEND, DUMP_FILE_MODE ) ;
  82. X    if ( dump_fd == -1 )
  83. X    {
  84. X        msg( LOG_ERR, func, "failed to open %s: %m", dump_file ) ;
  85. X        return ;
  86. X    }
  87. X    Sbuftype( dump_fd, SIO_LINEBUF ) ;
  88. X
  89. X    /*
  90. X     * Print the program name, version, and timestamp.
  91. X     * Note that the program_version variable contains the program name.
  92. X     */
  93. X    (void) time( ¤t_time ) ;
  94. X    Sprint( dump_fd, "INTERNAL STATE DUMP: %s\n", program_version ) ;
  95. X    Sprint( dump_fd, "Current time: %s\n", ctime( ¤t_time ) ) ;
  96. X
  97. X    dump_services( dump_fd ) ;
  98. X
  99. X    /*
  100. X     * Dump the server table
  101. X     */
  102. X    Sprint( dump_fd, "Server table dump:\n" ) ;
  103. X    for ( u = 0 ; u < pset_count( SERVERS( ps ) ) ; u++ )
  104. X        server_dump( SERP( pset_pointer( SERVERS( ps ), u ) ), dump_fd ) ;
  105. X    Sputchar( dump_fd, '\n' ) ;
  106. X
  107. X    /*
  108. X     * Dump the retry_table
  109. X     */
  110. X    Sprint( dump_fd, "Retry table dump:\n" ) ;
  111. X    for ( u = 0 ; u < pset_count( RETRIES( ps ) ) ; u++ )
  112. X        server_dump( SERP( pset_pointer( RETRIES( ps ), u ) ), dump_fd ) ;
  113. X    Sputchar( dump_fd, '\n' ) ;
  114. X
  115. X    /*
  116. X     * Dump the socket mask
  117. X     */
  118. X    Sprint( dump_fd, "Socket mask:" ) ;
  119. X    for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
  120. X        if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
  121. X            Sprint( dump_fd, " %d", fd ) ;
  122. X    Sputchar( dump_fd, '\n' ) ;
  123. X    Sprint( dump_fd, "mask_max = %d\n", ps.rws.mask_max ) ;
  124. X
  125. X    /*
  126. X     * Dump the descriptors that are open and are *not* in the socket mask
  127. X     */
  128. X    Sprint( dump_fd, "Open descriptors (not in socket mask):" ) ;
  129. X    for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
  130. X    {
  131. X        struct stat st ;
  132. X
  133. X        if ( FD_ISSET( fd, &ps.rws.socket_mask ) )
  134. X            continue ;
  135. X        if ( fstat( fd, &st ) == -1 )
  136. X            continue ;
  137. X        Sprint( dump_fd, " %d", fd ) ;
  138. X    }
  139. X    Sputchar( dump_fd, '\n' ) ;
  140. X    Sputchar( dump_fd, '\n' ) ;
  141. X
  142. X    Sprint( dump_fd, "active_services = %d\n", ps.rws.active_services ) ;
  143. X    Sprint( dump_fd, "available_services = %d\n", ps.rws.available_services ) ;
  144. X    Sprint( dump_fd, "descriptors_free = %d\n", ps.rws.descriptors_free ) ;
  145. X    Sprint( dump_fd, "running_servers = %d\n", pset_count( SERVERS( ps ) ) ) ;
  146. X    Sprint( dump_fd, "Logging service = %s\n",
  147. X                LOG_SERVICE( ps ) != NULL ? "enabled" : "not enabled" ) ;
  148. X    Sprint( dump_fd, "Shutdown service = %s\n",
  149. X                SHUTDOWN_SERVICE( ps ) != NULL ? "enabled" : "not enabled" ) ;
  150. X    Sputchar( dump_fd, '\n' ) ;
  151. X
  152. X    Sprint( dump_fd, "max_descriptors = %d\n", ps.ros.max_descriptors ) ;
  153. X    Sprint( dump_fd, "process_limit = %d\n", ps.ros.process_limit ) ;
  154. X    Sprint( dump_fd, "config_file = %s\n", ps.ros.config_file ) ;
  155. X    if ( debug.on )
  156. X        Sprint( dump_fd, "debug_fd = %d\n", debug.fd ) ;
  157. X    Sputchar( dump_fd, '\n' ) ;
  158. X
  159. X    Sprint( dump_fd, "END OF DUMP\n\n" ) ;
  160. X    Sclose( dump_fd ) ;
  161. X
  162. X    msg( LOG_INFO, func, "generated state dump in file %s", dump_file ) ;
  163. X}
  164. X
  165. X
  166. X
  167. X/*
  168. X * Types of consistency checks
  169. X */
  170. Xenum check_type { PERIODIC, USER_REQUESTED } ;
  171. X
  172. X
  173. XPRIVATE void consistency_check( type )
  174. X    enum check_type type ;
  175. X{
  176. X    register int            fd ;
  177. X    fd_set                    socket_mask_copy ;
  178. X    register unsigned     u ;
  179. X    int                         errors ;
  180. X    unsigned                 total_running_servers        = 0 ;
  181. X    unsigned                 total_retry_servers            = 0 ;
  182. X    unsigned                 error_count                        = 0 ;
  183. X    bool_int                 service_count_check_failed    = FALSE ;
  184. X    char                        *func                                = "consistency_check" ;
  185. X    PRIVATE unsigned        thread_check() ;
  186. X    PRIVATE unsigned        refcount_check() ;
  187. X    PRIVATE unsigned        service_count_check() ;
  188. X
  189. X    socket_mask_copy = ps.rws.socket_mask ;
  190. X
  191. X    for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ )
  192. X    {
  193. X        register struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ;
  194. X        char *sid = SVC_ID( sp ) ;
  195. X        unsigned    running_servers ;
  196. X        unsigned    retry_servers ;
  197. X
  198. X        error_count += refcount_check( sp, &running_servers, &retry_servers ) ;
  199. X
  200. X        if ( SVC_IS_AVAILABLE( sp ) || SVC_IS_DISABLED ( sp ) )
  201. X        {
  202. X            /*
  203. X             * In this case, there may be some servers running
  204. X             */
  205. X            if ( FD_ISSET( SVC_FD( sp ), &socket_mask_copy ) )
  206. X            {
  207. X                if ( SVC_IS_DISABLED( sp ) )
  208. X                {
  209. X                    msg( LOG_ERR, func,
  210. X                        "fd of disabled service %s still in socket mask", sid ) ;
  211. X                    error_count++ ;
  212. X                }
  213. X                FD_CLR( SVC_FD( sp ), &socket_mask_copy ) ;
  214. X            }
  215. X            error_count += thread_check( sp, running_servers, retry_servers ) ;
  216. X
  217. X            errors = service_count_check( sp, running_servers, retry_servers ) ;
  218. X            if ( ! errors && ! service_count_check_failed )
  219. X            {
  220. X                total_retry_servers += retry_servers ;
  221. X                total_running_servers += running_servers ;
  222. X            }
  223. X            if ( errors )
  224. X            {
  225. X                service_count_check_failed = TRUE ;
  226. X                error_count += errors ;
  227. X            }
  228. X
  229. X            if ( SVC_IS_DISABLED( sp ) && SVC_RUNNING_SERVERS( sp ) == 0 )
  230. X            {
  231. X                msg( LOG_ERR, func,
  232. X                    "disabled service %s has 0 running servers\n", sid ) ;
  233. X                error_count++ ;
  234. X                continue ;
  235. X            }
  236. X        }
  237. X        else
  238. X        {
  239. X            msg( LOG_ERR, func, "service %s not started", SVC_ID( sp ) ) ;
  240. X            error_count++ ;
  241. X        }
  242. X    }
  243. X
  244. X    if ( ! service_count_check_failed )
  245. X    {
  246. X        if ( total_running_servers != pset_count( SERVERS( ps ) ) )
  247. X        {
  248. X            msg( LOG_ERR, func,
  249. X                "total running servers (%d) != number of running servers (%d)",
  250. X                    total_running_servers, pset_count( SERVERS( ps ) ) ) ;
  251. X            error_count++ ;
  252. X        }
  253. X        if ( total_retry_servers != pset_count( RETRIES( ps ) ) )
  254. X        {
  255. X            msg( LOG_ERR, func,
  256. X                "total retry servers (%d) != number of retry servers (%d)",
  257. X                    total_retry_servers, pset_count( RETRIES( ps ) ) ) ;
  258. X            error_count++ ;
  259. X        }
  260. X    }
  261. X
  262. X    /*
  263. X     * Check if there are any descriptors set in socket_mask_copy
  264. X     */
  265. X    for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ )
  266. X        if ( FD_ISSET( fd, &socket_mask_copy ) )
  267. X        {
  268. X            msg( LOG_ERR, func,
  269. X                "descriptor %d set in socket mask but there is no service for it",
  270. X                    fd ) ;
  271. X            error_count++ ;
  272. X        }
  273. X
  274. X    if ( error_count > 0 )
  275. X        msg( LOG_WARNING, func,
  276. X                "Consistency check detected %d errors", error_count ) ;
  277. X    else
  278. X        if ( type == USER_REQUESTED || debug.on )
  279. X            msg( LOG_INFO, func, "Consistency check passed" ) ;
  280. X}
  281. X
  282. X
  283. X/*
  284. X * Check that the counts of running and retry servers stored in struct service
  285. X * are accurate
  286. X */
  287. XPRIVATE unsigned service_count_check( sp, running_servers, retry_servers )
  288. X    register struct service *sp ;
  289. X    unsigned running_servers ;
  290. X    unsigned retry_servers ;
  291. X{
  292. X    register char *sid = SVC_ID( sp ) ;
  293. X    int error_count = 0 ;
  294. X    char *func = "service_count_check" ;
  295. X
  296. X    if ( SVC_RUNNING_SERVERS( sp ) != running_servers )
  297. X    {
  298. X        msg( LOG_ERR, func,
  299. X            "service %s: actual running servers = %d, known running servers = %d",
  300. X                sid, running_servers, SVC_RUNNING_SERVERS( sp ) ) ;
  301. X        error_count++ ;
  302. X    }
  303. X    if ( SVC_RETRIES( sp ) != retry_servers )
  304. X    {
  305. X        msg( LOG_ERR, func,
  306. X            "service %s: actual retry servers = %d, known retry servers = %d",
  307. X                sid, retry_servers, SVC_RETRIES( sp ) ) ;
  308. X        error_count++ ;
  309. X    }
  310. X
  311. X    if ( error_count && debug.on )
  312. X        msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;
  313. X
  314. X    return( error_count ) ;
  315. X}
  316. X
  317. X
  318. X
  319. X/*
  320. X * If the service is single-threaded:
  321. X *            if the descriptor is set in the socket mask, there must
  322. X *            be a server running (or to be retried)
  323. X *    If the service is multi-threaded:
  324. X *            the descriptor must be always set
  325. X */
  326. XPRIVATE unsigned thread_check( sp, running_servers, retry_servers )
  327. X    register struct service *sp ;
  328. X    unsigned running_servers ;
  329. X    unsigned retry_servers ;
  330. X{
  331. X    unsigned error_count = 0 ;
  332. X    int sd = SVC_FD( sp ) ;
  333. X    char *sid = SVC_ID( sp ) ;
  334. X    char *func = "thread_check" ;
  335. X
  336. X    if ( SVC_WAITS( sp ) )
  337. X    {
  338. X        bool_int has_servers = ( running_servers + retry_servers > 0 ) ;
  339. X
  340. X        if ( has_servers && FD_ISSET( sd, &ps.rws.socket_mask ) )
  341. X        {
  342. X            msg( LOG_ERR, func,
  343. X"Active single-threaded service %s: server running, descriptor set", sid ) ;
  344. X            error_count++ ;
  345. X        }
  346. X        if ( !has_servers && !FD_ISSET( sd, &ps.rws.socket_mask ) )
  347. X        {
  348. X            msg( LOG_ERR, func,
  349. X"Active single-threaded service %s: no server running, descriptor not set",
  350. X                sid ) ;
  351. X            error_count++ ;
  352. X        }
  353. X    }
  354. X    else
  355. X        if ( ! FD_ISSET( sd, &ps.rws.socket_mask ) )
  356. X        {
  357. X            msg( LOG_ERR, func,
  358. X                "Active multi-threaded service %s: descriptor not set", sid ) ;
  359. X            error_count++ ;
  360. X        }
  361. X
  362. X    if ( error_count && debug.on )
  363. X        msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ;
  364. X
  365. X    return( error_count ) ;
  366. X}
  367. X
  368. X
  369. X
  370. X/*
  371. X * Count the number of references to the specified service contained
  372. X * in the specified table of servers; put the number of servers
  373. X * in *countp
  374. X */
  375. XPRIVATE int count_refs( sp, servers, countp )
  376. X    register struct service *sp ;
  377. X    register pset_h servers ;
  378. X    unsigned *countp ;
  379. X{
  380. X    register unsigned u ;
  381. X    register struct server *serp ;
  382. X    int refs = 0 ;
  383. X    unsigned count = 0 ;
  384. X
  385. X    for ( u = 0 ; u < pset_count( servers ) ; u++ )
  386. X    {
  387. X        serp = SERP( pset_pointer( SERVERS( ps ), u ) ) ;
  388. X        if ( SERVER_SERVICE( serp ) == sp )
  389. X        {
  390. X            refs++ ;
  391. X            count++ ;
  392. X        }
  393. X        if ( SERVER_CONNSERVICE( serp ) == sp )
  394. X            refs++ ;
  395. X        /*
  396. X         * XXX:    in the future we may want to check if the given service
  397. X         *            is any of the alternative services (currently only SPECIAL
  398. X         *            services can be alternative services and SPECIAL services
  399. X         *            are not included in the service table)
  400. X         */
  401. X    }
  402. X    *countp = count ;
  403. X    return( refs ) ;
  404. X}
  405. X
  406. X
  407. X/*
  408. X * Check for reference counting errors.
  409. X * Returns number of errors found.
  410. X * Always set the number of running and retry servers.
  411. X */
  412. XPRIVATE unsigned refcount_check( sp, running_servers, retry_servers )
  413. X    struct service *sp ;
  414. X    unsigned *running_servers ;
  415. X    unsigned *retry_servers ;
  416. X{
  417. X    char *sid = SVC_ID( sp ) ;
  418. X    unsigned errors = 0 ;
  419. X    int refs ;
  420. X    int refcount = SVC_REFCOUNT( sp ) ;
  421. X    char *func = "refcount_check" ;
  422. X
  423. X    if ( ! refcount > 0 )
  424. X    {
  425. X        msg( LOG_ERR, func, "%s service has bad refcount: %d\n",
  426. X                    sid, refcount ) ;
  427. X        errors++ ;
  428. X    }
  429. X
  430. X    /*
  431. X     * The service table holds a reference to the service. The remaining
  432. X     * references must be from servers and connections.
  433. X     */
  434. X    refcount-- ;
  435. X
  436. X    refs = count_refs( sp, SERVERS( ps ), running_servers ) ;
  437. X    if ( ! errors && refs > refcount )
  438. X    {
  439. X        msg( LOG_ERR, func,
  440. X            "running servers: too many references for %s (%d with max=%d)",
  441. X                sid, refs, refcount ) ;
  442. X        errors++ ;
  443. X    }
  444. X
  445. X    refs = count_refs( sp, RETRIES( ps ), retry_servers ) ;
  446. X    if ( ! errors && refs > refcount )
  447. X    {
  448. X        msg( LOG_ERR, func,
  449. X            "retry servers: too many references for %s (%d with max=%d)",
  450. X                sid, refs, refcount ) ;
  451. X        errors++ ;
  452. X    }
  453. X
  454. X    if ( errors && debug.on )
  455. X        msg( LOG_DEBUG, func, "%s: %d errors detected", sid, errors ) ;
  456. X
  457. X    return( errors ) ;
  458. X}
  459. X
  460. X
  461. Xvoid user_requested_check()
  462. X{
  463. X    consistency_check( USER_REQUESTED ) ;
  464. X}
  465. X
  466. X
  467. Xvoid periodic_check()
  468. X{
  469. X    consistency_check( PERIODIC ) ;
  470. X}
  471. X
  472. X
  473. X#ifndef NO_TIMERS
  474. X
  475. X#include <sys/time.h>
  476. X
  477. X#include "timer.h"
  478. X
  479. Xstatic timer_h cc_timer ;            /* consistency check timer */
  480. X
  481. Xstatus_e create_cc_timer()
  482. X{
  483. X    cc_timer = timer_create( TIMER_REAL, TIMER_RETURN_ERROR, INT_NULL ) ;
  484. X    return( cc_timer ? OK : FAILED ) ;
  485. X}
  486. X
  487. X
  488. XPRIVATE void cc_timer_action( tp, arg )
  489. X    timer_h tp ;
  490. X    void *arg ;
  491. X{
  492. X#ifdef lint
  493. X    tp = tp ;
  494. X    arg = arg ;
  495. X#endif
  496. X    M_SET( ps.flags, PERIODIC_CHECK_FLAG ) ;
  497. X}
  498. X
  499. X
  500. Xvoid enable_periodic_check( interval )
  501. X    unsigned interval ;
  502. X{
  503. X    struct itimerval itv ;
  504. X    struct timer_action ta ;
  505. X    char *func = "enable_periodic_check" ;
  506. X
  507. X    itv.it_value.tv_sec = itv.it_interval.tv_sec = interval ;
  508. X    itv.it_value.tv_usec = itv.it_interval.tv_usec = 0 ;
  509. X    ta.ta_flags = debug.on ? TIMER_BLOCK_SAME : TIMER_NOFLAGS ;
  510. X    ta.ta_func = cc_timer_action ;
  511. X    ta.ta_arg = VOID_NULL ;
  512. X    if ( timer_start( cc_timer, &itv, TIMER_RELATIVE, &ta ) == TIMER_ERR )
  513. X    {
  514. X        msg( LOG_ERR, func, "Failed to start concistency timer" ) ;
  515. X        return ;
  516. X    }
  517. X}
  518. X
  519. X#endif    /* ! NO_TIMERS */
  520. X
  521. END_OF_FILE
  522. if test 12327 -ne `wc -c <'xinetd/internals.c'`; then
  523.     echo shar: \"'xinetd/internals.c'\" unpacked with wrong size!
  524. fi
  525. # end of 'xinetd/internals.c'
  526. fi
  527. if test -f 'xinetd/signals.c' -a "${1}" != "-c" ; then 
  528.   echo shar: Will not clobber existing file \"'xinetd/signals.c'\"
  529. else
  530. echo shar: Extracting \"'xinetd/signals.c'\" \(12358 characters\)
  531. sed "s/^X//" >'xinetd/signals.c' <<'END_OF_FILE'
  532. X/*
  533. X * (c) Copyright 1992 by Panagiotis Tsirigotis
  534. X * All rights reserved.  The file named COPYRIGHT specifies the terms 
  535. X * and conditions for redistribution.
  536. X */
  537. X
  538. Xstatic char RCSid[] = "$Id: signals.c,v 6.9 1993/06/15 23:25:57 panos Exp $" ;
  539. X
  540. X#include <sys/types.h>
  541. X#include <sys/time.h>
  542. X#include <signal.h>
  543. X#include <syslog.h>
  544. X#include <errno.h>
  545. X#include <string.h>
  546. X
  547. X#include "str.h"
  548. X
  549. X#include "state.h"
  550. X#include "defs.h"
  551. X#include "config.h"
  552. X#include "flags.h"
  553. X
  554. Xextern int errno ;
  555. X
  556. Xvoid msg() ;
  557. X
  558. Xvoid exit() ;
  559. Xtime_t time() ;
  560. X
  561. X#define SIGSET_NULL                            ((sigset_t *)0)
  562. X#define SIGVEC_NULL                            ((struct sigvec *)0)
  563. X#define SIGACTION_NULL                        ((struct sigaction *)0)
  564. X
  565. X#ifdef NO_POSIX_SIGS
  566. X
  567. X#ifdef NO_POSIX_TYPES
  568. X/*
  569. X * XXX:    here we assume that in the case that NO_POSIX_TYPES is not defined
  570. X *            (i.e. the system has posix types) the sigset_t is also typedef'd
  571. X *            to 'int'. Our goal is to work with systems that have defined
  572. X *            sigset_t but do not yet support the posix signal interface.
  573. X */
  574. Xtypedef int sigset_t ;
  575. X
  576. Xstruct sigaction
  577. X{
  578. X    void            (*sa_handler)() ;
  579. X    sigset_t        sa_mask ;
  580. X    int            sa_flags ;
  581. X} ;
  582. X#endif    /* NO_POSIX_TYPES */
  583. X
  584. X#ifdef NO_SIGVEC
  585. X#define sigmask( sig )                        ( 1 << ( (sig) -1 ) )
  586. Xtypedef int (*sighandler_type)() ;
  587. X#define sigpause( x )
  588. X#define sigsetmask( x )
  589. X#endif    /* NO_SIGVEC */
  590. X
  591. X
  592. X#define sigsuspend( set )                    sigpause( *set )
  593. X#define sigemptyset( set )                    (*set) = 0
  594. X#define sigaddset( set, sig )                ( ( (*set) |= sigmask( sig ) ), 0 )
  595. X#define sigismember( set, sig )            ( ( (*set) & sigmask( sig ) ) != 0 )
  596. X
  597. X
  598. X/*
  599. X * Only works for SIG_SETMASK and SIG_UNBLOCK. Also oset must be NULL.
  600. X */
  601. Xint sigprocmask( how, set, oset )
  602. X    int how ;
  603. X    sigset_t *set ;
  604. X    sigset_t *oset ;
  605. X{
  606. X    if ( how == SIG_BLOCK || oset != NULL )
  607. X    {
  608. X        msg( LOG_ERR, "sigprocmask",
  609. X                                    "Bad args: how = %d, oset = %p", how, oset ) ;
  610. X        return( -1 ) ;
  611. X    }
  612. X
  613. X    if ( how == SIG_SETMASK )
  614. X    {
  615. X        (void) sigsetmask( *set ) ;
  616. X        return( 0 ) ;
  617. X    }
  618. X
  619. X    if ( how == SIG_UNBLOCK )
  620. X    {
  621. X        int current_mask = sigblock( 0 ) ;
  622. X
  623. X        (void) sigsetmask( current_mask & ~*set ) ;
  624. X        return( 0 ) ;
  625. X    }
  626. X    /* NOTREACHED */
  627. X}
  628. X
  629. X
  630. X/*
  631. X * NOTE: This is not a complete imitation of sigaction; in particular it
  632. X *            expects that sap is never NULL and that osap is always NULL.
  633. X */
  634. Xint sigaction( sig, sap, osap )
  635. X    int sig ;
  636. X    struct sigaction *sap ;
  637. X    struct sigaction *osap ;
  638. X{
  639. X    if ( sap == NULL || osap != NULL )
  640. X    {
  641. X        msg( LOG_ERR, "sigaction", "Bad args: sap = %p, osap = %p", sap, osap ) ;
  642. X        return( -1 ) ;
  643. X    }
  644. X
  645. X#ifndef NO_SIGVEC
  646. X    {
  647. X        struct sigvec sv ;
  648. X
  649. X        sv.sv_handler = sap->sa_handler ;
  650. X        sv.sv_mask = sap->sa_mask ;
  651. X        sv.sv_flags = sap->sa_flags ;
  652. X
  653. X        return( sigvec( sig, &sv, SIGVEC_NULL ) ) ;
  654. X    }
  655. X#else        /* NO_SIGVEC */
  656. X    {
  657. X        sighandler_type new_handler ;
  658. X
  659. X        new_handler = sa.sa_handler ;
  660. X        return( signal( sig, new_handler ) ? 0 : -1 ) ;
  661. X    }
  662. X#endif    /* ! NO_SIGVEC */
  663. X}
  664. X
  665. X#endif    /* NO_POSIX_SIGS */
  666. X
  667. X
  668. X/*
  669. X * reset_sigs is the list of signals that we need to reset to SIG_DFL.
  670. X * Currently, these are the signals whose actions we set to SIG_IGN.
  671. X * In general, we should also include any signals that have a handler
  672. X * that does anything other than setting a flag. We need to do this
  673. X * in case such a signal occurs while a forked process is providing
  674. X * an internal service.
  675. X */
  676. Xstatic sigset_t reset_sigs ;
  677. X
  678. X/*
  679. X * nsig is equal to the greatest signal number supported plus 1
  680. X */
  681. Xstatic int nsig ;
  682. X
  683. X
  684. X
  685. X/*
  686. X * When this function returns FAILED, we check the errno to determine
  687. X * if it failed because the signal number specified was invalid.
  688. X * This allows us to determine the number of supported signals.
  689. X */
  690. XPRIVATE status_e handle_signal( sig )
  691. X    register int sig ;
  692. X{
  693. X    struct sigaction        sa ;
  694. X    voidfunc                    sig_handler ;
  695. X    PRIVATE void            my_handler() ;                /* for the signals we are     */
  696. X                                                                /* interested in                */
  697. X    PRIVATE void            general_handler() ;        /* for everything else        */
  698. X
  699. X    switch ( sig )
  700. X    {
  701. X        case RECONFIG_SOFT_SIG:
  702. X        case RECONFIG_HARD_SIG:
  703. X        case TERMINATION_SIG:
  704. X        case STATE_DUMP_SIG:
  705. X        case CONSISTENCY_CHECK_SIG:
  706. X        case SERVER_EXIT_SIG:
  707. X#ifdef NO_TIMERS
  708. X        case RETRY_SIG:
  709. X#endif
  710. X        case QUIT_SIG:
  711. X            sig_handler = my_handler ;
  712. X            break ;
  713. X
  714. X        case SIGTTIN:
  715. X        case SIGTTOU:
  716. X        case SIGTSTP:
  717. X            if ( debug.on )
  718. X                return( OK ) ;
  719. X            /* FALL THROUGH */
  720. X             
  721. X        /*
  722. X         * We may receive a SIGPIPE when handling an internal stream 
  723. X         * service and the other end closes the connection.
  724. X         * We only care about internal services that don't require forking.
  725. X         */
  726. X        case SIGPIPE:
  727. X            sig_handler = SIG_IGN ;
  728. X            sigaddset( &reset_sigs, sig ) ;
  729. X            break ;
  730. X
  731. X        case SIGKILL:
  732. X        case SIGSTOP:
  733. X            return( OK ) ;            /* we can't catch these two */
  734. X        
  735. X        /*
  736. X         * If the following two cases are included, SIGSEGV and SIGBUS will
  737. X         * cause core dumps. We want that to happen when we are debugging
  738. X         * xinetd (i.e. DEBUG is defined) and we are not debugging the
  739. X         * signal recovery code (i.e. DEBUG_SIGNALS is not defined).
  740. X         */
  741. X#if defined( DEBUG ) && !defined( DEBUG_SIGNALS )
  742. X        case SIGSEGV:
  743. X        case SIGBUS:
  744. X            return( OK ) ;
  745. X#endif
  746. X
  747. X        case SIGTRAP:
  748. X            if ( debug.on )
  749. X                return( OK ) ;
  750. X        
  751. X        default:
  752. X            sig_handler = general_handler ;
  753. X    }
  754. X
  755. X    sa.sa_flags = 0 ;
  756. X    sigemptyset( &sa.sa_mask ) ;
  757. X    sa.sa_handler = sig_handler ;
  758. X    return( ( sigaction( sig, &sa, SIGACTION_NULL ) == -1 ) ? FAILED : OK ) ;
  759. X}
  760. X
  761. X
  762. X
  763. X/*
  764. X * Install signal handlers for all signals that can be caught.
  765. X * This implies that no core dumps are generated by default.
  766. X */
  767. Xstatus_e signal_init()
  768. X{
  769. X    register int        sig ;
  770. X    char                    *func = "install_signal_handlers" ;
  771. X    char                    *sig_name() ;
  772. X
  773. X    sigemptyset( &reset_sigs ) ;
  774. X#ifndef NO_TIMERS
  775. X    sigaddset( &reset_sigs, SIGALRM ) ;
  776. X#endif
  777. X
  778. X    for ( sig = 1 ;; sig++ )
  779. X        if ( handle_signal( sig ) == FAILED )
  780. X            if ( errno == EINVAL )
  781. X            {
  782. X                nsig = sig ;
  783. X                break ;
  784. X            }
  785. X            else
  786. X            {
  787. X                msg( LOG_CRIT, func,
  788. X                    "Failed to install signal handler for signal %s: %m",
  789. X                        sig_name( sig ) ) ;
  790. X                return( FAILED ) ;
  791. X            }
  792. X    return( OK ) ;
  793. X}
  794. X
  795. X
  796. Xvoid signal_wait()
  797. X{
  798. X    sigset_t masked_sigs ;
  799. X
  800. X    sigemptyset( &masked_sigs ) ;
  801. X    (void) sigsuspend( &masked_sigs ) ;
  802. X}
  803. X
  804. X
  805. X#define MAX_SIGNAL_COUNT                    50
  806. X#define MAX_INTERVAL_SIGNAL_COUNT        10
  807. X#define SIGNAL_INTERVAL                        1        /* second */
  808. X
  809. X/*
  810. X * This function handles SIGSEGV and SIGBUS.
  811. X * Emergency action is taken if a certain number (MAX_SIGNAL_COUNT) of 
  812. X * these signals is received over the lifetime of the program OR 
  813. X * if a certain number (MAX_INTERVAL_SIGNAL_COUNT) of these signals 
  814. X * is received within a certain time interval (SIGNAL_INTERVAL).
  815. X *
  816. X * The action depends on the type of the emergency:
  817. X *        Case 1: MAX_INTERVAL_SIGNAL_COUNT is exceeded
  818. X *            If a setjmp environment is available, do a longjmp, otherwise exit
  819. X *        Case 2: MAX_SIGNAL_COUNT is exceeded
  820. X *            Exit
  821. X *
  822. X * NOTE: We try to send a message to the log only once to avoid
  823. X *            looping in this function (in case there is a bug in msg())
  824. X */
  825. XPRIVATE void bad_signal()
  826. X{
  827. X    static time_t    interval_start ;
  828. X    static int        interval_signal_count ;
  829. X    static int        total_signal_count ;
  830. X    time_t            current_time ;
  831. X    char                *func = "bad_signal" ;
  832. X
  833. X    total_signal_count++ ;
  834. X    if ( total_signal_count == MAX_SIGNAL_COUNT )
  835. X    {
  836. X        msg( LOG_CRIT, func,
  837. X                "Received %d bad signals. Exiting...", total_signal_count ) ;
  838. X        exit( 1 ) ;
  839. X    }
  840. X    else if ( total_signal_count > MAX_SIGNAL_COUNT )
  841. X        _exit( 1 ) ;        /* in case of a problem in exit(3) */
  842. X    
  843. X    (void) time( ¤t_time ) ;
  844. X
  845. X    if ( interval_signal_count > 0 &&
  846. X                current_time - interval_start <= SIGNAL_INTERVAL )
  847. X    {
  848. X        interval_signal_count++ ;
  849. X        if ( interval_signal_count == MAX_INTERVAL_SIGNAL_COUNT )
  850. X        {
  851. X            if ( ps.rws.env_is_valid )
  852. X            {
  853. X                interval_start = current_time ;
  854. X                interval_signal_count = 1 ;
  855. X                msg( LOG_ERR, func, "Resetting..." ) ;
  856. X                longjmp( ps.rws.env, 1 ) ;
  857. X                /* NOTREACHED */
  858. X            }
  859. X            msg( LOG_CRIT, func,
  860. X                "Received %d signals in %d seconds. Exiting...",
  861. X                    interval_signal_count, SIGNAL_INTERVAL ) ;
  862. X            exit( 1 ) ;
  863. X        }
  864. X        else if ( interval_signal_count > MAX_INTERVAL_SIGNAL_COUNT )
  865. X            _exit( 1 ) ;            /* shouldn't happen */
  866. X    }
  867. X    else
  868. X    {
  869. X        interval_start = current_time ;
  870. X        interval_signal_count = 1 ;
  871. X    }
  872. X}
  873. X
  874. X
  875. X#if defined( sun ) && defined( sparc )
  876. X#undef SP
  877. X
  878. X#include <machine/reg.h>
  879. X#include <machine/frame.h>
  880. X
  881. XPRIVATE void stack_trace( scp )
  882. X    struct sigcontext *scp ;
  883. X{
  884. X    struct frame        *fp ;
  885. X    struct rwindow        *rwp ;
  886. X    char                    tracebuf[ 1000 ] ;
  887. X    int                    len    = 0 ;
  888. X    unsigned                size    = sizeof( tracebuf ) - 1 ;
  889. X
  890. X    tracebuf[ size ] = NUL ;
  891. X
  892. X    if ( scp->sc_wbcnt != 0 )
  893. X        return ;
  894. X    rwp = (struct rwindow *) scp->sc_sp ;
  895. X    len = strx_nprint( tracebuf, size, "%#x %#x", scp->sc_pc, rwp->rw_rtn ) ;
  896. X    size -= len ;
  897. X
  898. X    for ( fp = (struct frame *) rwp->rw_fp ; fp != NULL ; fp = fp->fr_savfp ) 
  899. X    {
  900. X        int cc ;
  901. X
  902. X        cc = strx_nprint( &tracebuf[ len ], size,
  903. X                                                " %#x", (unsigned) fp->fr_savpc ) ;
  904. X        len += cc ;
  905. X        size -= cc ;
  906. X        fp = fp->fr_savfp ;
  907. X    }
  908. X
  909. X    msg( LOG_CRIT, "stack_trace", "%s", tracebuf ) ;
  910. X}
  911. X#endif    /* sun && sparc */
  912. X
  913. X
  914. X
  915. Xchar *sig_name( sig )
  916. X    int sig ;
  917. X{
  918. X    static char signame_buf[ 30 ] ;
  919. X
  920. X#if !defined( NO_SIGLIST ) && defined( NSIG )
  921. X    extern char *sys_siglist[] ;
  922. X
  923. X    if ( sig < NSIG )
  924. X        return( strx_sprint( signame_buf, sizeof( signame_buf ),
  925. X                            "%d (%s)", sig, sys_siglist[ sig ] ) ) ;
  926. X#endif
  927. X    return( strx_sprint( signame_buf, sizeof( signame_buf ), "%d", sig ) ) ;
  928. X}
  929. X
  930. X
  931. X/*
  932. X * For SIGSEGV and SIGBUS we invoke the bad_signal() function (if this is 
  933. X * SunOS, we log the address where the problem occured).
  934. X *
  935. X * If we are not running under SunOS, we use the NO_SIGVEC flag to determine 
  936. X * if we have a struct sigcontext (since struct sigcontext is documented in 
  937. X * the sigvec man page).
  938. X *
  939. X * For other signals, we just log the fact that they occured.
  940. X * SIGINT is a special case since in debug.on mode, it will 
  941. X * cause termination.
  942. X */
  943. X
  944. X#ifdef sun
  945. X
  946. XPRIVATE void general_handler( sig, code, scp, addr )
  947. X    int sig, code ;
  948. X    struct sigcontext *scp;
  949. X    char *addr;
  950. X{
  951. X    int pc = scp->sc_pc ;
  952. X
  953. X#else        /* not a Sun */
  954. X
  955. X#ifndef NO_SIGVEC
  956. X
  957. XPRIVATE void general_handler( sig, code, scp )
  958. X    int sig, code ;
  959. X    struct sigcontext *scp;
  960. X{
  961. X    char *addr = NULL ;
  962. X    int pc = scp->sc_pc ;
  963. X
  964. X#else        /* defined( NO_SIGVEC ) */
  965. X
  966. XPRIVATE void general_handler( sig )
  967. X    int sig ;
  968. X{
  969. X    char *addr = NULL ;
  970. X    int pc = 0 ;
  971. X
  972. X#endif    /* ! NO_SIGVEC */
  973. X#endif    /* sun */
  974. X
  975. X    sigset_t badsigs ;
  976. X    char *func = "general_handler" ;
  977. X
  978. X    /*
  979. X     * Do this here to catch problems like SIGSEGV in msg()
  980. X     */
  981. X    sigemptyset( &badsigs ) ;
  982. X    sigaddset( &badsigs, sig ) ;
  983. X    (void) sigprocmask( SIG_UNBLOCK, &badsigs, SIGSET_NULL ) ;
  984. X
  985. X    switch ( sig )
  986. X    {
  987. X        case SIGBUS:
  988. X        case SIGSEGV:
  989. X            msg( LOG_CRIT, func,
  990. X                    "(%d) Unexpected signal: %s, pc = %#x, address = %#x.",
  991. X                        getpid(), sig_name( sig ), pc, addr ) ;
  992. X#if defined( sun ) && defined( sparc )
  993. X            stack_trace( scp ) ;
  994. X#endif
  995. X            bad_signal() ;
  996. X            break ;
  997. X        
  998. X        default:
  999. X            msg( LOG_NOTICE, func, "Unexpected signal %s (addr=%#x)",
  1000. X                        sig_name( sig ), addr ) ;
  1001. X            if ( debug.on && sig == SIGINT )
  1002. X                exit( 1 ) ;
  1003. X    }
  1004. X}
  1005. X
  1006. X
  1007. X/*
  1008. X * The job of this function is to set the flag that corresponds to the
  1009. X * received signal. No other action is taken.
  1010. X */
  1011. XPRIVATE void my_handler( sig )
  1012. X    int sig ;
  1013. X{
  1014. X    /*
  1015. X     * Signals are listed most-frequent-first
  1016. X     */
  1017. X    switch( sig )
  1018. X    {
  1019. X        case SERVER_EXIT_SIG:
  1020. X            M_SET( ps.flags, CHILD_FLAG ) ;
  1021. X            break ;
  1022. X        
  1023. X        case RETRY_SIG:
  1024. X            M_SET( ps.flags, RETRY_FLAG ) ;
  1025. X            break ;
  1026. X        
  1027. X        case RECONFIG_SOFT_SIG:
  1028. X            M_SET( ps.flags, SOFT_RECONFIG_FLAG ) ;
  1029. X            break ;
  1030. X        
  1031. X        case RECONFIG_HARD_SIG:
  1032. X            M_SET( ps.flags, HARD_RECONFIG_FLAG ) ;
  1033. X            break ;
  1034. X        
  1035. X        case TERMINATION_SIG:
  1036. X            M_SET( ps.flags, TERMINATE_FLAG ) ;
  1037. X            break ;
  1038. X        
  1039. X        case STATE_DUMP_SIG:
  1040. X            M_SET( ps.flags, DUMP_FLAG ) ;
  1041. X            break ;
  1042. X        
  1043. X        case CONSISTENCY_CHECK_SIG:
  1044. X            M_SET( ps.flags, CONSISTENCY_FLAG ) ;
  1045. X            break ;
  1046. X        
  1047. X        case QUIT_SIG:
  1048. X            M_SET( ps.flags, QUIT_FLAG ) ;
  1049. X            break ;
  1050. X    }
  1051. X}
  1052. X
  1053. X
  1054. X/*
  1055. X * Reset all signals to default action. Reset the signal mask
  1056. X *
  1057. X * This function is invoked from a forked process. That is why we
  1058. X * invoke _exit instead of exit (to avoid the possible stdio buffer flushes)
  1059. X */
  1060. Xvoid signal_default_state()
  1061. X{
  1062. X    register int sig ;
  1063. X    sigset_t empty ;
  1064. X
  1065. X    for ( sig = 1 ; sig < nsig ; sig++ )
  1066. X        if ( sigismember( &reset_sigs, sig ) == 1 )
  1067. X            if ( (int) signal( sig, SIG_DFL ) == -1 )
  1068. X            {
  1069. X                msg( LOG_ERR, "reset_signals",
  1070. X                    "signal(3) failed for signal %s: %m", sig_name( sig ) ) ;
  1071. X                if ( debug.on )
  1072. X                    _exit( 1 ) ;
  1073. X            }
  1074. X        
  1075. X    sigemptyset( &empty ) ;
  1076. X    (void) sigprocmask( SIG_SETMASK, &empty, SIGSET_NULL ) ;
  1077. X}
  1078. X
  1079. X
  1080. END_OF_FILE
  1081. if test 12358 -ne `wc -c <'xinetd/signals.c'`; then
  1082.     echo shar: \"'xinetd/signals.c'\" unpacked with wrong size!
  1083. fi
  1084. # end of 'xinetd/signals.c'
  1085. fi
  1086. echo shar: End of archive 22 \(of 31\).
  1087. cp /dev/null ark22isdone
  1088. MISSING=""
  1089. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ; do
  1090.     if test ! -f ark${I}isdone ; then
  1091.     MISSING="${MISSING} ${I}"
  1092.     fi
  1093. done
  1094. if test "${MISSING}" = "" ; then
  1095.     echo You have unpacked all 31 archives.
  1096.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1097. else
  1098.     echo You still need to unpack the following archives:
  1099.     echo "        " ${MISSING}
  1100. fi
  1101. ##  End of shell archive.
  1102. exit 0
  1103.