r11295: new service hashing code has assumign that the service
[samba.git] / source3 / param / loadparm.c
index 3c97a3bb37dffb1ec4a3e097678c880edea2dad6..6ad1ace755efdc54f6bbd35b7be467e45b71445c 100644 (file)
@@ -73,7 +73,7 @@ extern enum protocol_types Protocol;
 #endif
 
 /* some helpful bits */
-#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
+#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
 
 int keepalive = DEFAULT_KEEPALIVE;
@@ -109,7 +109,6 @@ typedef struct
        char *szPidDir;
        char *szRootdir;
        char *szDefaultService;
-       char *szDfree;
        char *szGetQuota;
        char *szSetQuota;
        char *szMsgCommand;
@@ -122,6 +121,7 @@ typedef struct
        char *szConfigFile;
        char *szSMBPasswdFile;
        char *szPrivateDir;
+        char *szCountersDir;
        char **szPassdbBackend;
        char **szPreloadModules;
        char *szPasswordServer;
@@ -150,6 +150,7 @@ typedef struct
        char *szNameResolveOrder;
        char *szPanicAction;
        char *szAddUserScript;
+        char *szRenameUserScript;
        char *szDelUserScript;
        char *szAddGroupScript;
        char *szDelGroupScript;
@@ -182,12 +183,6 @@ typedef struct
        char *szAddShareCommand;
        char *szChangeShareCommand;
        char *szDeleteShareCommand;
-        char *szEventLogOpenCommand;
-        char *szEventLogReadCommand;
-        char *szEventLogClearCommand;
-        char *szEventLogNumRecordsCommand;
-        char *szEventLogOldestRecordCommand;
-       char *szEventLogCloseCommand;
         char **szEventLogs;
        char *szGuestaccount;
        char *szManglingMethod;
@@ -241,6 +236,7 @@ typedef struct
        char *szLdapAdminDn;
        char *szAclCompat;
        char *szCupsServer;
+       char *szIPrintServer;
        int ldap_passwd_sync; 
        int ldap_replication_sleep;
        int ldap_timeout; /* This is initialised in init_globals */
@@ -361,6 +357,7 @@ typedef struct
        char **szVfsObjects;
        char *szMSDfsProxy;
        char *szAioWriteBehind;
+       char *szDfree;
        int iMinPrintSpace;
        int iMaxPrintJobs;
        int iMaxReportedPrintJobs;
@@ -379,6 +376,7 @@ typedef struct
        int iOplockContentionLimit;
        int iCSCPolicy;
        int iBlock_size;
+       int iDfreeCacheTime;
        BOOL bPreexecClose;
        BOOL bRootpreexecClose;
        int  iCaseSensitive;
@@ -442,6 +440,7 @@ typedef struct
        int iallocation_roundup_size;
        int iAioReadSize;
        int iAioWriteSize;
+       int iMap_readonly;
        param_opt_struct *param_opt;
 
        char dummy[3];          /* for alignment */
@@ -494,6 +493,7 @@ static service sDefault = {
        NULL,                   /* vfs objects */
        NULL,                   /* szMSDfsProxy */
        NULL,                   /* szAioWriteBehind */
+       NULL,                   /* szDfree */
        0,                      /* iMinPrintSpace */
        1000,                   /* iMaxPrintJobs */
        0,                      /* iMaxReportedPrintJobs */
@@ -511,7 +511,8 @@ static service sDefault = {
        DEFAULT_PRINTING,       /* iPrinting */
        2,                      /* iOplockContentionLimit */
        0,                      /* iCSCPolicy */
-       1024,           /* iBlock_size */
+       1024,                   /* iBlock_size */
+       0,                      /* iDfreeCacheTime */
        False,                  /* bPreexecClose */
        False,                  /* bRootpreexecClose */
        Auto,                   /* case sensitive */
@@ -575,6 +576,7 @@ static service sDefault = {
        SMB_ROUNDUP_ALLOCATION_SIZE,            /* iallocation_roundup_size */
        0,                      /* iAioReadSize */
        0,                      /* iAioWriteSize */
+       MAP_READONLY_YES,       /* iMap_readonly */
        
        NULL,                   /* Parametric options */
 
@@ -585,6 +587,9 @@ static service sDefault = {
 static service **ServicePtrs = NULL;
 static int iNumServices = 0;
 static int iServiceIndex = 0;
+static TDB_CONTEXT *ServiceHash;
+static int *invalid_services = NULL;
+static int num_invalid_services = 0;
 static BOOL bInGlobalSection = True;
 static BOOL bGlobalOnly = False;
 static int server_role;
@@ -605,7 +610,6 @@ static BOOL handle_netbios_scope( int snum, const char *pszParmValue, char **ptr
 static BOOL handle_charset( int snum, const char *pszParmValue, char **ptr );
 static BOOL handle_acl_compatibility( int snum, const char *pszParmValue, char **ptr);
 static BOOL handle_printing( int snum, const char *pszParmValue, char **ptr);
-static BOOL handle_eventlog( int snum, const char *pszParmValue, char **ptr);
 
 static void set_server_role(void);
 static void set_default_server_announce_type(void);
@@ -641,6 +645,7 @@ static const struct enum_list enum_printing[] = {
        {PRINT_PLP, "plp"},
        {PRINT_LPRNG, "lprng"},
        {PRINT_CUPS, "cups"},
+       {PRINT_IPRINT, "iprint"},
        {PRINT_LPRNT, "nt"},
        {PRINT_LPROS2, "os2"},
 #ifdef DEVELOPER
@@ -695,6 +700,18 @@ static const struct enum_list enum_announce_as[] = {
        {-1, NULL}
 };
 
+static const struct enum_list enum_map_readonly[] = {
+       {MAP_READONLY_NO, "no"},
+       {MAP_READONLY_NO, "false"},
+       {MAP_READONLY_NO, "0"},
+       {MAP_READONLY_YES, "yes"},
+       {MAP_READONLY_YES, "true"},
+       {MAP_READONLY_YES, "1"},
+       {MAP_READONLY_PERMISSIONS, "permissions"},
+       {MAP_READONLY_PERMISSIONS, "perms"},
+       {-1, NULL}
+};
+
 static const struct enum_list enum_case[] = {
        {CASE_LOWER, "lower"},
        {CASE_UPPER, "upper"},
@@ -831,6 +848,7 @@ static struct parm_struct parm_table[] = {
        {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
        {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, 
        {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, 
+       {"counters dir", P_STRING, P_GLOBAL, &Globals.szCountersDir, NULL, NULL, FLAG_ADVANCED},
        {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
        {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, 
        {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, 
@@ -964,7 +982,7 @@ static struct parm_struct parm_table[] = {
        {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
 
        {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, 
-       {"enable svcctl", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
+       {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
 
        {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
 
@@ -1007,6 +1025,7 @@ static struct parm_struct parm_table[] = {
        {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, handle_printing, enum_printing, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"cups options", P_STRING, P_LOCAL, &sDefault.szCupsOptions, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"cups server", P_STRING, P_GLOBAL, &Globals.szCupsServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
+       {"iprint server", P_STRING, P_GLOBAL, &Globals.szIPrintServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"enable spoolss", P_BOOLREV, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_HIDE}, 
@@ -1047,9 +1066,10 @@ static struct parm_struct parm_table[] = {
        {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
        {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
        {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
-       {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
-       {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
+       {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
+       {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
+       {"map readonly", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED }, 
        {"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED}, 
@@ -1063,6 +1083,7 @@ static struct parm_struct parm_table[] = {
        {N_("Logon Options"), P_SEP, P_SEPARATOR}, 
 
        {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED}, 
+        {"rename user script", P_STRING, P_GLOBAL, &Globals.szRenameUserScript, NULL, NULL, FLAG_ADVANCED},
        {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED}, 
        {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED}, 
        {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED}, 
@@ -1148,11 +1169,6 @@ static struct parm_struct parm_table[] = {
        {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, 
 
        {N_("EventLog Options"), P_SEP, P_SEPARATOR}, 
-       {"eventlog open command", P_STRING, P_GLOBAL, &Globals.szEventLogOpenCommand, handle_eventlog, NULL, FLAG_ADVANCED},
-       {"eventlog read command", P_STRING, P_GLOBAL, &Globals.szEventLogReadCommand, handle_eventlog, NULL, FLAG_ADVANCED}, 
-       {"eventlog clear command", P_STRING, P_GLOBAL, &Globals.szEventLogClearCommand, handle_eventlog, NULL, FLAG_ADVANCED},
-       {"eventlog num records command", P_STRING, P_GLOBAL, &Globals.szEventLogNumRecordsCommand, handle_eventlog, NULL, FLAG_ADVANCED},
-       {"eventlog oldest record command", P_STRING, P_GLOBAL, &Globals.szEventLogOldestRecordCommand, handle_eventlog, NULL, FLAG_ADVANCED},
        {"eventlog list",  P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        
        {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, 
@@ -1170,7 +1186,8 @@ static struct parm_struct parm_table[] = {
        {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
        {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
        {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED}, 
-       {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, FLAG_ADVANCED}, 
+       {"dfree cache time", P_STRING, P_LOCAL, &sDefault.iDfreeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
+       {"dfree command", P_STRING, P_LOCAL, &sDefault.szDfree, NULL, NULL, FLAG_ADVANCED}, 
        {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED}, 
        {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, NULL, NULL, FLAG_ADVANCED}, 
        {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED}, 
@@ -1273,6 +1290,7 @@ static void init_printer_values(service *pService)
                        break;
 
                case PRINT_CUPS:
+               case PRINT_IPRINT:
 #ifdef HAVE_CUPS
                        /* set the lpq command to contain the destination printer
                           name only.  This is used by cups_queue_get() */
@@ -1424,6 +1442,7 @@ static void init_globals(void)
 
        Globals.bLoadPrinters = True;
        Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
+
        /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
        /* Discovered by 2 days of pain by Don McCall @ HP :-). */
        Globals.max_xmit = 0x4104;
@@ -1516,7 +1535,6 @@ static void init_globals(void)
 #else
        Globals.szPassdbBackend = str_list_make("smbpasswd", NULL);
 #endif /* WITH_LDAP_SAMCONFIG */
-
        string_set(&Globals.szLdapSuffix, "");
        string_set(&Globals.szLdapMachineSuffix, "");
        string_set(&Globals.szLdapUserSuffix, "");
@@ -1570,12 +1588,7 @@ static void init_globals(void)
        string_set(&Globals.szWinbindSeparator, "\\");
        string_set(&Globals.szAclCompat, "");
        string_set(&Globals.szCupsServer, "");
-
-       string_set(&Globals.szEventLogOpenCommand, "");
-       string_set(&Globals.szEventLogReadCommand, "");
-       string_set(&Globals.szEventLogClearCommand, "");
-       string_set(&Globals.szEventLogNumRecordsCommand, "");
-       string_set(&Globals.szEventLogOldestRecordCommand, "");
+       string_set(&Globals.szIPrintServer, "");
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
        Globals.bWinbindEnumUsers = True;
@@ -1604,7 +1617,7 @@ static void init_globals(void)
           operations as root */
 
        Globals.bEnablePrivileges = False;
-       
+
        Globals.bASUSupport       = True;
        
        Globals.szServicesList = str_list_make( "Spooler NETLOGON", NULL );
@@ -1698,6 +1711,7 @@ FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
+FN_GLOBAL_STRING(lp_counters_dir, &Globals.szCountersDir)
 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
@@ -1714,7 +1728,6 @@ FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
-FN_GLOBAL_STRING(lp_dfree_command, &Globals.szDfree)
 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
@@ -1744,6 +1757,7 @@ FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
+FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
 
 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
@@ -1793,12 +1807,6 @@ FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
 
-FN_GLOBAL_STRING(lp_eventlog_open_cmd, &Globals.szEventLogOpenCommand)
-FN_GLOBAL_STRING(lp_eventlog_read_cmd, &Globals.szEventLogReadCommand)
-FN_GLOBAL_STRING(lp_eventlog_clear_cmd, &Globals.szEventLogClearCommand)
-FN_GLOBAL_STRING(lp_eventlog_num_records_cmd, &Globals.szEventLogNumRecordsCommand)
-FN_GLOBAL_STRING(lp_eventlog_oldest_record_cmd, &Globals.szEventLogOldestRecordCommand)
-FN_GLOBAL_STRING(lp_eventlog_close_cmd, &Globals.szEventLogCloseCommand)
 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
 
 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
@@ -1899,9 +1907,10 @@ FN_LOCAL_STRING(lp_username, szUsername)
 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
-FN_GLOBAL_LIST(lp_enable_svcctl, &Globals.szServicesList)
+FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
+FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
@@ -1930,6 +1939,7 @@ FN_LOCAL_STRING(lp_hide_files, szHideFiles)
 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
 FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
+FN_LOCAL_STRING(lp_dfree_command, szDfree)
 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
@@ -2004,9 +2014,11 @@ FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
+FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
+FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
 FN_LOCAL_CHAR(lp_magicchar, magic_char)
 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
 FN_GLOBAL_INTEGER(lp_winbind_max_idle_children, &Globals.winbind_max_idle_children)
@@ -2028,6 +2040,9 @@ static BOOL service_ok(int iService);
 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
 static BOOL do_section(const char *pszSectionName);
 static void init_copymap(service * pservice);
+static BOOL hash_a_service(const char *name, int number);
+static void free_service_byindex(int iService);
+static char * canonicalize_servicename(const char *name);
 
 /* This is a helper function for parametrical options support. */
 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
@@ -2320,6 +2335,31 @@ static void free_service(service *pservice)
        ZERO_STRUCTP(pservice);
 }
 
+
+/***************************************************************************
+ remove a service indexed in the ServicePtrs array from the ServiceHash
+ and free the dynamically allocated parts
+***************************************************************************/
+
+static void free_service_byindex(int idx)
+{
+       if ( !LP_SNUM_OK(idx) ) 
+               return;
+
+       ServicePtrs[idx]->valid = False;
+       invalid_services[num_invalid_services++] = idx;
+
+       /* we have to cleanup the hash record */
+
+       if (ServicePtrs[idx]->szService) {
+               char *canon_name = canonicalize_servicename( ServicePtrs[idx]->szService );
+               
+               tdb_delete_bystring(ServiceHash, canon_name );
+       }
+
+       free_service(ServicePtrs[idx]);
+}
+
 /***************************************************************************
  Add a new service to the services array initialising it with the given 
  service. 
@@ -2355,32 +2395,41 @@ static int add_a_service(const service *pservice, const char *name)
        }
 
        /* find an invalid one */
-       for (i = 0; i < iNumServices; i++)
-               if (!ServicePtrs[i]->valid)
-                       break;
+       i = iNumServices;
+       if (num_invalid_services > 0) {
+               i = invalid_services[--num_invalid_services];
+       }
 
        /* if not, then create one */
        if (i == iNumServices) {
                service **tsp;
+               int *tinvalid;
                
                tsp = SMB_REALLOC_ARRAY(ServicePtrs, service *, num_to_alloc);
-                                          
-               if (!tsp) {
+               if (tsp == NULL) {
                        DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
                        return (-1);
                }
-               else {
-                       ServicePtrs = tsp;
-                       ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
-               }
+               ServicePtrs = tsp;
+               ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
                if (!ServicePtrs[iNumServices]) {
                        DEBUG(0,("add_a_service: out of memory!\n"));
                        return (-1);
                }
-
                iNumServices++;
-       } else
-               free_service(ServicePtrs[i]);
+
+               /* enlarge invalid_services here for now... */
+               tinvalid = SMB_REALLOC_ARRAY(invalid_services, int,
+                                            num_to_alloc);
+               if (tinvalid == NULL) {
+                       DEBUG(0,("add_a_service: failed to enlarge "
+                                "invalid_services!\n"));
+                       return (-1);
+               }
+               invalid_services = tinvalid;
+       } else {
+               free_service_byindex(i);
+       }
 
        ServicePtrs[i]->valid = True;
 
@@ -2391,10 +2440,76 @@ static int add_a_service(const service *pservice, const char *name)
                
        DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
                i, ServicePtrs[i]->szService));
+
+       if (!hash_a_service(ServicePtrs[i]->szService, i)) {
+               return (-1);
+       }
                
        return (i);
 }
 
+/***************************************************************************
+  Convert a string to uppercase and remove whitespaces.
+***************************************************************************/
+
+static char *canonicalize_servicename(const char *src)
+{
+       static fstring canon; /* is fstring large enough? */
+       int dst_idx = 0;
+
+       if ( !src ) {
+               DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
+               return NULL;
+       }
+
+       fstrcpy( canon, src );
+       strupper_m( canon );
+
+#if 0 
+       for (; *src != '\0'; src += next_mb_char_size(src)) {
+               if (isspace(*src)) {
+                       continue;
+               }
+               if (dst_idx == sizeof(canon) - 1) {
+                       return NULL;
+               }
+               canon[dst_idx++] = toupper(*src);
+       }
+       canon[dst_idx] = '\0';
+#endif
+
+       return canon;
+}
+
+/***************************************************************************
+  Add a name/index pair for the services array to the hash table.
+***************************************************************************/
+
+static BOOL hash_a_service(const char *name, int idx)
+{
+       char *canon_name;
+
+       if ( !ServiceHash ) {
+               DEBUG(10,("hash_a_service: creating tdb servicehash\n"));
+               ServiceHash = tdb_open("servicehash", 1031, TDB_INTERNAL, 
+                                        (O_RDWR|O_CREAT), 0600);
+               if ( !ServiceHash ) {
+                       DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
+                       return False;
+               }
+       }
+
+       DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
+               idx, name));
+
+       if ( !(canon_name = canonicalize_servicename( name )) )
+               return False;
+
+        tdb_store_int32(ServiceHash, canon_name, idx);
+
+       return True;
+}
+
 /***************************************************************************
  Add a new home service, with the specified home directory, defaults coming 
  from service ifrom.
@@ -2627,15 +2742,23 @@ Find a service by name. Otherwise works like get_service.
 
 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
 {
-       int iService;
+       int iService = -1;
+       char *canon_name;
+
+       if (ServiceHash != NULL) {
+               if ( !(canon_name = canonicalize_servicename( pszServiceName )) )
+                       return -1;
+
+               iService = tdb_fetch_int32(ServiceHash, canon_name );
 
-       for (iService = iNumServices - 1; iService >= 0; iService--)
-               if (VALID(iService) &&
-                   strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
-                       if (pserviceDest != NULL)
+               if (LP_SNUM_OK(iService)) {
+                       if (pserviceDest != NULL) {
                                copy_service(pserviceDest, ServicePtrs[iService], NULL);
-                       break;
+                       }
+               } else {
+                       iService = -1;
                }
+       }
 
        return (iService);
 }
@@ -2892,11 +3015,7 @@ static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr)
        return True;
 }
 
-static BOOL handle_eventlog(int snum, const char *pszParmValue, char **ptr)
-{
-       string_set(ptr, pszParmValue);
-       return True;
-}
+
 
 static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr)
 {
@@ -3338,7 +3457,10 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                        break;
 
                case P_OCTAL:
-                       sscanf(pszParmValue, "%o", (int *)parm_ptr);
+                       i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
+                       if ( i != 1 ) {
+                           DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
+                       }
                        break;
 
                case P_LIST:
@@ -3692,13 +3814,13 @@ static void dump_a_service(service * pService, FILE * f)
                }
        }
 
-       if (pService->param_opt != NULL) {
-               data = pService->param_opt;
-               while(data) {
-                       fprintf(f, "\t%s = %s\n", data->key, data->value);
-                       data = data->next;
-               }
-       }
+               if (pService->param_opt != NULL) {
+                       data = pService->param_opt;
+                       while(data) {
+                               fprintf(f, "\t%s = %s\n", data->key, data->value);
+                               data = data->next;
+                       }
+               }
 }
 
 /***************************************************************************
@@ -3908,8 +4030,7 @@ void lp_killunused(BOOL (*snumused) (int))
                        continue;
 
                if (!snumused || !snumused(i)) {
-                       ServicePtrs[i]->valid = False;
-                       free_service(ServicePtrs[i]);
+                       free_service_byindex(i);
                }
        }
 }
@@ -3921,8 +4042,7 @@ void lp_killunused(BOOL (*snumused) (int))
 void lp_killservice(int iServiceIn)
 {
        if (VALID(iServiceIn)) {
-               ServicePtrs[iServiceIn]->valid = False;
-               free_service(ServicePtrs[iServiceIn]);
+               free_service_byindex(iServiceIn);
        }
 }
 
@@ -4122,7 +4242,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
                   are denied */
                lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
                if ( lp_enable_asu_support() )
-               lp_add_ipc("ADMIN$", False);
+                       lp_add_ipc("ADMIN$", False);
        }
 
        set_server_role();
@@ -4338,6 +4458,7 @@ BOOL lp_preferred_master(void)
 void lp_remove_service(int snum)
 {
        ServicePtrs[snum]->valid = False;
+       invalid_services[num_invalid_services++] = snum;
 }
 
 /*******************************************************************