"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/main.c" (8 Jan 2003, 10097 Bytes) of package /linux/misc/old/pidentd-3.0.19.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 "main.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** main.c - Main entrypoint for Pidentd 3.0
    3 **
    4 ** Copyright (c) 1997 Peter Eriksson <pen@lysator.liu.se>
    5 **
    6 ** This program is free software; you can redistribute it and/or
    7 ** modify it as you wish - as long as you don't claim that you wrote
    8 ** it.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   13 */
   14 
   15 #include "config.h"
   16 
   17 #include <stdio.h>
   18 #include <stdlib.h>
   19 #include <string.h>
   20 #include <syslog.h>
   21 #ifdef HAVE_UNISTD_H
   22 #include <unistd.h>
   23 #endif
   24 #include <signal.h>
   25 
   26 #include "pidentd.h"
   27 
   28 #if defined(HAVE_LIBTHREAD) && defined(HAVE_THR_SETCONCURRENCY)
   29 #  include <thread.h>
   30 #endif
   31 
   32 extern char *optarg;
   33 extern int optind;
   34 
   35 char *argv0 = "identd";
   36 
   37 int debug = 0;
   38 uid_t server_uid = NO_UID;
   39 gid_t server_gid = ROOT_GID;
   40 char *pidfile_path = PATH_PIDFILE;
   41 
   42 #ifdef HAVE_LIBDES
   43 int encrypt_flag = 0;
   44 char *encrypt_keyfile = PATH_KEYFILE;
   45 #endif
   46 
   47 pthread_attr_t cattr_detached;
   48 
   49 
   50 static void
   51 usage(FILE *fp)
   52 {
   53     fprintf(fp, "Usage: %s [options]\n", argv0);
   54     fputs("\n", fp);
   55     fputs("Options:\n", fp);
   56     fputs("  -d           Enable debug mode\n", fp);
   57     fputs("  -h           Print this information\n", fp);
   58     fputs("  -V           Print version and OS information\n", fp);
   59     fputs("\n", fp);
   60     fputs("  -w           Start in Inetd 'wait' mode\n", fp);
   61     fputs("  -i           Start in Inetd 'nowait' mode\n", fp);
   62     fputs("  -I           Start in Init mode\n", fp);
   63     fputs("  -b           Start in Standalone mode\n", fp);
   64     fputs("\n", fp);
   65     fputs("  -e           Enable protocol extensions\n", fp);
   66     fputs("  -m           Enable multiquery mode\n", fp);
   67 #ifdef HAVE_LIBDES
   68     fputs("  -E           Enable DES encrypted replies\n", fp);
   69 #endif
   70     fputs("  -n           Send uid numbers instead of usernames\n", fp);
   71     fputs("  -o           Return OTHER instead of UNIX\n", fp);
   72     fputs("  -N           Check for .noident files\n", fp);
   73     fputs("\n", fp);
   74     fputs("  -l           Log a message to syslog at startup\n", fp);
   75     fputs("  -t<time>     Request timeout limit in seconds\n", fp);
   76     fputs("  -p<port>     Port to listen for connections on\n", fp);
   77     fputs("  -g<group>    Group name/number to run as\n", fp);
   78     fputs("  -u<user>     User name/number to run as\n", fp);
   79     fputs("  -C<file>     Config file to include\n", fp);
   80     fputs("  -P<file>     Where to write the process id number\n", fp);
   81     fputs("  -K<threads>  Number of kernel lookup threads\n", fp);
   82 }
   83 
   84 
   85 static void
   86 program_header(FILE *fp)
   87 {
   88     fprintf(fp, "[Pidentd, version %s (compiled for %s) - %s %s]\n",
   89         server_version, osinfo_build,
   90         __DATE__, __TIME__);
   91 }
   92 
   93 void
   94 drop_root_privs(void)
   95 {
   96     if (geteuid() != ROOT_UID)
   97     return;
   98     
   99     if (server_uid == NO_UID)
  100     {
  101     if (str2uid("nobody", &server_uid, &server_gid) < 0)
  102         server_uid = ROOT_UID;
  103     }
  104     
  105     if (setgroups(1, &server_gid) < 0)
  106     goto Error;
  107     
  108     if (server_gid != ROOT_GID)
  109     if (setgid(server_gid) < 0)
  110         goto Error;
  111     
  112     if (server_uid != ROOT_UID)
  113     if (setuid(server_uid) < 0)
  114         goto Error;
  115 
  116     return;
  117   Error:
  118     syslog(LOG_ERR, "Error while changing user/group privileges");
  119     exit(EXIT_FAILURE);
  120 }    
  121 
  122 int
  123 main(int argc, char *argv[])
  124 {
  125     int c;
  126 #ifdef LOG_DAEMON
  127     int code = LOG_DAEMON;
  128 #else
  129     int code = 0;
  130 #endif
  131     int socket_type = -1;
  132     int init_mode = 0;
  133     int log_header = 0;
  134     
  135 
  136     if (argv[0] != NULL)
  137     {
  138     char *cp;
  139     
  140     cp = strrchr(argv[0], '/');
  141     if (cp != NULL)
  142         argv0 = s_strdup(cp+1);
  143     else
  144         argv0 = s_strdup(argv[0]);
  145     }
  146     
  147 #ifdef SIGTTOU    
  148     signal(SIGTTOU, SIG_IGN);
  149 #endif
  150     signal(SIGPIPE, SIG_IGN);
  151     
  152     s_openlog(argv0, LOG_PID|LOG_ODELAY, code);
  153 
  154     
  155     /*
  156     ** Try to autodetect how we was started.
  157     */
  158     socket_type = socktype(STDIN_FILENO);
  159     
  160     if (debug)
  161     fprintf(stderr, "socktype = %d\n", socket_type);
  162 
  163     if (socket_type == SOCKTYPE_LISTEN || socket_type == SOCKTYPE_CONNECTED)
  164     listen_sock = STDIN_FILENO;
  165     
  166     conf_parse(PATH_CFGFILE, 1);
  167 
  168     
  169     while ((c = getopt(argc, argv, "lNVEdhbwiIemnop:u:g:t:C:P:K:L:")) != -1)
  170     switch (c)
  171     {
  172 #ifdef HAVE_LIBDES
  173       case 'E':
  174         encrypt_flag = 1;
  175         break;
  176 #endif
  177         
  178       case 'n':
  179         uidonly_flag = 1;
  180         break;
  181         
  182       case 'd':
  183         debug++;
  184         break;
  185         
  186       case 'h':
  187         usage(stdout);
  188         return EXIT_SUCCESS;
  189         
  190       case 'e':
  191         extensions_enabled = 1;
  192         break;
  193         
  194       case 'm':
  195         multiquery_enabled = 1;
  196         break;
  197         
  198       case 'w':
  199         listen_sock = STDIN_FILENO;
  200         socket_type = SOCKTYPE_LISTEN;
  201         break;
  202         
  203       case 'i':
  204         listen_sock = STDIN_FILENO;
  205         socket_type = SOCKTYPE_CONNECTED;
  206         break;
  207         
  208       case 'I':
  209         listen_sock = -1;
  210         socket_type = SOCKTYPE_NOTSOCKET;
  211         init_mode = 1;
  212         break;
  213         
  214       case 'b':
  215         listen_sock = -1;
  216         socket_type = SOCKTYPE_NOTSOCKET;
  217         break;
  218 
  219       case 'l':
  220         log_header = 1;
  221         break;
  222         
  223       case 'p':
  224         if (str2port(optarg, &listen_port) < 0)
  225         {
  226         syslog(LOG_ERR, "invalid argument to '-p': %s", optarg);
  227         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  228             fprintf(stderr, "%s: invalid argument to '-p': %s",
  229                 argv0, optarg);
  230         return EXIT_FAILURE;
  231         }
  232         break;
  233 
  234       case 't':
  235         if (str2int(optarg, &request_timeout) < 0)
  236         {
  237         syslog(LOG_ERR, "invalid argument to '-t': %s", optarg);
  238         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  239             fprintf(stderr, "%s: invalid argument to '-t': %s",
  240                 argv0, optarg);
  241         return EXIT_FAILURE;
  242         }
  243         break;
  244         
  245       case 'g':
  246         if (str2gid(optarg, &server_gid) < 0)
  247         {
  248         syslog(LOG_ERR, "invalid argument to '-g': %s", optarg);
  249         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  250             fprintf(stderr, "%s: invalid argument to '-g': %s",
  251                 argv0, optarg);
  252         return EXIT_FAILURE;
  253         }
  254         break;
  255         
  256       case 'u':
  257         if (str2uid(optarg, &server_uid, &server_gid) < 0)
  258         {
  259         syslog(LOG_ERR, "invalid argument to '-u': %s", optarg);
  260         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  261             fprintf(stderr, "%s: invalid argument to '-u': %s",
  262                 argv0, optarg);
  263         return EXIT_FAILURE;
  264         }
  265         break;
  266 
  267       case 'L':
  268         code = syslog_str2fac(optarg);
  269         if (code < 0)
  270         {
  271         syslog(LOG_ERR, "invalid argument to '-L': %s", optarg);
  272         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  273             fprintf(stderr, "%s: invalid argument to '-L': %s",
  274                 argv0, optarg);
  275         return EXIT_FAILURE;
  276         }
  277         closelog();
  278         s_openlog(argv0, LOG_PID|LOG_ODELAY, code);
  279         break;
  280         
  281       case 'C':
  282         if (conf_parse(optarg, 0) < 0)
  283         {
  284         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  285             fprintf(stderr, "%s: error parsing config file: %s\n",
  286                 argv[0], optarg);
  287         return EXIT_FAILURE;
  288         }
  289         break;
  290         
  291       case 'P':
  292         pidfile_path = s_strdup(optarg);
  293         break;
  294 
  295       case 'K':
  296         if (str2int(optarg, &kernel_threads) < 0)
  297         {
  298         syslog(LOG_ERR, "invalid argument to '-K': %s", optarg);
  299         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  300             fprintf(stderr, "%s: invalid argument to '-K': %s",
  301                 argv0, optarg);
  302         return EXIT_FAILURE;
  303         }
  304         break;
  305 
  306       case 'o':
  307         opsys = "OTHER";
  308         break;
  309 
  310       case 'N':
  311         noident_flag = 1;
  312         break;
  313 
  314       case 'V':
  315         program_header(stdout);
  316         exit(EXIT_SUCCESS);
  317         
  318       default:
  319         if (socket_type == -1 || socket_type == SOCKTYPE_NOTSOCKET)
  320         usage(stderr);
  321         else
  322         syslog(LOG_ERR, "invalid command line option: %s",
  323                argv[optind]);
  324         
  325         return EXIT_FAILURE;
  326     }
  327 
  328     if (debug)
  329     program_header(stderr);
  330 
  331     if (socket_type == -1)
  332     {
  333     syslog(LOG_ERR, "unable to autodetect socket type");
  334     fprintf(stderr, "%s: unable to autodetect socket type\n",
  335         argv0);
  336     return EXIT_FAILURE;
  337     }
  338     
  339     if (ka_init())
  340     {
  341     syslog(LOG_ERR, "OS version mismatch - compiled for %s", osinfo_build);
  342     if (socket_type == SOCKTYPE_NOTSOCKET)
  343         fprintf(stderr,
  344             "%s: OS version mismatch - compiled for: %s\n",
  345             argv[0], osinfo_build);
  346     return EXIT_FAILURE;
  347     }
  348 
  349     
  350     if (!debug && 
  351     getppid() != INIT_PID && !init_mode &&
  352     socket_type != SOCKTYPE_CONNECTED &&
  353     listen_sock < 0)
  354     {
  355     become_daemon();
  356     }
  357 
  358 #ifdef HAVE_THR_SETCONCURRENCY
  359 #if 1
  360     thr_setconcurrency(kernel_threads+8);
  361 #else
  362     thr_setconcurrency(sysconf(_SC_NPROCESSORS_ONLN));
  363 #endif
  364 #endif
  365 
  366     if (log_header)
  367     syslog(LOG_INFO, "started");
  368     else
  369     syslog(LOG_DEBUG, "started");
  370 
  371 
  372     pthread_attr_init(&cattr_detached);
  373     pthread_attr_setdetachstate(&cattr_detached, PTHREAD_CREATE_DETACHED);
  374     
  375     
  376     if (socket_type != SOCKTYPE_CONNECTED)
  377     {
  378     if (!debug && pidfile_path != NULL)
  379         pidfile_create(pidfile_path);
  380     
  381     if (server_init() < 0)
  382     {
  383         if (debug)
  384         fprintf(stderr, "%s: failed binding to the TCP/IP socket\n",
  385             argv[0]);
  386         goto Exit;
  387     }
  388     }
  389 
  390 #ifdef HAVE_LIBDES
  391     if (encrypt_flag)
  392     {
  393     if (pdes_init(encrypt_keyfile) < 0)
  394     {
  395         syslog(LOG_ERR, "encryption could not be initalized: %m");
  396         if (debug)
  397         {
  398         fprintf(stderr, "%s: encryption could not be initialized: ",
  399             argv[0]);
  400         perror("");
  401         }
  402         goto Exit;
  403     }
  404     }
  405 #endif
  406 
  407 /* Sigh - stupid Linux handles threads like... Anyway, we'll have to
  408    add this kludge to work around the fact that threads in Linux can
  409    have different uid's... Luckily Linux doesn't need root to get at
  410    the needed information anyway. */
  411 #ifdef __linux__
  412     drop_root_privs();
  413 #endif
  414     
  415     if (kernel_init() < 0)
  416     {
  417     if (debug)
  418         fprintf(stderr, "%s: failed opening kernel devices\n",
  419             argv[0]);
  420     goto Exit;
  421     }
  422 
  423 #ifndef __linux__
  424     drop_root_privs();
  425 #endif
  426     
  427     timeout_init();
  428     request_init();
  429     
  430     if (socket_type != SOCKTYPE_CONNECTED)
  431     {
  432     if (debug)
  433         fprintf(stderr, "entering server main loop\n");
  434     
  435     server_run();
  436     }
  437     else
  438     return request_run(listen_sock, 1);
  439 
  440   Exit:
  441     syslog(LOG_DEBUG, "terminating");
  442     return EXIT_FAILURE;
  443 }