"Fossies" - the Fresh Open Source Software Archive

Member "ident2-v1.07_FINAL/daemon.c" (22 Jul 2005, 5302 Bytes) of package /linux/privat/old/ident2-v1.07_FINAL.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "daemon.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Ident-2 - an Identity server for UNIX
    3  * Copyright (C) 1998-2001 Michael Bacarella
    4  * Copyright (C) 2003 Netgraft Corporation
    5  *
    6  * This program is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU General Public License
    8  * as published by the Free Software Foundation; either version 2
    9  * of the License, or (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   19  *
   20  * Please view the file README for program information.
   21  *
   22  * ---------------------
   23  *  This file provides the 'daemon' implementation of
   24  *  ident2.
   25  *
   26  *  Daemon waits for connections
   27  *  forks, handles connections, cleans up,
   28  *  dies, etc.
   29  *
   30  *  Module entry point is ``daemon_service''
   31  * ---------------------
   32  */
   33 
   34 #include "ident2.h"
   35 
   36 
   37 static int
   38 _go_daemon (void)
   39 {
   40     switch (fork()) {
   41     case 0:
   42         setsid();
   43         m_register_pid ();
   44         m_reduce_rights ();
   45         return 0;
   46     case -1:
   47         syslog (LOG_ERR, "d_core: error fork(): %s\n", strerror(errno));
   48         return -1;
   49     default:
   50         exit (0);
   51     }
   52 }
   53     
   54     /*
   55      *  remove dead children from the process vector
   56      */
   57 static void
   58 _reap_proc (pid_t *pv, size_t Max_Connections)
   59 {
   60     pid_t *p;
   61     int r, s;
   62 
   63     for (p = pv; p < pv+Max_Connections; p++) {
   64         if (*p == 0)
   65             continue;
   66 
   67         while ((r = waitpid (*p, &s, WNOHANG)) == -1)
   68             if (errno != EINTR) {
   69                 syslog (LOG_NOTICE,
   70                     "warning: waitpid() error: %s",
   71                         strerror (errno));
   72                 break;
   73             }
   74         if (r == 0)
   75             continue;
   76         if (r > 0)
   77             *p = 0;
   78     }
   79 }
   80 
   81 
   82 static void
   83 declient (int s)
   84 {
   85     struct sockaddr sin;
   86     int ss = sizeof (sin);
   87     close (accept (s, (struct sockaddr *)&sin, &ss));
   88 }
   89 
   90                                                     
   91 static void _sig_ign (int s) { return; }
   92 
   93 
   94 static int
   95 _accept_connect (int sv, struct sockaddr_in *sin)
   96 {
   97     size_t sl = sizeof (struct sockaddr_in);
   98     int cl;
   99 
  100     while ((cl = accept(sv, (struct sockaddr *)sin, &sl)) == -1) {
  101         if (errno == EINTR)
  102             continue;
  103         return -1;
  104     }
  105     return cl;
  106 }
  107     
  108     /*
  109      *  will wait for a connection on SV,
  110      *  find a space in the proc table and fork() 
  111      *  child for it. the child will accept() it and
  112      *  process the waiting client.
  113      *  we rely on the delivery of EINTR to interrupt
  114      *  select(), which gives us a chance to test for
  115      *  deceased children.
  116      */
  117 static void
  118 d_core (int sv)
  119 {
  120     struct sigaction sa;
  121     struct sockaddr_in sin;
  122     pid_t   *pv;
  123                 /* become daemon */
  124     if (_go_daemon () == -1) {
  125         syslog (LOG_ERR, "d_core: error fork(): %s\n", strerror(errno));
  126         return;
  127     }
  128             
  129     pv = xmalloc (Max_Connections * sizeof (pid_t)); 
  130     memset (pv, 0, Max_Connections * sizeof(pid_t));
  131      
  132     sa.sa_handler = _sig_ign;
  133     sigemptyset (&sa.sa_mask);
  134     sa.sa_flags = 0;
  135     
  136     if (sigaction (SIGCHLD, &sa, NULL) == -1) {
  137         syslog (LOG_ERR, "error: registering SIGCHLD handler: %s",
  138             strerror (errno));
  139         return;
  140     }
  141     
  142     while (1) {
  143         pid_t *p;       
  144         int cl;
  145         fd_set rfd;
  146         
  147         FD_ZERO(&rfd);
  148         FD_SET(sv, &rfd);
  149         
  150         if (select (sv+1, &rfd, NULL, NULL, NULL) == -1) {
  151             if (errno != EINTR)
  152                 break;
  153             _reap_proc (pv, Max_Connections);
  154             continue;
  155         }
  156         if (!FD_ISSET (sv, &rfd))
  157             continue;
  158 
  159         for (p = pv; p < pv+Max_Connections; p++)
  160             if (*p == 0)
  161                 break;
  162             
  163         if (p == pv+Max_Connections) {
  164             syslog (LOG_INFO, "refusing %s: too many open "
  165                 "connections", inet_ntoa (sin.sin_addr));
  166             declient (sv);
  167         }
  168     
  169         if ((cl = _accept_connect (sv, &sin)) == -1) {
  170             syslog (LOG_NOTICE, "warning: inconsistency error: "
  171                 "select() and accept() disagree: %s",
  172                     strerror (errno));
  173             continue;
  174         }   
  175         
  176         if ((*p = fork()) == -1) {
  177             syslog (LOG_ERR, "warning: couldn't fork(): %s",
  178                 strerror (errno));
  179             *p = 0;
  180         } else if (*p == 0) {
  181             child_service (cl, cl);
  182             close (cl);
  183             exit (0);
  184         }
  185         close (cl); /* close now that it's mapped into the child */
  186     }
  187 }
  188 
  189 
  190 void daemon_service (void)
  191 {
  192     int s;
  193     struct sockaddr_in sin;
  194 
  195     openlog ("ident2", LOG_PID, LOG_DAEMON);
  196         
  197     if ((s = socket (PF_INET, SOCK_STREAM, 0)) == -1) {
  198         syslog (LOG_ERR, "error: socket(): %s", strerror (errno));
  199         return;
  200     }
  201     
  202     sin.sin_family = AF_INET;
  203     sin.sin_port = htons (Ident_Port);
  204     sin.sin_addr.s_addr = INADDR_ANY;
  205 
  206     if (bind (s, (struct sockaddr *)&sin, sizeof (sin)) == -1) {
  207         syslog (LOG_ERR, "error: binding to port %d: bind(): %s",
  208             Ident_Port, strerror (errno));
  209         fprintf (stderr, "error: binding to port %d: bind(): %s\n\n",
  210             Ident_Port, strerror (errno));
  211         return;
  212     }
  213     
  214     if (listen (s, 15) == -1) {
  215         syslog (LOG_ERR, "error: listening to port %d: listen(): %s",
  216                 Ident_Port, strerror (errno));
  217         fprintf (stderr, "error: listening to port %d: listen(): %s\n",
  218                 Ident_Port, strerror (errno));
  219         return;
  220     }
  221 
  222     fclose (stdin);
  223     fclose (stderr);
  224     fclose (stdout);
  225 
  226     syslog (LOG_NOTICE, "identity services started [%s]",
  227             ID_VERSION);
  228     d_core (s);
  229 
  230     syslog (LOG_ERR, "error: identity services terminated on "
  231         "internal error: See last (few) message(s)");
  232 
  233     closelog ();
  234     close (s);
  235     return; 
  236 }