r13513: Changing defaults:
[ira/wip.git] / source3 / param / loadparm.c
index a75a19f85caa4a1b40472a2f5b86f1ba37fd92f6..c1cac6b966866f9c855fc7d7cdee2871ff06b488 100644 (file)
 #include "includes.h"
 
 BOOL in_client = False;                /* Not in the client by default */
+BOOL in_server = False;                /* Not in the server by default */
 BOOL bLoaded = False;
 
 extern userdom_struct current_user_info;
 extern pstring user_socket_options;
+extern enum protocol_types Protocol;
 
 #ifndef GLOBAL_NAME
 #define GLOBAL_NAME "global"
@@ -72,8 +74,11 @@ extern pstring user_socket_options;
 #endif
 
 /* some helpful bits */
-#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
-#define VALID(i) 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)
+
+#define USERSHARE_VALID 1
+#define USERSHARE_PENDING_DELETE 2
 
 int keepalive = DEFAULT_KEEPALIVE;
 BOOL use_getwd_cache = True;
@@ -93,8 +98,7 @@ struct _param_opt_struct {
 /* 
  * This structure describes global (ie., server-wide) parameters.
  */
-typedef struct
-{
+typedef struct {
        char *smb_ports;
        char *dos_charset;
        char *unix_charset;
@@ -108,7 +112,6 @@ typedef struct
        char *szPidDir;
        char *szRootdir;
        char *szDefaultService;
-       char *szDfree;
        char *szGetQuota;
        char *szSetQuota;
        char *szMsgCommand;
@@ -121,7 +124,7 @@ typedef struct
        char *szConfigFile;
        char *szSMBPasswdFile;
        char *szPrivateDir;
-       char **szPassdbBackend;
+       char *szPassdbBackend;
        char **szPreloadModules;
        char *szPasswordServer;
        char *szSocketOptions;
@@ -145,10 +148,10 @@ typedef struct
        char *szNetbiosName;
        char **szNetbiosAliases;
        char *szNetbiosScope;
-       char *szDomainOtherSIDs;
        char *szNameResolveOrder;
        char *szPanicAction;
        char *szAddUserScript;
+        char *szRenameUserScript;
        char *szDelUserScript;
        char *szAddGroupScript;
        char *szDelGroupScript;
@@ -158,6 +161,7 @@ typedef struct
        char *szAddMachineScript;
        char *szShutdownScript;
        char *szAbortShutdownScript;
+       char *szUsernameMapScript;
        char *szCheckPasswordScript;
        char *szWINSHook;
        char *szWINSPartners;
@@ -166,25 +170,30 @@ typedef struct
        BOOL bUtmp;
        char *szIdmapUID;
        char *szIdmapGID;
-       BOOL bEnableRidAlgorithm;
+       BOOL bPassdbExpandExplicit;
        int AlgorithmicRidBase;
-       char *szTemplatePrimaryGroup;
        char *szTemplateHomedir;
        char *szTemplateShell;
        char *szWinbindSeparator;
-       BOOL bWinbindEnableLocalAccounts;
        BOOL bWinbindEnumUsers;
        BOOL bWinbindEnumGroups;
        BOOL bWinbindUseDefaultDomain;
        BOOL bWinbindTrustedDomainsOnly;
        BOOL bWinbindNestedGroups;
-       char *szWinbindBackend;
+       BOOL bWinbindRefreshTickets;
+       BOOL bWinbindOfflineLogon;
        char **szIdmapBackend;
        char *szAddShareCommand;
        char *szChangeShareCommand;
        char *szDeleteShareCommand;
+        char **szEventLogs;
        char *szGuestaccount;
        char *szManglingMethod;
+       char **szServicesList;
+       char *szUsersharePath;
+       char *szUsershareTemplateShare;
+       char **szUsersharePrefixAllowList;
+       char **szUsersharePrefixDenyList;
        int mangle_prefix;
        int max_log_size;
        char *szLogLevel;
@@ -215,9 +224,10 @@ typedef struct
        int machine_password_timeout;
        int change_notify_timeout;
        int map_to_guest;
-       int min_passwd_length;
        int oplock_break_wait_time;
        int winbind_cache_time;
+       int winbind_max_idle_children;
+       char **szWinbindNssInfo;
        int iLockSpinCount;
        int iLockSpinTime;
        char *szLdapMachineSuffix;
@@ -230,13 +240,14 @@ typedef struct
 #endif
        int ldap_ssl;
        char *szLdapSuffix;
-       char *szLdapFilter;
        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 */
+       int ldap_page_size;
        BOOL ldap_delete_dn;
        BOOL bMsAddPrinterWizard;
        BOOL bDNSproxy;
@@ -272,6 +283,7 @@ typedef struct
        BOOL bNTPipeSupport;
        BOOL bNTStatusSupport;
        BOOL bStatCache;
+       int iMaxStatCacheSize;
        BOOL bKernelOplocks;
        BOOL bAllowTrustedDomains;
        BOOL bLanmanAuth;
@@ -290,26 +302,32 @@ typedef struct
        BOOL bUnixExtensions;
        BOOL bDisableNetbios;
        BOOL bKernelChangeNotify;
+       BOOL bFamChangeNotify;
        BOOL bUseKerberosKeytab;
        BOOL bDeferSharingViolations;
        BOOL bEnablePrivileges;
+       BOOL bASUSupport;
+       BOOL bUsershareOwnerOnly;
        int restrict_anonymous;
        int name_cache_timeout;
        int client_signing;
        int server_signing;
+       int iUsershareMaxShares;
+
+       BOOL bResetOnZeroVC;
        param_opt_struct *param_opt;
-}
-global;
+} global;
 
 static global Globals;
 
 /* 
  * This structure describes a single service. 
  */
-typedef struct
-{
+typedef struct {
        BOOL valid;
        BOOL autoloaded;
+       int usershare;
+       time_t usershare_last_mod;
        char *szService;
        char *szPath;
        char *szUsername;
@@ -350,6 +368,8 @@ typedef struct
        char *fstype;
        char **szVfsObjects;
        char *szMSDfsProxy;
+       char *szAioWriteBehind;
+       char *szDfree;
        int iMinPrintSpace;
        int iMaxPrintJobs;
        int iMaxReportedPrintJobs;
@@ -368,6 +388,7 @@ typedef struct
        int iOplockContentionLimit;
        int iCSCPolicy;
        int iBlock_size;
+       int iDfreeCacheTime;
        BOOL bPreexecClose;
        BOOL bRootpreexecClose;
        int  iCaseSensitive;
@@ -425,18 +446,25 @@ typedef struct
        BOOL bMap_acl_inherit;
        BOOL bAfs_Share;
        BOOL bEASupport;
+       BOOL bAclCheckPermissions;
+       BOOL bAclMapFullControl;
+       BOOL bAclGroupControl;
        int iallocation_roundup_size;
+       int iAioReadSize;
+       int iAioWriteSize;
+       int iMap_readonly;
        param_opt_struct *param_opt;
 
        char dummy[3];          /* for alignment */
-}
-service;
+} service;
 
 
 /* This is a default service used to prime a services structure */
 static service sDefault = {
        True,                   /* valid */
        False,                  /* not autoloaded */
+       0,                      /* not a usershare */
+       (time_t)0,              /* No last mod time */
        NULL,                   /* szService */
        NULL,                   /* szPath */
        NULL,                   /* szUsername */
@@ -477,6 +505,8 @@ static service sDefault = {
        NULL,                   /* fstype */
        NULL,                   /* vfs objects */
        NULL,                   /* szMSDfsProxy */
+       NULL,                   /* szAioWriteBehind */
+       NULL,                   /* szDfree */
        0,                      /* iMinPrintSpace */
        1000,                   /* iMaxPrintJobs */
        0,                      /* iMaxReportedPrintJobs */
@@ -494,7 +524,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 */
@@ -534,7 +565,7 @@ static service sDefault = {
        False,                  /* bFakeOplocks */
        False,                  /* bDeleteVetoFiles */
        False,                  /* bDosFilemode */
-       False,                  /* bDosFiletimes */
+       True,                   /* bDosFiletimes */
        False,                  /* bDosFiletimeResolution */
        False,                  /* bFakeDirCreateTimes */
        True,                   /* bBlockingLocks */
@@ -552,7 +583,13 @@ static service sDefault = {
        False,                  /* bMap_acl_inherit */
        False,                  /* bAfs_Share */
        False,                  /* bEASupport */
+       True,                   /* bAclCheckPermissions */
+       True,                   /* bAclMapFullControl */
+       False,                  /* bAclGroupControl */
        SMB_ROUNDUP_ALLOCATION_SIZE,            /* iallocation_roundup_size */
+       0,                      /* iAioReadSize */
+       0,                      /* iAioWriteSize */
+       MAP_READONLY_YES,       /* iMap_readonly */
        
        NULL,                   /* Parametric options */
 
@@ -563,6 +600,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;
@@ -618,6 +658,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
@@ -672,6 +713,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"},
@@ -750,6 +803,7 @@ static const struct enum_list enum_map_to_guest[] = {
        {NEVER_MAP_TO_GUEST, "Never"},
        {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
        {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
+        {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
        {-1, NULL}
 };
 
@@ -801,15 +855,13 @@ static struct parm_struct parm_table[] = {
        {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
        {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED}, 
        {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED}, 
-       {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_DEPRECATED}, 
-       {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_DEPRECATED}, 
        {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, 
        {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, 
        {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, 
        {"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}, 
-       {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
+       {"passdb backend", P_STRING, 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}, 
        {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
@@ -843,7 +895,7 @@ static struct parm_struct parm_table[] = {
        {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
-       {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT}, 
+       {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED }, 
        {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED}, 
@@ -853,6 +905,9 @@ static struct parm_struct parm_table[] = {
        {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
        {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
 
+       {"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
+       {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
+       {"acl map full control", P_BOOL, P_LOCAL, &sDefault.bAclMapFullControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
        {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, 
        {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
@@ -899,6 +954,9 @@ static struct parm_struct parm_table[] = {
        {N_("Protocol Options"), P_SEP, P_SEPARATOR}, 
 
        {"allocation roundup size", P_INTEGER, P_LOCAL, &sDefault.iallocation_roundup_size, NULL, NULL, FLAG_ADVANCED}, 
+       {"aio read size", P_INTEGER, P_LOCAL, &sDefault.iAioReadSize, NULL, NULL, FLAG_ADVANCED}, 
+       {"aio write size", P_INTEGER, P_LOCAL, &sDefault.iAioWriteSize, NULL, NULL, FLAG_ADVANCED}, 
+       {"aio write behind", P_STRING, P_LOCAL, &sDefault.szAioWriteBehind, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
        {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED}, 
        {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED}, 
        {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
@@ -908,9 +966,10 @@ static struct parm_struct parm_table[] = {
        {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED}, 
        {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED}, 
        {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, 
+       {"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED}, 
 
        {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility,  NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
-       { "defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
+       {"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
        {"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
        {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED}, 
@@ -935,6 +994,9 @@ static struct parm_struct parm_table[] = {
        {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
        {"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}, 
+       {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
+
        {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
 
        {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
@@ -943,6 +1005,7 @@ static struct parm_struct parm_table[] = {
        {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED}, 
        {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED}, 
        {"kernel change notify", P_BOOL, P_GLOBAL, &Globals.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED}, 
+       {"fam change notify", P_BOOL, P_GLOBAL, &Globals.bFamChangeNotify, NULL, NULL, FLAG_ADVANCED},
 
        {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED}, 
        {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED}, 
@@ -976,8 +1039,10 @@ 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}, 
        {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
        {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
@@ -1015,11 +1080,13 @@ 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}, 
        {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, 
        {"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
 
@@ -1030,6 +1097,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}, 
@@ -1039,6 +1107,7 @@ static struct parm_struct parm_table[] = {
        {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED}, 
        {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
        {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
+       {"username map script", P_STRING, P_GLOBAL, &Globals.szUsernameMapScript, NULL, NULL, FLAG_ADVANCED}, 
 
        {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED}, 
        {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED}, 
@@ -1096,7 +1165,6 @@ static struct parm_struct parm_table[] = {
 #endif
        {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, 
-       {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED}, 
@@ -1106,6 +1174,7 @@ static struct parm_struct parm_table[] = {
        {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED}, 
        {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, 
        {"ldap timeout", P_INTEGER, P_GLOBAL, &Globals.ldap_timeout, NULL, NULL, FLAG_ADVANCED},
+       {"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED},
        {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, 
 
        {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR}, 
@@ -1113,6 +1182,9 @@ static struct parm_struct parm_table[] = {
        {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, 
        {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, 
 
+       {N_("EventLog Options"), P_SEP, P_SEPARATOR}, 
+       {"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}, 
        {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
        {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
@@ -1128,7 +1200,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_INTEGER, 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}, 
@@ -1153,6 +1226,12 @@ static struct parm_struct parm_table[] = {
        {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
        {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
+       {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
+       {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED}, 
+       {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
+       {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED}, 
+       {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED}, 
+       {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
        {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE }, 
        {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
@@ -1181,23 +1260,25 @@ static struct parm_struct parm_table[] = {
 
        {N_("Winbind options"), P_SEP, P_SEPARATOR}, 
 
-       {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED}, 
+       {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
        {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, 
        {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, 
        {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE}, 
        {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, 
        {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE}, 
-       {"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, NULL, FLAG_ADVANCED}, 
        {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
        {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED}, 
-       {"winbind enable local accounts", P_BOOL, P_GLOBAL, &Globals.bWinbindEnableLocalAccounts, NULL, NULL, FLAG_ADVANCED|FLAG_DEPRECATED}, 
        {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED}, 
+       {"winbind max idle children", P_INTEGER, P_GLOBAL, &Globals.winbind_max_idle_children, NULL, NULL, FLAG_ADVANCED}, 
+       {"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED}, 
+       {"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED}, 
+       {"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
 
        {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
 };
@@ -1231,6 +1312,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() */
@@ -1242,13 +1324,13 @@ static void init_printer_values(service *pService)
                        string_set(&pService->szQueuepausecommand, "");
                        string_set(&pService->szQueueresumecommand, "");
 #else
-                       string_set(&pService->szLpqcommand, "/usr/bin/lpq -P'%p'");
-                       string_set(&pService->szLprmcommand, "/usr/bin/lprm -P'%p' %j");
-                       string_set(&pService->szPrintcommand, "/usr/bin/lpr -P'%p' %s; rm %s");
+                       string_set(&pService->szLpqcommand, "lpq -P'%p'");
+                       string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
+                       string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
                        string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
                        string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
-                       string_set(&pService->szQueuepausecommand, "/usr/bin/disable '%p'");
-                       string_set(&pService->szQueueresumecommand, "/usr/bin/enable '%p'");
+                       string_set(&pService->szQueuepausecommand, "disable '%p'");
+                       string_set(&pService->szQueueresumecommand, "enable '%p'");
 #endif /* HAVE_CUPS */
                        break;
 
@@ -1291,11 +1373,17 @@ static void init_printer_values(service *pService)
  Initialise the global parameter structure.
 ***************************************************************************/
 
-static void init_globals(void)
+static void init_globals(BOOL first_time_only)
 {
        static BOOL done_init = False;
        pstring s;
 
+        /* If requested to initialize only once and we've already done it... */
+        if (first_time_only && done_init) {
+                /* ... then we have nothing more to do */
+                return;
+        }
+
        if (!done_init) {
                int i;
 
@@ -1311,7 +1399,7 @@ static void init_globals(void)
                        if ((parm_table[i].type == P_STRING ||
                             parm_table[i].type == P_USTRING) &&
                            parm_table[i].ptr)
-                               string_set(parm_table[i].ptr, "");
+                               string_set((char **)parm_table[i].ptr, "");
 
                string_set(&sDefault.fstype, FSTYPE_STRING);
 
@@ -1367,6 +1455,9 @@ static void init_globals(void)
        slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
                 DEFAULT_MINOR_VERSION);
        string_set(&Globals.szAnnounceVersion, s);
+#ifdef DEVELOPER
+       string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
+#endif
 
        pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
 
@@ -1381,7 +1472,8 @@ static void init_globals(void)
        Globals.AlgorithmicRidBase = BASE_RID;
 
        Globals.bLoadPrinters = True;
-       Globals.PrintcapCacheTime = 0;
+       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;
@@ -1421,6 +1513,7 @@ static void init_globals(void)
        Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
        Globals.change_notify_timeout = 60;     /* 1 minute default. */
        Globals.bKernelChangeNotify = True;     /* On if we have it. */
+       Globals.bFamChangeNotify = True;        /* On if we have it. */
        Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
        Globals.lm_interval = 60;
        Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
@@ -1441,6 +1534,7 @@ static void init_globals(void)
        Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
        Globals.bNTStatusSupport = True; /* Use NT status by default. */
        Globals.bStatCache = True;      /* use stat cache by default */
+       Globals.iMaxStatCacheSize = 0;  /* unlimited size in kb by default. */
        Globals.restrict_anonymous = 0;
        Globals.bClientLanManAuth = True;       /* Do use the LanMan hash if it is available */
        Globals.bClientPlaintextAuth = True;    /* Do use a plaintext password if is requested by the server */
@@ -1450,7 +1544,6 @@ static void init_globals(void)
        /* Note, that we will use NTLM2 session security (which is different), if it is available */
 
        Globals.map_to_guest = 0;       /* By Default, "Never" */
-       Globals.min_passwd_length = MINPASSWDLENGTH;    /* By Default, 5. */
        Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
        Globals.enhanced_browsing = True; 
        Globals.iLockSpinCount = 3; /* Try 3 times. */
@@ -1461,22 +1554,20 @@ static void init_globals(void)
        Globals.bUseMmap = True;
 #endif
        Globals.bUnixExtensions = True;
+       Globals.bResetOnZeroVC = False;
 
        /* hostname lookups can be very expensive and are broken on
           a large number of sites (tridge) */
        Globals.bHostnameLookups = False;
 
-       str_list_free(&Globals.szPassdbBackend);
 #ifdef WITH_LDAP_SAMCONFIG
        string_set(&Globals.szLdapServer, "localhost");
        Globals.ldap_port = 636;
-       Globals.szPassdbBackend = str_list_make("ldapsam_compat", NULL);
+       string_set(&Globals.szPassdbBackend, "ldapsam_compat");
 #else
-       Globals.szPassdbBackend = str_list_make("smbpasswd", NULL);
+       string_set(&Globals.szPassdbBackend, "smbpasswd");
 #endif /* WITH_LDAP_SAMCONFIG */
-
        string_set(&Globals.szLdapSuffix, "");
-       string_set(&Globals.szLdapFilter, "(uid=%u)");
        string_set(&Globals.szLdapMachineSuffix, "");
        string_set(&Globals.szLdapUserSuffix, "");
        string_set(&Globals.szLdapGroupSuffix, "");
@@ -1488,6 +1579,7 @@ static void init_globals(void)
        Globals.ldap_delete_dn = False;
        Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
        Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
+       Globals.ldap_page_size = LDAP_PAGE_SIZE;
 
        /* This is what we tell the afs client. in reality we set the token 
         * to never expire, though, when this runs out the afs client will 
@@ -1525,20 +1617,23 @@ static void init_globals(void)
 
        string_set(&Globals.szTemplateShell, "/bin/false");
        string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
-       string_set(&Globals.szTemplatePrimaryGroup, "nobody");
        string_set(&Globals.szWinbindSeparator, "\\");
        string_set(&Globals.szAclCompat, "");
        string_set(&Globals.szCupsServer, "");
+       string_set(&Globals.szIPrintServer, "");
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
-       Globals.bWinbindEnableLocalAccounts = False;
        Globals.bWinbindEnumUsers = True;
        Globals.bWinbindEnumGroups = True;
        Globals.bWinbindUseDefaultDomain = False;
        Globals.bWinbindTrustedDomainsOnly = False;
        Globals.bWinbindNestedGroups = False;
+       Globals.winbind_max_idle_children = 3;
+       Globals.szWinbindNssInfo = str_list_make("template", NULL);
+       Globals.bWinbindRefreshTickets = False;
+       Globals.bWinbindOfflineLogon = False;
 
-       Globals.bEnableRidAlgorithm = True;
+       Globals.bPassdbExpandExplicit = True;
 
        Globals.name_cache_timeout = 660; /* In seconds */
 
@@ -1551,11 +1646,17 @@ static void init_globals(void)
        Globals.bDeferSharingViolations = True;
        string_set(&Globals.smb_ports, SMB_PORTS);
 
-       /* don't enable privileges by default since Domain 
-          Admins can then assign thr rights to perform certain 
-          operations as root */
-
-       Globals.bEnablePrivileges = False;
+       Globals.bEnablePrivileges = True;
+       Globals.bASUSupport       = False;
+       
+       /* User defined shares. */
+       pstrcpy(s, dyn_LOCKDIR);
+       pstrcat(s, "/usershares");
+       string_set(&Globals.szUsersharePath, s);
+       string_set(&Globals.szUsershareTemplateShare, "");
+       Globals.iUsershareMaxShares = 0;
+       /* By default disallow sharing of directories not owned by the sharer. */
+       Globals.bUsershareOwnerOnly = True;
 }
 
 static TALLOC_CTX *lp_talloc;
@@ -1568,10 +1669,23 @@ void lp_talloc_free(void)
 {
        if (!lp_talloc)
                return;
-       talloc_destroy(lp_talloc);
+       talloc_free(lp_talloc);
        lp_talloc = NULL;
 }
 
+TALLOC_CTX *tmp_talloc_ctx(void)
+{
+       if (lp_talloc == NULL) {
+               lp_talloc = talloc_init(NULL);
+       }
+
+       if (lp_talloc == NULL) {
+               smb_panic("Could not create temporary talloc context\n");
+       }
+
+       return lp_talloc;
+}
+
 /*******************************************************************
  Convenience routine to grab string parameters into temporary memory
  and run standard_sub_basic on them. The buffers can be written to by
@@ -1662,7 +1776,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)
@@ -1688,10 +1801,11 @@ FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
-FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
+FN_GLOBAL_STRING(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)
@@ -1705,43 +1819,51 @@ FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
 
 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
+FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
 
 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
 
 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
-FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup)
 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
 FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
-FN_GLOBAL_BOOL(lp_winbind_enable_local_accounts, &Globals.bWinbindEnableLocalAccounts)
 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
+FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
+FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
 
 FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
-FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm)
+FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
 
 #ifdef WITH_LDAP_SAMCONFIG
 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
 FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
 #endif
 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
-FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
+FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
 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_usershare_path, &Globals.szUsersharePath)
+FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
+FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
 
+FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
+
+FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
+FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
@@ -1776,6 +1898,7 @@ FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
+FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
@@ -1792,9 +1915,11 @@ FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
 FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify)
+FN_GLOBAL_BOOL(lp_fam_change_notify, &Globals.bFamChangeNotify)
 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
+FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
@@ -1814,7 +1939,7 @@ FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
-FN_GLOBAL_INTEGER(lp_disable_spoolss, &Globals.bDisableSpoolss)
+FN_GLOBAL_INTEGER(_lp_disable_spoolss, &Globals.bDisableSpoolss)
 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
@@ -1822,10 +1947,11 @@ FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
 FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
-FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
+FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
+
 FN_LOCAL_STRING(lp_preexec, szPreExec)
 FN_LOCAL_STRING(lp_postexec, szPostExec)
 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
@@ -1838,8 +1964,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_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)
@@ -1867,6 +1995,8 @@ FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
 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)
@@ -1921,6 +2051,9 @@ FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
+FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
+FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
+FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
@@ -1938,9 +2071,15 @@ 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_allocation_roundup_size, iallocation_roundup_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)
+FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
@@ -1958,6 +2097,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 */
@@ -2223,12 +2365,12 @@ static void free_service(service *pservice)
        for (i = 0; parm_table[i].label; i++) {
                if ((parm_table[i].type == P_STRING ||
                     parm_table[i].type == P_USTRING) &&
-                   parm_table[i].class == P_LOCAL)
+                   parm_table[i].p_class == P_LOCAL)
                        string_free((char **)
                                    (((char *)pservice) +
                                     PTR_DIFF(parm_table[i].ptr, &sDefault)));
                else if (parm_table[i].type == P_LIST &&
-                        parm_table[i].class == P_LOCAL)
+                        parm_table[i].p_class == P_LOCAL)
                             str_list_free((char ***)
                                            (((char *)pservice) +
                                             PTR_DIFF(parm_table[i].ptr, &sDefault)));
@@ -2250,6 +2392,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. 
@@ -2285,32 +2452,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;
 
@@ -2321,10 +2497,62 @@ 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? */
+
+       if ( !src ) {
+               DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
+               return NULL;
+       }
+
+       fstrcpy( canon, src );
+       strlower_m( canon );
+
+       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.
@@ -2354,7 +2582,7 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService,
                string_set(&ServicePtrs[i]->comment, comment);
        }
 
-       /* set the browseable flag from the gloabl default */
+       /* set the browseable flag from the global default */
 
        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
 
@@ -2470,6 +2698,59 @@ static int map_parameter(const char *pszParmName)
        return (-1);
 }
 
+/***************************************************************************
+ Show all parameter's name, type, [values,] and flags.
+***************************************************************************/
+
+void show_parameter_list(void)
+{
+       int classIndex, parmIndex, enumIndex, flagIndex;
+       BOOL hadFlag;
+       const char *section_names[] = { "local", "global", NULL};
+       const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
+               "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING", "P_GSTRING",
+               "P_UGSTRING", "P_ENUM", "P_SEP"};
+       unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
+               FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
+               FLAG_HIDE, FLAG_DOS_STRING};
+       const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
+               "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
+               "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
+
+       for ( classIndex=0; section_names[classIndex]; classIndex++) {
+               printf("[%s]\n", section_names[classIndex]);
+               for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
+                       if (parm_table[parmIndex].p_class == classIndex) {
+                               printf("%s=%s", 
+                                       parm_table[parmIndex].label,
+                                       type[parm_table[parmIndex].type]);
+                               switch (parm_table[parmIndex].type) {
+                               case P_ENUM:
+                                       printf(",");
+                                       for (enumIndex=0; parm_table[parmIndex].enum_list[enumIndex].name; enumIndex++)
+                                               printf("%s%s",
+                                                       enumIndex ? "|" : "",
+                                                       parm_table[parmIndex].enum_list[enumIndex].name);
+                                       break;
+                               default:
+                                       break;
+                               }
+                               printf(",");
+                               hadFlag = False;
+                               for ( flagIndex=0; flag_names[flagIndex]; flagIndex++ ) {
+                                       if (parm_table[parmIndex].flags & flags[flagIndex]) {
+                                               printf("%s%s",
+                                                       hadFlag ? "|" : "",
+                                                       flag_names[flagIndex]);
+                                               hadFlag = True;
+                                       }
+                               }
+                               printf("\n");
+                       }
+               }
+       }
+}
+
 /***************************************************************************
  Set a boolean variable from the text value stored in the passed string.
  Returns True in success, False if the passed string does not correctly 
@@ -2504,15 +2785,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);
 }
@@ -2530,7 +2819,7 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL
        BOOL not_added;
 
        for (i = 0; parm_table[i].label; i++)
-               if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
+               if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
                    (bcopyall || pcopymapDest[i])) {
                        void *def_ptr = parm_table[i].ptr;
                        void *src_ptr =
@@ -2557,12 +2846,12 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL
                                        break;
 
                                case P_STRING:
-                                       string_set(dest_ptr,
+                                       string_set((char **)dest_ptr,
                                                   *(char **)src_ptr);
                                        break;
 
                                case P_USTRING:
-                                       string_set(dest_ptr,
+                                       string_set((char **)dest_ptr,
                                                   *(char **)src_ptr);
                                        strupper_m(*(char **)dest_ptr);
                                        break;
@@ -2769,6 +3058,8 @@ static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr)
        return True;
 }
 
+
+
 static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr)
 {
        BOOL ret;
@@ -3160,7 +3451,7 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
        if (snum < 0) {
                parm_ptr = def_ptr;
        } else {
-               if (parm_table[parmnum].class == P_GLOBAL) {
+               if (parm_table[parmnum].p_class == P_GLOBAL) {
                        DEBUG(0,
                              ("Global parameter %s found in service section!\n",
                               pszParmName));
@@ -3192,11 +3483,11 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
        switch (parm_table[parmnum].type)
        {
                case P_BOOL:
-                       set_boolean(parm_ptr, pszParmValue);
+                       set_boolean((BOOL *)parm_ptr, pszParmValue);
                        break;
 
                case P_BOOLREV:
-                       set_boolean(parm_ptr, pszParmValue);
+                       set_boolean((BOOL *)parm_ptr, pszParmValue);
                        *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
                        break;
 
@@ -3209,20 +3500,23 @@ 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:
-                       str_list_free(parm_ptr);
+                       str_list_free((char ***)parm_ptr);
                        *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
                        break;
 
                case P_STRING:
-                       string_set(parm_ptr, pszParmValue);
+                       string_set((char **)parm_ptr, pszParmValue);
                        break;
 
                case P_USTRING:
-                       string_set(parm_ptr, pszParmValue);
+                       string_set((char **)parm_ptr, pszParmValue);
                        strupper_m(*(char **)parm_ptr);
                        break;
 
@@ -3487,10 +3781,10 @@ static void dump_globals(FILE *f)
        int i;
        param_opt_struct *data;
        
-       fprintf(f, "# Global parameters\n[global]\n");
+       fprintf(f, "[global]\n");
 
        for (i = 0; parm_table[i].label; i++)
-               if (parm_table[i].class == P_GLOBAL &&
+               if (parm_table[i].p_class == P_GLOBAL &&
                    parm_table[i].ptr &&
                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
                        if (defaults_saved && is_default(i))
@@ -3532,11 +3826,11 @@ static void dump_a_service(service * pService, FILE * f)
        param_opt_struct *data;
        
        if (pService != &sDefault)
-               fprintf(f, "\n[%s]\n", pService->szService);
+               fprintf(f, "[%s]\n", pService->szService);
 
        for (i = 0; parm_table[i].label; i++) {
 
-               if (parm_table[i].class == P_LOCAL &&
+               if (parm_table[i].p_class == P_LOCAL &&
                    parm_table[i].ptr &&
                    (*parm_table[i].label != '-') &&
                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
@@ -3563,15 +3857,57 @@ 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;
+                       }
+               }
+}
+
+/***************************************************************************
+ Display the contents of a parameter of a single services record.
+***************************************************************************/
+
+BOOL dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
+{
+       service * pService = ServicePtrs[snum];
+       int i, result = False;
+       parm_class p_class;
+       unsigned flag = 0;
+
+       if (isGlobal) {
+               p_class = P_GLOBAL;
+               flag = FLAG_GLOBAL;
+       } else
+               p_class = P_LOCAL;
+       
+       for (i = 0; parm_table[i].label; i++) {
+               if (strwicmp(parm_table[i].label, parm_name) == 0 &&
+                   (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
+                   parm_table[i].ptr &&
+                   (*parm_table[i].label != '-') &&
+                   (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
+               {
+                       void *ptr;
+
+                       if (isGlobal)
+                               ptr = parm_table[i].ptr;
+                       else
+                               ptr = ((char *)pService) +
+                                       PTR_DIFF(parm_table[i].ptr, &sDefault);
+
+                       print_parameter(&parm_table[i],
+                                       ptr, f);
+                       fprintf(f, "\n");
+                       result = True;
+                       break;
                }
        }
-}
 
+       return result;
+}
 
 /***************************************************************************
  Return info about the next service  in a service. snum==GLOBAL_SECTION_SNUM gives the globals.
@@ -3583,7 +3919,7 @@ struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
        if (snum < 0) {
                /* do the globals */
                for (; parm_table[*i].label; (*i)++) {
-                       if (parm_table[*i].class == P_SEPARATOR)
+                       if (parm_table[*i].p_class == P_SEPARATOR)
                                return &parm_table[(*i)++];
 
                        if (!parm_table[*i].ptr
@@ -3601,10 +3937,10 @@ struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
                service *pService = ServicePtrs[snum];
 
                for (; parm_table[*i].label; (*i)++) {
-                       if (parm_table[*i].class == P_SEPARATOR)
+                       if (parm_table[*i].p_class == P_SEPARATOR)
                                return &parm_table[(*i)++];
 
-                       if (parm_table[*i].class == P_LOCAL &&
+                       if (parm_table[*i].p_class == P_LOCAL &&
                            parm_table[*i].ptr &&
                            (*parm_table[*i].label != '-') &&
                            ((*i) == 0 ||
@@ -3645,7 +3981,7 @@ static void dump_copy_map(BOOL *pcopymap)
        printf("\n\tNon-Copied parameters:\n");
 
        for (i = 0; parm_table[i].label; i++)
-               if (parm_table[i].class == P_LOCAL &&
+               if (parm_table[i].p_class == P_LOCAL &&
                    parm_table[i].ptr && !pcopymap[i] &&
                    (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
                {
@@ -3732,13 +4068,14 @@ void lp_killunused(BOOL (*snumused) (int))
                if (!VALID(i))
                        continue;
 
-               /* don't kill autoloaded services */
-               if ( ServicePtrs[i]->autoloaded )
+               /* don't kill autoloaded or usershare services */
+               if ( ServicePtrs[i]->autoloaded ||
+                               ServicePtrs[i]->usershare == USERSHARE_VALID) {
                        continue;
+               }
 
                if (!snumused || !snumused(i)) {
-                       ServicePtrs[i]->valid = False;
-                       free_service(ServicePtrs[i]);
+                       free_service_byindex(i);
                }
        }
 }
@@ -3750,8 +4087,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);
        }
 }
 
@@ -3814,6 +4150,28 @@ static void lp_save_defaults(void)
  Set the server type we will announce as via nmbd.
 ********************************************************************/
 
+static const struct srv_role_tab {
+       uint32 role;
+       const char *role_str;
+} srv_role_tab [] = {
+       { ROLE_STANDALONE, "ROLE_STANDALONE" },
+       { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
+       { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
+       { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
+       { 0, NULL }
+};
+
+const char* server_role_str(uint32 role)
+{
+       int i = 0;
+       for (i=0; srv_role_tab[i].role_str; i++) {
+               if (role == srv_role_tab[i].role) {
+                       return srv_role_tab[i].role_str;
+               }
+       }
+       return NULL;
+}
+
 static void set_server_role(void)
 {
        server_role = ROLE_STANDALONE;
@@ -3857,27 +4215,13 @@ static void set_server_role(void)
                        break;
        }
 
-       DEBUG(10, ("set_server_role: role = "));
-
-       switch(server_role) {
-       case ROLE_STANDALONE:
-               DEBUGADD(10, ("ROLE_STANDALONE\n"));
-               break;
-       case ROLE_DOMAIN_MEMBER:
-               DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
-               break;
-       case ROLE_DOMAIN_BDC:
-               DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
-               break;
-       case ROLE_DOMAIN_PDC:
-               DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
-               break;
-       }
+       DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
 }
 
 /***********************************************************
  If we should send plaintext/LANMAN passwords in the clinet
 ************************************************************/
+
 static void set_allowed_client_auth(void)
 {
        if (Globals.bClientNTLMv2Auth) {
@@ -3888,13 +4232,621 @@ static void set_allowed_client_auth(void)
        }
 }
 
+/***************************************************************************
+ JRA.
+ The following code allows smbd to read a user defined share file.
+ Yes, this is my intent. Yes, I'm comfortable with that...
+
+ THE FOLLOWING IS SECURITY CRITICAL CODE.
+
+ It washes your clothes, it cleans your house, it guards you while you sleep...
+ Do not f%^k with it....
+***************************************************************************/
+
+#define MAX_USERSHARE_FILE_SIZE (10*1024)
+
+/***************************************************************************
+ Check allowed stat state of a usershare file.
+ Ensure we print out who is dicking with us so the admin can
+ get their sorry ass fired.
+***************************************************************************/
+
+static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
+{
+       if (!S_ISREG(psbuf->st_mode)) {
+               DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
+                       "not a regular file\n",
+                       fname, (unsigned int)psbuf->st_uid ));
+               return False;
+       }
+
+       /* Ensure this doesn't have the other write bit set. */
+       if (psbuf->st_mode & S_IWOTH) {
+               DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
+                       "public write. Refusing to allow as a usershare file.\n",
+                       fname, (unsigned int)psbuf->st_uid ));
+               return False;
+       }
+
+       /* Should be 10k or less. */
+       if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
+               DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
+                       "too large (%u) to be a user share file.\n",
+                       fname, (unsigned int)psbuf->st_uid,
+                       (unsigned int)psbuf->st_size ));
+               return False;
+       }
+
+       return True;
+}
+
+/***************************************************************************
+ Parse the contents of a usershare file.
+***************************************************************************/
+
+enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, 
+                       SMB_STRUCT_STAT *psbuf,
+                       const char *servicename,
+                       int snum,
+                       char **lines,
+                       int numlines,
+                       pstring sharepath,
+                       pstring comment,
+                       SEC_DESC **ppsd)
+{
+       const char **prefixallowlist = lp_usershare_prefix_allow_list();
+       const char **prefixdenylist = lp_usershare_prefix_deny_list();
+       SMB_STRUCT_DIR *dp;
+       SMB_STRUCT_STAT sbuf;
+
+       if (numlines < 4) {
+               return USERSHARE_MALFORMED_FILE;
+       }
+
+       if (!strequal(lines[0], "#VERSION 1")) {
+               return USERSHARE_BAD_VERSION;
+       }
+
+       if (!strnequal(lines[1], "path=", 5)) {
+               return USERSHARE_MALFORMED_PATH;
+       }
+
+       pstrcpy(sharepath, &lines[1][5]);
+       trim_string(sharepath, " ", " ");
+
+       if (!strnequal(lines[2], "comment=", 8)) {
+               return USERSHARE_MALFORMED_COMMENT_DEF;
+       }
+
+       pstrcpy(comment, &lines[2][8]);
+       trim_string(comment, " ", " ");
+       trim_char(comment, '"', '"');
+
+       if (!strnequal(lines[3], "usershare_acl=", 14)) {
+               return USERSHARE_MALFORMED_ACL_DEF;
+       }
+
+       if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
+               return USERSHARE_ACL_ERR;
+       }
+
+       if (snum != -1 && strequal(sharepath, ServicePtrs[snum]->szPath)) {
+               /* Path didn't change, no checks needed. */
+               return USERSHARE_OK;
+       }
+
+       /* The path *must* be absolute. */
+       if (sharepath[0] != '/') {
+               DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
+                       servicename, sharepath));
+               return USERSHARE_PATH_NOT_ABSOLUTE;
+       }
+
+       /* If there is a usershare prefix deny list ensure one of these paths
+          doesn't match the start of the user given path. */
+       if (prefixdenylist) {
+               int i;
+               for ( i=0; prefixdenylist[i]; i++ ) {
+                       DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
+                               servicename, i, prefixdenylist[i], sharepath ));
+                       if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
+                               DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
+                                       "usershare prefix deny list entries.\n",
+                                       servicename, sharepath));
+                               return USERSHARE_PATH_IS_DENIED;
+                       }
+               }
+       }
+
+       /* If there is a usershare prefix allow list ensure one of these paths
+          does match the start of the user given path. */
+
+       if (prefixallowlist) {
+               int i;
+               for ( i=0; prefixallowlist[i]; i++ ) {
+                       DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
+                               servicename, i, prefixallowlist[i], sharepath ));
+                       if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
+                               break;
+                       }
+               }
+               if (prefixallowlist[i] == NULL) {
+                       DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
+                               "usershare prefix allow list entries.\n",
+                               servicename, sharepath));
+                       return USERSHARE_PATH_NOT_ALLOWED;
+               }
+        }
+
+       /* Ensure this is pointing to a directory. */
+       dp = sys_opendir(sharepath);
+
+       if (!dp) {
+               DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
+                       servicename, sharepath));
+               return USERSHARE_PATH_NOT_DIRECTORY;
+       }
+
+       /* Ensure the owner of the usershare file has permission to share
+          this directory. */
+
+       if (sys_stat(sharepath, &sbuf) == -1) {
+               DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
+                       servicename, sharepath, strerror(errno) ));
+               sys_closedir(dp);
+               return USERSHARE_POSIX_ERR;
+       }
+
+       sys_closedir(dp);
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
+                       servicename, sharepath ));
+               return USERSHARE_PATH_NOT_DIRECTORY;
+       }
+
+       /* Check if sharing is restricted to owner-only. */
+       /* psbuf is the stat of the usershare definition file,
+          sbuf is the stat of the target directory to be shared. */
+
+       if (lp_usershare_owner_only()) {
+               /* root can share anything. */
+               if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
+                       return USERSHARE_PATH_NOT_ALLOWED;
+               }
+       }
+
+       return USERSHARE_OK;
+}
+
+/***************************************************************************
+ Deal with a usershare file.
+ Returns:
+       >= 0 - snum
+       -1 - Bad name, invalid contents.
+          - service name already existed and not a usershare, problem
+           with permissions to share directory etc.
+***************************************************************************/
+
+static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
+{
+       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_STAT lsbuf;
+       pstring fname;
+       pstring sharepath;
+       pstring comment;
+       fstring service_name;
+       char **lines = NULL;
+       int numlines = 0;
+       int fd = -1;
+       int iService = -1;
+       TALLOC_CTX *ctx = NULL;
+       SEC_DESC *psd = NULL;
+
+       /* Ensure share name doesn't contain invalid characters. */
+       if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
+               DEBUG(0,("process_usershare_file: share name %s contains "
+                       "invalid characters (any of %s)\n",
+                       file_name, INVALID_SHARENAME_CHARS ));
+               return -1;
+       }
+
+       fstrcpy(service_name, file_name);
+
+       pstrcpy(fname, dir_name);
+       pstrcat(fname, "/");
+       pstrcat(fname, file_name);
+
+       /* Minimize the race condition by doing an lstat before we
+          open and fstat. Ensure this isn't a symlink link. */
+
+       if (sys_lstat(fname, &lsbuf) != 0) {
+               DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
+                       fname, strerror(errno) ));
+               return -1;
+       }
+
+       /* This must be a regular file, not a symlink, directory or
+          other strange filetype. */
+       if (!check_usershare_stat(fname, &lsbuf)) {
+               return -1;
+       }
+
+       /* See if there is already a servicenum for this name. */
+       /* tdb_fetch_int32 returns -1 if not found. */
+       iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
+
+       if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
+               /* Nothing changed - Mark valid and return. */
+               DEBUG(10,("process_usershare_file: service %s not changed.\n",
+                       service_name ));
+               ServicePtrs[iService]->usershare = USERSHARE_VALID;
+               return iService;
+       }
+
+       /* Try and open the file read only - no symlinks allowed. */
+#ifdef O_NOFOLLOW
+       fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
+#else
+       fd = sys_open(fname, O_RDONLY, 0);
+#endif
+
+       if (fd == -1) {
+               DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
+                       fname, strerror(errno) ));
+               return -1;
+       }
+
+       /* Now fstat to be *SURE* it's a regular file. */
+       if (sys_fstat(fd, &sbuf) != 0) {
+               close(fd);
+               DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
+                       fname, strerror(errno) ));
+               return -1;
+       }
+
+       /* Is it the same dev/inode as was lstated ? */
+       if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
+               close(fd);
+               DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
+                       "Symlink spoofing going on ?\n", fname ));
+               return -1;
+       }
+
+       /* This must be a regular file, not a symlink, directory or
+          other strange filetype. */
+       if (!check_usershare_stat(fname, &sbuf)) {
+               return -1;
+       }
+
+       lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
+
+       close(fd);
+       if (lines == NULL) {
+               DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
+                       fname, (unsigned int)sbuf.st_uid ));
+       }
+
+       /* Should we allow printers to be shared... ? */
+       ctx = talloc_init("usershare_sd_xctx");
+       if (!ctx) {
+               SAFE_FREE(lines);
+               return 1;
+       }
+
+       if (parse_usershare_file(ctx, &sbuf, service_name, iService, lines, numlines, sharepath, comment, &psd) != USERSHARE_OK) {
+               talloc_destroy(ctx);
+               SAFE_FREE(lines);
+               return -1;
+       }
+
+       SAFE_FREE(lines);
+
+       /* Everything ok - add the service possibly using a template. */
+       if (iService < 0) {
+               const service *sp = &sDefault;
+               if (snum_template != -1) {
+                       sp = ServicePtrs[snum_template];
+               }
+
+               if ((iService = add_a_service(sp, service_name)) < 0) {
+                       DEBUG(0, ("process_usershare_file: Failed to add "
+                               "new service %s\n", service_name));
+                       talloc_destroy(ctx);
+                       return -1;
+               }
+
+               /* Read only is controlled by usershare ACL below. */
+               ServicePtrs[iService]->bRead_only = False;
+       }
+
+       /* Write the ACL of the new/modified share. */
+       if (!set_share_security(ctx, service_name, psd)) {
+                DEBUG(0, ("process_usershare_file: Failed to set share "
+                       "security for user share %s\n",
+                       service_name ));
+               lp_remove_service(iService);
+               talloc_destroy(ctx);
+               return -1;
+       }
+
+       talloc_destroy(ctx);
+
+       /* If from a template it may be marked invalid. */
+       ServicePtrs[iService]->valid = True;
+
+       /* Set the service as a valid usershare. */
+       ServicePtrs[iService]->usershare = USERSHARE_VALID;
+
+       /* And note when it was loaded. */
+       ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
+       string_set(&ServicePtrs[iService]->szPath, sharepath);
+       string_set(&ServicePtrs[iService]->comment, comment);
+
+       return iService;
+}
+
+/***************************************************************************
+ Checks if a usershare entry has been modified since last load.
+***************************************************************************/
+
+static BOOL usershare_exists(int iService, time_t *last_mod)
+{
+       SMB_STRUCT_STAT lsbuf;
+       const char *usersharepath = Globals.szUsersharePath;
+       pstring fname;
+
+       pstrcpy(fname, usersharepath);
+       pstrcat(fname, "/");
+       pstrcat(fname, ServicePtrs[iService]->szService);
+
+       if (sys_lstat(fname, &lsbuf) != 0) {
+               return False;
+       }
+
+       if (!S_ISREG(lsbuf.st_mode)) {
+               return False;
+       }
+
+       *last_mod = lsbuf.st_mtime;
+       return True;
+}
+
+/***************************************************************************
+ Load a usershare service by name. Returns a valid servicenumber or -1.
+***************************************************************************/
+
+int load_usershare_service(const char *servicename)
+{
+       SMB_STRUCT_STAT sbuf;
+       const char *usersharepath = Globals.szUsersharePath;
+       int max_user_shares = Globals.iUsershareMaxShares;
+       int snum_template = -1;
+
+       if (*usersharepath == 0 ||  max_user_shares == 0) {
+               return -1;
+       }
+
+       if (sys_stat(usersharepath, &sbuf) != 0) {
+               DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
+                       usersharepath, strerror(errno) ));
+               return -1;
+       }
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               DEBUG(0,("load_usershare_service: %s is not a directory.\n",
+                       usersharepath ));
+               return -1;
+       }
+
+       /*
+        * This directory must be owned by root, and have the 't' bit set.
+        * It also must not be writable by "other".
+        */
+
+#ifdef S_ISVTX
+       if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+#else
+       if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+#endif
+               DEBUG(0,("load_usershare_service: directory %s is not owned by root "
+                       "or does not have the sticky bit 't' set or is writable by anyone.\n",
+                       usersharepath ));
+               return -1;
+       }
+
+       /* Ensure the template share exists if it's set. */
+       if (Globals.szUsershareTemplateShare[0]) {
+               /* We can't use lp_servicenumber here as we are recommending that
+                  template shares have -valid=False set. */
+               for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
+                       if (ServicePtrs[snum_template]->szService &&
+                                       strequal(ServicePtrs[snum_template]->szService,
+                                               Globals.szUsershareTemplateShare)) {
+                               break;
+                       }
+               }
+
+               if (snum_template == -1) {
+                       DEBUG(0,("load_usershare_service: usershare template share %s "
+                               "does not exist.\n",
+                               Globals.szUsershareTemplateShare ));
+                       return -1;
+               }
+       }
+
+       return process_usershare_file(usersharepath, servicename, snum_template);
+}
+
+/***************************************************************************
+ Load all user defined shares from the user share directory.
+ We only do this if we're enumerating the share list.
+ This is the function that can delete usershares that have
+ been removed.
+***************************************************************************/
+
+int load_usershare_shares(void)
+{
+       SMB_STRUCT_DIR *dp;
+       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_DIRENT *de;
+       int num_usershares = 0;
+       int max_user_shares = Globals.iUsershareMaxShares;
+       unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
+       unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
+       unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
+       int iService;
+       int snum_template = -1;
+       const char *usersharepath = Globals.szUsersharePath;
+       int ret = lp_numservices();
+
+       if (max_user_shares == 0 || *usersharepath == '\0') {
+               return lp_numservices();
+       }
+
+       if (sys_stat(usersharepath, &sbuf) != 0) {
+               DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
+                       usersharepath, strerror(errno) ));
+               return ret;
+       }
+
+       /*
+        * This directory must be owned by root, and have the 't' bit set.
+        * It also must not be writable by "other".
+        */
+
+#ifdef S_ISVTX
+       if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+#else
+       if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+#endif
+               DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
+                       "or does not have the sticky bit 't' set or is writable by anyone.\n",
+                       usersharepath ));
+               return ret;
+       }
+
+       /* Ensure the template share exists if it's set. */
+       if (Globals.szUsershareTemplateShare[0]) {
+               /* We can't use lp_servicenumber here as we are recommending that
+                  template shares have -valid=False set. */
+               for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
+                       if (ServicePtrs[snum_template]->szService &&
+                                       strequal(ServicePtrs[snum_template]->szService,
+                                               Globals.szUsershareTemplateShare)) {
+                               break;
+                       }
+               }
+
+               if (snum_template == -1) {
+                       DEBUG(0,("load_usershare_shares: usershare template share %s "
+                               "does not exist.\n",
+                               Globals.szUsershareTemplateShare ));
+                       return ret;
+               }
+       }
+
+       /* Mark all existing usershares as pending delete. */
+       for (iService = iNumServices - 1; iService >= 0; iService--) {
+               if (VALID(iService) && ServicePtrs[iService]->usershare) {
+                       ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
+               }
+       }
+
+       dp = sys_opendir(usersharepath);
+       if (!dp) {
+               DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
+                       usersharepath, strerror(errno) ));
+               return ret;
+       }
+
+       for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
+                       (de = sys_readdir(dp));
+                       num_dir_entries++ ) {
+               int r;
+               const char *n = de->d_name;
+
+               /* Ignore . and .. */
+               if (*n == '.') {
+                       if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
+                               continue;
+                       }
+               }
+
+               if (n[0] == ':') {
+                       /* Temporary file used when creating a share. */
+                       num_tmp_dir_entries++;
+               }
+
+               /* Allow 20% tmp entries. */
+               if (num_tmp_dir_entries > allowed_tmp_entries) {
+                       DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
+                               "in directory %s\n",
+                               num_tmp_dir_entries, usersharepath));
+                       break;
+               }
+
+               r = process_usershare_file(usersharepath, n, snum_template);
+               if (r == 0) {
+                       /* Update the services count. */
+                       num_usershares++;
+                       if (num_usershares >= max_user_shares) {
+                               DEBUG(0,("load_usershare_shares: max user shares reached "
+                                       "on file %s in directory %s\n",
+                                       n, usersharepath ));
+                               break;
+                       }
+               } else if (r == -1) {
+                       num_bad_dir_entries++;
+               }
+
+               /* Allow 20% bad entries. */
+               if (num_bad_dir_entries > allowed_bad_entries) {
+                       DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
+                               "in directory %s\n",
+                               num_bad_dir_entries, usersharepath));
+                       break;
+               }
+
+               /* Allow 20% bad entries. */
+               if (num_dir_entries > max_user_shares + allowed_bad_entries) {
+                       DEBUG(0,("load_usershare_shares: too many total entries (%u) "
+                       "in directory %s\n",
+                       num_dir_entries, usersharepath));
+                       break;
+               }
+       }
+
+       sys_closedir(dp);
+
+       /* Sweep through and delete any non-refreshed usershares that are
+          not currently in use. */
+       for (iService = iNumServices - 1; iService >= 0; iService--) {
+               if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
+                       if (conn_snum_used(iService)) {
+                               continue;
+                       }
+                       /* Remove from the share ACL db. */
+                       DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
+                               lp_servicename(iService) ));
+                       delete_share_security(iService);
+                       free_service_byindex(iService);
+               }
+       }
+
+       return lp_numservices();
+}
+
 /***************************************************************************
  Load the services array from the services file. Return True on success, 
  False on failure.
 ***************************************************************************/
 
-BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
-            BOOL add_ipc)
+BOOL lp_load(const char *pszFname,
+             BOOL global_only,
+             BOOL save_defaults,
+            BOOL add_ipc,
+             BOOL initialize_globals)
 {
        pstring n2;
        BOOL bRetval;
@@ -3913,7 +4865,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
        bInGlobalSection = True;
        bGlobalOnly = global_only;
 
-       init_globals();
+       init_globals(! initialize_globals);
        debug_init();
 
        if (save_defaults) {
@@ -3950,7 +4902,8 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
                /* When 'restrict anonymous = 2' guest connections to ipc$
                   are denied */
                lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
-               lp_add_ipc("ADMIN$", False);
+               if ( lp_enable_asu_support() )
+                       lp_add_ipc("ADMIN$", False);
        }
 
        set_server_role();
@@ -4003,8 +4956,10 @@ void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
 
        dump_a_service(&sDefault, f);
 
-       for (iService = 0; iService < maxtoprint; iService++)
+       for (iService = 0; iService < maxtoprint; iService++) {
+               fprintf(f,"\n");
                lp_dump_one(f, show_defaults, iService);
+       }
 }
 
 /***************************************************************************
@@ -4032,8 +4987,9 @@ int lp_servicenumber(const char *pszServiceName)
        int iService;
         fstring serviceName;
         
-        if (!pszServiceName)
+        if (!pszServiceName) {
                return GLOBAL_SECTION_SNUM;
+       }
         
        for (iService = iNumServices - 1; iService >= 0; iService--) {
                if (VALID(iService) && ServicePtrs[iService]->szService) {
@@ -4043,8 +4999,30 @@ int lp_servicenumber(const char *pszServiceName)
                         */
                        fstrcpy(serviceName, ServicePtrs[iService]->szService);
                        standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName));
-                       if (strequal(serviceName, pszServiceName))
+                       if (strequal(serviceName, pszServiceName)) {
                                break;
+                       }
+               }
+       }
+
+       if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
+               time_t last_mod;
+
+               if (!usershare_exists(iService, &last_mod)) {
+                       /* Remove the share security tdb entry for it. */
+                       delete_share_security(iService);
+                       /* Remove it from the array. */
+                       free_service_byindex(iService);
+                       /* Doesn't exist anymore. */
+                       return GLOBAL_SECTION_SNUM;
+               }
+
+               /* Has it been modified ? If so delete and reload. */
+               if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
+                       /* Remove it from the array. */
+                       free_service_byindex(iService);
+                       /* and now reload it. */
+                       iService = load_usershare_service(pszServiceName);
                }
        }
 
@@ -4164,6 +5142,7 @@ BOOL lp_preferred_master(void)
 void lp_remove_service(int snum)
 {
        ServicePtrs[snum]->valid = False;
+       invalid_services[num_invalid_services++] = snum;
 }
 
 /*******************************************************************
@@ -4257,15 +5236,6 @@ const char *lp_printername(int snum)
 }
 
 
-/****************************************************************
- Compatibility fn. for 2.2.2 code.....
-*****************************************************************/
-
-void get_private_directory(pstring privdir)
-{
-       pstrcpy (privdir, lp_private_dir());
-}
-
 /***********************************************************
  Allow daemons such as winbindd to fix their logfile name.
 ************************************************************/
@@ -4313,9 +5283,34 @@ const char *lp_printcapname(void)
  Ensure we don't use sendfile if server smb signing is active.
 ********************************************************************/
 
+static uint32 spoolss_state;
+
+BOOL lp_disable_spoolss( void )
+{
+       if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
+               spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
+
+       return spoolss_state == SVCCTL_STOPPED ? True : False;
+}
+
+void lp_set_spoolss_state( uint32 state )
+{
+       SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
+
+       spoolss_state = state;
+}
+
+uint32 lp_get_spoolss_state( void )
+{
+       return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
+}
+
+/*******************************************************************
+ Ensure we don't use sendfile if server smb signing is active.
+********************************************************************/
+
 BOOL lp_use_sendfile(int snum)
 {
-       extern enum protocol_types Protocol;
        /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
        if (Protocol < PROTOCOL_NT1) {
                return False;
@@ -4345,3 +5340,29 @@ void set_store_dos_attributes(int snum, BOOL val)
                return;
        ServicePtrs[(snum)]->bStoreDosAttributes = val;
 }
+
+void lp_set_mangling_method(const char *new_method)
+{
+       string_set(&Globals.szManglingMethod, new_method);
+}
+
+/*******************************************************************
+ Global state for POSIX pathname processing.
+********************************************************************/
+
+static BOOL posix_pathnames;
+
+BOOL lp_posix_pathnames(void)
+{
+       return posix_pathnames;
+}
+
+/*******************************************************************
+ Change everything needed to ensure POSIX pathname processing (currently
+ not much).
+********************************************************************/
+
+void lp_set_posix_pathnames(void)
+{
+       posix_pathnames = True;
+}