This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[jra/samba/.git] / source3 / nmbd / nmbd.c
index 051991f46de7d2277d8e36aec0b01d7f5bb8e28b..2b7d8033a2a8a7e8300fadd78b4cf066419e4dc9 100644 (file)
@@ -3,6 +3,7 @@
    NBT netbios routines and daemon - version 2
    Copyright (C) Andrew Tridgell 1994-1998
    Copyright (C) Jeremy Allison 1997-2002
+   Copyright (C) Jelmer Vernooij 2002 (Conversion to popt)
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,15 +27,17 @@ int ClientNMB       = -1;
 int ClientDGRAM     = -1;
 int global_nmb_port = -1;
 
-extern pstring global_myname;
-extern fstring global_myworkgroup;
-extern char **my_netbios_names;
-
 extern BOOL global_in_nmbd;
 
 /* are we running as a daemon ? */
 static BOOL is_daemon = False;
 
+/* fork or run in foreground ? */
+static BOOL Fork = True;
+
+/* log to standard output ? */
+static BOOL log_stdout = False;
+
 /* have we found LanMan clients yet? */
 BOOL found_lm_clients = False;
 
@@ -53,8 +56,8 @@ static void terminate(void)
        /* Write out wins.dat file if samba is a WINS server */
        wins_write_database(False);
   
-       /* Remove all SELF registered names. */
-       release_my_names();
+       /* Remove all SELF registered names from WINS */
+       release_wins_names();
   
        /* Announce all server entries as 0 time-to-live, 0 type. */
        announce_my_servers_removed();
@@ -78,7 +81,7 @@ static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len)
  Catch a SIGTERM signal.
  **************************************************************************** */
 
-static VOLATILE sig_atomic_t got_sig_term;
+static SIG_ATOMIC_T got_sig_term;
 
 static void sig_term(int sig)
 {
@@ -90,7 +93,7 @@ static void sig_term(int sig)
  Catch a SIGHUP signal.
  **************************************************************************** */
 
-static VOLATILE sig_atomic_t reload_after_sighup;
+static SIG_ATOMIC_T reload_after_sighup;
 
 static void sig_hup(int sig)
 {
@@ -98,6 +101,25 @@ static void sig_hup(int sig)
        sys_select_signal();
 }
 
+/*******************************************************************
+ Print out all talloc memory info.
+********************************************************************/
+
+void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len)
+{
+       TALLOC_CTX *ctx = talloc_init("info context");
+       char *info = NULL;
+
+       if (!ctx)
+               return;
+
+       info = talloc_describe_all(ctx);
+       if (info)
+               DEBUG(10,(info));
+       message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1 : 0, True);
+       talloc_destroy(ctx);
+}
+
 #if DUMP_CORE
 /**************************************************************************** **
  Prepare to dump a core file - carefully!
@@ -269,9 +291,8 @@ static BOOL reload_interfaces(time_t t)
 static BOOL reload_nmbd_services(BOOL test)
 {
        BOOL ret;
-       extern fstring remote_machine;
 
-       fstrcpy( remote_machine, "nmbd" );
+       set_remote_machine_name("nmbd");
 
        if ( lp_loaded() ) {
                pstring fname;
@@ -293,15 +314,6 @@ static BOOL reload_nmbd_services(BOOL test)
                reload_nmbd_services( True );
        }
 
-       /* Do a sanity check for a misconfigured nmbd */
-       if( lp_wins_support() && wins_srv_count() ) {
-               if( DEBUGLVL(0) ) {
-                       dbgtext( "ERROR: 'wins support = true' and 'wins server = <server>'\n" );
-                       dbgtext( "are conflicting settings.  nmbd aborting.\n" );
-               }
-               exit(10);
-       }
-
        return(ret);
 }
 
@@ -573,135 +585,31 @@ static BOOL open_sockets(BOOL isdaemon, int port)
        return( True );
 }
 
-/**************************************************************************** **
- Initialise connect, service and file structs.
- **************************************************************************** */
-
-static BOOL init_structs(void)
-{
-  extern fstring local_machine;
-  char *p, **ptr;
-  int namecount;
-  int n;
-  int nodup;
-  char *nbname;
-
-  if (! *global_myname)
-  {
-    fstrcpy( global_myname, myhostname() );
-    p = strchr_m( global_myname, '.' );
-    if (p)
-      *p = 0;
-  }
-  strupper( global_myname );
-
-  /* Add any NETBIOS name aliases. Ensure that the first entry
-     is equal to global_myname.
-   */
-  /* Work out the max number of netbios aliases that we have */
-  ptr = lp_netbios_aliases();
-  namecount = 0;
-  if (ptr)
-    for( ; *ptr; namecount++,ptr++ )
-      ;
-  if ( *global_myname )
-    namecount++;
-
-  /* Allocate space for the netbios aliases */
-  my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
-  if( NULL == my_netbios_names )
-  {
-     DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
-     return( False );
-  }
-  /* Use the global_myname string first */
-  namecount=0;
-  if ( *global_myname )
-    my_netbios_names[namecount++] = global_myname;
-  
-  ptr = lp_netbios_aliases();
-  if (ptr)
-  {
-    while ( *ptr )
-    {
-      nbname = strdup(*ptr);
-      if (nbname == NULL)
-      {
-        DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
-        return False;
-      }
-      strupper( nbname );
-      /* Look for duplicates */
-      nodup=1;
-      for( n=0; n<namecount; n++ )
-      {
-        if( 0 == strcmp( nbname, my_netbios_names[n] ) )
-          nodup=0;
-      }
-      if (nodup)
-        my_netbios_names[namecount++] = nbname;
-      else
-        SAFE_FREE(nbname);
-
-      ptr++;
-    }
-  }
-  
-  /* Terminate name list */
-  my_netbios_names[namecount++] = NULL;
-  
-  fstrcpy( local_machine, global_myname );
-  trim_string( local_machine, " ", " " );
-  p = strchr_m( local_machine, ' ' );
-  if (p)
-    *p = 0;
-  strlower( local_machine );
-
-  DEBUG( 5, ("Netbios name list:-\n") );
-  for( n=0; my_netbios_names[n]; n++ )
-    DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
-
-  return( True );
-}
-
-/**************************************************************************** **
- Usage on the program.
- **************************************************************************** */
-
-static void usage(char *pname)
-{
-
-  printf( "Usage: %s [-DaiohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname );
-  printf( "       [-n name] [-p port] [-s configuration file]\n" );
-  printf( "\t-D                    Become a daemon (default)\n" );
-  printf( "\t-a                    Append to log file (default)\n" );
-  printf( "\t-i                    Run interactive (not a daemon)\n" );
-  printf( "\t-o                    Overwrite log file, don't append\n" );
-  printf( "\t-h                    Print usage\n" );
-  printf( "\t-V                    Print version\n" );
-  printf( "\t-H hosts file         Load a netbios hosts file\n" );
-  printf( "\t-d debuglevel         Set the debuglevel\n" );
-  printf( "\t-l log basename.      Basename for log/debug files\n" );
-  printf( "\t-n netbiosname.       Primary netbios name\n" );
-  printf( "\t-p port               Listen on the specified port\n" );
-  printf( "\t-s configuration file Configuration file name\n" );
-  printf( "\n");
-}
-
-
 /**************************************************************************** **
  main program
  **************************************************************************** */
- int main(int argc,char *argv[])
+ int main(int argc, const char *argv[])
 {
-  int opt;
-  extern char *optarg;
-  extern BOOL  append_log;
-  BOOL opt_interactive = False;
-  pstring logfile;
-
-  append_log = True;  /* Default, override with '-o' option. */
+       static BOOL opt_interactive = False;
+       poptContext pc;
+       struct poptOption long_options[] = {
+       POPT_AUTOHELP
+       {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
+       {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
+       {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
+       {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
+       {"hosts", 'H', POPT_ARG_STRING, dyn_LMHOSTSFILE, 'H', "Load a netbios hosts file"},
+       {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
+       {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
+       {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
+       {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_socket_options },
+       {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version },
+       {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_netbios_name },
+       {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_log_base },
+       { NULL }
+       };
+       int opt;
+       pstring logfile;
 
   global_nmb_port = NMB_PORT;
   global_in_nmbd = True;
@@ -713,13 +621,6 @@ static void usage(char *pname)
   slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
   lp_set_logfile(logfile);
 
-  /* this is for people who can't start the program correctly */
-  while (argc > 1 && (*argv[1] != '-'))
-  {
-    argv++;
-    argc--;
-  }
-
   fault_setup((void (*)(void *))fault_continue );
 
   /* POSIX demands that signals are inherited. If the invoking process has
@@ -740,71 +641,24 @@ static void usage(char *pname)
 #if defined(SIGUSR2)
   BlockSignals(True, SIGUSR2);
 #endif
+  pc = poptGetContext("nmbd", argc, argv, long_options, 0);
+  
+  while((opt = poptGetNextOpt(pc)) != -1)
+    { }
+
+  poptFreeContext(pc);
+
+  if ( opt_interactive ) {
+    Fork = False;
+    log_stdout = True;
+  }
+
+  if ( log_stdout && Fork ) {
+    DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
+    exit(1);
+  }
 
-  while( EOF != 
-         (opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:i" )) )
-    {
-      switch (opt)
-        {
-        case 's':
-          pstrcpy(dyn_CONFIGFILE, optarg);
-          break;          
-        case 'N':
-        case 'B':
-        case 'I':
-        case 'C':
-        case 'G':
-          DEBUG(0,("Obsolete option '%c' used\n",opt));
-          break;
-        case 'i':
-          opt_interactive = True;
-          break;
-        case 'H':
-          pstrcpy(dyn_LMHOSTSFILE, optarg);
-          break;
-        case 'n':
-          pstrcpy(global_myname,optarg);
-          strupper(global_myname);
-          break;
-        case 'l':
-          slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", optarg);
-          lp_set_logfile(logfile);
-          break;
-        case 'a':
-          append_log = True;
-          break;
-        case 'o':
-          append_log = False;
-          break;
-        case 'D':
-          is_daemon = True;
-          break;
-        case 'd':
-          DEBUGLEVEL = atoi(optarg);
-          break;
-        case 'p':
-          global_nmb_port = atoi(optarg);
-          break;
-        case 'h':
-          usage(argv[0]);
-          exit(0);
-          break;
-        case 'V':
-         printf( "Version %s\n", VERSION );
-          exit(0);
-          break;
-        default:
-          if( !is_a_socket(0) )
-          {
-           DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
-            usage(argv[0]);
-            exit(0);
-          }
-          break;
-        }
-    }
-
-  setup_logging( argv[0], opt_interactive );
+  setup_logging( argv[0], log_stdout );
 
   reopen_logs();
 
@@ -814,14 +668,12 @@ static void usage(char *pname)
   if ( !reload_nmbd_services(False) )
     return(-1);
 
-  if(!init_structs())
+  if(!init_names())
     return -1;
 
   reload_nmbd_services( True );
 
-  fstrcpy( global_myworkgroup, lp_workgroup() );
-
-  if (strequal(global_myworkgroup,"*"))
+  if (strequal(lp_workgroup(),"*"))
   {
     DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
     exit(1);
@@ -838,7 +690,7 @@ static void usage(char *pname)
   if (is_daemon && !opt_interactive)
   {
     DEBUG( 2, ( "Becoming a daemon.\n" ) );
-    become_daemon();
+    become_daemon(Fork);
   }
 
 #if HAVE_SETPGID
@@ -853,7 +705,7 @@ static void usage(char *pname)
 #ifndef SYNC_DNS
   /* Setup the async dns. We do it here so it doesn't have all the other
      stuff initialised and thus chewing memory and sockets */
-  if(lp_we_are_a_wins_server()) {
+  if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
          start_async_dns();
   }
 #endif
@@ -867,11 +719,14 @@ static void usage(char *pname)
   message_register(MSG_FORCE_ELECTION, nmbd_message_election);
   message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
   message_register(MSG_SHUTDOWN, nmbd_terminate);
+  message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info);
 
   DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
 
-  if ( !open_sockets( is_daemon, global_nmb_port ) )
+  if ( !open_sockets( is_daemon, global_nmb_port ) ) {
+    kill_async_dns_child();
     return 1;
+  }
 
   /* Determine all the IP addresses we have. */
   load_interfaces();
@@ -880,6 +735,7 @@ static void usage(char *pname)
   if( False == create_subnets() )
   {
     DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
+    kill_async_dns_child();
     exit(1);
   }
 
@@ -891,6 +747,7 @@ static void usage(char *pname)
   if( !initialise_wins() )
   {
     DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
+    kill_async_dns_child();
     exit(1);
   }
 
@@ -905,6 +762,7 @@ static void usage(char *pname)
   if( False == register_my_workgroup_and_names() )
   {
     DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
+    kill_async_dns_child();
     exit(1);
   }
 
@@ -915,5 +773,6 @@ static void usage(char *pname)
 
   if (dbf)
     x_fclose(dbf);
+  kill_async_dns_child();
   return(0);
 }